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