4 * Copyright (C) 2004, 2006, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2002 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: ntservice.c,v 1.14 2009/06/23 23:47:44 tbox Exp */
28 #include <named/globals.h>
29 #include <named/ntservice.h>
30 #include <named/main.h>
31 #include <named/server.h>
33 /* Handle to SCM for updating service status */
34 static SERVICE_STATUS_HANDLE hServiceStatus
= 0;
35 static BOOL foreground
= FALSE
;
36 static char ConsoleTitle
[128];
39 * Forward declarations
41 void ServiceControl(DWORD dwCtrlCode
);
42 void GetArgs(int *, char ***, char ***);
43 int main(int, char *[], char *[]); /* From ns_main.c */
46 * Here we change the entry point for the executable to bindmain() from main()
47 * This allows us to invoke as a service or from the command line easily.
49 #pragma comment(linker, "/entry:bindmain")
52 * This is the entry point for the executable
53 * We can now call main() explicitly or via StartServiceCtrlDispatcher()
65 * We changed the entry point function, so we must initialize argv,
66 * etc. ourselves. Ick.
68 GetArgs(&argc
, &argv
, &envp
);
70 /* Command line users should put -f in the options. */
71 /* XXXMPA should use isc_commandline_parse() here. */
73 if (!strcmp(argv
[i
], "-f") ||
74 !strcmp(argv
[i
], "-g") ||
75 !strcmp(argv
[i
], "-v")) {
83 /* run in console window */
84 exit(main(argc
, argv
, envp
));
86 /* Start up as service */
87 char *SERVICE_NAME
= BIND_SERVICE_NAME
;
89 SERVICE_TABLE_ENTRY dispatchTable
[] = {
90 { TEXT(SERVICE_NAME
), (LPSERVICE_MAIN_FUNCTION
)main
},
94 rc
= StartServiceCtrlDispatcher(dispatchTable
);
96 fprintf(stderr
, "Use -f to run from the command line.\n");
104 * Initialize the Service by registering it.
109 /* Register handler with the SCM */
110 hServiceStatus
= RegisterServiceCtrlHandler(BIND_SERVICE_NAME
,
111 (LPHANDLER_FUNCTION
)ServiceControl
);
112 if (!hServiceStatus
) {
114 "could not register service control handler");
115 UpdateSCM(SERVICE_STOPPED
);
118 UpdateSCM(SERVICE_RUNNING
);
120 strcpy(ConsoleTitle
, "BIND Version ");
121 strcat(ConsoleTitle
, VERSION
);
122 SetConsoleTitle(ConsoleTitle
);
127 ntservice_shutdown() {
128 UpdateSCM(SERVICE_STOPPED
);
131 * Routine to check if this is a service or a foreground program
134 ntservice_isservice() {
138 * ServiceControl(): Handles requests from the SCM and passes them on
142 ServiceControl(DWORD dwCtrlCode
) {
143 /* Handle the requested control code */
145 case SERVICE_CONTROL_INTERROGATE
:
149 case SERVICE_CONTROL_SHUTDOWN
:
150 case SERVICE_CONTROL_STOP
:
151 ns_server_flushonshutdown(ns_g_server
, ISC_TRUE
);
153 UpdateSCM(SERVICE_STOPPED
);
161 * Tell the Service Control Manager the state of the service.
163 void UpdateSCM(DWORD state
) {
165 static DWORD dwState
= SERVICE_STOPPED
;
167 if (hServiceStatus
) {
171 memset(&ss
, 0, sizeof(SERVICE_STATUS
));
172 ss
.dwServiceType
|= SERVICE_WIN32_OWN_PROCESS
;
173 ss
.dwCurrentState
= dwState
;
174 ss
.dwControlsAccepted
= SERVICE_ACCEPT_STOP
|
175 SERVICE_ACCEPT_SHUTDOWN
;
177 ss
.dwServiceSpecificExitCode
= 0;
178 ss
.dwWin32ExitCode
= NO_ERROR
;
179 ss
.dwWaitHint
= dwState
== SERVICE_STOP_PENDING
? 10000 : 1000;
181 if (!SetServiceStatus(hServiceStatus
, &ss
)) {
182 ss
.dwCurrentState
= SERVICE_STOPPED
;
183 SetServiceStatus(hServiceStatus
, &ss
);
189 * C-runtime stuff used to initialize the app and
190 * get argv, argc, envp.
198 _CRTIMP
void __cdecl
__set_app_type(int);
199 _CRTIMP
void __cdecl
__getmainargs(int *, char ***, char ***, int,
201 void __cdecl
_setargv(void);
204 /* Pentium FDIV adjustment */
205 extern int _adjust_fdiv
;
206 extern int * _imp___adjust_fdiv
;
207 /* Floating point precision */
208 extern void _setdefaultprecision();
211 extern int _newmode
; /* malloc new() handler mode */
212 extern int _dowildcard
; /* passed to __getmainargs() */
214 typedef void (__cdecl
*_PVFV
)(void);
215 extern void __cdecl
_initterm(_PVFV
*, _PVFV
*);
216 extern _PVFV
*__onexitbegin
;
217 extern _PVFV
*__onexitend
;
218 extern _CRTIMP
char **__initenv
;
221 * Do the work that mainCRTStartup() would normally do
223 void GetArgs(int *argc
, char ***argv
, char ***envp
)
225 _startupinfo startinfo
;
228 * Set the app type to Console (check CRT/SRC/INTERNAL.H:
229 * \#define _CONSOLE_APP 1)
233 /* Mark this module as an EXE file */
234 __onexitbegin
= __onexitend
= (_PVFV
*)(-1);
236 startinfo
.newmode
= _newmode
;
237 __getmainargs(argc
, argv
, envp
, _dowildcard
, &startinfo
);
241 _adjust_fdiv
= * _imp___adjust_fdiv
;
242 _setdefaultprecision();