windows registry settings.

git-svn-id: file:///svn/unbound/trunk@1509 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2009-03-03 15:55:02 +00:00
parent 7de3900654
commit 53b51dbdef
21 changed files with 427 additions and 259 deletions

View File

@ -122,19 +122,19 @@ ALL_OBJ=$(addprefix $(BUILD),$(ALL_SRC:.c=.lo) \
$(addprefix compat/,$(LIBOBJS:.o=.lo))) $(COMPAT_OBJ)
ifeq "$(UB_ON_WINDOWS)" "yes"
DAEMON_SRC+=winrc/win_svc.c
DAEMON_SRC+=winrc/win_svc.c winrc/w_inst.c
DAEMON_OBJ+=$(BUILD)winrc/rsrc_unbound.o $(BUILD)winrc/win_svc.lo
HOST_OBJ+=$(BUILD)winrc/rsrc_unbound_host.o
CONTROL_OBJ+=$(BUILD)winrc/rsrc_unbound_control.o
CHECKCONF_OBJ+=$(BUILD)winrc/rsrc_unbound_checkconf.o
WINAPPS=unbound-service-install unbound-service-remove
SVCINST_SRC=winrc/unbound-service-install.c
SVCINST_SRC=winrc/unbound-service-install.c winrc/w_inst.c
SVCINST_OBJ=$(addprefix $(BUILD),$(SVCINST_SRC:.c=.lo)) $(COMPAT_OBJ) \
$(BUILD)winrc/rsrc_svcinst.o
SVCUNINST_SRC=winrc/unbound-service-remove.c
SVCUNINST_SRC=winrc/unbound-service-remove.c winrc/w_inst.c
SVCUNINST_OBJ=$(addprefix $(BUILD),$(SVCUNINST_SRC:.c=.lo)) $(COMPAT_OBJ) \
$(BUILD)winrc/rsrc_svcinst.o
$(BUILD)winrc/rsrc_svcuninst.o
ALL_SRC:=$(sort $(ALL_SRC) $(SVCINST_SRC) $(SVCUNINST_SRC))
ALL_OBJ:=$(sort $(ALL_OBJ) $(SVCINST_OBJ) $(SVCUNINST_OBJ))

View File

@ -998,8 +998,8 @@ worker_create(struct daemon* daemon, int id, int* ports, int n)
}
#ifdef UB_ON_WINDOWS
static void
ub_win_stop(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void* arg)
void
worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void* arg)
{
struct worker* worker = (struct worker*)arg;
verbose(VERB_QUERY, "caught stop signal (wsaevent)");
@ -1058,7 +1058,7 @@ worker_init(struct worker* worker, struct config_file *cfg,
#ifdef UB_ON_WINDOWS
if(!winsock_register_wsaevent(comm_base_internal(worker->base),
&worker->daemon->stop_ev, worker->daemon->stop_event,
ub_win_stop, worker)) {
&worker_win_stop_cb, worker)) {
log_err("could not register wsaevent");
worker_delete(worker);
return 0;

View File

@ -239,4 +239,7 @@ void worker_stats_clear(struct worker* worker);
/** statistics timer callback handler */
void worker_stat_timer_cb(void* arg);
/** windows worker stop event callback handler */
void worker_win_stop_cb(int fd, short ev, void* arg);
#endif /* DAEMON_WORKER_H */

View File

@ -1,5 +1,7 @@
3 March 2009: Wouter
- combined icon with 16x16(4) 32x32(4) 48x48(8) 64x64(8).
- service works on xp/vista, no config necessary (using defaults).
- windows registry settings.
2 March 2009: Wouter
- fixup --export-symbols to be -export-symbls for libtool.

View File

@ -847,3 +847,10 @@ codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
return 0;
}
#ifdef UB_ON_WINDOWS
void
worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void*
ATTR_UNUSED(arg)) {
log_assert(0);
}
#endif

View File

@ -118,6 +118,14 @@ struct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname),
return 0;
}
#ifdef UB_ON_WINDOWS
void
worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void*
ATTR_UNUSED(arg)) {
log_assert(0);
}
#endif
void
worker_alloc_cleanup(void* ATTR_UNUSED(arg))
{

View File

@ -118,6 +118,7 @@ fptr_whitelist_event(void (*fptr)(int, short, void *))
else if(fptr == &comm_point_local_handle_callback) return 1;
else if(fptr == &comm_point_raw_handle_callback) return 1;
else if(fptr == &tube_handle_signal) return 1;
else if(fptr == &worker_win_stop_cb) return 1;
return 0;
}

