ntservice.c 4.37 KB
Newer Older
Danny Mayer's avatar
Danny Mayer committed
1
/*
Tinderbox User's avatar
Tinderbox User committed
2
 * Copyright (C) 2004, 2006, 2007, 2009, 2011, 2013  Internet Systems Consortium, Inc. ("ISC")
Mark Andrews's avatar
Mark Andrews committed
3
 * Copyright (C) 1999-2002  Internet Software Consortium.
Danny Mayer's avatar
Danny Mayer committed
4
 *
Automatic Updater's avatar
Automatic Updater committed
5
 * Permission to use, copy, modify, and/or distribute this software for any
Danny Mayer's avatar
Danny Mayer committed
6
7
8
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
Mark Andrews's avatar
Mark Andrews committed
9
10
11
12
13
14
15
 * 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.
Danny Mayer's avatar
Danny Mayer committed
16
17
 */

Automatic Updater's avatar
Automatic Updater committed
18
/* $Id: ntservice.c,v 1.16 2011/01/13 08:50:29 tbox Exp $ */
Danny Mayer's avatar
Danny Mayer committed
19
20
21

#include <config.h>
#include <stdio.h>
22
23

#include <isc/app.h>
24
#include <isc/commandline.h>
Danny Mayer's avatar
Danny Mayer committed
25
#include <isc/log.h>
26
27

#include <named/globals.h>
Danny Mayer's avatar
Danny Mayer committed
28
29
#include <named/ntservice.h>
#include <named/main.h>
30
#include <named/server.h>
Danny Mayer's avatar
Danny Mayer committed
31
32

/* Handle to SCM for updating service status */
Andreas Gustafsson's avatar
Andreas Gustafsson committed
33
static SERVICE_STATUS_HANDLE hServiceStatus = 0;
34
static BOOL foreground = FALSE;
Danny Mayer's avatar
Danny Mayer committed
35
36
37
38
39
40
static char ConsoleTitle[128];

/*
 * Forward declarations
 */
void ServiceControl(DWORD dwCtrlCode);
41
int bindmain(int, char *[]); /* From main.c */
Andreas Gustafsson's avatar
Andreas Gustafsson committed
42

Danny Mayer's avatar
Danny Mayer committed
43
/*
Andreas Gustafsson's avatar
Andreas Gustafsson committed
44
 * Initialize the Service by registering it.
Danny Mayer's avatar
Danny Mayer committed
45
46
 */
void
47
ntservice_init(void) {
Danny Mayer's avatar
Danny Mayer committed
48
49
50
51
52
53
	if (!foreground) {
		/* Register handler with the SCM */
		hServiceStatus = RegisterServiceCtrlHandler(BIND_SERVICE_NAME,
					(LPHANDLER_FUNCTION)ServiceControl);
		if (!hServiceStatus) {
			ns_main_earlyfatal(
Andreas Gustafsson's avatar
Andreas Gustafsson committed
54
				"could not register service control handler");
Danny Mayer's avatar
Danny Mayer committed
55
56
57
58
			UpdateSCM(SERVICE_STOPPED);
			exit(1);
		}
		UpdateSCM(SERVICE_RUNNING);
Andreas Gustafsson's avatar
Andreas Gustafsson committed
59
	} else {
Danny Mayer's avatar
Danny Mayer committed
60
61
62
63
64
65
66
		strcpy(ConsoleTitle, "BIND Version ");
		strcat(ConsoleTitle, VERSION);
		SetConsoleTitle(ConsoleTitle);
	}
}

void
67
ntservice_shutdown(void) {
Andreas Gustafsson's avatar
Andreas Gustafsson committed
68
	UpdateSCM(SERVICE_STOPPED);
Danny Mayer's avatar
Danny Mayer committed
69
}
70
71
72
73
/*
 * Routine to check if this is a service or a foreground program
 */
