HRESULT Service_Monitor::MonitoringService(LPCTSTR pServiceName, DWORD dwStatus, HANDLE hStopEvent) { HRESULT hr = S_OK; DWORD dwError = ERROR_SUCCESS; DWORD dwWaitResult; SC_HANDLE hService; SERVICE_NOTIFY sNotify; hr = GetServiceHandle(pServiceName, &hService); if(FAILED(hr)) { goto Finished; } sNotify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE; sNotify.pfnNotifyCallback = (PFN_SC_NOTIFY_CALLBACK)NotifyCallBack; sNotify.pszServiceNames = (LPWSTR) pServiceName; sNotify.pContext = hStopEvent; dwError = NotifyServiceStatusChange(hService, dwStatus, &sNotify); if (dwError != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(dwError); _tprintf(L"\nERROR: fail to register status change callback [%x]\n", hr); goto Finished; } dwWaitResult = WaitForSingleObjectEx(hStopEvent, INFINITE, TRUE); switch (dwWaitResult) { // Event object was signaled case WAIT_OBJECT_0: case WAIT_IO_COMPLETION: break; // An error occurred default: hr = HRESULT_FROM_WIN32(GetLastError()); _tprintf(L"\nERROR: Monitoring service '%s' wait error [%x]\n", pServiceName, hr); } Finished: if (hService != NULL) { CloseServiceHandle(hService); } return hr; }
bool Module::StopService(_In_ SC_HANDLE serviceHandle) { // Signal service to stop. SERVICE_STATUS serviceStatus; BOOL controlServiceResult = ControlService(serviceHandle, SERVICE_CONTROL_STOP, &serviceStatus); if (!controlServiceResult) { DWORD lastError = GetLastError(); if (lastError != ERROR_SERVICE_NOT_ACTIVE && lastError != ERROR_SERVICE_CANNOT_ACCEPT_CTRL && serviceStatus.dwCurrentState != SERVICE_START_PENDING) { LOG_COMMENT(L"Failed to send service stop command."); return false; } } auto serviceStoppedCallback = [] (void* /*context*/) { }; // Register for service stopped event. SERVICE_NOTIFY serviceNotifyData = {}; serviceNotifyData.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE; serviceNotifyData.pfnNotifyCallback = serviceStoppedCallback; DWORD registerServiceEventResult = NotifyServiceStatusChange(serviceHandle, SERVICE_NOTIFY_STOPPED, &serviceNotifyData); if (registerServiceEventResult != ERROR_SUCCESS) { LOG_COMMENT(L"Failed to subscribe to service stopped event."); return false; } // Wait for event. DWORD sleepResult = SleepEx(/*time(ms)*/ 30000, /*APC*/ TRUE); if (sleepResult == 0) { LOG_COMMENT(L"Service took too long to stop."); return false; } // Cleanup. LOG_COMMENT(L"Service stopped."); return true; }
int main(int ac, _TCHAR** av) { int error; struct _THREAD_PARAM InputThreadParam; HANDLE InputEventHandle; HANDLE InputThreadHandle; SC_HANDLE ManagerHandle; SC_HANDLE ServiceHandle; _TCHAR* DriverPath; _TCHAR* ServiceName; HKEY ServiceKey; void* Cmdline; DWORD CmdlineLength; SERVICE_STATUS ServiceStatus; BOOLEAN isDone; DWORD res; _TCHAR KeyName[1024]; if (ac == 1) { printf("%s: <driver> <avs>\n", av[0]); return -1; } DriverPath = GetFullPath(av[1]); if (DriverPath == NULL) { printf("GetFullPath() == NULL\n"); return -1; } ServiceName = GetServiceName(DriverPath); if (ServiceName == NULL) { printf("GetServiceName() == NULL\n"); return -1; } Cmdline = AvToMultiRegSz(av + 2, &CmdlineLength); if (Cmdline == NULL) { printf("AvToMultiRegSz() == NULL\n"); return -1; } error = -1; InputEventHandle = NULL; InputThreadHandle = NULL; ServiceKey = NULL; ManagerHandle = NULL; ServiceHandle = NULL; ManagerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (ManagerHandle == NULL) { printf("OpenSCManager() == %u\n", GetLastError()); goto Cleanup; } /* remove the serice if already exist */ ServiceHandle = OpenService(ManagerHandle, ServiceName, SC_MANAGER_ALL_ACCESS); if (ServiceHandle != NULL) { if (DeleteService(ServiceHandle) == FALSE) { printf("DeleteService() == %u\n", GetLastError()); goto Cleanup; } ServiceHandle = NULL; } /* create the service */ ServiceHandle = CreateService(ManagerHandle, ServiceName, ServiceName, SC_MANAGER_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, DriverPath, NULL, NULL, NULL, NULL, NULL); if (ServiceHandle == NULL) { printf("CreateService() == %u\n", GetLastError()); goto Cleanup; } /* set registry */ _tcscpy(KeyName, _T("SYSTEM\\CurrentControlSet\\Services\\")); _tcscat(KeyName, ServiceName); if (RegOpenKey(HKEY_LOCAL_MACHINE, KeyName, &ServiceKey) != ERROR_SUCCESS) { printf("RegOpenKey() == %u\n", GetLastError()); goto Cleanup; } if (RegSetValueEx(ServiceKey, _T("Cmdline"), 0, REG_MULTI_SZ, Cmdline, CmdlineLength) != ERROR_SUCCESS) { printf("RegSetKeyValue() == %u\n", GetLastError()); goto Cleanup; } /* input thread */ InputEventHandle = CreateEvent(NULL, TRUE, FALSE, NULL); if (InputEventHandle == NULL) { printf("CreateEvent() == %u\n", GetLastError()); goto Cleanup; } InputThreadParam.InputEventHandle = InputEventHandle; InputThreadHandle = CreateThread(NULL, 0, InputThreadRoutine, &InputThreadParam, 0, NULL); if (InputThreadHandle == NULL) { printf("CreateThread() == %u\n", GetLastError()); goto Cleanup; } /* start the service */ if (StartService(ServiceHandle, 0, NULL) == FALSE) { printf("StartService() == %u\n", GetLastError()); goto Cleanup; } #if 0 /* VISTA */ { EventHandle = CreateHandle(); if (EventHandle) { printf("CreateEvent() == %u\n", GetLastError()); goto Cleanup; } memset(&ServiceNotify, 0, sizeof(ServiceNotify)); ServiceNotify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE; ServiceNotify.pfnNotifyCallback = onServiceChange; ServiceNotify.pContext = &EventHandle; NotifyServiceStatusChange(ServiceHandle, SERVICE_NOTIFY_STOPPED, &ServiceNotify); WaitForSingleObject(EventHandle, INFINITE); } #else /* ! VISTA */ { /* wait for the service to be stopped */ isDone = FALSE; while (isDone == FALSE) { res = WaitForSingleObject(InputEventHandle, 1000); if (res == WAIT_OBJECT_0) ControlService(ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus); if (QueryServiceStatus(ServiceHandle, &ServiceStatus) == FALSE) { printf("QueryServiceStatus() == %u\n", GetLastError()); ControlService(ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus); goto Cleanup; } if (ServiceStatus.dwCurrentState == SERVICE_STOPPED) { if (ServiceStatus.dwWin32ExitCode == ERROR_SERVICE_SPECIFIC_ERROR) error = ServiceStatus.dwServiceSpecificExitCode; else error = ServiceStatus.dwWin32ExitCode; isDone = TRUE; } } } #endif /* VISTA */ /* success */ Cleanup: if (InputThreadHandle != NULL) { TerminateThread(InputThreadHandle, 0); CloseHandle(InputThreadHandle); } if (InputEventHandle != NULL) CloseHandle(InputEventHandle); if (Cmdline != NULL) free(Cmdline); if (ServiceKey != NULL) RegCloseKey(ServiceKey); if (ServiceHandle != NULL) { if (DeleteService(ServiceHandle) == FALSE) printf("DeleteService() == %u\n", GetLastError()); CloseServiceHandle(ServiceHandle); } if (ManagerHandle != NULL) CloseServiceHandle(ManagerHandle); return error; }