Binary file not shown.

View File

@ -2,13 +2,13 @@
; severity default Success Informational Warning Error
; .bin file created with:
; "/c/Program Files/Microsoft SDKs/Windows/v6.1/Bin/mc" gen_msg.mc
; "/c/Program Files/Microsoft SDKs/Windows/v6.1/Bin/mc" -c gen_msg.mc
; mv MSG00001.bin gen_msg.bin
; rm gen_msg.h
; and pasted contents of gen_msg.rc into rsrc_unbound.rc
FacilityNames=(Server=0x1)
MessageIdTypeDef=WORD
MessageIdTypeDef=DWORD
MessageID=0x1
Severity=Success

View File

@ -4,10 +4,7 @@
#include "winver.h"
#include "config.h"
1 ICON "winrc/unbound64.ico"
2 ICON "winrc/unbound48.ico"
3 ICON "winrc/unbound32.ico"
4 ICON "winrc/unbound16.ico"
1 ICON "winrc/combined.ico"
1 VERSIONINFO
FILEVERSION RSRC_PACKAGE_VERSION

45
winrc/rsrc_svcuninst.rc Normal file
View File

@ -0,0 +1,45 @@
/*
Unbound resource file for windows. For use with windres
*/
#include "winver.h"
#include "config.h"
1 ICON "winrc/combined.ico"
1 VERSIONINFO
FILEVERSION RSRC_PACKAGE_VERSION
PRODUCTVERSION RSRC_PACKAGE_VERSION
FILEFLAGSMASK 0
FILEFLAGS 0
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE 0
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", "NLnet Labs"
VALUE "FileDescription", "Unbound Service Remove Util"
VALUE "FileVersion", PACKAGE_VERSION
VALUE "InternalName", "unbound-service-remove"
VALUE "OriginalFilename", "unbound-service-remove.exe"
VALUE "ProductName", "unbound"
VALUE "ProductVersion", PACKAGE_VERSION
VALUE "LegalCopyright", "(C) 2009 NLnet Labs. Source is BSD licensed."
END
END
BLOCK "VarFileInfo"
BEGIN
/* English(409), windows ANSI codepage (1252) */
VALUE "Translation", 0x409, 0x1252
END
END
/* error message formats */
LANGUAGE 0x9,0x1
1 11 "winrc/gen_msg.bin"
/* vista administrator access, show UAC prompt */
1 RT_MANIFEST "winrc/vista_admin.manifest"

View File

@ -4,10 +4,13 @@
#include "winver.h"
#include "config.h"
1 ICON "winrc/combined.ico"
/*
1 ICON "winrc/unbound64.ico"
2 ICON "winrc/unbound48.ico"
3 ICON "winrc/unbound32.ico"
4 ICON "winrc/unbound16.ico"
*/
1 VERSIONINFO
FILEVERSION RSRC_PACKAGE_VERSION
@ -41,4 +44,5 @@ END
/* error message formats */
LANGUAGE 0x9,0x1
/* id=1 type=RT_MESSAGETABLE */
1 11 "winrc/gen_msg.bin"

View File

@ -4,10 +4,7 @@
#include "winver.h"
#include "config.h"
1 ICON "winrc/unbound64.ico"
2 ICON "winrc/unbound48.ico"
3 ICON "winrc/unbound32.ico"
4 ICON "winrc/unbound16.ico"
1 ICON "winrc/combined.ico"
1 VERSIONINFO
FILEVERSION RSRC_PACKAGE_VERSION

View File

@ -4,10 +4,7 @@
#include "winver.h"
#include "config.h"
1 ICON "winrc/unbound64.ico"
2 ICON "winrc/unbound48.ico"
3 ICON "winrc/unbound32.ico"
4 ICON "winrc/unbound16.ico"
1 ICON "winrc/combined.ico"
1 VERSIONINFO
FILEVERSION RSRC_PACKAGE_VERSION

View File

@ -4,10 +4,7 @@
#include "winver.h"
#include "config.h"
1 ICON "winrc/unbound64.ico"
2 ICON "winrc/unbound48.ico"
3 ICON "winrc/unbound32.ico"
4 ICON "winrc/unbound16.ico"
1 ICON "winrc/combined.ico"
1 VERSIONINFO
FILEVERSION RSRC_PACKAGE_VERSION