BOOL
74
ntservice_isservice(void) {
75
76
	return(!foreground);
}
Automatic Updater's avatar
Automatic Updater committed
77
/*
Danny Mayer's avatar
Danny Mayer committed
78
 * ServiceControl(): Handles requests from the SCM and passes them on
79
 * to named.
Danny Mayer's avatar
Danny Mayer committed
80
81
82
83
 */
void
ServiceControl(DWORD dwCtrlCode) {
	/* Handle the requested control code */
Andreas Gustafsson's avatar
Andreas Gustafsson committed
84
	switch(dwCtrlCode) {
Automatic Updater's avatar
Automatic Updater committed
85
	case SERVICE_CONTROL_INTERROGATE:
Danny Mayer's avatar
Danny Mayer committed
86
87
88
		UpdateSCM(0);
		break;

Automatic Updater's avatar
Automatic Updater committed
89
90
	case SERVICE_CONTROL_SHUTDOWN:
	case SERVICE_CONTROL_STOP:
91
92
		ns_server_flushonshutdown(ns_g_server, ISC_TRUE);
		isc_app_shutdown();
Danny Mayer's avatar
Danny Mayer committed
93
94
		UpdateSCM(SERVICE_STOPPED);
		break;
Automatic Updater's avatar
Automatic Updater committed
95
	default:
Danny Mayer's avatar
Danny Mayer committed
96
		break;
Andreas Gustafsson's avatar
Andreas Gustafsson committed
97
	}
Danny Mayer's avatar
Danny Mayer committed
98
99
100
}

/*
Andreas Gustafsson's avatar
Andreas Gustafsson committed
101
 * Tell the Service Control Manager the state of the service.
Danny Mayer's avatar
Danny Mayer committed
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
 */
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);
		}
	}
}

128
/* unhook main */
Danny Mayer's avatar
Danny Mayer committed
129

130
#undef main
Danny Mayer's avatar
Danny Mayer committed
131
132

/*
133
134
135
 * This is the entry point for the executable
 * We can now call bindmain() explicitly or via StartServiceCtrlDispatcher()
 * as we need to.
Danny Mayer's avatar
Danny Mayer committed
136
 */
137
int main(int argc, char *argv[])
Danny Mayer's avatar
Danny Mayer committed
138
{
139
	int rc, ch;
Automatic Updater's avatar
Automatic Updater committed
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
	/* Command line users should put -f in the options. */
	isc_commandline_errprint = ISC_FALSE;
	while ((ch = isc_commandline_parse(argc, argv,
					   "46c:C:d:D:E:fFgi:lm:n:N:p:P:"
					   "sS:t:T:U:u:vVx:")) != -1) {
		switch (ch) {
		case 'f':
		case 'g':
		case 'v':
		case 'V':
			foreground = TRUE;
			break;
		default:
			break;
		}
	}
	isc_commandline_reset = ISC_TRUE;
Automatic Updater's avatar
Automatic Updater committed
158

159
160
161
162
163
164
	if (foreground) {
		/* run in console window */
		exit(bindmain(argc, argv));
	} else {
		/* Start up as service */
		char *SERVICE_NAME = BIND_SERVICE_NAME;
Danny Mayer's avatar
Danny Mayer committed
165

166
167
168
169
170
		SERVICE_TABLE_ENTRY dispatchTable[] = {
			{ TEXT(SERVICE_NAME),
			  (LPSERVICE_MAIN_FUNCTION)bindmain },
			{ NULL, NULL }
		};
Danny Mayer's avatar
Danny Mayer committed
171

172
173
174
175
176
177
178
179
180
		rc = StartServiceCtrlDispatcher(dispatchTable);
		if (!rc) {
			fprintf(stderr,
				"Use -f to run from the command line.\n");
			/* will be 1063 when launched as a console app */
			exit(GetLastError());
		}
	}
	exit(0);
Danny Mayer's avatar
Danny Mayer committed
181
}