/* * PROJECT: ReactOS Services * LICENSE: GPL - See COPYING in the top level directory * FILE: base/applications/mscutils/servman/control.c * PURPOSE: Pauses and resumes a service * COPYRIGHT: Copyright 2006-2010 Ged Murphy * */ #include "precomp.h" static BOOL DoControl(PMAIN_WND_INFO Info, HWND hProgress, DWORD Control) { SC_HANDLE hSCManager; SC_HANDLE hService; SERVICE_STATUS_PROCESS ServiceStatus = {0}; SERVICE_STATUS Status; DWORD BytesNeeded = 0; DWORD dwStartTickCount; DWORD dwOldCheckPoint; DWORD dwWaitTime; DWORD dwMaxWait; DWORD dwReqState; BOOL bRet = FALSE; /* Set the state we're interested in */ switch (Control) { case SERVICE_CONTROL_PAUSE: dwReqState = SERVICE_PAUSED; break; case SERVICE_CONTROL_CONTINUE: dwReqState = SERVICE_RUNNING; break; default: /* Unhandled control code */ return FALSE; } hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (hSCManager) { hService = OpenService(hSCManager, Info->pCurrentService->lpServiceName, SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE | SERVICE_QUERY_STATUS); if (hService) { if (hProgress) { /* Increment the progress bar */ IncrementProgressBar(hProgress, DEFAULT_STEP); } /* Send the control message to the service */ if (ControlService(hService, Control, &Status)) { /* Get the service status */ if (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ServiceStatus, sizeof(SERVICE_STATUS_PROCESS), &BytesNeeded)) { /* We don't want to wait for more than 30 seconds */ dwMaxWait = 30000; dwStartTickCount = GetTickCount(); /* Loop until it's at the correct state */ while (ServiceStatus.dwCurrentState != dwReqState) { dwOldCheckPoint = ServiceStatus.dwCheckPoint; dwWaitTime = ServiceStatus.dwWaitHint / 10; /* Get the latest status info */ if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ServiceStatus, sizeof(SERVICE_STATUS_PROCESS), &BytesNeeded)) { /* Something went wrong... */ break; } /* Is the service making progress? */ if (ServiceStatus.dwCheckPoint > dwOldCheckPoint) { /* It is, get the latest tickcount to reset the max wait time */ dwStartTickCount = GetTickCount(); dwOldCheckPoint = ServiceStatus.dwCheckPoint; IncrementProgressBar(hProgress, DEFAULT_STEP); } else { /* It's not, make sure we haven't exceeded our wait time */ if(GetTickCount() >= dwStartTickCount + dwMaxWait) { /* We have, give up */ break; } } /* Adjust the wait hint times */ if (dwWaitTime < 200) dwWaitTime = 200; else if (dwWaitTime > 10000) dwWaitTime = 10000; /* Wait before trying again */ Sleep(dwWaitTime); } } if (ServiceStatus.dwCurrentState == dwReqState) { bRet = TRUE; } } CloseServiceHandle(hService); } CloseServiceHandle(hSCManager); } return bRet; } BOOL DoPause(PMAIN_WND_INFO Info) { HWND hProgress; BOOL bRet = FALSE; /* Create a progress window to track the progress of the pausing service */ hProgress = CreateProgressDialog(Info->hMainWnd, IDS_PROGRESS_INFO_PAUSE); if (hProgress) { /* Set the service name and reset the progress bag */ InitializeProgressDialog(hProgress, Info->pCurrentService->lpServiceName); /* Resume the requested service */ bRet = DoControl(Info, hProgress, SERVICE_CONTROL_PAUSE); /* Complete and destroy the progress bar */ DestroyProgressDialog(hProgress, bRet); } return bRet; } BOOL DoResume(PMAIN_WND_INFO Info) { HWND hProgress; BOOL bRet = FALSE; /* Create a progress window to track the progress of the resuming service */ hProgress = CreateProgressDialog(Info->hMainWnd, IDS_PROGRESS_INFO_RESUME); if (hProgress) { /* Set the service name and reset the progress bag */ InitializeProgressDialog(hProgress, Info->pCurrentService->lpServiceName); /* Resume the requested service */ bRet = DoControl(Info, hProgress, SERVICE_CONTROL_CONTINUE); /* Complete and destroy the progress bar */ DestroyProgressDialog(hProgress, bRet); } return bRet; }