View File

@ -44,99 +44,12 @@
* (such as start and stop and status).
*/
#include "config.h"
#include "winrc/win_svc.h"
/** service name for unbound (internal to ServiceManager) */
#define SERVICE_NAME "unbound"
/** output for diagnostics */
static FILE *out;
/** exit with windows error */
static void
fatal_win(const char* str)
{
fprintf(out, "%s (%d)\n", str, (int)GetLastError());
exit(1);
}
/** put quotes around string. Needs one space in front
* @param str: to be quoted.
* @param maxlen: max length of the string buffer.
*/
static void
quote_it(char* str, size_t maxlen)
{
if(strlen(str) == maxlen) {
fprintf(out, "string too long %s", str);
exit(1);
}
str[0]='"';
str[strlen(str)+1]=0;
str[strlen(str)]='"';
}
/** change suffix */
static void
change(char* path, size_t max, const char* from, const char* to)
{
size_t fromlen = strlen(from);
size_t tolen = strlen(to);
size_t pathlen = strlen(path);
if(pathlen - fromlen + tolen >= max) {
fprintf(out, "string too long %s", path);
exit(1);
}
snprintf(path+pathlen-fromlen, max-(pathlen-fromlen), "%s", to);
}
/** Install service in servicecontrolmanager */
static void
wsvc_install(void)
{
SC_HANDLE scm;
SC_HANDLE sv;
TCHAR path[MAX_PATH+2+256];
fprintf(out, "installing unbound service\n");
if(!GetModuleFileName(NULL, path+1, MAX_PATH))
fatal_win("could not GetModuleFileName");
/* change 'unbound-service-install' to 'unbound' */
change(path, sizeof(path), "-service-install.exe", ".exe");
/* have to quote it because of spaces in directory names */
/* could append arguments to be sent to ServiceMain */
quote_it(path, sizeof(path));
strcat(path, " -w service");
scm = OpenSCManager(NULL, NULL, (int)SC_MANAGER_CREATE_SERVICE);
if(!scm) fatal_win("could not OpenSCManager");
sv = CreateService(
scm,
SERVICE_NAME, /* name of service */
"Unbound DNS validator", /* display name */
SERVICE_ALL_ACCESS, /* desired access */
SERVICE_WIN32_OWN_PROCESS, /* service type */
SERVICE_AUTO_START, /* start type */
SERVICE_ERROR_NORMAL, /* error control type */
path, /* path to service's binary */
NULL, /* no load ordering group */
NULL, /* no tag identifier */
NULL, /* no deps */
NULL, /* on LocalSystem */
NULL /* no password */
);
if(!sv) {
CloseServiceHandle(scm);
fatal_win("could not CreateService");
}
CloseServiceHandle(sv);
CloseServiceHandle(scm);
fprintf(out, "unbound service installed\n");
}
#include "winrc/w_inst.h"
/** Install service main */
int main(int ATTR_UNUSED(argc), char** ATTR_UNUSED(argv))
{
out = fopen("unbound-service-install.log", "w");
wsvc_install();
/*FILE* out = fopen("unbound-service-install.log", "w");*/
wsvc_install(NULL, "unbound-service-install.exe");
return 0;
}

View File

@ -44,48 +44,12 @@
* (such as start and stop and status).
*/
#include "config.h"
#include "winrc/win_svc.h"
/** service name for unbound (internal to ServiceManager) */
#define SERVICE_NAME "unbound"
/** output file for diagnostics */
static FILE* out = NULL;
/** exit with windows error */
static void
fatal_win(const char* str)
{
fprintf(out, "%s (%d)\n", str, (int)GetLastError());
exit(1);
}
/** Remove installed service from servicecontrolmanager */
static void
wsvc_remove(void)
{
SC_HANDLE scm;
SC_HANDLE sv;
fprintf(out, "removing unbound service\n");
scm = OpenSCManager(NULL, NULL, (int)SC_MANAGER_ALL_ACCESS);
if(!scm) fatal_win("could not OpenSCManager");
sv = OpenService(scm, SERVICE_NAME, DELETE);
if(!sv) {
CloseServiceHandle(scm);
fatal_win("could not OpenService");
}
if(!DeleteService(sv)) {
fatal_win("could not DeleteService");
}
CloseServiceHandle(sv);
CloseServiceHandle(scm);
fprintf(out, "unbound service removed\n");
}
#include "winrc/w_inst.h"
/** Install service main */
int main(int ATTR_UNUSED(argc), char** ATTR_UNUSED(argv))
{
out = fopen("unbound-service-remove.log", "w");
wsvc_remove();
/*FILE* out = fopen("unbound-service-remove.log", "w");*/
wsvc_remove(NULL);
return 0;
}

