BOOL CNTScmService::EnumDependents(DWORD dwServiceState, void* pUserData, ENUM_SERVICES_PROC lpEnumServicesFunc) const { //Validate our parameters ATLASSUME(m_hService != NULL); DWORD dwBytesNeeded; DWORD dwServices; BOOL bSuccess = EnumDependentServices(m_hService, dwServiceState, NULL, 0, &dwBytesNeeded, &dwServices); DWORD dwLastError = GetLastError(); if (!bSuccess && (dwLastError == ERROR_MORE_DATA) || (dwLastError == ERROR_INSUFFICIENT_BUFFER)) //Note we use ERROR_INSUFFICIENT_BUFFER here even though it is not documented as a legal return value from EnumDependentServices here { //Allocate some memory for the API ATL::CHeapPtr<ENUM_SERVICE_STATUS> lpServices; if (!lpServices.AllocateBytes(dwBytesNeeded)) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; } DWORD dwSize; bSuccess = EnumDependentServices(m_hService, dwServiceState, lpServices.m_pData, dwBytesNeeded, &dwSize, &dwServices); if (bSuccess) { BOOL bContinue = TRUE; for (DWORD i=0; i<dwServices && bContinue; i++) bContinue = lpEnumServicesFunc(pUserData, lpServices[i]); } } return bSuccess; }
LPENUM_SERVICE_STATUS EsEnumDependentServices( __in SC_HANDLE ServiceHandle, __in_opt ULONG State, __out PULONG Count ) { LOGICAL result; PVOID buffer; ULONG bufferSize; ULONG returnLength; ULONG servicesReturned; if (!State) State = SERVICE_STATE_ALL; bufferSize = 0x800; buffer = PhAllocate(bufferSize); if (!(result = EnumDependentServices( ServiceHandle, State, buffer, bufferSize, &returnLength, &servicesReturned ))) { if (GetLastError() == ERROR_MORE_DATA) { PhFree(buffer); bufferSize = returnLength; buffer = PhAllocate(bufferSize); result = EnumDependentServices( ServiceHandle, State, buffer, bufferSize, &returnLength, &servicesReturned ); } if (!result) { PhFree(buffer); return NULL; } } *Count = servicesReturned; return buffer; }
void CUtils::DealWithDependentServices(const char *szServiceName, const unsigned int iRequest) { DWORD dwBytes = 0; DWORD dwNumServices = 0; DWORD dwResumeHandle = 0; ENUM_SERVICE_STATUS status[100]; // service may have dependent services so stop them first SC_HANDLE hService = OpenService(hSCM, szServiceName, SERVICE_ENUMERATE_DEPENDENTS); if (hService) { if (EnumDependentServices(hService, SERVICE_ACTIVE, (ENUM_SERVICE_STATUS *)status, // returned info 100 * sizeof(ENUM_SERVICE_STATUS), // length of buffer &dwBytes, // returned length &dwNumServices)) // number services returned { for (DWORD i=0;i<dwNumServices;i++) { // recurse until we stop the last dependant ServiceRequest(status[i].lpServiceName, iRequest); } } CloseServiceHandle(hService); // if there were dependents, allow some time register service stops if (dwNumServices) Sleep(2000); } else _GetWindowsError(); }
BOOL TV2_HasDependantServices(LPWSTR lpServiceName) { HANDLE hSCManager; HANDLE hService; DWORD dwBytesNeeded, dwCount; BOOL bRet = FALSE; hSCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (hSCManager) { hService = OpenServiceW(hSCManager, lpServiceName, SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS); if (hService) { /* Does this have any dependencies? */ if (!EnumDependentServices(hService, SERVICE_STATE_ALL, NULL, 0, &dwBytesNeeded, &dwCount)) { if (GetLastError() == ERROR_MORE_DATA) { /* It does, return TRUE */ bRet = TRUE; } } CloseServiceHandle(hService); } CloseServiceHandle(hSCManager); } return bRet; }
int MAIN( int argc, WINCHAR *argv[] ) { SC_HANDLE hSCM, hService; DWORD needed, returned; LPENUM_SERVICE_STATUS pServices = NULL; DWORD i; if ( argc != 3 ) { printf(TEXT("Usage: %s <server> <service>\n"), argv[0]); exit( 1 ); } printf(TEXT("Opening the Service Control Manager on %s..."), (LPTSTR)argv[1]); if ( !(hSCM = OpenSCManager( (LPTSTR)argv[1], NULL, SC_MANAGER_ALL_ACCESS )) ) { printf(TEXT("failed.\n")); PrintLastError(); exit(1); } printf(TEXT("ok\n")); printf(TEXT("Opening service \"%s\"..."), (LPTSTR)argv[2]); if ( !(hService = OpenService( hSCM, (LPTSTR)argv[2], SERVICE_ALL_ACCESS )) ) { printf(TEXT("failed.\n")); PrintLastError(); CloseServiceHandle( hSCM ); exit(1); } printf(TEXT("ok\n")); printf(TEXT("Enumerating dependent services....")); needed = returned = 0; if ( !EnumDependentServices( hService, SERVICE_ACTIVE, NULL, 0, &needed, &returned ) ) { DWORD status; DWORD bufsize; status = GetLastError(); if ( status != ERROR_MORE_DATA ) { printf(TEXT("failed.\n")); printf(TEXT("error == %d\n"), status); CloseServiceHandle( hSCM ); exit(1); } pServices = (LPENUM_SERVICE_STATUS)malloc(needed); bufsize = needed; if ( !EnumDependentServices( hService, SERVICE_ACTIVE, pServices, bufsize, &needed, &returned ) ) { PrintLastError(); CloseServiceHandle( hSCM ); exit(1); } } printf(TEXT("ok\n")); if ( returned == 0 ) printf(TEXT("**no dependent services**\n")); for (i=0; i<returned; i++) { printf(TEXT("%s (%s)\n"), pServices[i].lpDisplayName, pServices[i].lpServiceName ); printf(TEXT("\ttype = 0x%x\n"), pServices[i].ServiceStatus.dwServiceType ); printf(TEXT("\tstate = 0x%x\n"), pServices[i].ServiceStatus.dwCurrentState ); printf(TEXT("\tcontrols accepted = 0x%x\n"), pServices[i].ServiceStatus.dwControlsAccepted ); printf(TEXT("\twin32 exit code = 0x%x\n"), pServices[i].ServiceStatus.dwWin32ExitCode ); printf(TEXT("\tsvc exit code = 0x%x\n"), pServices[i].ServiceStatus.dwServiceSpecificExitCode ); printf(TEXT("\tcheck point = 0x%x\n"), pServices[i].ServiceStatus.dwCheckPoint ); printf(TEXT("\twait hont = 0x%x\n"), pServices[i].ServiceStatus.dwWaitHint ); } free( pServices ); printf(TEXT("Closing Service handles...")); CloseServiceHandle( hSCM ); CloseServiceHandle( hService ); printf(TEXT("ok\n")); exit(0); }
/* * DriverSetInfo * * Purpose: * * Sets registry info for selected driver object * */ VOID DriverSetInfo( PROP_OBJECT_INFO *Context, HWND hwndDlg ) { BOOL cond = FALSE, bResult, fGroup, bRet; INT nEndOfList, nEnd, nStart; DWORD i, bytesNeeded, dwServices, dwGroups; LPWSTR lpType; SC_HANDLE SchSCManager; SC_HANDLE schService; LPENUM_SERVICE_STATUS lpDependencies = NULL; LPQUERY_SERVICE_CONFIG psci; LPSERVICE_DESCRIPTION psd; SERVICE_STATUS_PROCESS ssp; ENUM_SERVICE_STATUS ess; WCHAR szBuffer[MAX_PATH + 1]; if (Context == NULL) { ShowWindow(GetDlgItem(hwndDlg, IDC_QUERYFAIL), TRUE); return; } __try { ShowWindow(GetDlgItem(hwndDlg, IDC_QUERYFAIL), FALSE); psci = NULL; SchSCManager = NULL; bResult = FALSE; do { SchSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE); if (SchSCManager == NULL) { break; } schService = OpenService(SchSCManager, Context->lpObjectName, SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS); if (schService == NULL) { break; } bytesNeeded = 0; bResult = QueryServiceConfig(schService, NULL, 0, &bytesNeeded); if ((bResult == FALSE) && (bytesNeeded == 0)) { break; } psci = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bytesNeeded); if (psci == NULL) { break; } //disable comboboxes EnableWindow(GetDlgItem(hwndDlg, IDC_SERVICE_DEPENDENTSERVICES), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_SERVICE_DEPENDSONSERVICE), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_SERVICE_DEPENDSONGROUP), FALSE); bResult = QueryServiceConfig(schService, psci, bytesNeeded, &bytesNeeded); if (bResult) { //set key name (identical to object name) SetDlgItemText(hwndDlg, IDC_SERVICE_KEYNAME, Context->lpObjectName); //set image path info SetDlgItemText(hwndDlg, IDC_SERVICE_IMAGEPATH, psci->lpBinaryPathName); //set display name SetDlgItemText(hwndDlg, IDC_SERVICE_DISPLAYNAME, psci->lpDisplayName); //set load order group SetDlgItemText(hwndDlg, IDC_SERVICE_LOADORDERGROUP, psci->lpLoadOrderGroup); //Service Type lpType = T_UnknownType; switch (psci->dwServiceType) { case SERVICE_KERNEL_DRIVER: lpType = L"Kernel-Mode Driver"; break; case SERVICE_FILE_SYSTEM_DRIVER: lpType = L"File System Driver"; break; case SERVICE_ADAPTER: lpType = L"Adapter"; break; case SERVICE_RECOGNIZER_DRIVER: lpType = L"File System Recognizer"; break; case SERVICE_WIN32_OWN_PROCESS: lpType = L"Own Process"; break; case SERVICE_WIN32_SHARE_PROCESS: lpType = L"Share Process"; break; case (SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS): lpType = L"Own Process (Interactive)"; SetDlgItemText(hwndDlg, ID_SERVICE_NAME, psci->lpServiceStartName); break; case (SERVICE_WIN32_SHARE_PROCESS | SERVICE_INTERACTIVE_PROCESS): lpType = L"Share Process (Interactive)"; SetDlgItemText(hwndDlg, ID_SERVICE_NAME, psci->lpServiceStartName); break; } SetDlgItemText(hwndDlg, ID_SERVICE_TYPE, lpType); //Start Type lpType = T_UnknownType; switch (psci->dwStartType) { case SERVICE_AUTO_START: lpType = L"Auto"; break; case SERVICE_BOOT_START: lpType = L"Boot"; break; case SERVICE_DEMAND_START: lpType = L"On Demand"; break; case SERVICE_DISABLED: lpType = L"Disabled"; break; case SERVICE_SYSTEM_START: lpType = L"System"; break; } SetDlgItemText(hwndDlg, ID_SERVICE_START, lpType); //Error Control lpType = T_Unknown; switch (psci->dwErrorControl) { case SERVICE_ERROR_CRITICAL: lpType = L"Critical"; break; case SERVICE_ERROR_IGNORE: lpType = L"Ignore"; break; case SERVICE_ERROR_NORMAL: lpType = L"Normal"; break; case SERVICE_ERROR_SEVERE: lpType = L"Severe"; break; } SetDlgItemText(hwndDlg, ID_SERVICE_ERROR, lpType); //dwTagId if (psci->dwTagId) { RtlSecureZeroMemory(szBuffer, sizeof(szBuffer)); ultostr(psci->dwTagId, szBuffer); SetDlgItemText(hwndDlg, ID_SERVICE_TAG, szBuffer); } else { //not assigned tag SetDlgItemText(hwndDlg, ID_SERVICE_TAG, L""); } //State RtlSecureZeroMemory(&ssp, sizeof(ssp)); if (QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(ssp), &bytesNeeded)) { lpType = T_Unknown; switch (ssp.dwCurrentState) { case SERVICE_STOPPED: lpType = L"Stopped"; break; case SERVICE_START_PENDING: lpType = L"Start Pending"; break; case SERVICE_STOP_PENDING: lpType = L"Stop Pending"; break; case SERVICE_RUNNING: lpType = L"Running"; break; case SERVICE_CONTINUE_PENDING: lpType = L"Continue Pending"; break; case SERVICE_PAUSE_PENDING: lpType = L"Pause Pending"; break; case SERVICE_PAUSED: lpType = L"Paused"; break; } SetDlgItemText(hwndDlg, ID_SERVICE_CURRENT, lpType); } else { SetDlgItemText(hwndDlg, ID_SERVICE_CURRENT, T_CannotQuery); } //Service Description bRet = FALSE; SetDlgItemText(hwndDlg, ID_SERVICE_DESCRIPTION, L""); bytesNeeded = 0x1000; psd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bytesNeeded); if (psd) { bRet = QueryServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, (LPBYTE)psd, bytesNeeded, &bytesNeeded); if ((bRet == FALSE) && (bytesNeeded != 0)) { HeapFree(GetProcessHeap(), 0, psd); psd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bytesNeeded); } if (psd) { //set description or hide window bRet = QueryServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, (LPBYTE)psd, bytesNeeded, &bytesNeeded); if (bRet) { SetDlgItemText(hwndDlg, IDC_SERVICE_DESCRIPTION, psd->lpDescription); } HeapFree(GetProcessHeap(), 0, psd); } } if (bRet == FALSE) { //not enough memory, hide description window ShowWindow(GetDlgItem(hwndDlg, IDC_SERVICE_DESCRIPTION), SW_HIDE); } //Service Dependencies if (psci->lpDependencies) { //first list DependsOnService, DependsOnGroup nEndOfList = 0; nEnd = 0; nStart = 0; dwGroups = 0; dwServices = 0; //calc total number of symbols while ((psci->lpDependencies[nEndOfList] != L'\0') || (psci->lpDependencies[nEndOfList + 1] != L'\0')) nEndOfList++; if (nEndOfList > 0) { SendDlgItemMessage(hwndDlg, IDC_SERVICE_DEPENDSONGROUP, CB_RESETCONTENT, (WPARAM)0, (LPARAM)0); SendDlgItemMessage(hwndDlg, IDC_SERVICE_DEPENDSONSERVICE, CB_RESETCONTENT, (WPARAM)0, (LPARAM)0); //iterate through MULTI_SZ string do { while (psci->lpDependencies[nEnd] != L'\0') { nEnd++; } RtlSecureZeroMemory(&szBuffer, sizeof(szBuffer)); //maximum bytes that can be copied is sizeof(szBuffer) _strncpy(szBuffer, sizeof(szBuffer), &psci->lpDependencies[nStart], nEnd); //check if dependency is a group (has "+" before name) fGroup = (szBuffer[0] == SC_GROUP_IDENTIFIER); if (fGroup) { SendDlgItemMessage(hwndDlg, IDC_SERVICE_DEPENDSONGROUP, CB_ADDSTRING, (WPARAM)0, (LPARAM)&szBuffer[1]); dwGroups++; } else { SendDlgItemMessage(hwndDlg, IDC_SERVICE_DEPENDSONSERVICE, CB_ADDSTRING, (WPARAM)0, (LPARAM)&szBuffer); dwServices++; } nEnd++; nStart = nEnd; } while (nEnd < nEndOfList); //group present, enable combobox if (dwGroups > 0) { EnableWindow(GetDlgItem(hwndDlg, IDC_SERVICE_DEPENDSONGROUP), TRUE); SendDlgItemMessage(hwndDlg, IDC_SERVICE_DEPENDSONGROUP, CB_SETCURSEL, (WPARAM)0, (LPARAM)0); } //service present, enable combobox if (dwServices > 0) { EnableWindow(GetDlgItem(hwndDlg, IDC_SERVICE_DEPENDSONSERVICE), TRUE); SendDlgItemMessage(hwndDlg, IDC_SERVICE_DEPENDSONSERVICE, CB_SETCURSEL, (WPARAM)0, (LPARAM)0); } } //if (nEndOfList > 0) //second list services that depends on this service SendDlgItemMessage(hwndDlg, IDC_SERVICE_DEPENDENTSERVICES, CB_RESETCONTENT, (WPARAM)0, (LPARAM)0); dwServices = 0; bytesNeeded = 1024; bRet = FALSE; //avoid SCM unexpected behaviour by using preallocated buffer lpDependencies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bytesNeeded); if (lpDependencies) { bRet = EnumDependentServices(schService, SERVICE_STATE_ALL, lpDependencies, bytesNeeded, &bytesNeeded, &dwServices); if (bRet && (GetLastError() == ERROR_MORE_DATA)) { //more memory needed for enum HeapFree(GetProcessHeap(), 0, lpDependencies); dwServices = 0; lpDependencies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bytesNeeded); if (lpDependencies) { bRet = EnumDependentServices(schService, SERVICE_STATE_ALL, lpDependencies, bytesNeeded, &bytesNeeded, &dwServices); } } //list dependents if (bRet && dwServices) { for (i = 0; i < dwServices; i++) { ess = *(lpDependencies + i); SendDlgItemMessage(hwndDlg, IDC_SERVICE_DEPENDENTSERVICES, CB_ADDSTRING, (WPARAM)0, (LPARAM)ess.lpServiceName); } //enable combobox and set current selection to the first item EnableWindow(GetDlgItem(hwndDlg, IDC_SERVICE_DEPENDENTSERVICES), TRUE); SendDlgItemMessage(hwndDlg, IDC_SERVICE_DEPENDENTSERVICES, CB_SETCURSEL, (WPARAM)0, (LPARAM)0); } HeapFree(GetProcessHeap(), 0, lpDependencies); } } //if (psi->lpDependencies) } //bResult != FALSE CloseServiceHandle(schService); } while (cond); if (psci != NULL) { HeapFree(GetProcessHeap(), 0, psci); } if (SchSCManager) { CloseServiceHandle(SchSCManager); } if (bResult == FALSE) { EnumChildWindows(hwndDlg, DriverShowChildWindows, SW_HIDE); ShowWindow(GetDlgItem(hwndDlg, IDC_QUERYFAIL), SW_SHOW); } else { SetFocus(GetDlgItem(hwndDlg, ID_SERVICE_JUMPTOKEY)); } } __except (exceptFilter(GetExceptionCode(), GetExceptionInformation())) { EnumChildWindows(hwndDlg, DriverShowChildWindows, SW_HIDE); ShowWindow(GetDlgItem(hwndDlg, IDC_QUERYFAIL), SW_SHOW); return; } }
BOOL EnumDepend(LPCTSTR ServiceName) { SC_HANDLE hManager = NULL; SC_HANDLE hService = NULL; BOOL bResult = TRUE; DWORD BufferSize = 0; DWORD EntriesRead = 0; LPENUM_SERVICE_STATUS pBuffer = NULL; DWORD i; hManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (hManager == NULL) { _tprintf(_T("[SC] OpenSCManager FAILED %lu:\n\n"), GetLastError()); bResult = FALSE; goto done; } hService = OpenService(hManager, ServiceName, SERVICE_ENUMERATE_DEPENDENTS); if (hService == NULL) { _tprintf(_T("[SC] OpenService FAILED %lu:\n\n"), GetLastError()); bResult = FALSE; goto done; } if (!EnumDependentServices(hService, SERVICE_STATE_ALL, NULL, 0, &BufferSize, &EntriesRead)) { if (BufferSize == 0) { _tprintf(_T("[SC] EnumDependentServices FAILED %lu:\n\n"), GetLastError()); bResult = FALSE; goto done; } } pBuffer = HeapAlloc(GetProcessHeap(), 0, BufferSize); if (pBuffer == NULL) { SetLastError(ERROR_OUTOFMEMORY); _tprintf(_T("[SC] HeapAlloc FAILED %lu:\n\n"), GetLastError()); bResult = FALSE; goto done; } if (!EnumDependentServices(hService, SERVICE_STATE_ALL, pBuffer, BufferSize, &BufferSize, &EntriesRead)) { _tprintf(_T("[SC] EnumDependentServices FAILED %lu:\n\n"), GetLastError()); bResult = FALSE; goto done; } _tprintf(_T("Enum: entriesRead = %lu\n"), EntriesRead); for (i = 0; i < EntriesRead; i++) { _tprintf(_T("\n")); _tprintf(_T("SERVICE_NAME: %s\n"), pBuffer[i].lpServiceName); _tprintf(_T("DISPLAY_NAME: %s\n"), pBuffer[i].lpDisplayName); PrintServiceStatus(&pBuffer[i].ServiceStatus); } done: if (bResult == FALSE) ReportLastError(); if (pBuffer != NULL) HeapFree(GetProcessHeap(), 0, pBuffer); if (hService) CloseServiceHandle(hService); if (hManager) CloseServiceHandle(hManager); return bResult; }
BOOL MainFrame::StopDependentServices(SC_HANDLE schSCManager, SC_HANDLE schService) { DWORD i; DWORD dwBytesNeeded; DWORD dwCount; LPENUM_SERVICE_STATUS lpDependencies = NULL; ENUM_SERVICE_STATUS ess; SC_HANDLE hDepService; SERVICE_STATUS_PROCESS ssp; DWORD dwStartTime = GetTickCount(); DWORD dwTimeout = 30000; // 30-second time-out // Pass a zero-length buffer to get the required buffer size. if ( EnumDependentServices( schService, SERVICE_ACTIVE, lpDependencies, 0, &dwBytesNeeded, &dwCount ) ) { // If the Enum call succeeds, then there are no dependent // services, so do nothing. return TRUE; } else { if ( GetLastError() != ERROR_MORE_DATA ) return FALSE; // Unexpected error // Allocate a buffer for the dependencies. lpDependencies = (LPENUM_SERVICE_STATUS) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded ); if ( !lpDependencies ) return FALSE; __try { // Enumerate the dependencies. if ( !EnumDependentServices( schService, SERVICE_ACTIVE, lpDependencies, dwBytesNeeded, &dwBytesNeeded, &dwCount ) ) return FALSE; for ( i = 0; i < dwCount; i++ ) { ess = *(lpDependencies + i); // Open the service. hDepService = OpenService( schSCManager, ess.lpServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS ); if ( !hDepService ) return FALSE; __try { // Send a stop code. if ( !ControlService( hDepService, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS) &ssp ) ) return FALSE; // Wait for the service to stop. while ( ssp.dwCurrentState != SERVICE_STOPPED ) { Sleep( ssp.dwWaitHint ); if ( !QueryServiceStatusEx( hDepService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded ) ) return FALSE; if ( ssp.dwCurrentState == SERVICE_STOPPED ) break; if ( GetTickCount() - dwStartTime > dwTimeout ) return FALSE; } } __finally { // Always release the service handle. CloseServiceHandle( hDepService ); } } } __finally { // Always free the enumeration buffer. HeapFree( GetProcessHeap(), 0, lpDependencies ); } } return TRUE; }
BOOL StopDependentServices(SC_HANDLE hSCManager, SC_HANDLE hService) { LPENUM_SERVICE_STATUS lpDependencies = NULL; ENUM_SERVICE_STATUS ess; SC_HANDLE hDepService; SERVICE_STATUS_PROCESS ssp; DWORD i, dwBytesNeeded, dwCount; DWORD dwStartTime = GetTickCount(); DWORD dwTimeout = 30000; // 30 секундна пауза // Пускане на буфер с нулева дължина, за да се получи желания размер на буфера. if (EnumDependentServices(hService, SERVICE_ACTIVE, lpDependencies, 0, &dwBytesNeeded, &dwCount)) // Ако извикването на Enum-а е успешно, тогава няма зависими // сервиси, така че не се прави нищо. return TRUE; if (GetLastError() != ERROR_MORE_DATA) return FALSE; // Неочаквана грешка // Алокиране на буфер за зависимостите. lpDependencies = (LPENUM_SERVICE_STATUS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded); if (!lpDependencies) return FALSE; __try { // Избройват се зависимостите. if (!EnumDependentServices(hService, SERVICE_ACTIVE, lpDependencies, dwBytesNeeded, &dwBytesNeeded, &dwCount)) return FALSE; for (i=0; i<dwCount; i++) { ess = *(lpDependencies + i); // Отваря се сервиса hDepService = OpenService(hSCManager, ess.lpServiceName, SERVICE_STOP|SERVICE_QUERY_STATUS); if (!hDepService) return FALSE; __try { // Изпраща се стоп код. if (!ControlService(hDepService, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssp)) return FALSE; // Изчаква се сервиса да спре. while (ssp.dwCurrentState != SERVICE_STOPPED) { Sleep(ssp.dwWaitHint); if (!QueryServiceStatusEx(hDepService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) return FALSE; if (ssp.dwCurrentState == SERVICE_STOPPED) break; if (GetTickCount() - dwStartTime > dwTimeout) return FALSE; } } __finally { // Винаги се изпуска дръжката на сервиса. CloseServiceHandle(hDepService); } } } __finally { // Винаги се освобождава изброения буфер. HeapFree(GetProcessHeap(), 0, lpDependencies); } return TRUE; }
/* This function attempts to stop a service. It allows the caller to specify whether dependent services should also be stopped. It also accepts a timeout value, to prevent a scenario in which a service shutdown hangs, then the application stopping the service hangs Parameters: pszServiceName - service name string fStopDependencies - Indicates whether to stop dependent services. dwTimeout - maximum time (in milliseconds) to wait If the operation is successful, returns true. Otherwise, returns false. */ bool ServiceManager_t::StopService(_TCHAR * pszServiceName, bool fStopDependencies, DWORD dwTimeout) { SC_HANDLE schService; SERVICE_STATUS_PROCESS ssp; SERVICE_STATUS ssDummy; DWORD dwStartTime = GetTickCount(); DWORD dwBytesNeeded; if (!_QueryServiceStatusEx) { g_Log.Write(_T("Dynamic function QueryServiceStatusEx not initialized.")); return false; } schService = OpenService(schSCManager, pszServiceName, SERVICE_ALL_ACCESS); if (schService == NULL) { g_Log.Write(_T("Could not open service '%s'."), pszServiceName); return false; } // Make sure the service is not already stopped: if (!_QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) { g_Log.Write(_T("Could not tell if service '%s' already stopped - error %d."), pszServiceName, GetLastError()); return false; } if (ssp.dwCurrentState == SERVICE_STOPPED) return true; // If a stop is pending, just wait for it: while (ssp.dwCurrentState == SERVICE_STOP_PENDING) { Sleep(ssp.dwWaitHint); if (!_QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) { g_Log.Write(_T("Could not tell if service '%s' already stopped - error %d."), pszServiceName, GetLastError()); return false; } if (ssp.dwCurrentState == SERVICE_STOPPED) return true; if (GetTickCount() - dwStartTime > dwTimeout) { g_Log.Write(_T("Timed out waiting for service '%s' to stop."), pszServiceName); return false; } } // If the service is running, dependencies must be stopped first: if (fStopDependencies) { DWORD i; DWORD dwBytesNeeded; DWORD dwCount; LPENUM_SERVICE_STATUS lpDependencies = NULL; ENUM_SERVICE_STATUS ess; SC_HANDLE hDepService; // Pass a zero-length buffer to get the required buffer size: if (EnumDependentServices(schService, SERVICE_ACTIVE, lpDependencies, 0, &dwBytesNeeded, &dwCount)) { // If the Enum call succeeds, then there are no dependent services so do nothing } else { if (GetLastError() != ERROR_MORE_DATA) { g_Log.Write(_T("Unexpected error %d while trying to obtain buffer size needed to enumerate dependent services of '%s'."), GetLastError(), pszServiceName); return false; // Unexpected error. } // Allocate a buffer for the dependencies: lpDependencies = (LPENUM_SERVICE_STATUS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded); if (!lpDependencies) { g_Log.Write(_T("Unexpected error while trying to create buffer needed to enumerate dependent services of '%s'."), GetLastError(), pszServiceName); return false; // Unexpected error. } __try { // Enumerate the dependencies: if (!EnumDependentServices(schService, SERVICE_ACTIVE, lpDependencies, dwBytesNeeded, &dwBytesNeeded, &dwCount)) { g_Log.Write(_T("Unexpected error %d while trying to enumerate dependent services of '%s'."), GetLastError(), pszServiceName); return false; // Unexpected error. } for (i = 0; i < dwCount; i++) { ess = *(lpDependencies + i); // Open the service: hDepService = OpenService(schSCManager, ess.lpServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS); if (!hDepService) { g_Log.Write(_T("Unexpected error %d while trying to open dependent service '%s' of '%s'."), GetLastError(), ess.lpServiceName, pszServiceName); return false; // Unexpected error. } __try { // Send a stop code: if (!ControlService(hDepService, SERVICE_CONTROL_STOP, &ssDummy)) { g_Log.Write(_T("Unexpected error %d while trying to stop dependent service '%s' of '%s'."), GetLastError(), ess.lpServiceName, pszServiceName); return false; // Unexpected error. } // Wait for the service to stop: do { if (!_QueryServiceStatusEx(hDepService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) { g_Log.Write(_T("Unexpected error %d while trying to get status of dependent service '%s' of '%s'."), GetLastError(), ess.lpServiceName, pszServiceName); return false; // Unexpected error. } if (ssp.dwCurrentState == SERVICE_STOPPED) break; if (GetTickCount() - dwStartTime > dwTimeout) { g_Log.Write(_T("Timed out while trying to stop dependent service '%s' of '%s'."), ess.lpServiceName, pszServiceName); return false; } Sleep(ssp.dwWaitHint); } while (ssp.dwCurrentState != SERVICE_STOPPED); } __finally { // Always release the service handle: CloseServiceHandle(hDepService); } } // Next dependent service } __finally { // Always free the enumeration buffer: HeapFree(GetProcessHeap(), 0, lpDependencies); } } } // Send a stop code to the main service: if (!ControlService(schService, SERVICE_CONTROL_STOP, &ssDummy)) { g_Log.Write(_T("Unexpected error %d while trying to stop service '%s'."), GetLastError(), pszServiceName); return false; // Unexpected error. } // Wait for the service to stop: do { if (!_QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) { g_Log.Write(_T("Unexpected error %d while trying to get status of service '%s'."), GetLastError(), pszServiceName); return false; // Unexpected error. } if (ssp.dwCurrentState == SERVICE_STOPPED) break; if (GetTickCount() - dwStartTime > dwTimeout) { g_Log.Write(_T("Timed out while trying to stop service '%s'."), pszServiceName); return false; } Sleep(ssp.dwWaitHint); } while (ssp.dwCurrentState != SERVICE_STOPPED); // Return success: return true; }