1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/other-licenses/nsis/Contrib/ServicesHelper/Services.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,241 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include <windows.h> 1.9 +#include "../../../../toolkit/mozapps/update/common/pathhash.h" 1.10 + 1.11 +#pragma comment(lib, "advapi32.lib") 1.12 + 1.13 +typedef struct _stack_t { 1.14 + struct _stack_t *next; 1.15 + TCHAR text[MAX_PATH]; 1.16 +} stack_t; 1.17 + 1.18 +int popstring(stack_t **stacktop, LPTSTR str, int len); 1.19 +void pushstring(stack_t **stacktop, LPCTSTR str, int len); 1.20 + 1.21 +/** 1.22 + * Determines if the specified service exists or not 1.23 + * 1.24 + * @param serviceName The name of the service to check 1.25 + * @param exists Whether or not the service exists 1.26 + * @return TRUE if there were no errors 1.27 + */ 1.28 +static BOOL 1.29 +IsServiceInstalled(LPCWSTR serviceName, BOOL &exists) 1.30 +{ 1.31 + exists = FALSE; 1.32 + 1.33 + // Get a handle to the local computer SCM database with full access rights. 1.34 + SC_HANDLE serviceManager = OpenSCManager(NULL, NULL, 1.35 + SC_MANAGER_ENUMERATE_SERVICE); 1.36 + if (!serviceManager) { 1.37 + return FALSE; 1.38 + } 1.39 + 1.40 + SC_HANDLE serviceHandle = OpenServiceW(serviceManager, 1.41 + serviceName, 1.42 + SERVICE_QUERY_CONFIG); 1.43 + if (!serviceHandle && GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST) { 1.44 + CloseServiceHandle(serviceManager); 1.45 + return FALSE; 1.46 + } 1.47 + 1.48 + if (serviceHandle) { 1.49 + CloseServiceHandle(serviceHandle); 1.50 + exists = TRUE; 1.51 + } 1.52 + 1.53 + CloseServiceHandle(serviceManager); 1.54 + return TRUE; 1.55 +} 1.56 + 1.57 +/** 1.58 + * Determines if the specified service is installed or not 1.59 + * 1.60 + * @param stacktop A pointer to the top of the stack 1.61 + * @param variables A pointer to the NSIS variables 1.62 + * @return 0 if the service does not exist 1.63 + * 1 if the service does exist 1.64 + * -1 if there was an error. 1.65 + */ 1.66 +extern "C" void __declspec(dllexport) 1.67 +IsInstalled(HWND hwndParent, int string_size, 1.68 + TCHAR *variables, stack_t **stacktop, void *extra) 1.69 +{ 1.70 + TCHAR tmp[MAX_PATH] = { L'\0' }; 1.71 + WCHAR serviceName[MAX_PATH] = { '\0' }; 1.72 + popstring(stacktop, tmp, MAX_PATH); 1.73 + 1.74 +#if !defined(UNICODE) 1.75 + MultiByteToWideChar(CP_ACP, 0, tmp, -1, serviceName, MAX_PATH); 1.76 +#else 1.77 + wcscpy(serviceName, tmp); 1.78 +#endif 1.79 + 1.80 + BOOL serviceInstalled; 1.81 + if (!IsServiceInstalled(serviceName, serviceInstalled)) { 1.82 + pushstring(stacktop, TEXT("-1"), 3); 1.83 + } else { 1.84 + pushstring(stacktop, serviceInstalled ? TEXT("1") : TEXT("0"), 2); 1.85 + } 1.86 +} 1.87 + 1.88 +/** 1.89 + * Stops the specified service. 1.90 + * 1.91 + * @param serviceName The name of the service to stop 1.92 + * @return TRUE if the operation was successful 1.93 + */ 1.94 +static BOOL 1.95 +StopService(LPCWSTR serviceName) 1.96 +{ 1.97 + // Get a handle to the local computer SCM database with full access rights. 1.98 + SC_HANDLE serviceManager = OpenSCManager(NULL, NULL, 1.99 + SC_MANAGER_ENUMERATE_SERVICE); 1.100 + if (!serviceManager) { 1.101 + return FALSE; 1.102 + } 1.103 + 1.104 + SC_HANDLE serviceHandle = OpenServiceW(serviceManager, 1.105 + serviceName, 1.106 + SERVICE_STOP); 1.107 + if (!serviceHandle) { 1.108 + CloseServiceHandle(serviceManager); 1.109 + return FALSE; 1.110 + } 1.111 + 1.112 + //Stop the service so it deletes faster and so the uninstaller 1.113 + // can actually delete its EXE. 1.114 + DWORD totalWaitTime = 0; 1.115 + SERVICE_STATUS status; 1.116 + static const int maxWaitTime = 1000 * 60; // Never wait more than a minute 1.117 + BOOL stopped = FALSE; 1.118 + if (ControlService(serviceHandle, SERVICE_CONTROL_STOP, &status)) { 1.119 + do { 1.120 + Sleep(status.dwWaitHint); 1.121 + // + 10 milliseconds to make sure we always approach maxWaitTime 1.122 + totalWaitTime += (status.dwWaitHint + 10); 1.123 + if (status.dwCurrentState == SERVICE_STOPPED) { 1.124 + stopped = true; 1.125 + break; 1.126 + } else if (totalWaitTime > maxWaitTime) { 1.127 + break; 1.128 + } 1.129 + } while (QueryServiceStatus(serviceHandle, &status)); 1.130 + } 1.131 + 1.132 + CloseServiceHandle(serviceHandle); 1.133 + CloseServiceHandle(serviceManager); 1.134 + return stopped; 1.135 +} 1.136 + 1.137 +/** 1.138 + * Stops the specified service 1.139 + * 1.140 + * @param stacktop A pointer to the top of the stack 1.141 + * @param variables A pointer to the NSIS variables 1.142 + * @return 1 if the service was stopped, 0 on error 1.143 + */ 1.144 +extern "C" void __declspec(dllexport) 1.145 +Stop(HWND hwndParent, int string_size, 1.146 + TCHAR *variables, stack_t **stacktop, void *extra) 1.147 +{ 1.148 + TCHAR tmp[MAX_PATH] = { L'\0' }; 1.149 + WCHAR serviceName[MAX_PATH] = { '\0' }; 1.150 + 1.151 + popstring(stacktop, tmp, MAX_PATH); 1.152 + 1.153 +#if !defined(UNICODE) 1.154 + MultiByteToWideChar(CP_ACP, 0, tmp, -1, serviceName, MAX_PATH); 1.155 +#else 1.156 + wcscpy(serviceName, tmp); 1.157 +#endif 1.158 + 1.159 + if (StopService(serviceName)) { 1.160 + pushstring(stacktop, TEXT("1"), 2); 1.161 + } else { 1.162 + pushstring(stacktop, TEXT("0"), 2); 1.163 + } 1.164 +} 1.165 + 1.166 +/** 1.167 + * Determines a unique registry path from a file or directory path 1.168 + * 1.169 + * @param stacktop A pointer to the top of the stack 1.170 + * @param variables A pointer to the NSIS variables 1.171 + * @return The unique registry path or an empty string on error 1.172 + */ 1.173 +extern "C" void __declspec(dllexport) 1.174 +PathToUniqueRegistryPath(HWND hwndParent, int string_size, 1.175 + TCHAR *variables, stack_t **stacktop, 1.176 + void *extra) 1.177 +{ 1.178 + TCHAR tmp[MAX_PATH] = { L'\0' }; 1.179 + WCHAR installBasePath[MAX_PATH] = { '\0' }; 1.180 + popstring(stacktop, tmp, MAX_PATH); 1.181 + 1.182 +#if !defined(UNICODE) 1.183 + MultiByteToWideChar(CP_ACP, 0, tmp, -1, installBasePath, MAX_PATH); 1.184 +#else 1.185 + wcscpy(installBasePath, tmp); 1.186 +#endif 1.187 + 1.188 + WCHAR registryPath[MAX_PATH + 1] = { '\0' }; 1.189 + if (CalculateRegistryPathFromFilePath(installBasePath, registryPath)) { 1.190 + pushstring(stacktop, registryPath, wcslen(registryPath) + 1); 1.191 + } else { 1.192 + pushstring(stacktop, TEXT(""), 1); 1.193 + } 1.194 +} 1.195 + 1.196 +BOOL WINAPI 1.197 +DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) 1.198 +{ 1.199 + return TRUE; 1.200 +} 1.201 + 1.202 +/** 1.203 + * Removes an element from the top of the NSIS stack 1.204 + * 1.205 + * @param stacktop A pointer to the top of the stack 1.206 + * @param str The string to pop to 1.207 + * @param len The max length 1.208 + * @return 0 on success 1.209 +*/ 1.210 +int popstring(stack_t **stacktop, TCHAR *str, int len) 1.211 +{ 1.212 + // Removes the element from the top of the stack and puts it in the buffer 1.213 + stack_t *th; 1.214 + if (!stacktop || !*stacktop) { 1.215 + return 1; 1.216 + } 1.217 + 1.218 + th = (*stacktop); 1.219 + lstrcpyn(str,th->text, len); 1.220 + *stacktop = th->next; 1.221 + GlobalFree((HGLOBAL)th); 1.222 + return 0; 1.223 +} 1.224 + 1.225 +/** 1.226 + * Adds an element to the top of the NSIS stack 1.227 + * 1.228 + * @param stacktop A pointer to the top of the stack 1.229 + * @param str The string to push on the stack 1.230 + * @param len The length of the string to push on the stack 1.231 + * @return 0 on success 1.232 +*/ 1.233 +void pushstring(stack_t **stacktop, const TCHAR *str, int len) 1.234 +{ 1.235 + stack_t *th; 1.236 + if (!stacktop) { 1.237 + return; 1.238 + } 1.239 + 1.240 + th = (stack_t*)GlobalAlloc(GPTR, sizeof(stack_t) + len); 1.241 + lstrcpyn(th->text, str, len); 1.242 + th->next = *stacktop; 1.243 + *stacktop = th; 1.244 +}