tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Services.cpp (6803B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include <windows.h>
      6 #include "../../../../toolkit/mozapps/update/common/pathhash.h"
      7 
      8 #pragma comment(lib, "advapi32.lib") 
      9 
     10 typedef struct _stack_t {
     11  struct _stack_t *next;
     12  TCHAR text[MAX_PATH];
     13 } stack_t;
     14 
     15 int popstring(stack_t **stacktop, LPTSTR str, int len);
     16 void pushstring(stack_t **stacktop, LPCTSTR str, int len);
     17 
     18 /**
     19 * Determines if the specified service exists or not
     20 *
     21 * @param  serviceName The name of the service to check
     22 * @param  exists      Whether or not the service exists 
     23 * @return TRUE if there were no errors
     24 */
     25 static BOOL
     26 IsServiceInstalled(LPCWSTR serviceName, BOOL &exists)
     27 {
     28  exists = FALSE;
     29 
     30  // Get a handle to the local computer SCM database with full access rights.
     31  SC_HANDLE serviceManager = OpenSCManager(NULL, NULL, 
     32                                           SC_MANAGER_ENUMERATE_SERVICE);
     33  if (!serviceManager) {
     34    return FALSE;
     35  }
     36 
     37  SC_HANDLE serviceHandle = OpenServiceW(serviceManager, 
     38                                         serviceName, 
     39                                         SERVICE_QUERY_CONFIG);
     40  if (!serviceHandle && GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST) {
     41    CloseServiceHandle(serviceManager);
     42    return FALSE;
     43  }
     44 
     45  if (serviceHandle) {
     46    CloseServiceHandle(serviceHandle);
     47    exists = TRUE;
     48  } 
     49 
     50  CloseServiceHandle(serviceManager);
     51  return TRUE;
     52 }
     53 
     54 /**
     55 * Determines if the specified service is installed or not
     56 * 
     57 * @param  stacktop  A pointer to the top of the stack
     58 * @param  variables A pointer to the NSIS variables
     59 * @return 0 if the service does not exist
     60 *         1 if the service does exist
     61 *         -1 if there was an error.
     62 */
     63 extern "C" void __declspec(dllexport)
     64 IsInstalled(HWND hwndParent, int string_size, 
     65            TCHAR *variables, stack_t **stacktop, void *extra)
     66 {
     67  TCHAR tmp[MAX_PATH] = { L'\0' };
     68  WCHAR serviceName[MAX_PATH] = { '\0' };
     69  popstring(stacktop, tmp, MAX_PATH);
     70 
     71 #if !defined(UNICODE)
     72    MultiByteToWideChar(CP_ACP, 0, tmp, -1, serviceName, MAX_PATH);
     73 #else
     74    wcscpy(serviceName, tmp);
     75 #endif
     76 
     77  BOOL serviceInstalled;
     78  if (!IsServiceInstalled(serviceName, serviceInstalled)) {
     79    pushstring(stacktop, TEXT("-1"), 3);
     80  } else {
     81    pushstring(stacktop, serviceInstalled ? TEXT("1") : TEXT("0"), 2);
     82  }
     83 }
     84 
     85 /**
     86 * Stops the specified service.
     87 * 
     88 * @param  serviceName The name of the service to stop
     89 * @return TRUE if the operation was successful 
     90 */
     91 static BOOL
     92 StopService(LPCWSTR serviceName)
     93 {
     94  // Get a handle to the local computer SCM database with full access rights.
     95  SC_HANDLE serviceManager = OpenSCManager(NULL, NULL, 
     96                                           SC_MANAGER_ENUMERATE_SERVICE);
     97  if (!serviceManager) {
     98    return FALSE;
     99  }
    100 
    101  SC_HANDLE serviceHandle = OpenServiceW(serviceManager, 
    102                                         serviceName, 
    103                                         SERVICE_STOP);
    104  if (!serviceHandle) {
    105    CloseServiceHandle(serviceManager);
    106    return FALSE;
    107  }
    108 
    109  //Stop the service so it deletes faster and so the uninstaller
    110  // can actually delete its EXE.
    111  DWORD totalWaitTime = 0;
    112  SERVICE_STATUS status;
    113  static const int maxWaitTime = 1000 * 60; // Never wait more than a minute
    114  BOOL stopped = FALSE;
    115  if (ControlService(serviceHandle, SERVICE_CONTROL_STOP, &status)) {
    116    do {
    117      Sleep(status.dwWaitHint);
    118      // + 10 milliseconds to make sure we always approach maxWaitTime
    119      totalWaitTime += (status.dwWaitHint + 10);
    120      if (status.dwCurrentState == SERVICE_STOPPED) {
    121        stopped = true;
    122        break;
    123      } else if (totalWaitTime > maxWaitTime) {
    124        break;
    125      }
    126    } while (QueryServiceStatus(serviceHandle, &status));
    127  }
    128 
    129  CloseServiceHandle(serviceHandle);
    130  CloseServiceHandle(serviceManager);
    131  return stopped;
    132 }
    133 
    134 /**
    135 * Stops the specified service
    136 * 
    137 * @param  stacktop  A pointer to the top of the stack
    138 * @param  variables A pointer to the NSIS variables 
    139 * @return 1 if the service was stopped, 0 on error
    140 */
    141 extern "C" void __declspec(dllexport)
    142 Stop(HWND hwndParent, int string_size, 
    143     TCHAR *variables, stack_t **stacktop, void *extra)
    144 {
    145  TCHAR tmp[MAX_PATH] = { L'\0' };
    146  WCHAR serviceName[MAX_PATH] = { '\0' };
    147 
    148  popstring(stacktop, tmp, MAX_PATH);
    149 
    150 #if !defined(UNICODE)
    151    MultiByteToWideChar(CP_ACP, 0, tmp, -1, serviceName, MAX_PATH);
    152 #else
    153    wcscpy(serviceName, tmp);
    154 #endif
    155 
    156  if (StopService(serviceName)) {
    157    pushstring(stacktop, TEXT("1"), 2);
    158  } else {
    159    pushstring(stacktop, TEXT("0"), 2);
    160  }
    161 }
    162 
    163 /**
    164 * Determines a unique registry path from a file or directory path
    165 * 
    166 * @param  stacktop  A pointer to the top of the stack
    167 * @param  variables A pointer to the NSIS variables 
    168 * @return The unique registry path or an empty string on error
    169 */
    170 extern "C" void __declspec(dllexport)
    171 PathToUniqueRegistryPath(HWND hwndParent, int string_size, 
    172                         TCHAR *variables, stack_t **stacktop, 
    173                         void *extra)
    174 {
    175  TCHAR tmp[MAX_PATH] = { L'\0' };
    176  WCHAR installBasePath[MAX_PATH] = { '\0' };
    177  popstring(stacktop, tmp, MAX_PATH);
    178 
    179 #if !defined(UNICODE)
    180    MultiByteToWideChar(CP_ACP, 0, tmp, -1, installBasePath, MAX_PATH);
    181 #else
    182    wcscpy(installBasePath, tmp);
    183 #endif
    184 
    185  WCHAR registryPath[MAX_PATH + 1] = { '\0' };
    186  if (CalculateRegistryPathFromFilePath(installBasePath, registryPath)) {
    187    pushstring(stacktop, registryPath, wcslen(registryPath) + 1);
    188  } else {
    189    pushstring(stacktop, TEXT(""), 1);
    190  }
    191 }
    192 
    193 BOOL WINAPI 
    194 DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
    195 {
    196  return TRUE;
    197 }
    198 
    199 /**
    200 * Removes an element from the top of the NSIS stack
    201 *
    202 * @param  stacktop A pointer to the top of the stack
    203 * @param  str      The string to pop to
    204 * @param  len      The max length
    205 * @return 0 on success
    206 */
    207 int popstring(stack_t **stacktop, TCHAR *str, int len)
    208 {
    209  // Removes the element from the top of the stack and puts it in the buffer
    210  stack_t *th;
    211  if (!stacktop || !*stacktop) {
    212    return 1;
    213  }
    214 
    215  th = (*stacktop);
    216  lstrcpyn(str,th->text, len);
    217  *stacktop = th->next;
    218  GlobalFree((HGLOBAL)th);
    219  return 0;
    220 }
    221 
    222 /**
    223 * Adds an element to the top of the NSIS stack
    224 *
    225 * @param  stacktop A pointer to the top of the stack
    226 * @param  str      The string to push on the stack
    227 * @param  len      The length of the string to push on the stack
    228 * @return 0 on success
    229 */
    230 void pushstring(stack_t **stacktop, const TCHAR *str, int len)
    231 {
    232  stack_t *th;
    233  if (!stacktop) { 
    234    return;
    235  }
    236 
    237  th = (stack_t*)GlobalAlloc(GPTR, sizeof(stack_t) + len);
    238  lstrcpyn(th->text, str, len);
    239  th->next = *stacktop;
    240  *stacktop = th;
    241 }