aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/arch/win32/ArchMiscWindows.cpp
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@ubuntu.com>2018-04-25 18:07:30 -0400
committerLibravatarUnit 193 <unit193@ubuntu.com>2018-04-25 18:07:30 -0400
commit9b1b081cfdb1c0fb6457278775e0823f8bc10f62 (patch)
treece8840148d8445055ba9e4f12263b2208f234c16 /src/lib/arch/win32/ArchMiscWindows.cpp
Import Upstream version 2.0.0+dfsgupstream/2.0.0+dfsg
Diffstat (limited to 'src/lib/arch/win32/ArchMiscWindows.cpp')
-rw-r--r--src/lib/arch/win32/ArchMiscWindows.cpp524
1 files changed, 524 insertions, 0 deletions
diff --git a/src/lib/arch/win32/ArchMiscWindows.cpp b/src/lib/arch/win32/ArchMiscWindows.cpp
new file mode 100644
index 0000000..924afa2
--- /dev/null
+++ b/src/lib/arch/win32/ArchMiscWindows.cpp
@@ -0,0 +1,524 @@
+/*
+ * barrier -- mouse and keyboard sharing utility
+ * Copyright (C) 2012-2016 Symless Ltd.
+ * Copyright (C) 2002 Chris Schoeneman
+ *
+ * This package is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * found in the file LICENSE that should have accompanied this file.
+ *
+ * This package is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "arch/win32/ArchMiscWindows.h"
+#include "arch/win32/ArchDaemonWindows.h"
+#include "base/Log.h"
+#include "common/Version.h"
+
+#include <Wtsapi32.h>
+#pragma warning(disable: 4099)
+#include <Userenv.h>
+#pragma warning(default: 4099)
+
+// parent process name for services in Vista
+#define SERVICE_LAUNCHER "services.exe"
+
+#ifndef ES_SYSTEM_REQUIRED
+#define ES_SYSTEM_REQUIRED ((DWORD)0x00000001)
+#endif
+#ifndef ES_DISPLAY_REQUIRED
+#define ES_DISPLAY_REQUIRED ((DWORD)0x00000002)
+#endif
+#ifndef ES_CONTINUOUS
+#define ES_CONTINUOUS ((DWORD)0x80000000)
+#endif
+typedef DWORD EXECUTION_STATE;
+
+//
+// ArchMiscWindows
+//
+
+ArchMiscWindows::Dialogs* ArchMiscWindows::s_dialogs = NULL;
+DWORD ArchMiscWindows::s_busyState = 0;
+ArchMiscWindows::STES_t ArchMiscWindows::s_stes = NULL;
+HICON ArchMiscWindows::s_largeIcon = NULL;
+HICON ArchMiscWindows::s_smallIcon = NULL;
+HINSTANCE ArchMiscWindows::s_instanceWin32 = NULL;
+
+void
+ArchMiscWindows::cleanup()
+{
+ delete s_dialogs;
+}
+
+void
+ArchMiscWindows::init()
+{
+ // stop windows system error dialogs from showing.
+ SetErrorMode(SEM_FAILCRITICALERRORS);
+
+ s_dialogs = new Dialogs;
+}
+
+void
+ArchMiscWindows::setIcons(HICON largeIcon, HICON smallIcon)
+{
+ s_largeIcon = largeIcon;
+ s_smallIcon = smallIcon;
+}
+
+void
+ArchMiscWindows::getIcons(HICON& largeIcon, HICON& smallIcon)
+{
+ largeIcon = s_largeIcon;
+ smallIcon = s_smallIcon;
+}
+
+int
+ArchMiscWindows::runDaemon(RunFunc runFunc)
+{
+ return ArchDaemonWindows::runDaemon(runFunc);
+}
+
+void
+ArchMiscWindows::daemonRunning(bool running)
+{
+ ArchDaemonWindows::daemonRunning(running);
+}
+
+void
+ArchMiscWindows::daemonFailed(int result)
+{
+ ArchDaemonWindows::daemonFailed(result);
+}
+
+UINT
+ArchMiscWindows::getDaemonQuitMessage()
+{
+ return ArchDaemonWindows::getDaemonQuitMessage();
+}
+
+HKEY
+ArchMiscWindows::openKey(HKEY key, const TCHAR* keyName)
+{
+ return openKey(key, keyName, false);
+}
+
+HKEY
+ArchMiscWindows::openKey(HKEY key, const TCHAR* const* keyNames)
+{
+ return openKey(key, keyNames, false);
+}
+
+HKEY
+ArchMiscWindows::addKey(HKEY key, const TCHAR* keyName)
+{
+ return openKey(key, keyName, true);
+}
+
+HKEY
+ArchMiscWindows::addKey(HKEY key, const TCHAR* const* keyNames)
+{
+ return openKey(key, keyNames, true);
+}
+
+HKEY
+ArchMiscWindows::openKey(HKEY key, const TCHAR* keyName, bool create)
+{
+ // ignore if parent is NULL
+ if (key == NULL) {
+ return NULL;
+ }
+
+ // open next key
+ HKEY newKey;
+ LONG result = RegOpenKeyEx(key, keyName, 0,
+ KEY_WRITE | KEY_QUERY_VALUE, &newKey);
+ if (result != ERROR_SUCCESS && create) {
+ DWORD disp;
+ result = RegCreateKeyEx(key, keyName, 0, TEXT(""),
+ 0, KEY_WRITE | KEY_QUERY_VALUE,
+ NULL, &newKey, &disp);
+ }
+ if (result != ERROR_SUCCESS) {
+ RegCloseKey(key);
+ return NULL;
+ }
+
+ // switch to new key
+ RegCloseKey(key);
+ return newKey;
+}
+
+HKEY
+ArchMiscWindows::openKey(HKEY key, const TCHAR* const* keyNames, bool create)
+{
+ for (size_t i = 0; key != NULL && keyNames[i] != NULL; ++i) {
+ // open next key
+ key = openKey(key, keyNames[i], create);
+ }
+ return key;
+}
+
+void
+ArchMiscWindows::closeKey(HKEY key)
+{
+ assert(key != NULL);
+ if (key==NULL) return;
+ RegCloseKey(key);
+}
+
+void
+ArchMiscWindows::deleteKey(HKEY key, const TCHAR* name)
+{
+ assert(key != NULL);
+ assert(name != NULL);
+ if (key==NULL || name==NULL) return;
+ RegDeleteKey(key, name);
+}
+
+void
+ArchMiscWindows::deleteValue(HKEY key, const TCHAR* name)
+{
+ assert(key != NULL);
+ assert(name != NULL);
+ if (key==NULL || name==NULL) return;
+ RegDeleteValue(key, name);
+}
+
+bool
+ArchMiscWindows::hasValue(HKEY key, const TCHAR* name)
+{
+ DWORD type;
+ LONG result = RegQueryValueEx(key, name, 0, &type, NULL, NULL);
+ return (result == ERROR_SUCCESS &&
+ (type == REG_DWORD || type == REG_SZ));
+}
+
+ArchMiscWindows::EValueType
+ArchMiscWindows::typeOfValue(HKEY key, const TCHAR* name)
+{
+ DWORD type;
+ LONG result = RegQueryValueEx(key, name, 0, &type, NULL, NULL);
+ if (result != ERROR_SUCCESS) {
+ return kNO_VALUE;
+ }
+ switch (type) {
+ case REG_DWORD:
+ return kUINT;
+
+ case REG_SZ:
+ return kSTRING;
+
+ case REG_BINARY:
+ return kBINARY;
+
+ default:
+ return kUNKNOWN;
+ }
+}
+
+void
+ArchMiscWindows::setValue(HKEY key,
+ const TCHAR* name, const std::string& value)
+{
+ assert(key != NULL);
+ if (key == NULL) {
+ // TODO: throw exception
+ return;
+ }
+ RegSetValueEx(key, name, 0, REG_SZ,
+ reinterpret_cast<const BYTE*>(value.c_str()),
+ (DWORD)value.size() + 1);
+}
+
+void
+ArchMiscWindows::setValue(HKEY key, const TCHAR* name, DWORD value)
+{
+ assert(key != NULL);
+ if (key == NULL) {
+ // TODO: throw exception
+ return;
+ }
+ RegSetValueEx(key, name, 0, REG_DWORD,
+ reinterpret_cast<CONST BYTE*>(&value),
+ sizeof(DWORD));
+}
+
+void
+ArchMiscWindows::setValueBinary(HKEY key,
+ const TCHAR* name, const std::string& value)
+{
+ assert(key != NULL);
+ assert(name != NULL);
+ if (key == NULL || name == NULL) {
+ // TODO: throw exception
+ return;
+ }
+ RegSetValueEx(key, name, 0, REG_BINARY,
+ reinterpret_cast<const BYTE*>(value.data()),
+ (DWORD)value.size());
+}
+
+std::string
+ArchMiscWindows::readBinaryOrString(HKEY key, const TCHAR* name, DWORD type)
+{
+ // get the size of the string
+ DWORD actualType;
+ DWORD size = 0;
+ LONG result = RegQueryValueEx(key, name, 0, &actualType, NULL, &size);
+ if (result != ERROR_SUCCESS || actualType != type) {
+ return std::string();
+ }
+
+ // if zero size then return empty string
+ if (size == 0) {
+ return std::string();
+ }
+
+ // allocate space
+ char* buffer = new char[size];
+
+ // read it
+ result = RegQueryValueEx(key, name, 0, &actualType,
+ reinterpret_cast<BYTE*>(buffer), &size);
+ if (result != ERROR_SUCCESS || actualType != type) {
+ delete[] buffer;
+ return std::string();
+ }
+
+ // clean up and return value
+ if (type == REG_SZ && buffer[size - 1] == '\0') {
+ // don't include terminating nul; std::string will add one.
+ --size;
+ }
+ std::string value(buffer, size);
+ delete[] buffer;
+ return value;
+}
+
+std::string
+ArchMiscWindows::readValueString(HKEY key, const TCHAR* name)
+{
+ return readBinaryOrString(key, name, REG_SZ);
+}
+
+std::string
+ArchMiscWindows::readValueBinary(HKEY key, const TCHAR* name)
+{
+ return readBinaryOrString(key, name, REG_BINARY);
+}
+
+DWORD
+ArchMiscWindows::readValueInt(HKEY key, const TCHAR* name)
+{
+ DWORD type;
+ DWORD value;
+ DWORD size = sizeof(value);
+ LONG result = RegQueryValueEx(key, name, 0, &type,
+ reinterpret_cast<BYTE*>(&value), &size);
+ if (result != ERROR_SUCCESS || type != REG_DWORD) {
+ return 0;
+ }
+ return value;
+}
+
+void
+ArchMiscWindows::addDialog(HWND hwnd)
+{
+ s_dialogs->insert(hwnd);
+}
+
+void
+ArchMiscWindows::removeDialog(HWND hwnd)
+{
+ s_dialogs->erase(hwnd);
+}
+
+bool
+ArchMiscWindows::processDialog(MSG* msg)
+{
+ for (Dialogs::const_iterator index = s_dialogs->begin();
+ index != s_dialogs->end(); ++index) {
+ if (IsDialogMessage(*index, msg)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+ArchMiscWindows::addBusyState(DWORD busyModes)
+{
+ s_busyState |= busyModes;
+ setThreadExecutionState(s_busyState);
+}
+
+void
+ArchMiscWindows::removeBusyState(DWORD busyModes)
+{
+ s_busyState &= ~busyModes;
+ setThreadExecutionState(s_busyState);
+}
+
+void
+ArchMiscWindows::setThreadExecutionState(DWORD busyModes)
+{
+ // look up function dynamically so we work on older systems
+ if (s_stes == NULL) {
+ HINSTANCE kernel = LoadLibrary("kernel32.dll");
+ if (kernel != NULL) {
+ s_stes = reinterpret_cast<STES_t>(GetProcAddress(kernel,
+ "SetThreadExecutionState"));
+ }
+ if (s_stes == NULL) {
+ s_stes = &ArchMiscWindows::dummySetThreadExecutionState;
+ }
+ }
+
+ // convert to STES form
+ EXECUTION_STATE state = 0;
+ if ((busyModes & kSYSTEM) != 0) {
+ state |= ES_SYSTEM_REQUIRED;
+ }
+ if ((busyModes & kDISPLAY) != 0) {
+ state |= ES_DISPLAY_REQUIRED;
+ }
+ if (state != 0) {
+ state |= ES_CONTINUOUS;
+ }
+
+ // do it
+ s_stes(state);
+}
+
+DWORD
+ArchMiscWindows::dummySetThreadExecutionState(DWORD)
+{
+ // do nothing
+ return 0;
+}
+
+void
+ArchMiscWindows::wakeupDisplay()
+{
+ // We can't use ::setThreadExecutionState here because it sets
+ // ES_CONTINUOUS, which we don't want.
+
+ if (s_stes == NULL) {
+ HINSTANCE kernel = LoadLibrary("kernel32.dll");
+ if (kernel != NULL) {
+ s_stes = reinterpret_cast<STES_t>(GetProcAddress(kernel,
+ "SetThreadExecutionState"));
+ }
+ if (s_stes == NULL) {
+ s_stes = &ArchMiscWindows::dummySetThreadExecutionState;
+ }
+ }
+
+ s_stes(ES_DISPLAY_REQUIRED);
+
+ // restore the original execution states
+ setThreadExecutionState(s_busyState);
+}
+
+bool
+ArchMiscWindows::wasLaunchedAsService()
+{
+ String name;
+ if (!getParentProcessName(name)) {
+ LOG((CLOG_ERR "cannot determine if process was launched as service"));
+ return false;
+ }
+
+ return (name == SERVICE_LAUNCHER);
+}
+
+bool
+ArchMiscWindows::getParentProcessName(String &name)
+{
+ PROCESSENTRY32 parentEntry;
+ if (!getParentProcessEntry(parentEntry)){
+ LOG((CLOG_ERR "could not get entry for parent process"));
+ return false;
+ }
+
+ name = parentEntry.szExeFile;
+ return true;
+}
+
+BOOL WINAPI
+ArchMiscWindows::getSelfProcessEntry(PROCESSENTRY32& entry)
+{
+ // get entry from current PID
+ return getProcessEntry(entry, GetCurrentProcessId());
+}
+
+BOOL WINAPI
+ArchMiscWindows::getParentProcessEntry(PROCESSENTRY32& entry)
+{
+ // get the current process, so we can get parent PID
+ PROCESSENTRY32 selfEntry;
+ if (!getSelfProcessEntry(selfEntry)) {
+ return FALSE;
+ }
+
+ // get entry from parent PID
+ return getProcessEntry(entry, selfEntry.th32ParentProcessID);
+}
+
+BOOL WINAPI
+ArchMiscWindows::getProcessEntry(PROCESSENTRY32& entry, DWORD processID)
+{
+ // first we need to take a snapshot of the running processes
+ HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (snapshot == INVALID_HANDLE_VALUE) {
+ LOG((CLOG_ERR "could not get process snapshot (error: %i)",
+ GetLastError()));
+ return FALSE;
+ }
+
+ entry.dwSize = sizeof(PROCESSENTRY32);
+
+ // get the first process, and if we can't do that then it's
+ // unlikely we can go any further
+ BOOL gotEntry = Process32First(snapshot, &entry);
+ if (!gotEntry) {
+ LOG((CLOG_ERR "could not get first process entry (error: %i)",
+ GetLastError()));
+ return FALSE;
+ }
+
+ while(gotEntry) {
+
+ if (entry.th32ProcessID == processID) {
+ // found current process
+ return TRUE;
+ }
+
+ // now move on to the next entry (when we reach end, loop will stop)
+ gotEntry = Process32Next(snapshot, &entry);
+ }
+
+ return FALSE;
+}
+
+HINSTANCE
+ArchMiscWindows::instanceWin32()
+{
+ assert(s_instanceWin32 != NULL);
+ return s_instanceWin32;
+}
+
+void
+ArchMiscWindows::setInstanceWin32(HINSTANCE instance)
+{
+ assert(instance != NULL);
+ s_instanceWin32 = instance;
+} \ No newline at end of file