]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
windows registry settings.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 3 Mar 2009 15:55:02 +0000 (15:55 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 3 Mar 2009 15:55:02 +0000 (15:55 +0000)
git-svn-id: file:///svn/unbound/trunk@1509 be551aaa-1e26-0410-a405-d3ace91eadb9

21 files changed:
Makefile.in
daemon/worker.c
daemon/worker.h
doc/Changelog
libunbound/libworker.c
smallapp/worker_cb.c
util/fptr_wlist.c
winrc/gen_msg.bin
winrc/gen_msg.mc
winrc/rsrc_svcinst.rc
winrc/rsrc_svcuninst.rc [new file with mode: 0644]
winrc/rsrc_unbound.rc
winrc/rsrc_unbound_checkconf.rc
winrc/rsrc_unbound_control.rc
winrc/rsrc_unbound_host.rc
winrc/unbound-service-install.c
winrc/unbound-service-remove.c
winrc/w_inst.c [new file with mode: 0644]
winrc/w_inst.h [new file with mode: 0644]
winrc/win_svc.c
winrc/win_svc.h

index be88f164ef9ed914ba44096126d80508dd682e6e..fbea6575048a384f4661494ddcaa742036457ccd 100644 (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))
 
index 244c6768a0414708d4533e4df5723e0cd1ca6baf..ec5bd7aa7529afc8d754c47e31deeb29c2f18b75 100644 (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;
index 47e349ed9487a3d926ed1676964da039c2c8676b..e9bf38a4a9edf120906c13a96ea3b0b98e61e72d 100644 (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 */
index ca2075d0d73dc558c206cfed32320bcb38535c42..76746b4f7a6143fa2e9a9c25817fe719efd6d4c7 100644 (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.
index 5f90bf249c110774fb44353191db15d90090bf6e..a68a4092d4f610775bfde1055d103937e9716fd6 100644 (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
index 0026eec97e66944140c3772f8e8db20be6a45323..a020a48ab55dd036defae5cb10dee0847aa8738d 100644 (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))
 {
index 7646ceb92180cbd3863a010b203792f3b9a4f3cc..16de532c1d1db467b0f7ce18df176e5c4c04b351 100644 (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;
 }
 
index 85612c7a235b7e2e7b83b64a5c9a4148071ef036..6e560057c26813430527e8906f6388206e0c7e82 100644 (file)
Binary files a/winrc/gen_msg.bin and b/winrc/gen_msg.bin differ
index 360805c410be8243f279eee302f47511c8ff626d..bde32176e8bb7cd0bb28bcd81735f83949c73b00 100644 (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
index 581eba30b1295d6af76708725689adcfd2436cc0..cb325f4c493510073bf1a2b7175f95d56527d77b 100644 (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
diff --git a/winrc/rsrc_svcuninst.rc b/winrc/rsrc_svcuninst.rc
new file mode 100644 (file)
index 0000000..ecff8dc
--- /dev/null
@@ -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"
+
index b6306f21e216757a089d824fc12f3578556fe451..cc05d0eeb51dace7fd784a3aeb13ec290305924e 100644 (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"
index 7a000a962b87fed2447a3513c3c52a7803353155..de61900bffb173a73e9fabf435afda2f64a5c627 100644 (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
index 312702ea650149dab4b32478d14edc0ae5bf2f27..f9e1245dbfa917a48cc494a1af25bb711b477f46 100644 (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
index 5a801e292f279dec0a462afde252cc2199b6d609..d00f95cf4d84e8d8492e9029bb03174f612fabc3 100644 (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
index 3364196bc95c7e12de527886e20a4ff88f0bc5c1..a68851444fc339caa425a09ada6a540d62708fe8 100644 (file)
  * (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;
 }
index 700b7aa9ddcfb2575f3fe58a09c81868dda5e22f..1d4abb090aaabdb63814fe56157b7de702c19197 100644 (file)
  * (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;
 }
diff --git a/winrc/w_inst.c b/winrc/w_inst.c
new file mode 100644 (file)
index 0000000..76b23ba
--- /dev/null
@@ -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");
+}
diff --git a/winrc/w_inst.h b/winrc/w_inst.h
new file mode 100644 (file)
index 0000000..94384be
--- /dev/null
@@ -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 */
index a1fe11b940cb3224b56e5ad4afa5bd254c2103c0..20014de3370c131de624125fc172eb9fd71ed237 100644 (file)
  */
 #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);
index c9717e46f6eee5baca116feab1a1ade32844e7de..0c030e7209e90d23e9096cfed4719a28eb42fa71 100644 (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).