From f50ae72ec3417cae55dd4e085991c01af9fdc5f1 Mon Sep 17 00:00:00 2001 From: Martin Nagy Date: Wed, 11 Feb 2009 20:37:59 +0100 Subject: Initial commit --- bin/named/win32/ntservice.c | 239 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 bin/named/win32/ntservice.c (limited to 'bin/named/win32/ntservice.c') diff --git a/bin/named/win32/ntservice.c b/bin/named/win32/ntservice.c new file mode 100644 index 0000000..74570cf --- /dev/null +++ b/bin/named/win32/ntservice.c @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1999-2002 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: ntservice.c,v 1.12 2007/06/19 23:46:59 tbox Exp $ */ + +#include +#include + +#include +#include + +#include +#include +#include +#include + +/* Handle to SCM for updating service status */ +static SERVICE_STATUS_HANDLE hServiceStatus = 0; +static BOOL foreground = FALSE; +static char ConsoleTitle[128]; + +/* + * Forward declarations + */ +void ServiceControl(DWORD dwCtrlCode); +void GetArgs(int *, char ***, char ***); +int main(int, char *[], char *[]); /* From ns_main.c */ + +/* + * Here we change the entry point for the executable to bindmain() from main() + * This allows us to invoke as a service or from the command line easily. + */ +#pragma comment(linker, "/entry:bindmain") + +/* + * This is the entry point for the executable + * We can now call main() explicitly or via StartServiceCtrlDispatcher() + * as we need to. + */ +int bindmain() +{ + int rc, + i = 1; + + int argc; + char **envp, **argv; + + /* + * We changed the entry point function, so we must initialize argv, + * etc. ourselves. Ick. + */ + GetArgs(&argc, &argv, &envp); + + /* Command line users should put -f in the options */ + while (argv[i]) { + if (!strcmp(argv[i], "-f") || !strcmp(argv[i], "-g")) { + foreground = TRUE; + break; + } + i++; + } + + if (foreground) { + /* run in console window */ + exit(main(argc, argv, envp)); + } else { + /* Start up as service */ + char *SERVICE_NAME = BIND_SERVICE_NAME; + + SERVICE_TABLE_ENTRY dispatchTable[] = { + { TEXT(SERVICE_NAME), (LPSERVICE_MAIN_FUNCTION)main }, + { NULL, NULL } + }; + + rc = StartServiceCtrlDispatcher(dispatchTable); + if (!rc) { + fprintf(stderr, "Use -f to run from the command line.\n"); + exit(GetLastError()); + } + } + exit(0); +} + +/* + * Initialize the Service by registering it. + */ +void +ntservice_init() { + if (!foreground) { + /* Register handler with the SCM */ + hServiceStatus = RegisterServiceCtrlHandler(BIND_SERVICE_NAME, + (LPHANDLER_FUNCTION)ServiceControl); + if (!hServiceStatus) { + ns_main_earlyfatal( + "could not register service control handler"); + UpdateSCM(SERVICE_STOPPED); + exit(1); + } + UpdateSCM(SERVICE_RUNNING); + } else { + strcpy(ConsoleTitle, "BIND Version "); + strcat(ConsoleTitle, VERSION); + SetConsoleTitle(ConsoleTitle); + } +} + +void +ntservice_shutdown() { + UpdateSCM(SERVICE_STOPPED); +} +/* + * Routine to check if this is a service or a foreground program + */ +BOOL +ntservice_isservice() { + return(!foreground); +} +/* + * ServiceControl(): Handles requests from the SCM and passes them on + * to named. + */ +void +ServiceControl(DWORD dwCtrlCode) { + /* Handle the requested control code */ + switch(dwCtrlCode) { + case SERVICE_CONTROL_INTERROGATE: + UpdateSCM(0); + break; + + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + ns_server_flushonshutdown(ns_g_server, ISC_TRUE); + isc_app_shutdown(); + UpdateSCM(SERVICE_STOPPED); + break; + default: + break; + } +} + +/* + * Tell the Service Control Manager the state of the service. + */ +void UpdateSCM(DWORD state) { + SERVICE_STATUS ss; + static DWORD dwState = SERVICE_STOPPED; + + if (hServiceStatus) { + if (state) + dwState = state; + + memset(&ss, 0, sizeof(SERVICE_STATUS)); + ss.dwServiceType |= SERVICE_WIN32_OWN_PROCESS; + ss.dwCurrentState = dwState; + ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | + SERVICE_ACCEPT_SHUTDOWN; + ss.dwCheckPoint = 0; + ss.dwServiceSpecificExitCode = 0; + ss.dwWin32ExitCode = NO_ERROR; + ss.dwWaitHint = dwState == SERVICE_STOP_PENDING ? 10000 : 1000; + + if (!SetServiceStatus(hServiceStatus, &ss)) { + ss.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(hServiceStatus, &ss); + } + } +} + +/* + * C-runtime stuff used to initialize the app and + * get argv, argc, envp. + */ + +typedef struct +{ + int newmode; +} _startupinfo; + +_CRTIMP void __cdecl __set_app_type(int); +_CRTIMP void __cdecl __getmainargs(int *, char ***, char ***, int, + _startupinfo *); +void __cdecl _setargv(void); + +#ifdef _M_IX86 +/* Pentium FDIV adjustment */ +extern int _adjust_fdiv; +extern int * _imp___adjust_fdiv; +/* Floating point precision */ +extern void _setdefaultprecision(); +#endif + +extern int _newmode; /* malloc new() handler mode */ +extern int _dowildcard; /* passed to __getmainargs() */ + +typedef void (__cdecl *_PVFV)(void); +extern void __cdecl _initterm(_PVFV *, _PVFV *); +extern _PVFV *__onexitbegin; +extern _PVFV *__onexitend; +extern _CRTIMP char **__initenv; + +/* + * Do the work that mainCRTStartup() would normally do + */ +void GetArgs(int *argc, char ***argv, char ***envp) +{ + _startupinfo startinfo; + + /* + * Set the app type to Console (check CRT/SRC/INTERNAL.H: + * \#define _CONSOLE_APP 1) + */ + __set_app_type(1); + + /* Mark this module as an EXE file */ + __onexitbegin = __onexitend = (_PVFV *)(-1); + + startinfo.newmode = _newmode; + __getmainargs(argc, argv, envp, _dowildcard, &startinfo); + __initenv = *envp; + +#ifdef _M_IX86 + _adjust_fdiv = * _imp___adjust_fdiv; + _setdefaultprecision(); +#endif +} -- cgit