[DEVMGMT]
[reactos.git] / reactos / base / applications / mscutils / servman / control.c
1 /*
2 * PROJECT: ReactOS Services
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/mscutils/servman/control.c
5 * PURPOSE: Pauses and resumes a service
6 * COPYRIGHT: Copyright 2006-2015 Ged Murphy <gedmurphy@reactos.org>
7 *
8 */
9
10 #include "precomp.h"
11
12 #define MAX_WAIT_TIME 30000
13
14 BOOL
15 DoControlService(LPWSTR ServiceName,
16 HWND hProgress,
17 DWORD Control)
18 {
19 SC_HANDLE hSCManager;
20 SC_HANDLE hService;
21 SERVICE_STATUS_PROCESS ServiceStatus = {0};
22 SERVICE_STATUS Status;
23 DWORD BytesNeeded = 0;
24 DWORD StartTickCount;
25 DWORD OldCheckPoint;
26 DWORD WaitTime;
27 DWORD MaxWait;
28 DWORD ReqState, i;
29 BOOL Result;
30
31 /* Set the state we're interested in */
32 switch (Control)
33 {
34 case SERVICE_CONTROL_PAUSE:
35 ReqState = SERVICE_PAUSED;
36 break;
37 case SERVICE_CONTROL_CONTINUE:
38 ReqState = SERVICE_RUNNING;
39 break;
40 default:
41 /* Unhandled control code */
42 return FALSE;
43 }
44
45 hSCManager = OpenSCManagerW(NULL,
46 NULL,
47 SC_MANAGER_CONNECT);
48 if (!hSCManager) return FALSE;
49
50 hService = OpenServiceW(hSCManager,
51 ServiceName,
52 SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE | SERVICE_QUERY_STATUS);
53 if (!hService)
54 {
55 CloseServiceHandle(hSCManager);
56 return FALSE;
57 }
58
59 /* Send the control message to the service */
60 Result = ControlService(hService,
61 Control,
62 &Status);
63 if (Result)
64 {
65 if (hProgress)
66 {
67 /* Increment the progress bar */
68 IncrementProgressBar(hProgress, DEFAULT_STEP);
69 }
70
71 /* Get the service status */
72 Result = QueryServiceStatusEx(hService,
73 SC_STATUS_PROCESS_INFO,
74 (LPBYTE)&ServiceStatus,
75 sizeof(SERVICE_STATUS_PROCESS),
76 &BytesNeeded);
77 if (Result)
78 {
79 Result = FALSE;
80 MaxWait = MAX_WAIT_TIME;
81 OldCheckPoint = ServiceStatus.dwCheckPoint;
82 StartTickCount = GetTickCount();
83
84 /* Loop until it's at the correct state */
85 while (ServiceStatus.dwCurrentState != ReqState)
86 {
87 /* Fixup the wait time */
88 WaitTime = ServiceStatus.dwWaitHint / 10;
89
90 if (WaitTime < 1000) WaitTime = 1000;
91 else if (WaitTime > 10000) WaitTime = 10000;
92
93 /* We don't wanna wait for up to 10 secs without incrementing */
94 for (i = WaitTime / 1000; i > 0; i--)
95 {
96 Sleep(1000);
97 if (hProgress)
98 {
99 /* Increment the progress bar */
100 IncrementProgressBar(hProgress, DEFAULT_STEP);
101 }
102 }
103
104 /* Get the latest status info */
105 if (!QueryServiceStatusEx(hService,
106 SC_STATUS_PROCESS_INFO,
107 (LPBYTE)&ServiceStatus,
108 sizeof(SERVICE_STATUS_PROCESS),
109 &BytesNeeded))
110 {
111 /* Something went wrong... */
112 break;
113 }
114
115 /* Is the service making progress? */
116 if (ServiceStatus.dwCheckPoint > OldCheckPoint)
117 {
118 /* It is, get the latest tickcount to reset the max wait time */
119 StartTickCount = GetTickCount();
120 OldCheckPoint = ServiceStatus.dwCheckPoint;
121 IncrementProgressBar(hProgress, DEFAULT_STEP);
122 }
123 else
124 {
125 /* It's not, make sure we haven't exceeded our wait time */
126 if(GetTickCount() >= StartTickCount + MaxWait)
127 {
128 /* We have, give up */
129 break;
130 }
131 }
132 }
133 }
134
135 if (ServiceStatus.dwCurrentState == ReqState)
136 {
137 Result = TRUE;
138 }
139 }
140
141 CloseServiceHandle(hService);
142 CloseServiceHandle(hSCManager);
143
144 return Result;
145 }