1 /* 2 * PROJECT: ReactOS Services 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: base/applications/mscutils/servman/start.c 5 * PURPOSE: Start a service 6 * COPYRIGHT: Copyright 2005-2015 Ged Murphy <gedmurphy@reactos.org> 7 * 8 */ 9 10 #include "precomp.h" 11 12 #define NDEBUG 13 #include <debug.h> 14 15 #define MAX_WAIT_TIME 30000 16 17 DWORD 18 DoStartService(LPWSTR ServiceName, 19 HANDLE hProgress, 20 LPWSTR lpStartParams) 21 { 22 SC_HANDLE hSCManager; 23 SC_HANDLE hService; 24 SERVICE_STATUS_PROCESS ServiceStatus; 25 DWORD BytesNeeded = 0; 26 DWORD StartTickCount; 27 DWORD OldCheckPoint; 28 DWORD WaitTime; 29 DWORD MaxWait; 30 BOOL Result = FALSE; 31 32 BOOL bWhiteSpace = TRUE; 33 LPWSTR lpChar; 34 DWORD dwArgsCount = 0; 35 DWORD dwResult = ERROR_SUCCESS; 36 LPCWSTR *lpArgsVector = NULL; 37 38 if (lpStartParams != NULL) 39 { 40 /* Count the number of arguments */ 41 lpChar = lpStartParams; 42 while (*lpChar != 0) 43 { 44 if (iswspace(*lpChar)) 45 { 46 bWhiteSpace = TRUE; 47 } 48 else 49 { 50 if (bWhiteSpace != FALSE) 51 { 52 dwArgsCount++; 53 bWhiteSpace = FALSE; 54 } 55 } 56 57 lpChar++; 58 } 59 60 /* 61 * Allocate the arguments vector. 62 * Do not add the service name here because services.exe does it for us! 63 */ 64 lpArgsVector = LocalAlloc(LMEM_FIXED, dwArgsCount * sizeof(LPCWSTR)); 65 if (!lpArgsVector) 66 return GetLastError(); 67 68 /* Fill the arguments vector */ 69 dwArgsCount = 0; 70 bWhiteSpace = TRUE; 71 lpChar = lpStartParams; 72 while (*lpChar != 0) 73 { 74 if (iswspace(*lpChar)) 75 { 76 *lpChar = 0; 77 bWhiteSpace = TRUE; 78 } 79 else 80 { 81 if (bWhiteSpace != FALSE) 82 { 83 lpArgsVector[dwArgsCount] = lpChar; 84 dwArgsCount++; 85 bWhiteSpace = FALSE; 86 } 87 } 88 89 lpChar++; 90 } 91 } 92 93 hSCManager = OpenSCManagerW(NULL, 94 NULL, 95 SC_MANAGER_CONNECT); 96 if (!hSCManager) 97 { 98 dwResult = GetLastError(); 99 if (lpArgsVector) 100 LocalFree((LPVOID)lpArgsVector); 101 return dwResult; 102 } 103 104 hService = OpenServiceW(hSCManager, 105 ServiceName, 106 SERVICE_START | SERVICE_QUERY_STATUS); 107 if (!hService) 108 { 109 dwResult = GetLastError(); 110 CloseServiceHandle(hSCManager); 111 if (lpArgsVector) 112 LocalFree((LPVOID)lpArgsVector); 113 return dwResult; 114 } 115 116 /* Start the service */ 117 Result = StartServiceW(hService, 118 dwArgsCount, 119 lpArgsVector); 120 if (!Result && GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) 121 { 122 /* If it's already running, just return TRUE */ 123 Result = TRUE; 124 } 125 else if (Result) 126 { 127 if (hProgress) 128 { 129 /* Increment the progress bar */ 130 IncrementProgressBar(hProgress, DEFAULT_STEP); 131 } 132 133 /* Get the service status to check if it's running */ 134 Result = QueryServiceStatusEx(hService, 135 SC_STATUS_PROCESS_INFO, 136 (LPBYTE)&ServiceStatus, 137 sizeof(SERVICE_STATUS_PROCESS), 138 &BytesNeeded); 139 if (Result) 140 { 141 Result = FALSE; 142 MaxWait = MAX_WAIT_TIME; 143 OldCheckPoint = ServiceStatus.dwCheckPoint; 144 StartTickCount = GetTickCount(); 145 146 /* Loop until it's running */ 147 while (ServiceStatus.dwCurrentState != SERVICE_RUNNING) 148 { 149 int i; 150 /* Fixup the wait time */ 151 WaitTime = ServiceStatus.dwWaitHint / 10; 152 153 if (WaitTime < 1000) WaitTime = 1000; 154 else if (WaitTime > 10000) WaitTime = 10000; 155 156 /* We don't wanna wait for up to 10 secs without incrementing */ 157 for (i = WaitTime / 1000; i > 0; i--) 158 { 159 Sleep(1000); 160 if (hProgress) 161 { 162 /* Increment the progress bar */ 163 IncrementProgressBar(hProgress, DEFAULT_STEP); 164 } 165 } 166 167 168 /* Get the latest status info */ 169 if (!QueryServiceStatusEx(hService, 170 SC_STATUS_PROCESS_INFO, 171 (LPBYTE)&ServiceStatus, 172 sizeof(SERVICE_STATUS_PROCESS), 173 &BytesNeeded)) 174 { 175 /* Something went wrong... */ 176 dwResult = GetLastError(); 177 DPRINT1("QueryServiceStatusEx failed: %d\n", dwResult); 178 break; 179 } 180 181 /* Is the service making progress? */ 182 if (ServiceStatus.dwCheckPoint > OldCheckPoint) 183 { 184 /* It is, get the latest tickcount to reset the max wait time */ 185 StartTickCount = GetTickCount(); 186 OldCheckPoint = ServiceStatus.dwCheckPoint; 187 } 188 else 189 { 190 /* It's not, make sure we haven't exceeded our wait time */ 191 if (GetTickCount() >= StartTickCount + MaxWait) 192 { 193 /* We have, give up */ 194 DPRINT1("Timeout\n"); 195 dwResult = ERROR_SERVICE_REQUEST_TIMEOUT; 196 break; 197 } 198 } 199 } 200 } 201 else 202 { 203 dwResult = GetLastError(); 204 } 205 206 if (ServiceStatus.dwCurrentState == SERVICE_RUNNING) 207 { 208 dwResult = ERROR_SUCCESS; 209 } 210 } 211 212 CloseServiceHandle(hService); 213 CloseServiceHandle(hSCManager); 214 215 if (lpArgsVector) 216 LocalFree((LPVOID)lpArgsVector); 217 218 return dwResult; 219 } 220