• Main Page
  • Classes
  • Files
  • File List

CArchMiscWindows.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2012 Bolton Software Ltd.
00004  * Copyright (C) 2002 Chris Schoeneman
00005  * 
00006  * This package is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * found in the file COPYING that should have accompanied this file.
00009  * 
00010  * This package is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
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 // parent process name for services in Vista
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 // CArchMiscWindows
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             // cannot determine OS;  assume windows 95 family
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             // cannot determine OS;  assume not modern
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     // ignore if parent is NULL
00179     if (key == NULL) {
00180         return NULL;
00181     }
00182 
00183     // open next key
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     // switch to new key
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         // open next key
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; // TODO: throw exception
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; // TODO: throw exception
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; // TODO: throw exception
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     // get the size of the string
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     // if zero size then return empty string
00318     if (size == 0) {
00319         return std::string();
00320     }
00321 
00322     // allocate space
00323     char* buffer = new char[size];
00324 
00325     // read it
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     // clean up and return value
00334     if (type == REG_SZ && buffer[size - 1] == '\0') {
00335         // don't include terminating nul;  std::string will add one.
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     // look up function dynamically so we work on older systems
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     // convert to STES form
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     // do it
00435     s_stes(state);
00436 }
00437 
00438 DWORD
00439 CArchMiscWindows::dummySetThreadExecutionState(DWORD)
00440 {
00441     // do nothing
00442     return 0;
00443 }
00444 
00445 void
00446 CArchMiscWindows::wakeupDisplay()
00447 {
00448     // We can't use ::setThreadExecutionState here because it sets
00449     // ES_CONTINUOUS, which we don't want.
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     // restore the original execution states
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     // get entry from current PID
00497     return getProcessEntry(entry, GetCurrentProcessId());
00498 }
00499 
00500 BOOL WINAPI 
00501 CArchMiscWindows::getParentProcessEntry(PROCESSENTRY32& entry)
00502 {
00503     // get the current process, so we can get parent PID
00504     PROCESSENTRY32 selfEntry;
00505     if (!getSelfProcessEntry(selfEntry)) {
00506         return FALSE;
00507     }
00508 
00509     // get entry from parent PID
00510     return getProcessEntry(entry, selfEntry.th32ParentProcessID);
00511 }
00512 
00513 BOOL WINAPI 
00514 CArchMiscWindows::getProcessEntry(PROCESSENTRY32& entry, DWORD processID)
00515 {
00516     // first we need to take a snapshot of the running processes
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     // get the first process, and if we can't do that then it's 
00527     // unlikely we can go any further
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             // found current process
00539             return TRUE;
00540         }
00541 
00542         // now move on to the next entry (when we reach end, loop will stop)
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 }

Generated on Thu May 23 2013 00:00:03 for Synergy by  doxygen 1.7.1