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