static void WINAPI serviceMain(DWORD argc, TCHAR *argv[]) { wchar_t applicationFilename[MAX_PATH]; wchar_t applicationDirectory[MAX_PATH]; GetModuleFileName(nullptr, applicationFilename, sizeof(applicationFilename)); // This binary's file path. // Strip off the filename, keep only the path: wcsncpy_s(applicationDirectory, sizeof(applicationDirectory), applicationFilename, (wcsrchr(applicationFilename, '\\') - applicationFilename)); applicationDirectory[wcslen(applicationDirectory)] = '\0'; // Make sure new path is null terminated // Services are run by the SCM, and inherit its working directory - usually System32. // Set the working directory to the same location as the binary. SetCurrentDirectory(applicationDirectory); g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, serviceCtrlHandler); if (g_StatusHandle == nullptr) { OutputDebugStringA("RegisterServiceCtrlHandler() failed\n"); serviceSetState(0, SERVICE_STOPPED, GetLastError()); return; } serviceSetState(SERVICE_ACCEPT_STOP, SERVICE_RUNNING, 0); DWORD ThreadID; g_ServiceThread = CreateThread(nullptr, 0, serviceWorkerThread, nullptr, 0, &ThreadID); if (g_ServiceThread == nullptr) { OutputDebugStringA("CreateThread() failed\n"); serviceSetState(0, SERVICE_STOPPED, GetLastError()); return; } WaitForSingleObject(g_ServiceThread, INFINITE); // Wait here for a stop signal. CloseHandle(g_ServiceThread); serviceSetState(0, SERVICE_STOPPED, 0); }
static void WINAPI serviceCtrlHandler(DWORD CtrlCode) { switch (CtrlCode) { case SERVICE_CONTROL_STOP: { cRoot::Get()->QueueExecuteConsoleCommand("stop"); serviceSetState(0, SERVICE_STOP_PENDING, 0); break; } default: { break; } } }
void WINAPI serviceCtrlHandler(DWORD CtrlCode) { switch (CtrlCode) { case SERVICE_CONTROL_STOP: { cRoot::m_ShouldStop = true; serviceSetState(0, SERVICE_STOP_PENDING, 0); break; } default: { break; } } }