* LICENSE: GPL - See COPYING in the top level directory
* FILE: base/applications/mscutils/servman/stop.c
* PURPOSE: Stops running a service
- * COPYRIGHT: Copyright 2006-2010 Ged Murphy <gedmurphy@reactos.org>
+ * COPYRIGHT: Copyright 2006-2015 Ged Murphy <gedmurphy@reactos.org>
*
*/
#include "precomp.h"
-static BOOL
-StopService(PMAIN_WND_INFO pInfo,
- LPWSTR lpServiceName,
- HWND hProgress OPTIONAL)
+#define MAX_WAIT_TIME 30000
+
+BOOL
+DoStopService(_In_z_ LPWSTR ServiceName,
+ _In_opt_ HANDLE hProgress)
{
SC_HANDLE hSCManager;
SC_HANDLE hService;
SERVICE_STATUS_PROCESS ServiceStatus;
- DWORD dwBytesNeeded;
- DWORD dwStartTime;
- DWORD dwTimeout;
+ DWORD BytesNeeded;
+ DWORD StartTime;
+ DWORD WaitTime;
+ DWORD Timeout;
BOOL bRet = FALSE;
- if (hProgress)
- {
- /* Set the service name and reset the progress bag */
- InitializeProgressDialog(hProgress, lpServiceName);
- }
-
- hSCManager = OpenSCManager(NULL,
- NULL,
- SC_MANAGER_CONNECT);
- if (hSCManager)
- {
- hService = OpenService(hSCManager,
- lpServiceName,
- SERVICE_STOP | SERVICE_QUERY_STATUS);
- if (hService)
- {
- if (hProgress)
- {
- /* Increment the progress bar */
- IncrementProgressBar(hProgress, DEFAULT_STEP);
- }
- /* Set the wait time to 30 secs */
- dwStartTime = GetTickCount();
- dwTimeout = 30000;
-
- /* Send the service the stop code */
- if (ControlService(hService,
- SERVICE_CONTROL_STOP,
- (LPSERVICE_STATUS)&ServiceStatus))
- {
- if (hProgress)
- {
- /* Increment the progress bar */
- IncrementProgressBar(hProgress, DEFAULT_STEP);
- }
-
- while (ServiceStatus.dwCurrentState != SERVICE_STOPPED)
- {
- /* Don't sleep for more than 3 seconds */
- if (ServiceStatus.dwWaitHint > 3000)
- ServiceStatus.dwWaitHint = 3000;
-
- Sleep(ServiceStatus.dwWaitHint);
-
- if (hProgress)
- {
- /* Increment the progress bar */
- IncrementProgressBar(hProgress, DEFAULT_STEP);
- }
-
- if (QueryServiceStatusEx(hService,
- SC_STATUS_PROCESS_INFO,
- (LPBYTE)&ServiceStatus,
- sizeof(SERVICE_STATUS_PROCESS),
- &dwBytesNeeded))
- {
- /* Have we exceeded our wait time? */
- if (GetTickCount() - dwStartTime > dwTimeout)
- {
- /* Yep, give up */
- break;
- }
- }
- }
-
- /* If the service is stopped, return TRUE */
- if (ServiceStatus.dwCurrentState == SERVICE_STOPPED)
- {
- bRet = TRUE;
- }
- }
-
- CloseServiceHandle(hService);
- }
+ hSCManager = OpenSCManagerW(NULL,
+ NULL,
+ SC_MANAGER_CONNECT);
+ if (!hSCManager) return FALSE;
+ hService = OpenServiceW(hSCManager,
+ ServiceName,
+ SERVICE_STOP | SERVICE_QUERY_STATUS);
+ if (!hService)
+ {
CloseServiceHandle(hSCManager);
+ return FALSE;
}
- return bRet;
-}
-
-static BOOL
-StopDependantServices(PMAIN_WND_INFO pInfo,
- LPWSTR lpServiceList,
- HWND hProgress OPTIONAL)
-{
- LPWSTR lpStr;
- BOOL bRet = FALSE;
-
- lpStr = lpServiceList;
-
- /* Loop through all the services in the list */
- while (TRUE)
+ if (hProgress)
{
- /* Break when we hit the double null */
- if (*lpStr == L'\0' && *(lpStr + 1) == L'\0')
- break;
-
- /* If this isn't our first time in the loop we'll
- have been left on a null char */
- if (*lpStr == L'\0')
- lpStr++;
-
- /* Stop the requested service */
- bRet = StopService(pInfo,
- lpStr,
- hProgress);
-
- /* Complete the progress bar if we succeeded */
- if (bRet)
- {
- CompleteProgressBar(hProgress);
- }
-
- /* Move onto the next string */
- while (*lpStr != L'\0')
- lpStr++;
+ /* Increment the progress bar */
+ IncrementProgressBar(hProgress, DEFAULT_STEP);
}
- return bRet;
-}
+ /* Set the start and max wait times */
+ StartTime = GetTickCount();
+ Timeout = MAX_WAIT_TIME;
-BOOL
-DoStop(PMAIN_WND_INFO pInfo)
-{
- HWND hProgress;
- LPWSTR lpServiceList;
- BOOL bRet = FALSE;
- BOOL bStopMainService = TRUE;
-
- if (pInfo)
+ /* Send the service the stop code */
+ if (ControlService(hService,
+ SERVICE_CONTROL_STOP,
+ (LPSERVICE_STATUS)&ServiceStatus))
{
- /* Does the service have any dependent services which need stopping first */
- lpServiceList = GetListOfServicesToStop(pInfo->pCurrentService->lpServiceName);
- if (lpServiceList)
+ if (hProgress)
{
- /* Tag the service list to the main wnd info */
- pInfo->pTag = (PVOID)lpServiceList;
-
- /* List them and ask the user if they want to stop them */
- if (DialogBoxParamW(hInstance,
- MAKEINTRESOURCEW(IDD_DLG_DEPEND_STOP),
- pInfo->hMainWnd,
- StopDependsDialogProc,
- (LPARAM)pInfo) == IDOK)
- {
- /* Create a progress window to track the progress of the stopping services */
- hProgress = CreateProgressDialog(pInfo->hMainWnd,
- IDS_PROGRESS_INFO_STOP);
-
- /* Stop all the dependant services */
- StopDependantServices(pInfo, lpServiceList, hProgress);
+ /* Increment the progress bar */
+ IncrementProgressBar(hProgress, DEFAULT_STEP);
+ }
- /* Now stop the requested one */
- bRet = StopService(pInfo,
- pInfo->pCurrentService->lpServiceName,
- hProgress);
+ while (ServiceStatus.dwCurrentState != SERVICE_STOPPED)
+ {
+ int i;
+ /* Fixup the wait time */
+ WaitTime = ServiceStatus.dwWaitHint / 10;
- /* We've already stopped the main service, don't try to stop it again */
- bStopMainService = FALSE;
+ if (WaitTime < 1000) WaitTime = 1000;
+ else if (WaitTime > 10000) WaitTime = 10000;
+ /* We don't wanna wait for up to 10 secs without incrementing */
+ for (i = WaitTime / 1000; i > 0; i--)
+ {
+ Sleep(1000);
if (hProgress)
{
- /* Complete and destroy the progress bar */
- DestroyProgressDialog(hProgress, TRUE);
+ /* Increment the progress bar */
+ IncrementProgressBar(hProgress, DEFAULT_STEP);
}
}
- else
+
+ if (QueryServiceStatusEx(hService,
+ SC_STATUS_PROCESS_INFO,
+ (LPBYTE)&ServiceStatus,
+ sizeof(SERVICE_STATUS_PROCESS),
+ &BytesNeeded))
{
- /* Don't stop the main service if the user selected not to */
- bStopMainService = FALSE;
+ /* Have we exceeded our wait time? */
+ if (GetTickCount() - StartTime > Timeout)
+ {
+ /* Yep, give up */
+ break;
+ }
}
-
- HeapFree(GetProcessHeap(),
- 0,
- lpServiceList);
}
- /* If the service has no running dependents, then we stop it here */
- if (bStopMainService)
+ /* If the service is stopped, return TRUE */
+ if (ServiceStatus.dwCurrentState == SERVICE_STOPPED)
{
- /* Create a progress window to track the progress of the stopping service */
- hProgress = CreateProgressDialog(pInfo->hMainWnd,
- IDS_PROGRESS_INFO_STOP);
-
- /* Stop the requested service */
- bRet = StopService(pInfo,
- pInfo->pCurrentService->lpServiceName,
- hProgress);
-
- if (hProgress)
- {
- /* Complete and destroy the progress bar */
- DestroyProgressDialog(hProgress, TRUE);
- }
+ bRet = TRUE;
}
}
+ CloseServiceHandle(hService);
+
+ CloseServiceHandle(hSCManager);
+
return bRet;
}