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/control.c
5c2c66affSColin Finck * PURPOSE: Pauses and resumes a service
6c2c66affSColin Finck * COPYRIGHT: Copyright 2006-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
DoControlService(LPWSTR ServiceName,HWND hProgress,DWORD Control)18c2c66affSColin Finck DoControlService(LPWSTR ServiceName,
19c2c66affSColin Finck HWND hProgress,
20c2c66affSColin Finck DWORD Control)
21c2c66affSColin Finck {
22c2c66affSColin Finck SC_HANDLE hSCManager;
23c2c66affSColin Finck SC_HANDLE hService;
24c2c66affSColin Finck SERVICE_STATUS_PROCESS ServiceStatus = {0};
25c2c66affSColin Finck SERVICE_STATUS Status;
26c2c66affSColin Finck DWORD BytesNeeded = 0;
27c2c66affSColin Finck DWORD StartTickCount;
28c2c66affSColin Finck DWORD OldCheckPoint;
29c2c66affSColin Finck DWORD WaitTime;
30c2c66affSColin Finck DWORD MaxWait;
31c2c66affSColin Finck DWORD ReqState, i;
32c2c66affSColin Finck BOOL Result;
33*b3947d52SKyle Katarn DWORD dwResult = ERROR_SUCCESS;
34c2c66affSColin Finck
35c2c66affSColin Finck /* Set the state we're interested in */
36c2c66affSColin Finck switch (Control)
37c2c66affSColin Finck {
38c2c66affSColin Finck case SERVICE_CONTROL_PAUSE:
39c2c66affSColin Finck ReqState = SERVICE_PAUSED;
40c2c66affSColin Finck break;
41c2c66affSColin Finck case SERVICE_CONTROL_CONTINUE:
42c2c66affSColin Finck ReqState = SERVICE_RUNNING;
43c2c66affSColin Finck break;
44c2c66affSColin Finck default:
45c2c66affSColin Finck /* Unhandled control code */
46*b3947d52SKyle Katarn DPRINT1("Unknown control command: 0x%X\n", Control);
47*b3947d52SKyle Katarn return ERROR_INVALID_SERVICE_CONTROL;
48c2c66affSColin Finck }
49c2c66affSColin Finck
50c2c66affSColin Finck hSCManager = OpenSCManagerW(NULL,
51c2c66affSColin Finck NULL,
52c2c66affSColin Finck SC_MANAGER_CONNECT);
53*b3947d52SKyle Katarn if (!hSCManager) return GetLastError();
54c2c66affSColin Finck
55c2c66affSColin Finck hService = OpenServiceW(hSCManager,
56c2c66affSColin Finck ServiceName,
57c2c66affSColin Finck SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE | SERVICE_QUERY_STATUS);
58c2c66affSColin Finck if (!hService)
59c2c66affSColin Finck {
60*b3947d52SKyle Katarn dwResult = GetLastError();
61c2c66affSColin Finck CloseServiceHandle(hSCManager);
62*b3947d52SKyle Katarn return dwResult;
63c2c66affSColin Finck }
64c2c66affSColin Finck
65c2c66affSColin Finck /* Send the control message to the service */
66c2c66affSColin Finck Result = ControlService(hService,
67c2c66affSColin Finck Control,
68c2c66affSColin Finck &Status);
69c2c66affSColin Finck if (Result)
70c2c66affSColin Finck {
71c2c66affSColin Finck if (hProgress)
72c2c66affSColin Finck {
73c2c66affSColin Finck /* Increment the progress bar */
74c2c66affSColin Finck IncrementProgressBar(hProgress, DEFAULT_STEP);
75c2c66affSColin Finck }
76c2c66affSColin Finck
77c2c66affSColin Finck /* Get the service status */
78c2c66affSColin Finck Result = QueryServiceStatusEx(hService,
79c2c66affSColin Finck SC_STATUS_PROCESS_INFO,
80c2c66affSColin Finck (LPBYTE)&ServiceStatus,
81c2c66affSColin Finck sizeof(SERVICE_STATUS_PROCESS),
82c2c66affSColin Finck &BytesNeeded);
83c2c66affSColin Finck if (Result)
84c2c66affSColin Finck {
85c2c66affSColin Finck Result = FALSE;
86c2c66affSColin Finck MaxWait = MAX_WAIT_TIME;
87c2c66affSColin Finck OldCheckPoint = ServiceStatus.dwCheckPoint;
88c2c66affSColin Finck StartTickCount = GetTickCount();
89c2c66affSColin Finck
90c2c66affSColin Finck /* Loop until it's at the correct state */
91c2c66affSColin Finck while (ServiceStatus.dwCurrentState != ReqState)
92c2c66affSColin Finck {
93c2c66affSColin Finck /* Fixup the wait time */
94c2c66affSColin Finck WaitTime = ServiceStatus.dwWaitHint / 10;
95c2c66affSColin Finck
96c2c66affSColin Finck if (WaitTime < 1000) WaitTime = 1000;
97c2c66affSColin Finck else if (WaitTime > 10000) WaitTime = 10000;
98c2c66affSColin Finck
99c2c66affSColin Finck /* We don't wanna wait for up to 10 secs without incrementing */
100c2c66affSColin Finck for (i = WaitTime / 1000; i > 0; i--)
101c2c66affSColin Finck {
102c2c66affSColin Finck Sleep(1000);
103c2c66affSColin Finck if (hProgress)
104c2c66affSColin Finck {
105c2c66affSColin Finck /* Increment the progress bar */
106c2c66affSColin Finck IncrementProgressBar(hProgress, DEFAULT_STEP);
107c2c66affSColin Finck }
108c2c66affSColin Finck }
109c2c66affSColin Finck
110c2c66affSColin Finck /* Get the latest status info */
111c2c66affSColin Finck if (!QueryServiceStatusEx(hService,
112c2c66affSColin Finck SC_STATUS_PROCESS_INFO,
113c2c66affSColin Finck (LPBYTE)&ServiceStatus,
114c2c66affSColin Finck sizeof(SERVICE_STATUS_PROCESS),
115c2c66affSColin Finck &BytesNeeded))
116c2c66affSColin Finck {
117c2c66affSColin Finck /* Something went wrong... */
118*b3947d52SKyle Katarn dwResult = GetLastError();
119*b3947d52SKyle Katarn DPRINT1("QueryServiceStatusEx failed: %d\n", dwResult);
120c2c66affSColin Finck break;
121c2c66affSColin Finck }
122c2c66affSColin Finck
123c2c66affSColin Finck /* Is the service making progress? */
124c2c66affSColin Finck if (ServiceStatus.dwCheckPoint > OldCheckPoint)
125c2c66affSColin Finck {
126c2c66affSColin Finck /* It is, get the latest tickcount to reset the max wait time */
127c2c66affSColin Finck StartTickCount = GetTickCount();
128c2c66affSColin Finck OldCheckPoint = ServiceStatus.dwCheckPoint;
129c2c66affSColin Finck IncrementProgressBar(hProgress, DEFAULT_STEP);
130c2c66affSColin Finck }
131c2c66affSColin Finck else
132c2c66affSColin Finck {
133c2c66affSColin Finck /* It's not, make sure we haven't exceeded our wait time */
134c2c66affSColin Finck if (GetTickCount() >= StartTickCount + MaxWait)
135c2c66affSColin Finck {
136c2c66affSColin Finck /* We have, give up */
137*b3947d52SKyle Katarn DPRINT1("Timeout\n");
138*b3947d52SKyle Katarn dwResult = ERROR_SERVICE_REQUEST_TIMEOUT;
139c2c66affSColin Finck break;
140c2c66affSColin Finck }
141c2c66affSColin Finck }
142c2c66affSColin Finck }
143c2c66affSColin Finck }
144*b3947d52SKyle Katarn else
145*b3947d52SKyle Katarn {
146*b3947d52SKyle Katarn dwResult = GetLastError();
147*b3947d52SKyle Katarn }
148c2c66affSColin Finck
149c2c66affSColin Finck if (ServiceStatus.dwCurrentState == ReqState)
150c2c66affSColin Finck {
151*b3947d52SKyle Katarn dwResult = ERROR_SUCCESS;
152c2c66affSColin Finck }
153c2c66affSColin Finck }
154*b3947d52SKyle Katarn else
155*b3947d52SKyle Katarn {
156*b3947d52SKyle Katarn dwResult = GetLastError();
157*b3947d52SKyle Katarn }
158c2c66affSColin Finck
159c2c66affSColin Finck CloseServiceHandle(hService);
160c2c66affSColin Finck CloseServiceHandle(hSCManager);
161c2c66affSColin Finck
162*b3947d52SKyle Katarn return dwResult;
163c2c66affSColin Finck }
164