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