/* * 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 * */ #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; }