/* NetHalt - NT service library * Copyright (C) 2008 Daniel Collins * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of the author nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "ntservice.h" #include "lib.h" SERVICE_STATUS svc_status; static SERVICE_STATUS_HANDLE svc_handle; static jmp_buf exit_jmp; static void WINAPI ServiceMain(DWORD argc, char **argv); static void ServiceState(DWORD state); static void WINAPI ServiceCallback(DWORD signal); int main(int argc, char **argv) { SERVICE_TABLE_ENTRY serviceTable[] = { {(char*)svc_name, &ServiceMain}, {NULL, NULL} }; if(!(StartServiceCtrlDispatcher(serviceTable))) { LogError("StartServiceCtrlDispatcher() failed: %s", w32_error(GetLastError())); return 1; } return 0; } /* Start the service */ static void WINAPI ServiceMain(DWORD argc, char **argv) { svc_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; svc_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; svc_status.dwWin32ExitCode = NO_ERROR; svc_status.dwCheckPoint = 0; svc_status.dwWaitHint = 30000; svc_handle = RegisterServiceCtrlHandler(svc_name, (LPHANDLER_FUNCTION)&ServiceCallback); if(!svc_handle) { LogError("RegisterServiceCtrlHandler() failed: %s", w32_error(GetLastError())); return; } ServiceState(SERVICE_START_PENDING); if(setjmp(exit_jmp) == 0) { svc_init(); ServiceState(SERVICE_RUNNING); svc_main(); } svc_cleanup(); ServiceState(SERVICE_STOPPED); } /* Update the service status and notify the SCM */ static void ServiceState(DWORD state) { svc_status.dwCurrentState = state; svc_status.dwCheckPoint++; SetServiceStatus(svc_handle, &svc_status); } /* Handle service control signals */ static void WINAPI ServiceCallback(DWORD signal) { if(signal == SERVICE_CONTROL_SHUTDOWN || signal == SERVICE_CONTROL_STOP) { ServiceState(SERVICE_STOP_PENDING); return; } ServiceState(svc_status.dwCurrentState); } /* Write an event to the event log */ void LogEvent(int type, int id, char const *fmt, ...) { static HANDLE evlog = NULL; char msg[1024], *msgp = msg; va_list argv; if(!evlog && !(evlog = OpenEventLog(NULL, svc_log))) { return; } va_start(argv, fmt); vsnprintf(msg, 1024, fmt, argv); va_end(argv); ReportEvent(evlog, type, 0, id, NULL, 1, 0, (LPCSTR*)&msgp, NULL); } /* Log an error to the event log and exit */ void die_r(char const *file, int line, char const *fmt, ...) { char msg[1024]; va_list argv; va_start(argv, fmt); vsnprintf(msg, 1024, fmt, argv); va_end(argv); LogError("Fatal error at %s:%d:\n%s", file, line, msg); svc_status.dwWin32ExitCode = 1; longjmp(exit_jmp, 1); }