#include <config.h>
#include <stdio.h>
#include <isc/app.h>
#include <isc/log.h>
#include <named/globals.h>
#include <named/ntservice.h>
#include <named/main.h>
#include <named/server.h>
static SERVICE_STATUS_HANDLE hServiceStatus = 0;
static BOOL foreground = FALSE;
static char ConsoleTitle[128];
void ServiceControl(DWORD dwCtrlCode);
void GetArgs(int *, char ***, char ***);
int main(int, char *[], char *[]);
#pragma comment(linker, "/entry:bindmain")
int bindmain()
{
int rc,
i = 1;
int argc;
char **envp, **argv;
GetArgs(&argc, &argv, &envp);
while (argv[i]) {
if (!strcmp(argv[i], "-f") ||
!strcmp(argv[i], "-g") ||
!strcmp(argv[i], "-v") ||
!strcmp(argv[i], "-V")) {
foreground = TRUE;
break;
}
i++;
}
if (foreground) {
exit(main(argc, argv, envp));
} else {
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);
}
void
ntservice_init() {
if (!foreground) {
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);
}
BOOL
ntservice_isservice() {
return(!foreground);
}
void
ServiceControl(DWORD dwCtrlCode) {
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;
}
}
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);
}
}
}
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
extern int _adjust_fdiv;
extern int * _imp___adjust_fdiv;
extern void _setdefaultprecision();
#endif
extern int _newmode;
extern int _dowildcard;
typedef void (__cdecl *_PVFV)(void);
extern void __cdecl _initterm(_PVFV *, _PVFV *);
extern _PVFV *__onexitbegin;
extern _PVFV *__onexitend;
extern _CRTIMP char **__initenv;
void GetArgs(int *argc, char ***argv, char ***envp)
{
_startupinfo startinfo;
__set_app_type(1);
__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
}