00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "CArchMiscWindows.h"
00020 #include "CArchDaemonWindows.h"
00021 #include "CLog.h"
00022
00023 #include <Wtsapi32.h>
00024 #pragma warning(disable: 4099)
00025 #include <Userenv.h>
00026 #pragma warning(default: 4099)
00027 #include "Version.h"
00028
00029
00030 #define SERVICE_LAUNCHER "services.exe"
00031
00032 #ifndef ES_SYSTEM_REQUIRED
00033 #define ES_SYSTEM_REQUIRED ((DWORD)0x00000001)
00034 #endif
00035 #ifndef ES_DISPLAY_REQUIRED
00036 #define ES_DISPLAY_REQUIRED ((DWORD)0x00000002)
00037 #endif
00038 #ifndef ES_CONTINUOUS
00039 #define ES_CONTINUOUS ((DWORD)0x80000000)
00040 #endif
00041 typedef DWORD EXECUTION_STATE;
00042
00043
00044
00045
00046
00047 CArchMiscWindows::CDialogs* CArchMiscWindows::s_dialogs = NULL;
00048 DWORD CArchMiscWindows::s_busyState = 0;
00049 CArchMiscWindows::STES_t CArchMiscWindows::s_stes = NULL;
00050 HICON CArchMiscWindows::s_largeIcon = NULL;
00051 HICON CArchMiscWindows::s_smallIcon = NULL;
00052 HINSTANCE CArchMiscWindows::s_instanceWin32 = NULL;
00053
00054 void
00055 CArchMiscWindows::cleanup()
00056 {
00057 delete s_dialogs;
00058 }
00059
00060 void
00061 CArchMiscWindows::init()
00062 {
00063 s_dialogs = new CDialogs;
00064 isWindows95Family();
00065 }
00066
00067 bool
00068 CArchMiscWindows::isWindows95Family()
00069 {
00070 static bool init = false;
00071 static bool result = false;
00072
00073 if (!init) {
00074 OSVERSIONINFO version;
00075 version.dwOSVersionInfoSize = sizeof(version);
00076 if (GetVersionEx(&version) == 0) {
00077
00078 result = true;
00079 }
00080 else {
00081 result = (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
00082 }
00083 init = true;
00084 }
00085 return result;
00086 }
00087
00088 bool
00089 CArchMiscWindows::isWindowsModern()
00090 {
00091 static bool init = false;
00092 static bool result = false;
00093
00094 if (!init) {
00095 OSVERSIONINFO version;
00096 version.dwOSVersionInfoSize = sizeof(version);
00097 if (GetVersionEx(&version) == 0) {
00098
00099 result = false;
00100 }
00101 else {
00102 result = ((version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
00103 version.dwMajorVersion == 4 &&
00104 version.dwMinorVersion > 0) ||
00105 (version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
00106 version.dwMajorVersion > 4));
00107 }
00108 init = true;
00109 }
00110 return result;
00111 }
00112
00113 void
00114 CArchMiscWindows::setIcons(HICON largeIcon, HICON smallIcon)
00115 {
00116 s_largeIcon = largeIcon;
00117 s_smallIcon = smallIcon;
00118 }
00119
00120 void
00121 CArchMiscWindows::getIcons(HICON& largeIcon, HICON& smallIcon)
00122 {
00123 largeIcon = s_largeIcon;
00124 smallIcon = s_smallIcon;
00125 }
00126
00127 int
00128 CArchMiscWindows::runDaemon(RunFunc runFunc)
00129 {
00130 return CArchDaemonWindows::runDaemon(runFunc);
00131 }
00132
00133 void
00134 CArchMiscWindows::daemonRunning(bool running)
00135 {
00136 CArchDaemonWindows::daemonRunning(running);
00137 }
00138
00139 void
00140 CArchMiscWindows::daemonFailed(int result)
00141 {
00142 CArchDaemonWindows::daemonFailed(result);
00143 }
00144
00145 UINT
00146 CArchMiscWindows::getDaemonQuitMessage()
00147 {
00148 return CArchDaemonWindows::getDaemonQuitMessage();
00149 }
00150
00151 HKEY
00152 CArchMiscWindows::openKey(HKEY key, const TCHAR* keyName)
00153 {
00154 return openKey(key, keyName, false);
00155 }
00156
00157 HKEY
00158 CArchMiscWindows::openKey(HKEY key, const TCHAR* const* keyNames)
00159 {
00160 return openKey(key, keyNames, false);
00161 }
00162
00163 HKEY
00164 CArchMiscWindows::addKey(HKEY key, const TCHAR* keyName)
00165 {
00166 return openKey(key, keyName, true);
00167 }
00168
00169 HKEY
00170 CArchMiscWindows::addKey(HKEY key, const TCHAR* const* keyNames)
00171 {
00172 return openKey(key, keyNames, true);
00173 }
00174
00175 HKEY
00176 CArchMiscWindows::openKey(HKEY key, const TCHAR* keyName, bool create)
00177 {
00178
00179 if (key == NULL) {
00180 return NULL;
00181 }
00182
00183
00184 HKEY newKey;
00185 LONG result = RegOpenKeyEx(key, keyName, 0,
00186 KEY_WRITE | KEY_QUERY_VALUE, &newKey);
00187 if (result != ERROR_SUCCESS && create) {
00188 DWORD disp;
00189 result = RegCreateKeyEx(key, keyName, 0, TEXT(""),
00190 0, KEY_WRITE | KEY_QUERY_VALUE,
00191 NULL, &newKey, &disp);
00192 }
00193 if (result != ERROR_SUCCESS) {
00194 RegCloseKey(key);
00195 return NULL;
00196 }
00197
00198
00199 RegCloseKey(key);
00200 return newKey;
00201 }
00202
00203 HKEY
00204 CArchMiscWindows::openKey(HKEY key, const TCHAR* const* keyNames, bool create)
00205 {
00206 for (size_t i = 0; key != NULL && keyNames[i] != NULL; ++i) {
00207
00208 key = openKey(key, keyNames[i], create);
00209 }
00210 return key;
00211 }
00212
00213 void
00214 CArchMiscWindows::closeKey(HKEY key)
00215 {
00216 assert(key != NULL);
00217 if (key==NULL) return;
00218 RegCloseKey(key);
00219 }
00220
00221 void
00222 CArchMiscWindows::deleteKey(HKEY key, const TCHAR* name)
00223 {
00224 assert(key != NULL);
00225 assert(name != NULL);
00226 if (key==NULL || name==NULL) return;
00227 RegDeleteKey(key, name);
00228 }
00229
00230 void
00231 CArchMiscWindows::deleteValue(HKEY key, const TCHAR* name)
00232 {
00233 assert(key != NULL);
00234 assert(name != NULL);
00235 if (key==NULL || name==NULL) return;
00236 RegDeleteValue(key, name);
00237 }
00238
00239 bool
00240 CArchMiscWindows::hasValue(HKEY key, const TCHAR* name)
00241 {
00242 DWORD type;
00243 LONG result = RegQueryValueEx(key, name, 0, &type, NULL, NULL);
00244 return (result == ERROR_SUCCESS &&
00245 (type == REG_DWORD || type == REG_SZ));
00246 }
00247
00248 CArchMiscWindows::EValueType
00249 CArchMiscWindows::typeOfValue(HKEY key, const TCHAR* name)
00250 {
00251 DWORD type;
00252 LONG result = RegQueryValueEx(key, name, 0, &type, NULL, NULL);
00253 if (result != ERROR_SUCCESS) {
00254 return kNO_VALUE;
00255 }
00256 switch (type) {
00257 case REG_DWORD:
00258 return kUINT;
00259
00260 case REG_SZ:
00261 return kSTRING;
00262
00263 case REG_BINARY:
00264 return kBINARY;
00265
00266 default:
00267 return kUNKNOWN;
00268 }
00269 }
00270
00271 void
00272 CArchMiscWindows::setValue(HKEY key,
00273 const TCHAR* name, const std::string& value)
00274 {
00275 assert(key != NULL);
00276 assert(name != NULL);
00277 if(key ==NULL || name==NULL) return;
00278 RegSetValueEx(key, name, 0, REG_SZ,
00279 reinterpret_cast<const BYTE*>(value.c_str()),
00280 (DWORD)value.size() + 1);
00281 }
00282
00283 void
00284 CArchMiscWindows::setValue(HKEY key, const TCHAR* name, DWORD value)
00285 {
00286 assert(key != NULL);
00287 assert(name != NULL);
00288 if(key ==NULL || name==NULL) return;
00289 RegSetValueEx(key, name, 0, REG_DWORD,
00290 reinterpret_cast<CONST BYTE*>(&value),
00291 sizeof(DWORD));
00292 }
00293
00294 void
00295 CArchMiscWindows::setValueBinary(HKEY key,
00296 const TCHAR* name, const std::string& value)
00297 {
00298 assert(key != NULL);
00299 assert(name != NULL);
00300 if(key ==NULL || name==NULL) return;
00301 RegSetValueEx(key, name, 0, REG_BINARY,
00302 reinterpret_cast<const BYTE*>(value.data()),
00303 (DWORD)value.size());
00304 }
00305
00306 std::string
00307 CArchMiscWindows::readBinaryOrString(HKEY key, const TCHAR* name, DWORD type)
00308 {
00309
00310 DWORD actualType;
00311 DWORD size = 0;
00312 LONG result = RegQueryValueEx(key, name, 0, &actualType, NULL, &size);
00313 if (result != ERROR_SUCCESS || actualType != type) {
00314 return std::string();
00315 }
00316
00317
00318 if (size == 0) {
00319 return std::string();
00320 }
00321
00322
00323 char* buffer = new char[size];
00324
00325
00326 result = RegQueryValueEx(key, name, 0, &actualType,
00327 reinterpret_cast<BYTE*>(buffer), &size);
00328 if (result != ERROR_SUCCESS || actualType != type) {
00329 delete[] buffer;
00330 return std::string();
00331 }
00332
00333
00334 if (type == REG_SZ && buffer[size - 1] == '\0') {
00335
00336 --size;
00337 }
00338 std::string value(buffer, size);
00339 delete[] buffer;
00340 return value;
00341 }
00342
00343 std::string
00344 CArchMiscWindows::readValueString(HKEY key, const TCHAR* name)
00345 {
00346 return readBinaryOrString(key, name, REG_SZ);
00347 }
00348
00349 std::string
00350 CArchMiscWindows::readValueBinary(HKEY key, const TCHAR* name)
00351 {
00352 return readBinaryOrString(key, name, REG_BINARY);
00353 }
00354
00355 DWORD
00356 CArchMiscWindows::readValueInt(HKEY key, const TCHAR* name)
00357 {
00358 DWORD type;
00359 DWORD value;
00360 DWORD size = sizeof(value);
00361 LONG result = RegQueryValueEx(key, name, 0, &type,
00362 reinterpret_cast<BYTE*>(&value), &size);
00363 if (result != ERROR_SUCCESS || type != REG_DWORD) {
00364 return 0;
00365 }
00366 return value;
00367 }
00368
00369 void
00370 CArchMiscWindows::addDialog(HWND hwnd)
00371 {
00372 s_dialogs->insert(hwnd);
00373 }
00374
00375 void
00376 CArchMiscWindows::removeDialog(HWND hwnd)
00377 {
00378 s_dialogs->erase(hwnd);
00379 }
00380
00381 bool
00382 CArchMiscWindows::processDialog(MSG* msg)
00383 {
00384 for (CDialogs::const_iterator index = s_dialogs->begin();
00385 index != s_dialogs->end(); ++index) {
00386 if (IsDialogMessage(*index, msg)) {
00387 return true;
00388 }
00389 }
00390 return false;
00391 }
00392
00393 void
00394 CArchMiscWindows::addBusyState(DWORD busyModes)
00395 {
00396 s_busyState |= busyModes;
00397 setThreadExecutionState(s_busyState);
00398 }
00399
00400 void
00401 CArchMiscWindows::removeBusyState(DWORD busyModes)
00402 {
00403 s_busyState &= ~busyModes;
00404 setThreadExecutionState(s_busyState);
00405 }
00406
00407 void
00408 CArchMiscWindows::setThreadExecutionState(DWORD busyModes)
00409 {
00410
00411 if (s_stes == NULL) {
00412 HINSTANCE kernel = LoadLibrary("kernel32.dll");
00413 if (kernel != NULL) {
00414 s_stes = reinterpret_cast<STES_t>(GetProcAddress(kernel,
00415 "SetThreadExecutionState"));
00416 }
00417 if (s_stes == NULL) {
00418 s_stes = &CArchMiscWindows::dummySetThreadExecutionState;
00419 }
00420 }
00421
00422
00423 EXECUTION_STATE state = 0;
00424 if ((busyModes & kSYSTEM) != 0) {
00425 state |= ES_SYSTEM_REQUIRED;
00426 }
00427 if ((busyModes & kDISPLAY) != 0) {
00428 state |= ES_DISPLAY_REQUIRED;
00429 }
00430 if (state != 0) {
00431 state |= ES_CONTINUOUS;
00432 }
00433
00434
00435 s_stes(state);
00436 }
00437
00438 DWORD
00439 CArchMiscWindows::dummySetThreadExecutionState(DWORD)
00440 {
00441
00442 return 0;
00443 }
00444
00445 void
00446 CArchMiscWindows::wakeupDisplay()
00447 {
00448
00449
00450
00451 if (s_stes == NULL) {
00452 HINSTANCE kernel = LoadLibrary("kernel32.dll");
00453 if (kernel != NULL) {
00454 s_stes = reinterpret_cast<STES_t>(GetProcAddress(kernel,
00455 "SetThreadExecutionState"));
00456 }
00457 if (s_stes == NULL) {
00458 s_stes = &CArchMiscWindows::dummySetThreadExecutionState;
00459 }
00460 }
00461
00462 s_stes(ES_DISPLAY_REQUIRED);
00463
00464
00465 setThreadExecutionState(s_busyState);
00466 }
00467
00468 bool
00469 CArchMiscWindows::wasLaunchedAsService()
00470 {
00471 CString name;
00472 if (!getParentProcessName(name)) {
00473 LOG((CLOG_ERR "cannot determine if process was launched as service"));
00474 return false;
00475 }
00476
00477 return (name == SERVICE_LAUNCHER);
00478 }
00479
00480 bool
00481 CArchMiscWindows::getParentProcessName(CString &name)
00482 {
00483 PROCESSENTRY32 parentEntry;
00484 if (!getParentProcessEntry(parentEntry)){
00485 LOG((CLOG_ERR "could not get entry for parent process"));
00486 return false;
00487 }
00488
00489 name = parentEntry.szExeFile;
00490 return true;
00491 }
00492
00493 BOOL WINAPI
00494 CArchMiscWindows::getSelfProcessEntry(PROCESSENTRY32& entry)
00495 {
00496
00497 return getProcessEntry(entry, GetCurrentProcessId());
00498 }
00499
00500 BOOL WINAPI
00501 CArchMiscWindows::getParentProcessEntry(PROCESSENTRY32& entry)
00502 {
00503
00504 PROCESSENTRY32 selfEntry;
00505 if (!getSelfProcessEntry(selfEntry)) {
00506 return FALSE;
00507 }
00508
00509
00510 return getProcessEntry(entry, selfEntry.th32ParentProcessID);
00511 }
00512
00513 BOOL WINAPI
00514 CArchMiscWindows::getProcessEntry(PROCESSENTRY32& entry, DWORD processID)
00515 {
00516
00517 HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
00518 if (snapshot == INVALID_HANDLE_VALUE) {
00519 LOG((CLOG_ERR "could not get process snapshot (error: %i)",
00520 GetLastError()));
00521 return FALSE;
00522 }
00523
00524 entry.dwSize = sizeof(PROCESSENTRY32);
00525
00526
00527
00528 BOOL gotEntry = Process32First(snapshot, &entry);
00529 if (!gotEntry) {
00530 LOG((CLOG_ERR "could not get first process entry (error: %i)",
00531 GetLastError()));
00532 return FALSE;
00533 }
00534
00535 while(gotEntry) {
00536
00537 if (entry.th32ProcessID == processID) {
00538
00539 return TRUE;
00540 }
00541
00542
00543 gotEntry = Process32Next(snapshot, &entry);
00544 }
00545
00546 return FALSE;
00547 }
00548
00549 HINSTANCE
00550 CArchMiscWindows::instanceWin32()
00551 {
00552 assert(s_instanceWin32 != NULL);
00553 return s_instanceWin32;
00554 }
00555
00556 void
00557 CArchMiscWindows::setInstanceWin32(HINSTANCE instance)
00558 {
00559 assert(instance != NULL);
00560 s_instanceWin32 = instance;
00561 }