| 1 | /* | 
|---|
| 2 | * synergy -- mouse and keyboard sharing utility | 
|---|
| 3 | * Copyright (C) 2002 Chris Schoeneman | 
|---|
| 4 | * | 
|---|
| 5 | * This package is free software; you can redistribute it and/or | 
|---|
| 6 | * modify it under the terms of the GNU General Public License | 
|---|
| 7 | * found in the file COPYING that should have accompanied this file. | 
|---|
| 8 | * | 
|---|
| 9 | * This package is distributed in the hope that it will be useful, | 
|---|
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
| 12 | * GNU General Public License for more details. | 
|---|
| 13 | */ | 
|---|
| 14 |  | 
|---|
| 15 | #include "CArchMiscWindows.h" | 
|---|
| 16 | #include "CArchDaemonWindows.h" | 
|---|
| 17 |  | 
|---|
| 18 | #ifndef ES_SYSTEM_REQUIRED | 
|---|
| 19 | #define ES_SYSTEM_REQUIRED  ((DWORD)0x00000001) | 
|---|
| 20 | #endif | 
|---|
| 21 | #ifndef ES_DISPLAY_REQUIRED | 
|---|
| 22 | #define ES_DISPLAY_REQUIRED ((DWORD)0x00000002) | 
|---|
| 23 | #endif | 
|---|
| 24 | #ifndef ES_CONTINUOUS | 
|---|
| 25 | #define ES_CONTINUOUS       ((DWORD)0x80000000) | 
|---|
| 26 | #endif | 
|---|
| 27 | typedef DWORD EXECUTION_STATE; | 
|---|
| 28 |  | 
|---|
| 29 | // | 
|---|
| 30 | // CArchMiscWindows | 
|---|
| 31 | // | 
|---|
| 32 |  | 
|---|
| 33 | CArchMiscWindows::CDialogs* CArchMiscWindows::s_dialogs   = NULL; | 
|---|
| 34 | DWORD                                           CArchMiscWindows::s_busyState = 0; | 
|---|
| 35 | CArchMiscWindows::STES_t        CArchMiscWindows::s_stes      = NULL; | 
|---|
| 36 | HICON                                           CArchMiscWindows::s_largeIcon = NULL; | 
|---|
| 37 | HICON                                           CArchMiscWindows::s_smallIcon = NULL; | 
|---|
| 38 |  | 
|---|
| 39 | void | 
|---|
| 40 | CArchMiscWindows::init() | 
|---|
| 41 | { | 
|---|
| 42 | s_dialogs = new CDialogs; | 
|---|
| 43 | isWindows95Family(); | 
|---|
| 44 | } | 
|---|
| 45 |  | 
|---|
| 46 | bool | 
|---|
| 47 | CArchMiscWindows::isWindows95Family() | 
|---|
| 48 | { | 
|---|
| 49 | static bool init   = false; | 
|---|
| 50 | static bool result = false; | 
|---|
| 51 |  | 
|---|
| 52 | if (!init) { | 
|---|
| 53 | OSVERSIONINFO version; | 
|---|
| 54 | version.dwOSVersionInfoSize = sizeof(version); | 
|---|
| 55 | if (GetVersionEx(&version) == 0) { | 
|---|
| 56 | // cannot determine OS;  assume windows 95 family | 
|---|
| 57 | result = true; | 
|---|
| 58 | } | 
|---|
| 59 | else { | 
|---|
| 60 | result = (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS); | 
|---|
| 61 | } | 
|---|
| 62 | init = true; | 
|---|
| 63 | } | 
|---|
| 64 | return result; | 
|---|
| 65 | } | 
|---|
| 66 |  | 
|---|
| 67 | bool | 
|---|
| 68 | CArchMiscWindows::isWindowsModern() | 
|---|
| 69 | { | 
|---|
| 70 | static bool init   = false; | 
|---|
| 71 | static bool result = false; | 
|---|
| 72 |  | 
|---|
| 73 | if (!init) { | 
|---|
| 74 | OSVERSIONINFO version; | 
|---|
| 75 | version.dwOSVersionInfoSize = sizeof(version); | 
|---|
| 76 | if (GetVersionEx(&version) == 0) { | 
|---|
| 77 | // cannot determine OS;  assume not modern | 
|---|
| 78 | result = false; | 
|---|
| 79 | } | 
|---|
| 80 | else { | 
|---|
| 81 | result = ((version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && | 
|---|
| 82 | version.dwMajorVersion == 4 && | 
|---|
| 83 | version.dwMinorVersion > 0) || | 
|---|
| 84 | (version.dwPlatformId == VER_PLATFORM_WIN32_NT && | 
|---|
| 85 | version.dwMajorVersion > 4)); | 
|---|
| 86 | } | 
|---|
| 87 | init = true; | 
|---|
| 88 | } | 
|---|
| 89 | return result; | 
|---|
| 90 | } | 
|---|
| 91 |  | 
|---|
| 92 | void | 
|---|
| 93 | CArchMiscWindows::setIcons(HICON largeIcon, HICON smallIcon) | 
|---|
| 94 | { | 
|---|
| 95 | s_largeIcon = largeIcon; | 
|---|
| 96 | s_smallIcon = smallIcon; | 
|---|
| 97 | } | 
|---|
| 98 |  | 
|---|
| 99 | void | 
|---|
| 100 | CArchMiscWindows::getIcons(HICON& largeIcon, HICON& smallIcon) | 
|---|
| 101 | { | 
|---|
| 102 | largeIcon = s_largeIcon; | 
|---|
| 103 | smallIcon = s_smallIcon; | 
|---|
| 104 | } | 
|---|
| 105 |  | 
|---|
| 106 | int | 
|---|
| 107 | CArchMiscWindows::runDaemon(RunFunc runFunc) | 
|---|
| 108 | { | 
|---|
| 109 | return CArchDaemonWindows::runDaemon(runFunc); | 
|---|
| 110 | } | 
|---|
| 111 |  | 
|---|
| 112 | void | 
|---|
| 113 | CArchMiscWindows::daemonRunning(bool running) | 
|---|
| 114 | { | 
|---|
| 115 | CArchDaemonWindows::daemonRunning(running); | 
|---|
| 116 | } | 
|---|
| 117 |  | 
|---|
| 118 | void | 
|---|
| 119 | CArchMiscWindows::daemonFailed(int result) | 
|---|
| 120 | { | 
|---|
| 121 | CArchDaemonWindows::daemonFailed(result); | 
|---|
| 122 | } | 
|---|
| 123 |  | 
|---|
| 124 | UINT | 
|---|
| 125 | CArchMiscWindows::getDaemonQuitMessage() | 
|---|
| 126 | { | 
|---|
| 127 | return CArchDaemonWindows::getDaemonQuitMessage(); | 
|---|
| 128 | } | 
|---|
| 129 |  | 
|---|
| 130 | HKEY | 
|---|
| 131 | CArchMiscWindows::openKey(HKEY key, const TCHAR* keyName) | 
|---|
| 132 | { | 
|---|
| 133 | return openKey(key, keyName, false); | 
|---|
| 134 | } | 
|---|
| 135 |  | 
|---|
| 136 | HKEY | 
|---|
| 137 | CArchMiscWindows::openKey(HKEY key, const TCHAR* const* keyNames) | 
|---|
| 138 | { | 
|---|
| 139 | return openKey(key, keyNames, false); | 
|---|
| 140 | } | 
|---|
| 141 |  | 
|---|
| 142 | HKEY | 
|---|
| 143 | CArchMiscWindows::addKey(HKEY key, const TCHAR* keyName) | 
|---|
| 144 | { | 
|---|
| 145 | return openKey(key, keyName, true); | 
|---|
| 146 | } | 
|---|
| 147 |  | 
|---|
| 148 | HKEY | 
|---|
| 149 | CArchMiscWindows::addKey(HKEY key, const TCHAR* const* keyNames) | 
|---|
| 150 | { | 
|---|
| 151 | return openKey(key, keyNames, true); | 
|---|
| 152 | } | 
|---|
| 153 |  | 
|---|
| 154 | HKEY | 
|---|
| 155 | CArchMiscWindows::openKey(HKEY key, const TCHAR* keyName, bool create) | 
|---|
| 156 | { | 
|---|
| 157 | // ignore if parent is NULL | 
|---|
| 158 | if (key == NULL) { | 
|---|
| 159 | return NULL; | 
|---|
| 160 | } | 
|---|
| 161 |  | 
|---|
| 162 | // open next key | 
|---|
| 163 | HKEY newKey; | 
|---|
| 164 | LONG result = RegOpenKeyEx(key, keyName, 0, | 
|---|
| 165 | KEY_WRITE | KEY_QUERY_VALUE, &newKey); | 
|---|
| 166 | if (result != ERROR_SUCCESS && create) { | 
|---|
| 167 | DWORD disp; | 
|---|
| 168 | result = RegCreateKeyEx(key, keyName, 0, TEXT(""), | 
|---|
| 169 | 0, KEY_WRITE | KEY_QUERY_VALUE, | 
|---|
| 170 | NULL, &newKey, &disp); | 
|---|
| 171 | } | 
|---|
| 172 | if (result != ERROR_SUCCESS) { | 
|---|
| 173 | RegCloseKey(key); | 
|---|
| 174 | return NULL; | 
|---|
| 175 | } | 
|---|
| 176 |  | 
|---|
| 177 | // switch to new key | 
|---|
| 178 | RegCloseKey(key); | 
|---|
| 179 | return newKey; | 
|---|
| 180 | } | 
|---|
| 181 |  | 
|---|
| 182 | HKEY | 
|---|
| 183 | CArchMiscWindows::openKey(HKEY key, const TCHAR* const* keyNames, bool create) | 
|---|
| 184 | { | 
|---|
| 185 | for (size_t i = 0; key != NULL && keyNames[i] != NULL; ++i) { | 
|---|
| 186 | // open next key | 
|---|
| 187 | key = openKey(key, keyNames[i], create); | 
|---|
| 188 | } | 
|---|
| 189 | return key; | 
|---|
| 190 | } | 
|---|
| 191 |  | 
|---|
| 192 | void | 
|---|
| 193 | CArchMiscWindows::closeKey(HKEY key) | 
|---|
| 194 | { | 
|---|
| 195 | assert(key  != NULL); | 
|---|
| 196 | RegCloseKey(key); | 
|---|
| 197 | } | 
|---|
| 198 |  | 
|---|
| 199 | void | 
|---|
| 200 | CArchMiscWindows::deleteKey(HKEY key, const TCHAR* name) | 
|---|
| 201 | { | 
|---|
| 202 | assert(key  != NULL); | 
|---|
| 203 | assert(name != NULL); | 
|---|
| 204 | RegDeleteKey(key, name); | 
|---|
| 205 | } | 
|---|
| 206 |  | 
|---|
| 207 | void | 
|---|
| 208 | CArchMiscWindows::deleteValue(HKEY key, const TCHAR* name) | 
|---|
| 209 | { | 
|---|
| 210 | assert(key  != NULL); | 
|---|
| 211 | assert(name != NULL); | 
|---|
| 212 | RegDeleteValue(key, name); | 
|---|
| 213 | } | 
|---|
| 214 |  | 
|---|
| 215 | bool | 
|---|
| 216 | CArchMiscWindows::hasValue(HKEY key, const TCHAR* name) | 
|---|
| 217 | { | 
|---|
| 218 | DWORD type; | 
|---|
| 219 | LONG result = RegQueryValueEx(key, name, 0, &type, NULL, NULL); | 
|---|
| 220 | return (result == ERROR_SUCCESS && | 
|---|
| 221 | (type == REG_DWORD || type == REG_SZ)); | 
|---|
| 222 | } | 
|---|
| 223 |  | 
|---|
| 224 | CArchMiscWindows::EValueType | 
|---|
| 225 | CArchMiscWindows::typeOfValue(HKEY key, const TCHAR* name) | 
|---|
| 226 | { | 
|---|
| 227 | DWORD type; | 
|---|
| 228 | LONG result = RegQueryValueEx(key, name, 0, &type, NULL, NULL); | 
|---|
| 229 | if (result != ERROR_SUCCESS) { | 
|---|
| 230 | return kNO_VALUE; | 
|---|
| 231 | } | 
|---|
| 232 | switch (type) { | 
|---|
| 233 | case REG_DWORD: | 
|---|
| 234 | return kUINT; | 
|---|
| 235 |  | 
|---|
| 236 | case REG_SZ: | 
|---|
| 237 | return kSTRING; | 
|---|
| 238 |  | 
|---|
| 239 | case REG_BINARY: | 
|---|
| 240 | return kBINARY; | 
|---|
| 241 |  | 
|---|
| 242 | default: | 
|---|
| 243 | return kUNKNOWN; | 
|---|
| 244 | } | 
|---|
| 245 | } | 
|---|
| 246 |  | 
|---|
| 247 | void | 
|---|
| 248 | CArchMiscWindows::setValue(HKEY key, | 
|---|
| 249 | const TCHAR* name, const std::string& value) | 
|---|
| 250 | { | 
|---|
| 251 | assert(key  != NULL); | 
|---|
| 252 | assert(name != NULL); | 
|---|
| 253 | RegSetValueEx(key, name, 0, REG_SZ, | 
|---|
| 254 | reinterpret_cast<const BYTE*>(value.c_str()), | 
|---|
| 255 | value.size() + 1); | 
|---|
| 256 | } | 
|---|
| 257 |  | 
|---|
| 258 | void | 
|---|
| 259 | CArchMiscWindows::setValue(HKEY key, const TCHAR* name, DWORD value) | 
|---|
| 260 | { | 
|---|
| 261 | assert(key  != NULL); | 
|---|
| 262 | assert(name != NULL); | 
|---|
| 263 | RegSetValueEx(key, name, 0, REG_DWORD, | 
|---|
| 264 | reinterpret_cast<CONST BYTE*>(&value), | 
|---|
| 265 | sizeof(DWORD)); | 
|---|
| 266 | } | 
|---|
| 267 |  | 
|---|
| 268 | void | 
|---|
| 269 | CArchMiscWindows::setValueBinary(HKEY key, | 
|---|
| 270 | const TCHAR* name, const std::string& value) | 
|---|
| 271 | { | 
|---|
| 272 | assert(key  != NULL); | 
|---|
| 273 | assert(name != NULL); | 
|---|
| 274 | RegSetValueEx(key, name, 0, REG_BINARY, | 
|---|
| 275 | reinterpret_cast<const BYTE*>(value.data()), | 
|---|
| 276 | value.size()); | 
|---|
| 277 | } | 
|---|
| 278 |  | 
|---|
| 279 | std::string | 
|---|
| 280 | CArchMiscWindows::readBinaryOrString(HKEY key, const TCHAR* name, DWORD type) | 
|---|
| 281 | { | 
|---|
| 282 | // get the size of the string | 
|---|
| 283 | DWORD actualType; | 
|---|
| 284 | DWORD size = 0; | 
|---|
| 285 | LONG result = RegQueryValueEx(key, name, 0, &actualType, NULL, &size); | 
|---|
| 286 | if (result != ERROR_SUCCESS || actualType != type) { | 
|---|
| 287 | return std::string(); | 
|---|
| 288 | } | 
|---|
| 289 |  | 
|---|
| 290 | // if zero size then return empty string | 
|---|
| 291 | if (size == 0) { | 
|---|
| 292 | return std::string(); | 
|---|
| 293 | } | 
|---|
| 294 |  | 
|---|
| 295 | // allocate space | 
|---|
| 296 | char* buffer = new char[size]; | 
|---|
| 297 |  | 
|---|
| 298 | // read it | 
|---|
| 299 | result = RegQueryValueEx(key, name, 0, &actualType, | 
|---|
| 300 | reinterpret_cast<BYTE*>(buffer), &size); | 
|---|
| 301 | if (result != ERROR_SUCCESS || actualType != type) { | 
|---|
| 302 | delete[] buffer; | 
|---|
| 303 | return std::string(); | 
|---|
| 304 | } | 
|---|
| 305 |  | 
|---|
| 306 | // clean up and return value | 
|---|
| 307 | if (type == REG_SZ && buffer[size - 1] == '\0') { | 
|---|
| 308 | // don't include terminating nul;  std::string will add one. | 
|---|
| 309 | --size; | 
|---|
| 310 | } | 
|---|
| 311 | std::string value(buffer, size); | 
|---|
| 312 | delete[] buffer; | 
|---|
| 313 | return value; | 
|---|
| 314 | } | 
|---|
| 315 |  | 
|---|
| 316 | std::string | 
|---|
| 317 | CArchMiscWindows::readValueString(HKEY key, const TCHAR* name) | 
|---|
| 318 | { | 
|---|
| 319 | return readBinaryOrString(key, name, REG_SZ); | 
|---|
| 320 | } | 
|---|
| 321 |  | 
|---|
| 322 | std::string | 
|---|
| 323 | CArchMiscWindows::readValueBinary(HKEY key, const TCHAR* name) | 
|---|
| 324 | { | 
|---|
| 325 | return readBinaryOrString(key, name, REG_BINARY); | 
|---|
| 326 | } | 
|---|
| 327 |  | 
|---|
| 328 | DWORD | 
|---|
| 329 | CArchMiscWindows::readValueInt(HKEY key, const TCHAR* name) | 
|---|
| 330 | { | 
|---|
| 331 | DWORD type; | 
|---|
| 332 | DWORD value; | 
|---|
| 333 | DWORD size = sizeof(value); | 
|---|
| 334 | LONG result = RegQueryValueEx(key, name, 0, &type, | 
|---|
| 335 | reinterpret_cast<BYTE*>(&value), &size); | 
|---|
| 336 | if (result != ERROR_SUCCESS || type != REG_DWORD) { | 
|---|
| 337 | return 0; | 
|---|
| 338 | } | 
|---|
| 339 | return value; | 
|---|
| 340 | } | 
|---|
| 341 |  | 
|---|
| 342 | void | 
|---|
| 343 | CArchMiscWindows::addDialog(HWND hwnd) | 
|---|
| 344 | { | 
|---|
| 345 | s_dialogs->insert(hwnd); | 
|---|
| 346 | } | 
|---|
| 347 |  | 
|---|
| 348 | void | 
|---|
| 349 | CArchMiscWindows::removeDialog(HWND hwnd) | 
|---|
| 350 | { | 
|---|
| 351 | s_dialogs->erase(hwnd); | 
|---|
| 352 | } | 
|---|
| 353 |  | 
|---|
| 354 | bool | 
|---|
| 355 | CArchMiscWindows::processDialog(MSG* msg) | 
|---|
| 356 | { | 
|---|
| 357 | for (CDialogs::const_iterator index = s_dialogs->begin(); | 
|---|
| 358 | index != s_dialogs->end(); ++index) { | 
|---|
| 359 | if (IsDialogMessage(*index, msg)) { | 
|---|
| 360 | return true; | 
|---|
| 361 | } | 
|---|
| 362 | } | 
|---|
| 363 | return false; | 
|---|
| 364 | } | 
|---|
| 365 |  | 
|---|
| 366 | void | 
|---|
| 367 | CArchMiscWindows::addBusyState(DWORD busyModes) | 
|---|
| 368 | { | 
|---|
| 369 | s_busyState |= busyModes; | 
|---|
| 370 | setThreadExecutionState(s_busyState); | 
|---|
| 371 | } | 
|---|
| 372 |  | 
|---|
| 373 | void | 
|---|
| 374 | CArchMiscWindows::removeBusyState(DWORD busyModes) | 
|---|
| 375 | { | 
|---|
| 376 | s_busyState &= ~busyModes; | 
|---|
| 377 | setThreadExecutionState(s_busyState); | 
|---|
| 378 | } | 
|---|
| 379 |  | 
|---|
| 380 | void | 
|---|
| 381 | CArchMiscWindows::setThreadExecutionState(DWORD busyModes) | 
|---|
| 382 | { | 
|---|
| 383 | // look up function dynamically so we work on older systems | 
|---|
| 384 | if (s_stes == NULL) { | 
|---|
| 385 | HINSTANCE kernel = LoadLibrary("kernel32.dll"); | 
|---|
| 386 | if (kernel != NULL) { | 
|---|
| 387 | s_stes = reinterpret_cast<STES_t>(GetProcAddress(kernel, | 
|---|
| 388 | "SetThreadExecutionState")); | 
|---|
| 389 | } | 
|---|
| 390 | if (s_stes == NULL) { | 
|---|
| 391 | s_stes = &CArchMiscWindows::dummySetThreadExecutionState; | 
|---|
| 392 | } | 
|---|
| 393 | } | 
|---|
| 394 |  | 
|---|
| 395 | // convert to STES form | 
|---|
| 396 | EXECUTION_STATE state = 0; | 
|---|
| 397 | if ((busyModes & kSYSTEM) != 0) { | 
|---|
| 398 | state |= ES_SYSTEM_REQUIRED; | 
|---|
| 399 | } | 
|---|
| 400 | if ((busyModes & kDISPLAY) != 0) { | 
|---|
| 401 | state |= ES_DISPLAY_REQUIRED; | 
|---|
| 402 | } | 
|---|
| 403 | if (state != 0) { | 
|---|
| 404 | state |= ES_CONTINUOUS; | 
|---|
| 405 | } | 
|---|
| 406 |  | 
|---|
| 407 | // do it | 
|---|
| 408 | s_stes(state); | 
|---|
| 409 | } | 
|---|
| 410 |  | 
|---|
| 411 | DWORD | 
|---|
| 412 | CArchMiscWindows::dummySetThreadExecutionState(DWORD) | 
|---|
| 413 | { | 
|---|
| 414 | // do nothing | 
|---|
| 415 | return 0; | 
|---|
| 416 | } | 
|---|