237
winrc/w_inst.c Normal file
View File

@ -0,0 +1,237 @@
/*
* winrc/w_inst.h - install and remove functions
*
* Copyright (c) 2009, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* 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 NLNET LABS 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
* "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 REGENTS OR CONTRIBUTORS 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.
*/
/**
* \file
*
* Contains install and remove functions that manipulate the
* windows services API and windows registry.
*/
#include "config.h"
#include "winrc/w_inst.h"
#include "winrc/win_svc.h"
/** exit with windows error */
static void
fatal_win(FILE* out, const char* str)
{
if(out) fprintf(out, "%s (%d)\n", str, (int)GetLastError());
exit(1);
}
/** install registry entries for eventlog */
static void
event_reg_install(FILE* out, const char* pathname)
{
char buf[1024];
HKEY hk;
DWORD t;
if(out) fprintf(out, "install reg entries for %s\n", pathname);
snprintf(buf, sizeof(buf), "SYSTEM\\CurrentControlSet\\Services"
"\\EventLog\\Application\\%s", SERVICE_NAME);
if(RegCreateKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR)buf,
0, /* reserved, mustbezero */
NULL, /* class of key, ignored */
REG_OPTION_NON_VOLATILE, /* values saved on disk */
KEY_WRITE, /* we want write permission */
NULL, /* use default security descriptor */
&hk, /* result */
NULL)) /* not interested if key new or existing */
fatal_win(out, "could not create registry key");
/* message file */
if(RegSetValueEx(hk, (LPCTSTR)"EventMessageFile",
0, /* reserved, mustbezero */
REG_EXPAND_SZ, /* value type (string w env subst) */
pathname, /* data */
(DWORD)strlen(pathname)+1)) /* length of data */
{
RegCloseKey(hk);
fatal_win(out, "could not registry set EventMessageFile");
}
/* event types */
t = EVENTLOG_SUCCESS | EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE
| EVENTLOG_INFORMATION_TYPE;
if(RegSetValueEx(hk, (LPCTSTR)"TypesSupported", 0, REG_DWORD,
(LPBYTE)&t, sizeof(t))) {
RegCloseKey(hk);
fatal_win(out, "could not registry set TypesSupported");
}
/* category message file */
if(RegSetValueEx(hk, (LPCTSTR)"CategoryMessageFile", 0, REG_EXPAND_SZ,
pathname, (DWORD)strlen(pathname)+1)) {
RegCloseKey(hk);
fatal_win(out, "could not registry set CategoryMessageFile");
}
t = 1;
if(RegSetValueEx(hk, (LPCTSTR)"CategoryCount", 0, REG_DWORD,
(LPBYTE)&t, sizeof(t))) {
RegCloseKey(hk);
fatal_win(out, "could not registry set CategoryCount");
}
RegCloseKey(hk);
if(out) fprintf(out, "installed reg entries\n");
}
/** remove regisytry entries for eventlog */
static void
event_reg_remove(FILE* out)
{
char buf[1024];
HKEY hk;
if(out) fprintf(out, "remove reg entries\n");
snprintf(buf, sizeof(buf), "SYSTEM\\CurrentControlSet\\Services"
"\\EventLog\\Application");
if(RegCreateKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR)buf,
0, /* reserved, mustbezero */
NULL, /* class of key, ignored */
REG_OPTION_NON_VOLATILE, /* values saved on disk */
DELETE, /* we want key delete permission */
NULL, /* use default security descriptor */
&hk, /* result */
NULL)) /* not interested if key new or existing */
fatal_win(out, "could not open registry key");
if(RegDeleteKey(hk, (LPCTSTR)SERVICE_NAME)) {
RegCloseKey(hk);
fatal_win(out, "could not delete registry key");
}
RegCloseKey(hk);
if(out) fprintf(out, "removed reg entries\n");
}
/**
* put quotes around string. Needs one space in front
* @param out: debugfile
* @param str: to be quoted.
* @param maxlen: max length of the string buffer.
*/
static void
quote_it(FILE* out, char* str, size_t maxlen)
{
if(strlen(str) == maxlen) {
if(out) fprintf(out, "string too long %s", str);
exit(1);
}
str[0]='"';
str[strlen(str)+1]=0;
str[strlen(str)]='"';
}
/** change suffix */
static void
change(FILE* out, char* path, size_t max, const char* from, const char* to)
{
size_t fromlen = strlen(from);
size_t tolen = strlen(to);
size_t pathlen = strlen(path);
if(pathlen - fromlen + tolen >= max) {
if(out) fprintf(out, "string too long %s", path);
exit(1);
}
snprintf(path+pathlen-fromlen, max-(pathlen-fromlen), "%s", to);
}
/** Install service in servicecontrolmanager */
void
wsvc_install(FILE* out, const char* rename)
{
SC_HANDLE scm;
SC_HANDLE sv;
TCHAR path[MAX_PATH+2+256];
if(out) fprintf(out, "installing unbound service\n");
if(!GetModuleFileName(NULL, path+1, MAX_PATH))
fatal_win(out, "could not GetModuleFileName");
/* change 'unbound-service-install' to 'unbound' */
if(rename)
change(out, path+1, sizeof(path)-1, rename, "unbound.exe");
event_reg_install(out, path+1);
/* have to quote it because of spaces in directory names */
/* could append arguments to be sent to ServiceMain */
quote_it(out, path, sizeof(path));
strcat(path, " -w service");
scm = OpenSCManager(NULL, NULL, (int)SC_MANAGER_CREATE_SERVICE);
if(!scm) fatal_win(out, "could not OpenSCManager");
sv = CreateService(
scm,
SERVICE_NAME, /* name of service */
"Unbound DNS validator", /* display name */
SERVICE_ALL_ACCESS, /* desired access */
SERVICE_WIN32_OWN_PROCESS, /* service type */
SERVICE_AUTO_START, /* start type */
SERVICE_ERROR_NORMAL, /* error control type */
path, /* path to service's binary */
NULL, /* no load ordering group */
NULL, /* no tag identifier */
NULL, /* no deps */
NULL, /* on LocalSystem */
NULL /* no password */
);
if(!sv) {
CloseServiceHandle(scm);
fatal_win(out, "could not CreateService");
}
CloseServiceHandle(sv);
CloseServiceHandle(scm);
if(out) fprintf(out, "unbound service installed\n");
}
/** Remove installed service from servicecontrolmanager */
void
wsvc_remove(FILE* out)
{
SC_HANDLE scm;
SC_HANDLE sv;
if(out) fprintf(out, "removing unbound service\n");
scm = OpenSCManager(NULL, NULL, (int)SC_MANAGER_ALL_ACCESS);
if(!scm) fatal_win(out, "could not OpenSCManager");
sv = OpenService(scm, SERVICE_NAME, DELETE);
if(!sv) {
CloseServiceHandle(scm);
fatal_win(out, "could not OpenService");
}
if(!DeleteService(sv)) {
fatal_win(out, "could not DeleteService");
}
CloseServiceHandle(sv);
CloseServiceHandle(scm);
event_reg_remove(out);
if(out) fprintf(out, "unbound service removed\n");
}

