$(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))
}
#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)");
#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;
/** 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 */
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.
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
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))
{
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;
}
; 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
#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
--- /dev/null
+/*
+ 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"
+
#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
/* error message formats */
LANGUAGE 0x9,0x1
+/* id=1 type=RT_MESSAGETABLE */
1 11 "winrc/gen_msg.bin"
#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
#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
#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
* (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;
}
* (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;
}
--- /dev/null
+/*
+ * 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");
+}
--- /dev/null
+/*
+ * 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 */
*/
#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;
/** 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
/* 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;
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) {
/* 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);
}
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. */
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);
#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).