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
DoStartService(LPWSTR ServiceName,HANDLE hProgress,LPWSTR lpStartParams)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