59
winrc/w_inst.h Normal file
View File

@ -0,0 +1,59 @@
/*
* winrc/w_inst.h - install and remove functions
*
* Copyright (c) 2009, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* 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 NLNET LABS 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
* "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 REGENTS OR CONTRIBUTORS 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.
*/
/**
* \file
*
* Contains install and remove functions that manipulate the
* windows services API and windows registry.
*/
#ifndef WINRC_W_INST_H
#define WINRC_W_INST_H
/**
* Install service in servicecontrolmanager, setup registry
* @param out: debug output printed here (errors). or NULL.
* @param rename: if nonNULL this executable is not unbound.exe but this name.
*/
void wsvc_install(FILE* out, const char* rename);
/**
* Remove installed service from servicecontrolmanager, registry entries
* @param out: debug output printed here (errors). or NULL.
*/
void wsvc_remove(FILE* out);
#endif /* WINRC_W_INST_H */

View File

@ -45,20 +45,18 @@
*/
#include "config.h"
#include "winrc/win_svc.h"
#include "winrc/w_inst.h"
#include "daemon/daemon.h"
#include "util/config_file.h"
/** service name for unbound (internal to ServiceManager) */
#define SERVICE_NAME "unbound"
/** from gen_msg.h - success message record for windows message log */
#define MSG_GENERIC_SUCCESS ((WORD)0x00010001L)
#define MSG_GENERIC_SUCCESS ((DWORD)0x20010001L)
/** from gen_msg.h - informational message record for windows message log */
#define MSG_GENERIC_INFO ((WORD)0x40010002L)
#define MSG_GENERIC_INFO ((DWORD)0x60010002L)
/** from gen_msg.h - warning message record for windows message log */
#define MSG_GENERIC_WARN ((WORD)0x80010003L)
#define MSG_GENERIC_WARN ((DWORD)0xA0010003L)
/** from gen_msg.h - error message record for windows message log */
#define MSG_GENERIC_ERR ((WORD)0xC0010004L)
#define MSG_GENERIC_ERR ((DWORD)0xE0010004L)
/** global service status */
SERVICE_STATUS service_status;
@ -71,89 +69,6 @@ const char* service_cfgfile = CONFIGFILE;
/** commandline verbosity. global communication to service_main() */
int service_cmdline_verbose = 0;
/** exit with windows error */
static void
fatal_win(const char* str)
{
fatal_exit("%s (%d)", str, (int)GetLastError());
}
/** put quotes around string. Needs one space in front
* @param str: to be quoted.
* @param maxlen: max length of the string buffer.
*/
static void
quote_it(char* str, size_t maxlen)
{
if(strlen(str) == maxlen)
fatal_exit("string too long %s", str);
str[0]='"';
str[strlen(str)+1]=0;
str[strlen(str)]='"';
}
/** Install service in servicecontrolmanager */
static void
wsvc_install(void)
{
SC_HANDLE scm;
SC_HANDLE sv;
TCHAR path[MAX_PATH+2+256];
printf("installing unbound service\n");
if(!GetModuleFileName(NULL, path+1, MAX_PATH))
fatal_win("could not GetModuleFileName");
/* have to quote it because of spaces in directory names */
/* could append arguments to be sent to ServiceMain */
quote_it(path, sizeof(path));
strcat(path, " -w service");
scm = OpenSCManager(NULL, NULL, (int)SC_MANAGER_CREATE_SERVICE);
if(!scm) fatal_win("could not OpenSCManager");
sv = CreateService(
scm,
SERVICE_NAME, /* name of service */
"Unbound DNS validator", /* display name */
SERVICE_ALL_ACCESS, /* desired access */
SERVICE_WIN32_OWN_PROCESS, /* service type */
SERVICE_AUTO_START, /* start type */
SERVICE_ERROR_NORMAL, /* error control type */
path, /* path to service's binary */
NULL, /* no load ordering group */
NULL, /* no tag identifier */
NULL, /* no deps */
NULL, /* on LocalSystem */
NULL /* no password */
);
if(!sv) {
CloseServiceHandle(scm);
fatal_win("could not CreateService");
}
CloseServiceHandle(sv);
CloseServiceHandle(scm);
printf("unbound service installed\n");
}
/** Remove installed service from servicecontrolmanager */
static void
wsvc_remove(void)
{
SC_HANDLE scm;
SC_HANDLE sv;
printf("removing unbound service\n");
scm = OpenSCManager(NULL, NULL, (int)SC_MANAGER_ALL_ACCESS);
if(!scm) fatal_win("could not OpenSCManager");
sv = OpenService(scm, SERVICE_NAME, DELETE);
if(!sv) {
CloseServiceHandle(scm);
fatal_win("could not OpenService");
}
if(!DeleteService(sv)) {
fatal_win("could not DeleteService");
}
CloseServiceHandle(sv);
CloseServiceHandle(scm);
printf("unbound service removed\n");
}
/**
* Report current service status to service control manager
* @param state: current state
@ -244,35 +159,45 @@ service_init(struct daemon** d, struct config_file** c)
/* create daemon */
daemon = daemon_init();
if(!daemon) return 0;
report_status(SERVICE_START_PENDING, NO_ERROR, 3000);
report_status(SERVICE_START_PENDING, NO_ERROR, 2800);
/* read config */
cfg = config_create();
if(!cfg) return 0;
if(!config_read(cfg, service_cfgfile, daemon->chroot)) {
if(errno != ENOENT) {
/* could not read config file */
log_err("error in config file");
return 0;
}
/* could not open config file, using defaults */
log_warn("could not open config file, using defaults");
}
report_status(SERVICE_START_PENDING, NO_ERROR, 3000);
report_status(SERVICE_START_PENDING, NO_ERROR, 2600);
verbose(VERB_QUERY, "winservice - apply settings");
/* apply settings and init */
verbosity = cfg->verbosity + service_cmdline_verbose;
if(cfg->directory && cfg->directory[0]) {
if(chdir(cfg->directory)) return 0;
verbose(VERB_QUERY, "chdir to %s", cfg->directory);
if(chdir(cfg->directory)) {
log_err("could not chdir to %s: %s",
cfg->directory, strerror(errno));
if(errno != ENOENT)
return 0;
log_warn("could not change directory - continuing");
} else
verbose(VERB_QUERY, "chdir to %s", cfg->directory);
}
/* log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir); DEBUG*/
report_status(SERVICE_START_PENDING, NO_ERROR, 3000);
report_status(SERVICE_START_PENDING, NO_ERROR, 2400);
verbose(VERB_QUERY, "winservice - apply cfg");
daemon_apply_cfg(daemon, cfg);
/* open ports */
/* keep reporting that we are busy starting */
report_status(SERVICE_START_PENDING, NO_ERROR, 3000);
report_status(SERVICE_START_PENDING, NO_ERROR, 2200);
verbose(VERB_QUERY, "winservice - open ports");
if(!daemon_open_shared_ports(daemon)) return 0;
report_status(SERVICE_START_PENDING, NO_ERROR, 3000);
verbose(VERB_QUERY, "winservice - ports opened");
report_status(SERVICE_START_PENDING, NO_ERROR, 2000);
*d = daemon;
*c = cfg;
@ -292,6 +217,8 @@ service_main(DWORD ATTR_UNUSED(argc), LPTSTR* ATTR_UNUSED(argv))
struct config_file* cfg = NULL;
struct daemon* daemon = NULL;
reportev("Trying to report event");
service_status_handle = RegisterServiceCtrlHandler(SERVICE_NAME,
(LPHANDLER_FUNCTION)hdlr);
if(!service_status_handle) {
@ -323,16 +250,18 @@ service_main(DWORD ATTR_UNUSED(argc), LPTSTR* ATTR_UNUSED(argv))
/* SetServiceStatus SERVICE_RUNNING;*/
report_status(SERVICE_RUNNING, NO_ERROR, 0);
verbose(VERB_QUERY, "winservice - init complete");
/* daemon performs work */
daemon_fork(daemon);
/* exit */
verbose(VERB_ALGO, "cleanup.");
verbose(VERB_ALGO, "winservice - cleanup.");
report_status(SERVICE_STOP_PENDING, NO_ERROR, 0);
daemon_cleanup(daemon);
config_delete(cfg);
daemon_delete(daemon);
daemon_delete(daemon);
verbose(VERB_QUERY, "winservice - full stop");
report_status(SERVICE_STOPPED, NO_ERROR, 0);
}
@ -343,8 +272,13 @@ service_start(const char* cfgfile, int v)
SERVICE_TABLE_ENTRY myservices[2] = {
{SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)service_main},
{NULL, NULL} };
log_init("C:\\unbound.log", 0, 0);
log_info("open logfile");
verbosity=v;
if(1) {
/* DEBUG log to file */
fclose(fopen("C:\\unbound.log", "w"));
log_init("C:\\unbound.log", 0, 0);
verbose(VERB_QUERY, "open logfile");
}
service_cfgfile = cfgfile;
service_cmdline_verbose = v;
/* this call returns when service has stopped. */
@ -357,9 +291,9 @@ void
wsvc_command_option(const char* wopt, const char* cfgfile, int v)
{
if(strcmp(wopt, "install") == 0)
wsvc_install();
wsvc_install(stdout, NULL);
else if(strcmp(wopt, "remove") == 0)
wsvc_remove();
wsvc_remove(stdout);
else if(strcmp(wopt, "service") == 0)
service_start(cfgfile, v);
else fatal_exit("unknown option: %s", wopt);

View File

@ -47,6 +47,9 @@
#ifndef WINRC_WIN_SVC_H
#define WINRC_WIN_SVC_H
/** service name for unbound (internal to ServiceManager) */
#define SERVICE_NAME "unbound"
/**
* Handle commandline service for windows.
* @param wopt: windows option string (install, remove, service).