From d4aca7552303885744561289a98c8b72f00fd65f Mon Sep 17 00:00:00 2001 From: Ged Murphy Date: Tue, 5 Jan 2010 21:43:00 +0000 Subject: [PATCH] Clean up the pause and resume code and a few other bits and bobs svn path=/trunk/; revision=44965 --- .../applications/mscutils/servman/control.c | 164 ++++++++++-------- .../applications/mscutils/servman/precomp.h | 10 +- .../applications/mscutils/servman/start.c | 2 + .../base/applications/mscutils/servman/stop.c | 4 + 4 files changed, 98 insertions(+), 82 deletions(-) diff --git a/reactos/base/applications/mscutils/servman/control.c b/reactos/base/applications/mscutils/servman/control.c index 41fac161aef..99582a6af28 100644 --- a/reactos/base/applications/mscutils/servman/control.c +++ b/reactos/base/applications/mscutils/servman/control.c @@ -2,158 +2,168 @@ * PROJECT: ReactOS Services * LICENSE: GPL - See COPYING in the top level directory * FILE: base/applications/mscutils/servman/control.c - * PURPOSE: Stops, pauses and resumes a service - * COPYRIGHT: Copyright 2006-2007 Ged Murphy + * PURPOSE: Pauses and resumes a service + * COPYRIGHT: Copyright 2006-2010 Ged Murphy * */ #include "precomp.h" -BOOL -Control(PMAIN_WND_INFO Info, - HWND hProgDlg, - DWORD Control) +static BOOL +DoControl(PMAIN_WND_INFO Info, + HWND hProgress, + DWORD Control) { SC_HANDLE hSCManager; - SC_HANDLE hSc; + SC_HANDLE hService; SERVICE_STATUS_PROCESS ServiceStatus = {0}; SERVICE_STATUS Status; DWORD BytesNeeded = 0; + DWORD dwStartTickCount; + DWORD dwOldCheckPoint; + DWORD dwWaitTime; + DWORD dwMaxWait; BOOL bRet = FALSE; - BOOL bDispErr = TRUE; hSCManager = OpenSCManager(NULL, NULL, - SC_MANAGER_ALL_ACCESS); - if (hSCManager != NULL) + SC_MANAGER_CONNECT); + if (hSCManager) { - hSc = OpenService(hSCManager, - Info->pCurrentService->lpServiceName, - SERVICE_ALL_ACCESS); - if (hSc != NULL) + hService = OpenService(hSCManager, + Info->pCurrentService->lpServiceName, + SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE | SERVICE_QUERY_CONFIG); + if (hService) { - if (ControlService(hSc, + if (hProgress) + { + /* Increment the progress bar */ + IncrementProgressBar(hProgress, DEFAULT_STEP); + } + + /* Send the control message to the service */ + if (ControlService(hService, Control, &Status)) { - bDispErr = FALSE; - - if (QueryServiceStatusEx(hSc, + /* Get the service status */ + if (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ServiceStatus, sizeof(SERVICE_STATUS_PROCESS), &BytesNeeded)) { - DWORD dwStartTickCount = GetTickCount(); - DWORD dwOldCheckPoint = ServiceStatus.dwCheckPoint; - DWORD dwMaxWait = 2000 * 60; // wait for 2 mins - - IncrementProgressBar(hProgDlg, DEFAULT_STEP); + /* 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 != Control) { - DWORD dwWaitTime = ServiceStatus.dwWaitHint / 10; + dwOldCheckPoint = ServiceStatus.dwCheckPoint; + dwWaitTime = ServiceStatus.dwWaitHint / 10; - if (!QueryServiceStatusEx(hSc, + /* 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) { - /* The service is making progress, increment the progress bar */ - IncrementProgressBar(hProgDlg, DEFAULT_STEP); + /* 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) { - /* give up */ + /* We have, give up */ break; } } - if(dwWaitTime < 200) + /* 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 == Control) + { + bRet = TRUE; + } } - CloseServiceHandle(hSc); + CloseServiceHandle(hService); } CloseServiceHandle(hSCManager); } - if (ServiceStatus.dwCurrentState == Control) + 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) { - CompleteProgressBar(hProgDlg); - Sleep(500); - bRet = TRUE; - } - else - { - if (bDispErr) - GetError(); - else - DisplayString(_T("The service failed to start")); + /* 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 DoPause(PMAIN_WND_INFO Info) +BOOL +DoResume(PMAIN_WND_INFO Info) { - BOOL ret = FALSE; - HWND hProgDlg; + HWND hProgress; + BOOL bRet = FALSE; - hProgDlg = CreateProgressDialog(Info->hMainWnd, - IDS_PROGRESS_INFO_PAUSE); - if (hProgDlg) + /* Create a progress window to track the progress of the resuming service */ + hProgress = CreateProgressDialog(Info->hMainWnd, + IDS_PROGRESS_INFO_RESUME); + if (hProgress) { - InitializeProgressDialog(hProgDlg, Info->pCurrentService->lpServiceName); + /* Set the service name and reset the progress bag */ + InitializeProgressDialog(hProgress, Info->pCurrentService->lpServiceName); - ret = Control(Info, - hProgDlg, - SERVICE_CONTROL_PAUSE); + /* Resume the requested service */ + bRet = DoControl(Info, hProgress, SERVICE_CONTROL_CONTINUE); - DestroyWindow(hProgDlg); + /* Complete and destroy the progress bar */ + DestroyProgressDialog(hProgress, bRet); } - return ret; -} - - -BOOL DoResume(PMAIN_WND_INFO Info) -{ - BOOL ret = FALSE; - HWND hProgDlg; - - hProgDlg = CreateProgressDialog(Info->hMainWnd, - IDS_PROGRESS_INFO_RESUME); - if (hProgDlg) - { - InitializeProgressDialog(hProgDlg, Info->pCurrentService->lpServiceName); - - ret = Control(Info, - hProgDlg, - SERVICE_CONTROL_CONTINUE); - - DestroyWindow(hProgDlg); - } - - return ret; + return bRet; } diff --git a/reactos/base/applications/mscutils/servman/precomp.h b/reactos/base/applications/mscutils/servman/precomp.h index 3948aa6d20b..9b829ad78df 100644 --- a/reactos/base/applications/mscutils/servman/precomp.h +++ b/reactos/base/applications/mscutils/servman/precomp.h @@ -90,7 +90,7 @@ typedef struct _STOP_INFO } STOP_INFO, *PSTOP_INFO; /* control */ -BOOL Control(PMAIN_WND_INFO Info, HWND hProgDlg, DWORD Control); +BOOL Control(PMAIN_WND_INFO Info, HWND hProgress, DWORD Control); BOOL DoStop(PMAIN_WND_INFO Info); BOOL DoPause(PMAIN_WND_INFO Info); BOOL DoResume(PMAIN_WND_INFO Info); @@ -98,10 +98,10 @@ BOOL DoResume(PMAIN_WND_INFO Info); /* progress.c */ #define DEFAULT_STEP 0 HWND CreateProgressDialog(HWND hParent, UINT LabelId); -BOOL DestroyProgressDialog(HWND hProgDlg, BOOL bComplete); -VOID InitializeProgressDialog(HWND hProgDlg, LPWSTR lpServiceName); -VOID IncrementProgressBar(HWND hProgDlg, UINT NewPos); -VOID CompleteProgressBar(HWND hProgDlg); +BOOL DestroyProgressDialog(HWND hProgress, BOOL bComplete); +VOID InitializeProgressDialog(HWND hProgress, LPWSTR lpServiceName); +VOID IncrementProgressBar(HWND hProgress, UINT NewPos); +VOID CompleteProgressBar(HWND hProgress); /* query.c */ ENUM_SERVICE_STATUS_PROCESS* GetSelectedService(PMAIN_WND_INFO Info); diff --git a/reactos/base/applications/mscutils/servman/start.c b/reactos/base/applications/mscutils/servman/start.c index b1522b009df..986437e0820 100644 --- a/reactos/base/applications/mscutils/servman/start.c +++ b/reactos/base/applications/mscutils/servman/start.c @@ -39,6 +39,7 @@ DoStartService(PMAIN_WND_INFO Info, IncrementProgressBar(hProgress, DEFAULT_STEP); } + /* Start the service */ bRet = StartService(hService, 0, NULL); @@ -85,6 +86,7 @@ DoStartService(PMAIN_WND_INFO Info, /* It is, get the latest tickcount to reset the max wait time */ dwStartTickCount = GetTickCount(); dwOldCheckPoint = ServiceStatus.dwCheckPoint; + IncrementProgressBar(hProgress, DEFAULT_STEP); } else { diff --git a/reactos/base/applications/mscutils/servman/stop.c b/reactos/base/applications/mscutils/servman/stop.c index 327abcbb659..da36ac536e1 100644 --- a/reactos/base/applications/mscutils/servman/stop.c +++ b/reactos/base/applications/mscutils/servman/stop.c @@ -197,6 +197,10 @@ DoStop(PMAIN_WND_INFO pInfo) /* Don't stop the main service if the user selected not to */ bStopMainService = FALSE; } + + HeapFree(GetProcessHeap(), + 0, + lpServiceList); } /* If the service has no running dependents, then we stop it here */