mirror of
https://github.com/reactos/reactos.git
synced 2025-01-11 08:38:17 +00:00
c424146e2c
svn path=/branches/cmake-bringup/; revision=48236
227 lines
6.9 KiB
C
227 lines
6.9 KiB
C
/*
|
|
* PROJECT: ReactOS Services
|
|
* 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>
|
|
*
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
static BOOL
|
|
StopService(PMAIN_WND_INFO pInfo,
|
|
LPWSTR lpServiceName,
|
|
HWND hProgress OPTIONAL)
|
|
{
|
|
SC_HANDLE hSCManager;
|
|
SC_HANDLE hService;
|
|
SERVICE_STATUS_PROCESS ServiceStatus;
|
|
DWORD dwBytesNeeded;
|
|
DWORD dwStartTime;
|
|
DWORD dwTimeout;
|
|
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);
|
|
}
|
|
|
|
CloseServiceHandle(hSCManager);
|
|
}
|
|
|
|
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)
|
|
{
|
|
/* 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++;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
BOOL
|
|
DoStop(PMAIN_WND_INFO pInfo)
|
|
{
|
|
HWND hProgress;
|
|
LPWSTR lpServiceList;
|
|
BOOL bRet = FALSE;
|
|
BOOL bStopMainService = TRUE;
|
|
|
|
if (pInfo)
|
|
{
|
|
/* Does the service have any dependent services which need stopping first */
|
|
lpServiceList = GetListOfServicesToStop(pInfo->pCurrentService->lpServiceName);
|
|
if (lpServiceList)
|
|
{
|
|
/* 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);
|
|
|
|
/* Now stop the requested one */
|
|
bRet = StopService(pInfo,
|
|
pInfo->pCurrentService->lpServiceName,
|
|
hProgress);
|
|
|
|
/* We've already stopped the main service, don't try to stop it again */
|
|
bStopMainService = FALSE;
|
|
|
|
if (hProgress)
|
|
{
|
|
/* Complete and destroy the progress bar */
|
|
DestroyProgressDialog(hProgress, TRUE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* 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 */
|
|
if (bStopMainService)
|
|
{
|
|
/* 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);
|
|
}
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|