#include "ServiceUtils.h" // // Literally COPIED from https://learn.microsoft.com/en-us/windows/win32/services/stopping-a-service // Purpose: // Stops the service. // // Parameters: // None // // Return value: // None // BOOL __stdcall DoStopSvc(LPCWSTR szSvcName) { BOOL success = FALSE; SERVICE_STATUS_PROCESS ssp; DWORD dwStartTime = GetTickCount(); DWORD dwBytesNeeded; DWORD dwTimeout = 30000; // 30-second time-out DWORD dwWaitTime; // Get a handle to the SCM database. SC_HANDLE schSCManager = OpenSCManager( NULL, // local computer NULL, // ServicesActive database SC_MANAGER_ALL_ACCESS); // full access rights if (NULL == schSCManager) { printf("OpenSCManager failed (%d)\n", GetLastError()); return success; } // Get a handle to the service. SC_HANDLE schService = OpenServiceW( schSCManager, // SCM database szSvcName, // name of service SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS); if (schService == NULL) { printf("OpenService failed (%d)\n", GetLastError()); CloseServiceHandle(schSCManager); return success; } // Make sure the service is not already stopped. if (!QueryServiceStatusEx( schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) { printf("QueryServiceStatusEx failed (%d)\n", GetLastError()); goto stop_cleanup; } if (ssp.dwCurrentState == SERVICE_STOPPED) { printf("Service is already stopped.\n"); success = TRUE; goto stop_cleanup; } // If a stop is pending, wait for it. while (ssp.dwCurrentState == SERVICE_STOP_PENDING) { printf("Service stop pending...\n"); // Do not wait longer than the wait hint. A good interval is // one-tenth of the wait hint but not less than 1 second // and not more than 10 seconds. dwWaitTime = ssp.dwWaitHint / 10; if (dwWaitTime < 1000) dwWaitTime = 1000; else if (dwWaitTime > 10000) dwWaitTime = 10000; Sleep(dwWaitTime); if (!QueryServiceStatusEx( schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) { printf("QueryServiceStatusEx failed (%d)\n", GetLastError()); goto stop_cleanup; } if (ssp.dwCurrentState == SERVICE_STOPPED) { printf("Service stopped successfully.\n"); success = TRUE; goto stop_cleanup; } if (GetTickCount() - dwStartTime > dwTimeout) { printf("Service stop timed out.\n"); goto stop_cleanup; } } // If the service is running, dependencies must be stopped first. StopDependentServices(schSCManager, schService); // Send a stop code to the service. if (!ControlService( schService, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssp)) { printf("ControlService failed (%d)\n", GetLastError()); goto stop_cleanup; } // Wait for the service to stop. while (ssp.dwCurrentState != SERVICE_STOPPED) { Sleep(ssp.dwWaitHint); if (!QueryServiceStatusEx( schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) { printf("QueryServiceStatusEx failed (%d)\n", GetLastError()); goto stop_cleanup; } if (ssp.dwCurrentState == SERVICE_STOPPED) { success = TRUE; break; } if (GetTickCount() - dwStartTime > dwTimeout) { printf("Wait timed out\n"); goto stop_cleanup; } } printf("Service stopped successfully\n"); success = TRUE; stop_cleanup: CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return success; } BOOL __stdcall 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; } // // Purpose: // Starts the service if possible. // // Parameters: // None // // Return value: // None // BOOL __stdcall DoStartSvc(LPCWSTR szSvcName) { BOOL success = FALSE; SERVICE_STATUS_PROCESS ssStatus; DWORD dwOldCheckPoint; DWORD dwStartTickCount; DWORD dwWaitTime; DWORD dwBytesNeeded; // Get a handle to the SCM database. SC_HANDLE schSCManager = OpenSCManager( NULL, // local computer NULL, // servicesActive database SC_MANAGER_ALL_ACCESS); // full access rights if (NULL == schSCManager) { printf("OpenSCManager failed (%d)\n", GetLastError()); return success; } // Get a handle to the service. SC_HANDLE schService = OpenService( schSCManager, // SCM database szSvcName, // name of service SERVICE_ALL_ACCESS); // full access if (schService == NULL) { printf("OpenService failed (%d)\n", GetLastError()); CloseServiceHandle(schSCManager); return success; } // Check the status in case the service is not stopped. if (!QueryServiceStatusEx( schService, // handle to service SC_STATUS_PROCESS_INFO, // information level (LPBYTE)&ssStatus, // address of structure sizeof(SERVICE_STATUS_PROCESS), // size of structure &dwBytesNeeded)) // size needed if buffer is too small { printf("QueryServiceStatusEx failed (%d)\n", GetLastError()); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return success; } // Check if the service is already running. It would be possible // to stop the service here, but for simplicity this example just returns. if (ssStatus.dwCurrentState != SERVICE_STOPPED && ssStatus.dwCurrentState != SERVICE_STOP_PENDING) { printf("Cannot start the service because it is already running\n"); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); success = TRUE; return success; } // Save the tick count and initial checkpoint. dwStartTickCount = GetTickCount(); dwOldCheckPoint = ssStatus.dwCheckPoint; // Wait for the service to stop before attempting to start it. while (ssStatus.dwCurrentState == SERVICE_STOP_PENDING) { // Do not wait longer than the wait hint. A good interval is // one-tenth of the wait hint but not less than 1 second // and not more than 10 seconds. dwWaitTime = ssStatus.dwWaitHint / 10; if (dwWaitTime < 1000) dwWaitTime = 1000; else if (dwWaitTime > 10000) dwWaitTime = 10000; Sleep(dwWaitTime); // Check the status until the service is no longer stop pending. if (!QueryServiceStatusEx( schService, // handle to service SC_STATUS_PROCESS_INFO, // information level (LPBYTE)&ssStatus, // address of structure sizeof(SERVICE_STATUS_PROCESS), // size of structure &dwBytesNeeded)) // size needed if buffer is too small { printf("QueryServiceStatusEx failed (%d)\n", GetLastError()); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return success; } if (ssStatus.dwCheckPoint > dwOldCheckPoint) { // Continue to wait and check. dwStartTickCount = GetTickCount(); dwOldCheckPoint = ssStatus.dwCheckPoint; } else { if (GetTickCount() - dwStartTickCount > ssStatus.dwWaitHint) { printf("Timeout waiting for service to stop\n"); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return success; } } } // Attempt to start the service. if (!StartService( schService, // handle to service 0, // number of arguments NULL)) // no arguments { printf("StartService failed (%d)\n", GetLastError()); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return success; } else printf("Service start pending...\n"); // Check the status until the service is no longer start pending. if (!QueryServiceStatusEx( schService, // handle to service SC_STATUS_PROCESS_INFO, // info level (LPBYTE)&ssStatus, // address of structure sizeof(SERVICE_STATUS_PROCESS), // size of structure &dwBytesNeeded)) // if buffer too small { printf("QueryServiceStatusEx failed (%d)\n", GetLastError()); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return success; } // Save the tick count and initial checkpoint. dwStartTickCount = GetTickCount(); dwOldCheckPoint = ssStatus.dwCheckPoint; while (ssStatus.dwCurrentState == SERVICE_START_PENDING) { // Do not wait longer than the wait hint. A good interval is // one-tenth the wait hint, but no less than 1 second and no // more than 10 seconds. dwWaitTime = ssStatus.dwWaitHint / 10; if (dwWaitTime < 1000) dwWaitTime = 1000; else if (dwWaitTime > 10000) dwWaitTime = 10000; Sleep(dwWaitTime); // Check the status again. if (!QueryServiceStatusEx( schService, // handle to service SC_STATUS_PROCESS_INFO, // info level (LPBYTE)&ssStatus, // address of structure sizeof(SERVICE_STATUS_PROCESS), // size of structure &dwBytesNeeded)) // if buffer too small { printf("QueryServiceStatusEx failed (%d)\n", GetLastError()); break; } if (ssStatus.dwCheckPoint > dwOldCheckPoint) { // Continue to wait and check. dwStartTickCount = GetTickCount(); dwOldCheckPoint = ssStatus.dwCheckPoint; } else { if (GetTickCount() - dwStartTickCount > ssStatus.dwWaitHint) { // No progress made within the wait hint. break; } } } // Determine whether the service is running. if (ssStatus.dwCurrentState == SERVICE_RUNNING) { printf("Service started successfully.\n"); success = TRUE; } else { printf("Service not started. \n"); printf(" Current State: %d\n", ssStatus.dwCurrentState); printf(" Exit Code: %d\n", ssStatus.dwWin32ExitCode); printf(" Check Point: %d\n", ssStatus.dwCheckPoint); printf(" Wait Hint: %d\n", ssStatus.dwWaitHint); } CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return success; } BOOL __stdcall DoReStartSvcAsync(std::string szSvcName){ STARTUPINFOA si = { sizeof(si) }; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); ZeroMemory(&pi, sizeof(pi)); // Command to be executed std::string cmd = "powershell -command 'Restart-Service -Name "; cmd.append(szSvcName); cmd.append("'"); // Start the child process. if (!CreateProcessA( NULL, // No module name (use command line) (LPSTR)(cmd.c_str()), // Command line NULL, // Process handle not inheritable NULL, // Thread handle not inheritable TRUE, // Set handle inheritance to FALSE CREATE_NEW_CONSOLE, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure &pi) // Pointer to PROCESS_INFORMATION structure ) { printf("CreateProcess failed '%s' (%08x).\n", cmd.c_str(), GetLastError()); return FALSE; } // Close process and thread handles. CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return TRUE; }