]> git.proxmox.com Git - mirror_smartmontools-debian.git/blobdiff - os_win32/daemon_win32.cpp
Imported Upstream version 6.1+svn3812
[mirror_smartmontools-debian.git] / os_win32 / daemon_win32.cpp
index 481f0b5faf187cbcab5f18389f5eaa0ba86f6139..ae3dc29173697a84f4c779df12f1a1d338279283 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Home page of code is: http://smartmontools.sourceforge.net
  *
- * Copyright (C) 2004-11 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2004-13 Christian Franke <smartmontools-support@lists.sourceforge.net>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
-// Need MB_SERVICE_NOTIFICATION (NT4/2000/XP), IsDebuggerPresent() (Win98/ME/NT4/2000/XP)
-#define WINVER 0x0400
+#define WINVER 0x0600
 #define _WIN32_WINNT WINVER
 
+#include "daemon_win32.h"
+
+const char * daemon_win32_cpp_cvsid = "$Id: daemon_win32.cpp 3760 2013-01-30 18:43:39Z chrfranke $"
+  DAEMON_WIN32_H_CVSID;
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <crtdbg.h>
 #endif
 
-#include "daemon_win32.h"
-
-const char * daemon_win32_cpp_cvsid = "$Id: daemon_win32.cpp 3426 2011-10-06 18:23:15Z chrfranke $"
-  DAEMON_WIN32_H_CVSID;
+#ifndef SERVICE_CONFIG_DELAYED_AUTO_START_INFO
+// Missing in older MinGW headers
+#define SERVICE_CONFIG_DELAYED_AUTO_START_INFO 3
+#endif
 
 
 /////////////////////////////////////////////////////////////////////////////
 
-#define ARGUSED(x) ((void)(x))
-
 // Prevent spawning of child process if debugging
 #ifdef _DEBUG
 #define debugging() IsDebuggerPresent()
@@ -58,94 +59,94 @@ const char * daemon_win32_cpp_cvsid = "$Id: daemon_win32.cpp 3426 2011-10-06 18:
 
 static void make_name(char * name, int sig)
 {
-       int i;
-       if (!GetModuleFileNameA(NULL, name, EVT_NAME_LEN-10))
-               strcpy(name, "DaemonEvent");
-       for (i = 0; name[i]; i++) {
-               char c = name[i];
-               if (!(   ('0' <= c && c <= '9')
-                     || ('A' <= c && c <= 'Z')
-                     || ('a' <= c && c <= 'z')))
-                         name[i] = '_';
-       }
-       sprintf(name+strlen(name), "-%d", sig);
+  int i;
+  if (!GetModuleFileNameA(NULL, name, EVT_NAME_LEN-10))
+    strcpy(name, "DaemonEvent");
+  for (i = 0; name[i]; i++) {
+    char c = name[i];
+    if (!(   ('0' <= c && c <= '9')
+          || ('A' <= c && c <= 'Z')
+          || ('a' <= c && c <= 'z')))
+        name[i] = '_';
+  }
+  sprintf(name+strlen(name), "-%d", sig);
 }
 
 
 static HANDLE create_event(int sig, BOOL initial, BOOL errmsg, BOOL * exists)
 {
-       char name[EVT_NAME_LEN];
-       HANDLE h;
-       if (sig >= 0)
-               make_name(name, sig);
-       else
-               name[0] = 0;
-       if (exists)
-               *exists = FALSE;
-       if (!(h = CreateEventA(NULL, FALSE, initial, (name[0] ? name : NULL)))) {
-               if (errmsg)
-                       fprintf(stderr, "CreateEvent(.,\"%s\"): Error=%ld\n", name, GetLastError());
-               return 0;
-       }
-
-       if (GetLastError() == ERROR_ALREADY_EXISTS) {
-               if (!exists) {
-                       if (errmsg)
-                               fprintf(stderr, "CreateEvent(.,\"%s\"): Exists\n", name);
-                       CloseHandle(h);
-                       return 0;
-               }
-               *exists = TRUE;
-       }
-       return h;
+  char name[EVT_NAME_LEN];
+  HANDLE h;
+  if (sig >= 0)
+    make_name(name, sig);
+  else
+    name[0] = 0;
+  if (exists)
+    *exists = FALSE;
+  if (!(h = CreateEventA(NULL, FALSE, initial, (name[0] ? name : NULL)))) {
+    if (errmsg)
+      fprintf(stderr, "CreateEvent(.,\"%s\"): Error=%ld\n", name, GetLastError());
+    return 0;
+  }
+
+  if (GetLastError() == ERROR_ALREADY_EXISTS) {
+    if (!exists) {
+      if (errmsg)
+        fprintf(stderr, "CreateEvent(.,\"%s\"): Exists\n", name);
+      CloseHandle(h);
+      return 0;
+    }
+    *exists = TRUE;
+  }
+  return h;
 }
 
 
 static HANDLE open_event(int sig)
 {
-       char name[EVT_NAME_LEN];
-       make_name(name, sig);
-       return OpenEventA(EVENT_MODIFY_STATE, FALSE, name);
+  char name[EVT_NAME_LEN];
+  make_name(name, sig);
+  return OpenEventA(EVENT_MODIFY_STATE, FALSE, name);
 }
 
 
 static int event_exists(int sig)
 {
-       char name[EVT_NAME_LEN];
-       HANDLE h;
-       make_name(name, sig);
-       if (!(h = OpenEventA(EVENT_MODIFY_STATE, FALSE, name)))
-               return 0;
-       CloseHandle(h);
-       return 1;
+  char name[EVT_NAME_LEN];
+  HANDLE h;
+  make_name(name, sig);
+  if (!(h = OpenEventA(EVENT_MODIFY_STATE, FALSE, name)))
+    return 0;
+  CloseHandle(h);
+  return 1;
 }
 
 
 static int sig_event(int sig)
 {
-       char name[EVT_NAME_LEN];
-       HANDLE h;
-       make_name(name, sig);
-       if (!(h = OpenEventA(EVENT_MODIFY_STATE, FALSE, name))) {
-               make_name(name, EVT_RUNNING);
-               if (!(h = OpenEvent(EVENT_MODIFY_STATE, FALSE, name)))
-                       return -1;
-               CloseHandle(h);
-               return 0;
-       }
-       SetEvent(h);
-       CloseHandle(h);
-       return 1;
+  char name[EVT_NAME_LEN];
+  HANDLE h;
+  make_name(name, sig);
+  if (!(h = OpenEventA(EVENT_MODIFY_STATE, FALSE, name))) {
+    make_name(name, EVT_RUNNING);
+    if (!(h = OpenEvent(EVENT_MODIFY_STATE, FALSE, name)))
+      return -1;
+    CloseHandle(h);
+    return 0;
+  }
+  SetEvent(h);
+  CloseHandle(h);
+  return 1;
 }
 
 
 static void daemon_help(FILE * f, const char * ident, const char * message)
 {
-       fprintf(f,
-               "%s: %s.\n"
-               "Use \"%s status|stop|reload|restart|sigusr1|sigusr2\" to control daemon.\n",
-               ident, message, ident);
-       fflush(f);
+  fprintf(f,
+    "%s: %s.\n"
+    "Use \"%s status|stop|reload|restart|sigusr1|sigusr2\" to control daemon.\n",
+    ident, message, ident);
+  fflush(f);
 }
 
 
@@ -155,64 +156,64 @@ static void daemon_help(FILE * f, const char * ident, const char * message)
 
 static BOOL WINAPI parent_console_handler(DWORD event)
 {
-       switch (event) {
-               case CTRL_C_EVENT:
-               case CTRL_BREAK_EVENT:
-                       return TRUE; // Ignore
-       }
-       return FALSE; // continue with next handler ...
+  switch (event) {
+    case CTRL_C_EVENT:
+    case CTRL_BREAK_EVENT:
+      return TRUE; // Ignore
+  }
+  return FALSE; // continue with next handler ...
 }
 
 
 static int parent_main(HANDLE rev)
 {
-       HANDLE dev;
-       HANDLE ht[2];
-       char * cmdline;
-       STARTUPINFO si;
-       PROCESS_INFORMATION pi;
-       DWORD rc, exitcode;
-
-       // Ignore ^C, ^BREAK in parent
-       SetConsoleCtrlHandler(parent_console_handler, TRUE/*add*/);
-
-       // Create event used by child to signal daemon_detach()
-       if (!(dev = create_event(EVT_DETACHED, FALSE/*not signaled*/, TRUE, NULL/*must not exist*/))) {
-               CloseHandle(rev);
-               return 101;
-       }
-
-       // Restart process with same args
-       cmdline = GetCommandLineA();
-       memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
-       
-       if (!CreateProcessA(
-               NULL, cmdline,
-               NULL, NULL, TRUE/*inherit*/,
-               0, NULL, NULL, &si, &pi)) {
-               fprintf(stderr, "CreateProcess(.,\"%s\",.) failed, Error=%ld\n", cmdline, GetLastError());
-               CloseHandle(rev); CloseHandle(dev);
-               return 101;
-       }
-       CloseHandle(pi.hThread);
-
-       // Wait for daemon_detach() or exit()
-       ht[0] = dev; ht[1] = pi.hProcess;
-       rc = WaitForMultipleObjects(2, ht, FALSE/*or*/, INFINITE);
-       if (!(/*WAIT_OBJECT_0(0) <= rc && */ rc < WAIT_OBJECT_0+2)) {
-               fprintf(stderr, "WaitForMultipleObjects returns %lX\n", rc);
-               TerminateProcess(pi.hProcess, 200);
-       }
-       CloseHandle(rev); CloseHandle(dev);
-
-       // Get exit code
-       if (!GetExitCodeProcess(pi.hProcess, &exitcode))
-               exitcode = 201;
-       else if (exitcode == STILL_ACTIVE) // detach()ed, assume OK
-               exitcode = 0;
-
-       CloseHandle(pi.hProcess);
-       return exitcode;
+  HANDLE dev;
+  HANDLE ht[2];
+  char * cmdline;
+  STARTUPINFO si;
+  PROCESS_INFORMATION pi;
+  DWORD rc, exitcode;
+
+  // Ignore ^C, ^BREAK in parent
+  SetConsoleCtrlHandler(parent_console_handler, TRUE/*add*/);
+
+  // Create event used by child to signal daemon_detach()
+  if (!(dev = create_event(EVT_DETACHED, FALSE/*not signaled*/, TRUE, NULL/*must not exist*/))) {
+    CloseHandle(rev);
+    return 101;
+  }
+
+  // Restart process with same args
+  cmdline = GetCommandLineA();
+  memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
+
+  if (!CreateProcessA(
+    NULL, cmdline,
+    NULL, NULL, TRUE/*inherit*/,
+    0, NULL, NULL, &si, &pi)) {
+    fprintf(stderr, "CreateProcess(.,\"%s\",.) failed, Error=%ld\n", cmdline, GetLastError());
+    CloseHandle(rev); CloseHandle(dev);
+    return 101;
+  }
+  CloseHandle(pi.hThread);
+
+  // Wait for daemon_detach() or exit()
+  ht[0] = dev; ht[1] = pi.hProcess;
+  rc = WaitForMultipleObjects(2, ht, FALSE/*or*/, INFINITE);
+  if (!(/*WAIT_OBJECT_0(0) <= rc && */ rc < WAIT_OBJECT_0+2)) {
+    fprintf(stderr, "WaitForMultipleObjects returns %lX\n", rc);
+    TerminateProcess(pi.hProcess, 200);
+  }
+  CloseHandle(rev); CloseHandle(dev);
+
+  // Get exit code
+  if (!GetExitCodeProcess(pi.hProcess, &exitcode))
+    exitcode = 201;
+  else if (exitcode == STILL_ACTIVE) // detach()ed, assume OK
+    exitcode = 0;
+
+  CloseHandle(pi.hProcess);
+  return exitcode;
 }
 
 
@@ -248,77 +249,77 @@ static int reopen_stdin, reopen_stdout, reopen_stderr;
 
 static BOOL WINAPI child_console_handler(DWORD event)
 {
-       // Caution: runs in a new thread
-       // TODO: Guard with a mutex
-       HANDLE h = 0;
-       switch (event) {
-               case CTRL_C_EVENT: // <CONTROL-C> (SIGINT)
-                       h = sigint_handle; break;
-               case CTRL_BREAK_EVENT: // <CONTROL-Break> (SIGBREAK/SIGQUIT)
-               case CTRL_CLOSE_EVENT: // User closed console or abort via task manager
-                       h = sigbreak_handle; break;
-               case CTRL_LOGOFF_EVENT: // Logout/Shutdown (SIGTERM)
-               case CTRL_SHUTDOWN_EVENT:
-                       h = sigterm_handle; break;
-       }
-       if (!h)
-               return FALSE; // continue with next handler
-       // Signal event
-       if (!SetEvent(h))
-               return FALSE;
-       return TRUE;
+  // Caution: runs in a new thread
+  // TODO: Guard with a mutex
+  HANDLE h = 0;
+  switch (event) {
+    case CTRL_C_EVENT: // <CONTROL-C> (SIGINT)
+      h = sigint_handle; break;
+    case CTRL_BREAK_EVENT: // <CONTROL-Break> (SIGBREAK/SIGQUIT)
+    case CTRL_CLOSE_EVENT: // User closed console or abort via task manager
+      h = sigbreak_handle; break;
+    case CTRL_LOGOFF_EVENT: // Logout/Shutdown (SIGTERM)
+    case CTRL_SHUTDOWN_EVENT:
+      h = sigterm_handle; break;
+  }
+  if (!h)
+    return FALSE; // continue with next handler
+  // Signal event
+  if (!SetEvent(h))
+    return FALSE;
+  return TRUE;
 }
 
 
 static void child_exit(void)
 {
-       int i;
-       char * cmdline;
-       HANDLE rst;
-       STARTUPINFO si;
-       PROCESS_INFORMATION pi;
-
-       for (i = 0; i < num_sig_handlers; i++)
-               CloseHandle(sig_events[i]);
-       num_sig_handlers = 0;
-       CloseHandle(running_event); running_event = 0;
-
-       // Restart?
-       if (!(rst = open_event(EVT_RESTART)))
-               return; // No => normal exit
-
-       // Yes => Signal exit and restart process
-       Sleep(500);
-       SetEvent(rst);
-       CloseHandle(rst);
-       Sleep(500);
-
-       cmdline = GetCommandLineA();
-       memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
-       si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE;
-
-       if (!CreateProcessA(
-               NULL, cmdline,
-               NULL, NULL, TRUE/*inherit*/,
-               0, NULL, NULL, &si, &pi)) {
-               fprintf(stderr, "CreateProcess(.,\"%s\",.) failed, Error=%ld\n", cmdline, GetLastError());
-       }
-       CloseHandle(pi.hThread); CloseHandle(pi.hProcess);
+  int i;
+  char * cmdline;
+  HANDLE rst;
+  STARTUPINFO si;
+  PROCESS_INFORMATION pi;
+
+  for (i = 0; i < num_sig_handlers; i++)
+    CloseHandle(sig_events[i]);
+  num_sig_handlers = 0;
+  CloseHandle(running_event); running_event = 0;
+
+  // Restart?
+  if (!(rst = open_event(EVT_RESTART)))
+    return; // No => normal exit
+
+  // Yes => Signal exit and restart process
+  Sleep(500);
+  SetEvent(rst);
+  CloseHandle(rst);
+  Sleep(500);
+
+  cmdline = GetCommandLineA();
+  memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
+  si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE;
+
+  if (!CreateProcessA(
+    NULL, cmdline,
+    NULL, NULL, TRUE/*inherit*/,
+    0, NULL, NULL, &si, &pi)) {
+    fprintf(stderr, "CreateProcess(.,\"%s\",.) failed, Error=%ld\n", cmdline, GetLastError());
+  }
+  CloseHandle(pi.hThread); CloseHandle(pi.hProcess);
 }
 
 static int child_main(HANDLE hev,int (*main_func)(int, char **), int argc, char **argv)
 {
-       // Keep EVT_RUNNING open until exit
-       running_event = hev;
+  // Keep EVT_RUNNING open until exit
+  running_event = hev;
 
-       // Install console handler
-       SetConsoleCtrlHandler(child_console_handler, TRUE/*add*/);
+  // Install console handler
+  SetConsoleCtrlHandler(child_console_handler, TRUE/*add*/);
 
-       // Install restart handler
-       atexit(child_exit);
+  // Install restart handler
+  atexit(child_exit);
 
-       // Continue in main_func() to do the real work
-       return main_func(argc, argv);
+  // Continue in main_func() to do the real work
+  return main_func(argc, argv);
 }
 
 
@@ -326,33 +327,33 @@ static int child_main(HANDLE hev,int (*main_func)(int, char **), int argc, char
 
 sigfunc_t daemon_signal(int sig, sigfunc_t func)
 {
-       int i;
-       HANDLE h;
-       if (func == SIG_DFL || func == SIG_IGN)
-               return func; // TODO
-       for (i = 0; i < num_sig_handlers; i++) {
-               if (sig_numbers[i] == sig) {
-                       sigfunc_t old = sig_handlers[i];
-                       sig_handlers[i] = func;
-                       return old;
-               }
-       }
-       if (num_sig_handlers >= MAX_SIG_HANDLERS)
-               return SIG_ERR;
-       if (!(h = create_event((!svc_mode ? sig : -1), FALSE, TRUE, NULL)))
-               return SIG_ERR;
-       sig_events[num_sig_handlers]   = h;
-       sig_numbers[num_sig_handlers]  = sig;
-       sig_handlers[num_sig_handlers] = func;
-       switch (sig) {
-               case SIGHUP:   sighup_handle   = h; break;
-               case SIGINT:   sigint_handle   = h; break;
-               case SIGTERM:  sigterm_handle  = h; break;
-               case SIGBREAK: sigbreak_handle = h; break;
-               case SIGUSR1:  sigusr1_handle  = h; break;
-       }
-       num_sig_handlers++;
-       return SIG_DFL;
+  int i;
+  HANDLE h;
+  if (func == SIG_DFL || func == SIG_IGN)
+    return func; // TODO
+  for (i = 0; i < num_sig_handlers; i++) {
+    if (sig_numbers[i] == sig) {
+      sigfunc_t old = sig_handlers[i];
+      sig_handlers[i] = func;
+      return old;
+    }
+  }
+  if (num_sig_handlers >= MAX_SIG_HANDLERS)
+    return SIG_ERR;
+  if (!(h = create_event((!svc_mode ? sig : -1), FALSE, TRUE, NULL)))
+    return SIG_ERR;
+  sig_events[num_sig_handlers]   = h;
+  sig_numbers[num_sig_handlers]  = sig;
+  sig_handlers[num_sig_handlers] = func;
+  switch (sig) {
+    case SIGHUP:   sighup_handle   = h; break;
+    case SIGINT:   sigint_handle   = h; break;
+    case SIGTERM:  sigterm_handle  = h; break;
+    case SIGBREAK: sigbreak_handle = h; break;
+    case SIGUSR1:  sigusr1_handle  = h; break;
+  }
+  num_sig_handlers++;
+  return SIG_DFL;
 }
 
 
@@ -360,15 +361,15 @@ sigfunc_t daemon_signal(int sig, sigfunc_t func)
 
 const char * daemon_strsignal(int sig)
 {
-       switch (sig) {
-               case SIGHUP:  return "SIGHUP";
-               case SIGINT:  return "SIGINT";
-               case SIGTERM: return "SIGTERM";
-               case SIGBREAK:return "SIGBREAK";
-               case SIGUSR1: return "SIGUSR1";
-               case SIGUSR2: return "SIGUSR2";
-               default:      return "*UNKNOWN*";
-       }
+  switch (sig) {
+    case SIGHUP:  return "SIGHUP";
+    case SIGINT:  return "SIGINT";
+    case SIGTERM: return "SIGTERM";
+    case SIGBREAK:return "SIGBREAK";
+    case SIGUSR1: return "SIGUSR1";
+    case SIGUSR2: return "SIGUSR2";
+    default:      return "*UNKNOWN*";
+  }
 }
 
 
@@ -376,26 +377,26 @@ const char * daemon_strsignal(int sig)
 
 void daemon_sleep(int seconds)
 {
-       do {
-               if (num_sig_handlers <= 0) {
-                       Sleep(seconds*1000L);
-               }
-               else {
-                       // Wait for any signal or timeout
-                       DWORD rc = WaitForMultipleObjects(num_sig_handlers, sig_events,
-                               FALSE/*OR*/, seconds*1000L);
-                       if (rc != WAIT_TIMEOUT) {
-                               if (!(/*WAIT_OBJECT_0(0) <= rc && */ rc < WAIT_OBJECT_0+(unsigned)num_sig_handlers)) {
-                                       fprintf(stderr,"WaitForMultipleObjects returns %lu\n", rc);
-                                       Sleep(seconds*1000L);
-                                       return;
-                               }
-                               // Call Handler
-                               sig_handlers[rc-WAIT_OBJECT_0](sig_numbers[rc-WAIT_OBJECT_0]);
-                               break;
-                       }
-               }
-       } while (svc_paused);
+  do {
+    if (num_sig_handlers <= 0) {
+      Sleep(seconds*1000L);
+    }
+    else {
+      // Wait for any signal or timeout
+      DWORD rc = WaitForMultipleObjects(num_sig_handlers, sig_events,
+        FALSE/*OR*/, seconds*1000L);
+      if (rc != WAIT_TIMEOUT) {
+        if (!(/*WAIT_OBJECT_0(0) <= rc && */ rc < WAIT_OBJECT_0+(unsigned)num_sig_handlers)) {
+          fprintf(stderr,"WaitForMultipleObjects returns %lu\n", rc);
+          Sleep(seconds*1000L);
+          return;
+        }
+        // Call Handler
+        sig_handlers[rc-WAIT_OBJECT_0](sig_numbers[rc-WAIT_OBJECT_0]);
+        break;
+      }
+    }
+  } while (svc_paused);
 }
 
 
@@ -403,39 +404,39 @@ void daemon_sleep(int seconds)
 
 void daemon_disable_console()
 {
-       SetConsoleCtrlHandler(child_console_handler, FALSE/*remove*/);
-       reopen_stdin = reopen_stdout = reopen_stderr = 0;
-       if (isatty(fileno(stdin))) {
-               fclose(stdin); reopen_stdin = 1;
-       }
-       if (isatty(fileno(stdout))) {
-               fclose(stdout); reopen_stdout = 1;
-       }
-       if (isatty(fileno(stderr))) {
-               fclose(stderr); reopen_stderr = 1;
-       }
-       FreeConsole();
-       SetConsoleCtrlHandler(child_console_handler, TRUE/*add*/);
+  SetConsoleCtrlHandler(child_console_handler, FALSE/*remove*/);
+  reopen_stdin = reopen_stdout = reopen_stderr = 0;
+  if (isatty(fileno(stdin))) {
+    fclose(stdin); reopen_stdin = 1;
+  }
+  if (isatty(fileno(stdout))) {
+    fclose(stdout); reopen_stdout = 1;
+  }
+  if (isatty(fileno(stderr))) {
+    fclose(stderr); reopen_stderr = 1;
+  }
+  FreeConsole();
+  SetConsoleCtrlHandler(child_console_handler, TRUE/*add*/);
 }
 
 int daemon_enable_console(const char * title)
 {
-       BOOL ok;
-       SetConsoleCtrlHandler(child_console_handler, FALSE/*remove*/);
-       ok = AllocConsole();
-       SetConsoleCtrlHandler(child_console_handler, TRUE/*add*/);
-       if (!ok)
-               return -1;
-       if (title)
-               SetConsoleTitleA(title);
-       if (reopen_stdin)
-               freopen("conin$",  "r", stdin);
-       if (reopen_stdout)
-               freopen("conout$", "w", stdout);
-       if (reopen_stderr)
-               freopen("conout$", "w", stderr);
-       reopen_stdin = reopen_stdout = reopen_stderr = 0;
-       return 0;
+  BOOL ok;
+  SetConsoleCtrlHandler(child_console_handler, FALSE/*remove*/);
+  ok = AllocConsole();
+  SetConsoleCtrlHandler(child_console_handler, TRUE/*add*/);
+  if (!ok)
+    return -1;
+  if (title)
+    SetConsoleTitleA(title);
+  if (reopen_stdin)
+    freopen("conin$",  "r", stdin);
+  if (reopen_stdout)
+    freopen("conout$", "w", stdout);
+  if (reopen_stderr)
+    freopen("conout$", "w", stderr);
+  reopen_stdin = reopen_stdout = reopen_stderr = 0;
+  return 0;
 }
 
 
@@ -443,101 +444,28 @@ int daemon_enable_console(const char * title)
 
 int daemon_detach(const char * ident)
 {
-       if (!svc_mode) {
-               if (ident) {
-                       // Print help
-                       FILE * f = ( isatty(fileno(stdout)) ? stdout
-                                          : isatty(fileno(stderr)) ? stderr : NULL);
-                       if (f)
-                               daemon_help(f, ident, "now detaches from console into background mode");
-               }
-               // Signal detach to parent
-               if (sig_event(EVT_DETACHED) != 1) {
-                       if (!debugging())
-                               return -1;
-               }
-               daemon_disable_console();
-       }
-       else {
-               // Signal end of initialization to service control manager
-               service_report_status(SERVICE_RUNNING, 0);
-               reopen_stdin = reopen_stdout = reopen_stderr = 1;
-       }
-
-       return 0;
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-// MessageBox
-
-#ifndef _MT
-//MT runtime not necessary, because mbox_thread uses no unsafe lib functions
-//#error Program must be linked with multithreaded runtime library
-#endif
-
-static LONG mbox_count; // # mbox_thread()s
-static HANDLE mbox_mutex; // Show 1 box at a time (not necessary for service)
-
-typedef struct mbox_args_s {
-       HANDLE taken; const char * title, * text; int mode;
-} mbox_args;
-
-
-// Thread to display one message box
-
-static ULONG WINAPI mbox_thread(LPVOID arg)
-{
-       // Take args
-       mbox_args * mb = (mbox_args *)arg;
-       char title[100]; char text[1000]; int mode;
-       strncpy(title, mb->title, sizeof(title)-1); title[sizeof(title)-1] = 0;
-       strncpy(text , mb->text , sizeof(text )-1); text [sizeof(text )-1] = 0;
-       mode = mb->mode;
-       SetEvent(mb->taken);
-
-       // Show only one box at a time
-       WaitForSingleObject(mbox_mutex, INFINITE);
-       MessageBoxA(NULL, text, title, mode);
-       ReleaseMutex(mbox_mutex);
-
-       InterlockedDecrement(&mbox_count);
-       return 0;
-}
-
-
-// Display a message box
-int daemon_messagebox(int system, const char * title, const char * text)
-{
-       mbox_args mb;
-       HANDLE ht; DWORD tid;
-
-       // Create mutex during first call
-       if (!mbox_mutex)
-               mbox_mutex = CreateMutex(NULL/*!inherit*/, FALSE/*!owned*/, NULL/*unnamed*/);
-
-       // Allow at most 10 threads
-       if (InterlockedIncrement(&mbox_count) > 10) {
-               InterlockedDecrement(&mbox_count);
-               return -1;
-       }
-
-       // Create thread
-       mb.taken = CreateEvent(NULL/*!inherit*/, FALSE, FALSE/*!signaled*/, NULL/*unnamed*/);
-       mb.mode = MB_OK|MB_ICONWARNING
-                |(svc_mode?MB_SERVICE_NOTIFICATION:0)
-                |(system?MB_SYSTEMMODAL:MB_APPLMODAL);
-       mb.title = title;
-       mb.text = text;
-       if (!(ht = CreateThread(NULL, 0, mbox_thread, &mb, 0, &tid)))
-               return -1;
-
-       // Wait for args taken
-       if (WaitForSingleObject(mb.taken, 10000) != WAIT_OBJECT_0)
-               TerminateThread(ht, 0);
-       CloseHandle(mb.taken);
-       CloseHandle(ht);
-       return 0;
+  if (!svc_mode) {
+    if (ident) {
+      // Print help
+      FILE * f = ( isatty(fileno(stdout)) ? stdout
+             : isatty(fileno(stderr)) ? stderr : NULL);
+      if (f)
+        daemon_help(f, ident, "now detaches from console into background mode");
+    }
+    // Signal detach to parent
+    if (sig_event(EVT_DETACHED) != 1) {
+      if (!debugging())
+        return -1;
+    }
+    daemon_disable_console();
+  }
+  else {
+    // Signal end of initialization to service control manager
+    service_report_status(SERVICE_RUNNING, 0);
+    reopen_stdin = reopen_stdout = reopen_stderr = 1;
+  }
+
+  return 0;
 }
 
 
@@ -550,151 +478,108 @@ int daemon_spawn(const char * cmd,
                  const char * inpbuf, int inpsize,
                  char *       outbuf, int outsize )
 {
-       HANDLE pipe_inp_r, pipe_inp_w, pipe_out_r, pipe_out_w, pipe_err_w, h;
-       char temp_path[MAX_PATH];
-       DWORD flags, num_io, exitcode;
-       int use_file, state, i;
-       SECURITY_ATTRIBUTES sa;
-       STARTUPINFO si; PROCESS_INFORMATION pi;
-       HANDLE self = GetCurrentProcess();
-
-       if (GetVersion() & 0x80000000L) {
-               // Win9x/ME: A calling process never receives EOF if output of COMMAND.COM or
-               // any other DOS program is redirected via a pipe. Using a temp file instead.
-               use_file = 1; flags = DETACHED_PROCESS;
-       }
-       else {
-               // NT4/2000/XP: If DETACHED_PROCESS is used, CMD.EXE opens a new console window
-               // for each external command in a redirected .BAT file.
-               // Even (DETACHED_PROCESS|CREATE_NO_WINDOW) does not work.
-               use_file = 0; flags = CREATE_NO_WINDOW;
-       }
-
-       // Create stdin pipe with inheritable read side
-       memset(&sa, 0, sizeof(sa)); sa.nLength = sizeof(sa);
-       sa.bInheritHandle = TRUE;
-       if (!CreatePipe(&pipe_inp_r, &h, &sa/*inherit*/, inpsize*2+13))
-               return -1;
-       if (!DuplicateHandle(self, h, self, &pipe_inp_w,
-               0, FALSE/*!inherit*/, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE)) {
-               CloseHandle(pipe_inp_r);
-               return -1;
-       }
-
-       memset(&sa, 0, sizeof(sa)); sa.nLength = sizeof(sa);
-       sa.bInheritHandle = TRUE;
-       if (!use_file) {
-               // Create stdout pipe with inheritable write side
-               if (!CreatePipe(&h, &pipe_out_w, &sa/*inherit*/, outsize)) {
-                       CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-                       return -1;
-               }
-       }
-       else {
-               // Create temp file with inheritable write handle
-               char temp_dir[MAX_PATH];
-               if (!GetTempPathA(sizeof(temp_dir), temp_dir))
-                       strcpy(temp_dir, ".");
-               if (!GetTempFileNameA(temp_dir, "out"/*prefix*/, 0/*create unique*/, temp_path)) {
-                       CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-                       return -1;
-               }
-               if ((h = CreateFileA(temp_path, GENERIC_READ|GENERIC_WRITE,
-                       0/*no sharing*/, &sa/*inherit*/, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) {
-                       CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-                       return -1;
-               }
-               if (!DuplicateHandle(self, h, self, &pipe_out_w,
-                       GENERIC_WRITE, TRUE/*inherit*/, 0)) {
-                       CloseHandle(h); CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-                       return -1;
-               }
-       }
-
-       if (!DuplicateHandle(self, h, self, &pipe_out_r,
-               GENERIC_READ, FALSE/*!inherit*/, DUPLICATE_CLOSE_SOURCE)) {
-               CloseHandle(pipe_out_w); CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-               return -1;
-       }
-
-       // Create stderr handle as dup of stdout write side
-       if (!DuplicateHandle(self, pipe_out_w, self, &pipe_err_w,
-               0, TRUE/*inherit*/, DUPLICATE_SAME_ACCESS)) {
-               CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
-               CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-               return -1;
-       }
-
-       // Create process with pipes/file as stdio
-       memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
-       si.hStdInput  = pipe_inp_r;
-       si.hStdOutput = pipe_out_w;
-       si.hStdError  = pipe_err_w;
-       si.dwFlags = STARTF_USESTDHANDLES;
-       if (!CreateProcessA(
-               NULL, (char*)cmd,
-               NULL, NULL, TRUE/*inherit*/,
-               flags/*DETACHED_PROCESS or CREATE_NO_WINDOW*/,
-               NULL, NULL, &si, &pi)) {
-               CloseHandle(pipe_err_w);
-               CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
-               CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-               return -1;
-       }
-       CloseHandle(pi.hThread);
-       // Close inherited handles
-       CloseHandle(pipe_inp_r);
-       CloseHandle(pipe_out_w);
-       CloseHandle(pipe_err_w);
-
-       // Copy inpbuf to stdin
-       // convert \n => \r\n 
-       for (i = 0; i < inpsize; ) {
-               int len = 0;
-               while (i+len < inpsize && inpbuf[i+len] != '\n')
-                       len++;
-               if (len > 0)
-                       WriteFile(pipe_inp_w, inpbuf+i, len, &num_io, NULL);
-               i += len;
-               if (i < inpsize) {
-                       WriteFile(pipe_inp_w, "\r\n", 2, &num_io, NULL);
-                       i++;
-               }
-       }
-       CloseHandle(pipe_inp_w);
-
-       exitcode = 42;
-       for (state = 0; state < 2; state++) {
-               // stdout pipe: read pipe first
-               // stdout file: wait for process first
-               if (state == use_file) {
-                       // Copy stdout to output buffer until full, rest to /dev/null
-                       // convert \r\n => \n
-                       if (use_file)
-                               SetFilePointer(pipe_out_r, 0, NULL, FILE_BEGIN);
-                       for (i = 0; ; ) {
-                               char buf[256];
-                               int j;
-                               if (!ReadFile(pipe_out_r, buf, sizeof(buf), &num_io, NULL) || num_io == 0)
-                                       break;
-                               for (j = 0; i < outsize-1 && j < (int)num_io; j++) {
-                                       if (buf[j] != '\r')
-                                               outbuf[i++] = buf[j];
-                               }
-                       }
-                       outbuf[i] = 0;
-                       CloseHandle(pipe_out_r);
-                       if (use_file)
-                               DeleteFileA(temp_path);
-               }
-               else {
-                       // Wait for process exitcode
-                       WaitForSingleObject(pi.hProcess, INFINITE);
-                       GetExitCodeProcess(pi.hProcess, &exitcode);
-                       CloseHandle(pi.hProcess);
-               }
-       }
-       return exitcode;
+  HANDLE self = GetCurrentProcess();
+
+  // Create stdin pipe with inheritable read side
+  SECURITY_ATTRIBUTES sa;
+  memset(&sa, 0, sizeof(sa)); sa.nLength = sizeof(sa);
+  sa.bInheritHandle = TRUE;
+  HANDLE pipe_inp_r, pipe_inp_w, h;
+  if (!CreatePipe(&pipe_inp_r, &h, &sa/*inherit*/, inpsize*2+13))
+    return -1;
+  if (!DuplicateHandle(self, h, self, &pipe_inp_w,
+    0, FALSE/*!inherit*/, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE)) {
+    CloseHandle(pipe_inp_r);
+    return -1;
+  }
+
+  // Create stdout pipe with inheritable write side
+  memset(&sa, 0, sizeof(sa)); sa.nLength = sizeof(sa);
+  sa.bInheritHandle = TRUE;
+  HANDLE pipe_out_w;
+  if (!CreatePipe(&h, &pipe_out_w, &sa/*inherit*/, outsize)) {
+    CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
+    return -1;
+  }
+
+  HANDLE pipe_out_r;
+  if (!DuplicateHandle(self, h, self, &pipe_out_r,
+    GENERIC_READ, FALSE/*!inherit*/, DUPLICATE_CLOSE_SOURCE)) {
+    CloseHandle(pipe_out_w); CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
+    return -1;
+  }
+
+  // Create stderr handle as dup of stdout write side
+  HANDLE pipe_err_w;
+  if (!DuplicateHandle(self, pipe_out_w, self, &pipe_err_w,
+    0, TRUE/*inherit*/, DUPLICATE_SAME_ACCESS)) {
+    CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
+    CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
+    return -1;
+  }
+
+  // Create process with pipes as stdio
+  STARTUPINFO si;
+  memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
+  si.hStdInput  = pipe_inp_r;
+  si.hStdOutput = pipe_out_w;
+  si.hStdError  = pipe_err_w;
+  si.dwFlags = STARTF_USESTDHANDLES;
+  PROCESS_INFORMATION pi;
+  if (!CreateProcessA(
+    NULL, (char*)cmd,
+    NULL, NULL, TRUE/*inherit*/,
+    CREATE_NO_WINDOW, // DETACHED_PROCESS does not work
+    NULL, NULL, &si, &pi)) {
+    CloseHandle(pipe_err_w);
+    CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
+    CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
+    return -1;
+  }
+  CloseHandle(pi.hThread);
+  // Close inherited handles
+  CloseHandle(pipe_inp_r);
+  CloseHandle(pipe_out_w);
+  CloseHandle(pipe_err_w);
+
+  // Copy inpbuf to stdin
+  // convert \n => \r\n
+  DWORD num_io;
+  int i;
+  for (i = 0; i < inpsize; ) {
+    int len = 0;
+    while (i+len < inpsize && inpbuf[i+len] != '\n')
+      len++;
+    if (len > 0)
+      WriteFile(pipe_inp_w, inpbuf+i, len, &num_io, NULL);
+    i += len;
+    if (i < inpsize) {
+      WriteFile(pipe_inp_w, "\r\n", 2, &num_io, NULL);
+      i++;
+    }
+  }
+  CloseHandle(pipe_inp_w);
+
+  // Copy stdout to output buffer until full, rest to /dev/null
+  // convert \r\n => \n
+  for (i = 0; ; ) {
+    char buf[256];
+    if (!ReadFile(pipe_out_r, buf, sizeof(buf), &num_io, NULL) || num_io == 0)
+      break;
+    for (int j = 0; i < outsize-1 && j < (int)num_io; j++) {
+      if (buf[j] != '\r')
+        outbuf[i++] = buf[j];
+    }
+  }
+  outbuf[i] = 0;
+  CloseHandle(pipe_out_r);
+
+  // Wait for process exitcode
+  DWORD exitcode = 42;
+  WaitForSingleObject(pi.hProcess, INFINITE);
+  GetExitCodeProcess(pi.hProcess, &exitcode);
+  CloseHandle(pi.hProcess);
+  return exitcode;
 }
 
 
@@ -703,128 +588,128 @@ int daemon_spawn(const char * cmd,
 
 static int wait_signaled(HANDLE h, int seconds)
 {
-       int i;
-       for (i = 0; ; ) {
-               if (WaitForSingleObject(h, 1000L) == WAIT_OBJECT_0)
-                       return 0;
-               if (++i >= seconds)
-                       return -1;
-               fputchar('.'); fflush(stdout);
-       }
+  int i;
+  for (i = 0; ; ) {
+    if (WaitForSingleObject(h, 1000L) == WAIT_OBJECT_0)
+      return 0;
+    if (++i >= seconds)
+      return -1;
+    fputchar('.'); fflush(stdout);
+  }
 }
 
 
 static int wait_evt_running(int seconds, int exists)
 {
-       int i;
-       if (event_exists(EVT_RUNNING) == exists)
-               return 0;
-       for (i = 0; ; ) {
-               Sleep(1000);
-               if (event_exists(EVT_RUNNING) == exists)
-                       return 0;
-               if (++i >= seconds)
-                       return -1;
-               fputchar('.'); fflush(stdout);
-       }
+  int i;
+  if (event_exists(EVT_RUNNING) == exists)
+    return 0;
+  for (i = 0; ; ) {
+    Sleep(1000);
+    if (event_exists(EVT_RUNNING) == exists)
+      return 0;
+    if (++i >= seconds)
+      return -1;
+    fputchar('.'); fflush(stdout);
+  }
 }
 
 
 static int is_initd_command(char * s)
 {
-       if (!strcmp(s, "status"))
-               return EVT_RUNNING;
-       if (!strcmp(s, "stop"))
-               return SIGTERM;
-       if (!strcmp(s, "reload"))
-               return SIGHUP;
-       if (!strcmp(s, "sigusr1"))
-               return SIGUSR1;
-       if (!strcmp(s, "sigusr2"))
-               return SIGUSR2;
-       if (!strcmp(s, "restart"))
-               return EVT_RESTART;
-       return -1;
+  if (!strcmp(s, "status"))
+    return EVT_RUNNING;
+  if (!strcmp(s, "stop"))
+    return SIGTERM;
+  if (!strcmp(s, "reload"))
+    return SIGHUP;
+  if (!strcmp(s, "sigusr1"))
+    return SIGUSR1;
+  if (!strcmp(s, "sigusr2"))
+    return SIGUSR2;
+  if (!strcmp(s, "restart"))
+    return EVT_RESTART;
+  return -1;
 }
 
 
 static int initd_main(const char * ident, int argc, char **argv)
 {
-       int rc;
-       if (argc < 2)
-               return -1;
-       if ((rc = is_initd_command(argv[1])) < 0)
-               return -1;
-       if (argc != 2) {
-               printf("%s: no arguments allowed for command %s\n", ident, argv[1]);
-               return 1;
-       }
-
-       switch (rc) {
-               default:
-               case EVT_RUNNING:
-                       printf("Checking for %s:", ident); fflush(stdout);
-                       rc = event_exists(EVT_RUNNING);
-                       puts(rc ? " running" : " not running");
-                       return (rc ? 0 : 1);
-
-               case SIGTERM:
-                       printf("Stopping %s:", ident); fflush(stdout);
-                       rc = sig_event(SIGTERM);
-                       if (rc <= 0) {
-                               puts(rc < 0 ? " not running" : " error");
-                               return (rc < 0 ? 0 : 1);
-                       }
-                       rc = wait_evt_running(10, 0);
-                       puts(!rc ? " done" : " timeout");
-                       return (!rc ? 0 : 1);
-
-               case SIGHUP:
-                       printf("Reloading %s:", ident); fflush(stdout);
-                       rc = sig_event(SIGHUP);
-                       puts(rc > 0 ? " done" : rc == 0 ? " error" : " not running");
-                       return (rc > 0 ? 0 : 1);
-
-               case SIGUSR1:
-               case SIGUSR2:
-                       printf("Sending SIGUSR%d to %s:", (rc-SIGUSR1+1), ident); fflush(stdout);
-                       rc = sig_event(rc);
-                       puts(rc > 0 ? " done" : rc == 0 ? " error" : " not running");
-                       return (rc > 0 ? 0 : 1);
-
-               case EVT_RESTART:
-                       {
-                               HANDLE rst;
-                               printf("Stopping %s:", ident); fflush(stdout);
-                               if (event_exists(EVT_DETACHED)) {
-                                       puts(" not detached, cannot restart");
-                                       return 1;
-                               }
-                               if (!(rst = create_event(EVT_RESTART, FALSE, FALSE, NULL))) {
-                                       puts(" error");
-                                       return 1;
-                               }
-                               rc = sig_event(SIGTERM);
-                               if (rc <= 0) {
-                                       puts(rc < 0 ? " not running" : " error");
-                                       CloseHandle(rst);
-                                       return 1;
-                               }
-                               rc = wait_signaled(rst, 10);
-                               CloseHandle(rst);
-                               if (rc) {
-                                       puts(" timeout");
-                                       return 1;
-                               }
-                               puts(" done");
-                               Sleep(100);
-
-                               printf("Starting %s:", ident); fflush(stdout);
-                               rc = wait_evt_running(10, 1);
-                               puts(!rc ? " done" : " error");
-                               return (!rc ? 0 : 1);
-                       }
-       }
+  int rc;
+  if (argc < 2)
+    return -1;
+  if ((rc = is_initd_command(argv[1])) < 0)
+    return -1;
+  if (argc != 2) {
+    printf("%s: no arguments allowed for command %s\n", ident, argv[1]);
+    return 1;
+  }
+
+  switch (rc) {
+    default:
+    case EVT_RUNNING:
+      printf("Checking for %s:", ident); fflush(stdout);
+      rc = event_exists(EVT_RUNNING);
+      puts(rc ? " running" : " not running");
+      return (rc ? 0 : 1);
+
+    case SIGTERM:
+      printf("Stopping %s:", ident); fflush(stdout);
+      rc = sig_event(SIGTERM);
+      if (rc <= 0) {
+        puts(rc < 0 ? " not running" : " error");
+        return (rc < 0 ? 0 : 1);
+      }
+      rc = wait_evt_running(10, 0);
+      puts(!rc ? " done" : " timeout");
+      return (!rc ? 0 : 1);
+
+    case SIGHUP:
+      printf("Reloading %s:", ident); fflush(stdout);
+      rc = sig_event(SIGHUP);
+      puts(rc > 0 ? " done" : rc == 0 ? " error" : " not running");
+      return (rc > 0 ? 0 : 1);
+
+    case SIGUSR1:
+    case SIGUSR2:
+      printf("Sending SIGUSR%d to %s:", (rc-SIGUSR1+1), ident); fflush(stdout);
+      rc = sig_event(rc);
+      puts(rc > 0 ? " done" : rc == 0 ? " error" : " not running");
+      return (rc > 0 ? 0 : 1);
+
+    case EVT_RESTART:
+      {
+        HANDLE rst;
+        printf("Stopping %s:", ident); fflush(stdout);
+        if (event_exists(EVT_DETACHED)) {
+          puts(" not detached, cannot restart");
+          return 1;
+        }
+        if (!(rst = create_event(EVT_RESTART, FALSE, FALSE, NULL))) {
+          puts(" error");
+          return 1;
+        }
+        rc = sig_event(SIGTERM);
+        if (rc <= 0) {
+          puts(rc < 0 ? " not running" : " error");
+          CloseHandle(rst);
+          return 1;
+        }
+        rc = wait_signaled(rst, 10);
+        CloseHandle(rst);
+        if (rc) {
+          puts(" timeout");
+          return 1;
+        }
+        puts(" done");
+        Sleep(100);
+
+        printf("Starting %s:", ident); fflush(stdout);
+        rc = wait_evt_running(10, 1);
+        puts(!rc ? " done" : " error");
+        return (!rc ? 0 : 1);
+      }
+  }
 }
 
 
@@ -841,38 +726,30 @@ static SERVICE_STATUS svc_status;
 
 static void service_report_status(int state, int seconds)
 {
-       // TODO: Avoid race
-       static DWORD checkpoint = 1;
-       static DWORD accept_more = SERVICE_ACCEPT_PARAMCHANGE; // Win2000/XP
-       svc_status.dwCurrentState = state;
-       svc_status.dwWaitHint = seconds*1000;
-       switch (state) {
-               default:
-                       svc_status.dwCheckPoint = checkpoint++;
-                       break;
-               case SERVICE_RUNNING:
-               case SERVICE_STOPPED:
-                       svc_status.dwCheckPoint = 0;
-       }
-       switch (state) {
-               case SERVICE_START_PENDING:
-               case SERVICE_STOP_PENDING:
-                       svc_status.dwControlsAccepted = 0;
-                       break;
-               default:
-                       svc_status.dwControlsAccepted =
-                               SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN|
-                               SERVICE_ACCEPT_PAUSE_CONTINUE|accept_more;
-                       break;
-       }
-       if (!SetServiceStatus(svc_handle, &svc_status)) {
-               if (svc_status.dwControlsAccepted & accept_more) {
-                       // Retry without SERVICE_ACCEPT_PARAMCHANGE (WinNT4)
-                       svc_status.dwControlsAccepted &= ~accept_more;
-                       accept_more = 0;
-                       SetServiceStatus(svc_handle, &svc_status);
-               }
-       }
+  // TODO: Avoid race
+  static DWORD checkpoint = 1;
+  svc_status.dwCurrentState = state;
+  svc_status.dwWaitHint = seconds*1000;
+  switch (state) {
+    default:
+      svc_status.dwCheckPoint = checkpoint++;
+      break;
+    case SERVICE_RUNNING:
+    case SERVICE_STOPPED:
+      svc_status.dwCheckPoint = 0;
+  }
+  switch (state) {
+    case SERVICE_START_PENDING:
+    case SERVICE_STOP_PENDING:
+      svc_status.dwControlsAccepted = 0;
+      break;
+    default:
+      svc_status.dwControlsAccepted =
+        SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN|
+        SERVICE_ACCEPT_PAUSE_CONTINUE|SERVICE_ACCEPT_PARAMCHANGE;
+      break;
+  }
+  SetServiceStatus(svc_handle, &svc_status);
 }
 
 
@@ -880,35 +757,35 @@ static void service_report_status(int state, int seconds)
 
 static void WINAPI service_control(DWORD ctrlcode)
 {
-       switch (ctrlcode) {
-               case SERVICE_CONTROL_STOP:
-               case SERVICE_CONTROL_SHUTDOWN:
-                       service_report_status(SERVICE_STOP_PENDING, 30);
-                       svc_paused = 0;
-                       SetEvent(sigterm_handle);
-                       break;
-               case SERVICE_CONTROL_PARAMCHANGE: // Win2000/XP
-                       service_report_status(svc_status.dwCurrentState, 0);
-                       svc_paused = 0;
-                       SetEvent(sighup_handle); // reload
-                       break;
-               case SERVICE_CONTROL_PAUSE:
-                       service_report_status(SERVICE_PAUSED, 0);
-                       svc_paused = 1;
-                       break;
-               case SERVICE_CONTROL_CONTINUE:
-                       service_report_status(SERVICE_RUNNING, 0);
-                       {
-                               int was_paused = svc_paused;
-                               svc_paused = 0;
-                               SetEvent(was_paused ? sighup_handle : sigusr1_handle); // reload:recheck
-                       }
-                       break;
-               case SERVICE_CONTROL_INTERROGATE:
-               default: // unknown
-                       service_report_status(svc_status.dwCurrentState, 0);
-                       break;
-       }
+  switch (ctrlcode) {
+    case SERVICE_CONTROL_STOP:
+    case SERVICE_CONTROL_SHUTDOWN:
+      service_report_status(SERVICE_STOP_PENDING, 30);
+      svc_paused = 0;
+      SetEvent(sigterm_handle);
+      break;
+    case SERVICE_CONTROL_PARAMCHANGE: // Win2000/XP
+      service_report_status(svc_status.dwCurrentState, 0);
+      svc_paused = 0;
+      SetEvent(sighup_handle); // reload
+      break;
+    case SERVICE_CONTROL_PAUSE:
+      service_report_status(SERVICE_PAUSED, 0);
+      svc_paused = 1;
+      break;
+    case SERVICE_CONTROL_CONTINUE:
+      service_report_status(SERVICE_RUNNING, 0);
+      {
+        int was_paused = svc_paused;
+        svc_paused = 0;
+        SetEvent(was_paused ? sighup_handle : sigusr1_handle); // reload:recheck
+      }
+      break;
+    case SERVICE_CONTROL_INTERROGATE:
+    default: // unknown
+      service_report_status(svc_status.dwCurrentState, 0);
+      break;
+  }
 }
 
 
@@ -916,19 +793,19 @@ static void WINAPI service_control(DWORD ctrlcode)
 
 static void service_exit(void)
 {
-       // Close signal events
-       int i;
-       for (i = 0; i < num_sig_handlers; i++)
-               CloseHandle(sig_events[i]);
-       num_sig_handlers = 0;
-
-       // Set exitcode
-       if (daemon_winsvc_exitcode) {
-               svc_status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
-               svc_status.dwServiceSpecificExitCode = daemon_winsvc_exitcode;
-       }
-       // Report stopped
-       service_report_status(SERVICE_STOPPED, 0);
+  // Close signal events
+  int i;
+  for (i = 0; i < num_sig_handlers; i++)
+    CloseHandle(sig_events[i]);
+  num_sig_handlers = 0;
+
+  // Set exitcode
+  if (daemon_winsvc_exitcode) {
+    svc_status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
+    svc_status.dwServiceSpecificExitCode = daemon_winsvc_exitcode;
+  }
+  // Report stopped
+  service_report_status(SERVICE_STOPPED, 0);
 }
 
 
@@ -939,54 +816,106 @@ static char ** svc_main_argv;
 
 // Main function for service, called by service dispatcher
 
-static void WINAPI service_main(DWORD argc, LPSTR * argv)
+static void WINAPI service_main(DWORD /*argc*/, LPSTR * argv)
 {
-       char path[MAX_PATH], *p;
-       ARGUSED(argc);
+  char path[MAX_PATH], *p;
+
+  // Register control handler
+  svc_handle = RegisterServiceCtrlHandler(argv[0], service_control);
 
-       // Register control handler
-       svc_handle = RegisterServiceCtrlHandler(argv[0], service_control);
+  // Init service status
+  svc_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+  service_report_status(SERVICE_START_PENDING, 10);
 
-       // Init service status
-       svc_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
-       service_report_status(SERVICE_START_PENDING, 10);
+  // Service started in \windows\system32, change to .exe directory
+  if (GetModuleFileNameA(NULL, path, sizeof(path)) && (p = strrchr(path, '\\'))) {
+    *p = 0; SetCurrentDirectoryA(path);
+  }
 
-       // Service started in \windows\system32, change to .exe directory
-       if (GetModuleFileNameA(NULL, path, sizeof(path)) && (p = strrchr(path, '\\'))) {
-               *p = 0; SetCurrentDirectoryA(path);
-       }
-       
-       // Install exit handler
-       atexit(service_exit);
+  // Install exit handler
+  atexit(service_exit);
 
-       // Do the real work, service status later updated by daemon_detach()
-       daemon_winsvc_exitcode = svc_main_func(svc_main_argc, svc_main_argv);
+  // Do the real work, service status later updated by daemon_detach()
+  daemon_winsvc_exitcode = svc_main_func(svc_main_argc, svc_main_argv);
 
-       exit(daemon_winsvc_exitcode);
-       // ... continued in service_exit()
+  exit(daemon_winsvc_exitcode);
+  // ... continued in service_exit()
 }
 
 
 /////////////////////////////////////////////////////////////////////////////
 // Windows Service Admin Functions
 
-// Set Service description (Win2000/XP)
 
-static int svcadm_setdesc(SC_HANDLE hs, const char * desc)
+// Make registry key name for event message file
+static bool make_evtkey(char * buf, unsigned size, const char * ident)
+{
+  static const char prefix[] = "SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application\\";
+  const unsigned pfxlen = sizeof(prefix)-1;
+  unsigned idlen = strlen(ident);
+  if (pfxlen + idlen >= size) {
+    printf(" Buffer overflow\n");
+    return false;
+  }
+  memcpy(buf, prefix, pfxlen);
+  memcpy(buf+pfxlen, ident, idlen+1);
+  return true;
+}
+
+// Install this exe as event message file
+static void inst_evtmsg(const char * ident)
+{
+  printf("Installing event message file for %s:", ident); fflush(stdout);
+
+  char mypath[MAX_PATH];
+  if (!GetModuleFileNameA((HMODULE)0, mypath, sizeof(mypath))) {
+    printf(" unknown program path, Error=%ld\n", GetLastError());
+    return;
+  }
+
+  char subkey[MAX_PATH];
+  if (!make_evtkey(subkey, sizeof(subkey), ident))
+    return;
+
+  HKEY hk;
+  LONG err = RegCreateKeyExA(HKEY_LOCAL_MACHINE, subkey, 0, (char *)0, 0, KEY_ALL_ACCESS,
+                             (SECURITY_ATTRIBUTES *)0, &hk, (DWORD *)0);
+  if (err != ERROR_SUCCESS) {
+    printf(" RegCreateKeyEx failed, error=%ld\n", err);
+    return;
+  }
+
+  err = RegSetValueExA(hk, "EventMessageFile", 0, REG_SZ,
+                       (const BYTE *)mypath, strlen(mypath)+1);
+  if (err == ERROR_SUCCESS) {
+    DWORD val = EVENTLOG_INFORMATION_TYPE
+               |EVENTLOG_WARNING_TYPE
+               |EVENTLOG_ERROR_TYPE;
+    err = RegSetValueExA(hk, "TypesSupported", 0, REG_DWORD,
+                         (const BYTE *)&val, sizeof(val));
+  }
+  if (err != ERROR_SUCCESS)
+    printf(" RegSetValueEx failed, error=%ld\n", err);
+
+  RegCloseKey(hk);
+  puts(" done");
+}
+
+// Uninstall event message file
+static void uninst_evtmsg(const char * ident)
 {
-       HINSTANCE hdll;
-       BOOL (WINAPI * ChangeServiceConfig2A_p)(SC_HANDLE, DWORD, LPVOID);
-       BOOL ret;
-       if (!(hdll = LoadLibraryA("ADVAPI32.DLL")))
-               return FALSE;
-       if (!((ChangeServiceConfig2A_p = (BOOL (WINAPI *)(SC_HANDLE, DWORD, LPVOID))GetProcAddress(hdll, "ChangeServiceConfig2A"))))
-               ret = FALSE;
-       else {
-               SERVICE_DESCRIPTIONA sd = { (char *)desc };
-               ret = ChangeServiceConfig2A_p(hs, SERVICE_CONFIG_DESCRIPTION, &sd);
-       }
-       FreeLibrary(hdll);
-       return ret;
+  printf("Removing event message file for %s:", ident); fflush(stdout);
+
+  char subkey[MAX_PATH];
+  if (!make_evtkey(subkey, sizeof(subkey), ident))
+    return;
+
+  LONG err = RegDeleteKeyA(HKEY_LOCAL_MACHINE, subkey);
+  if (err != ERROR_SUCCESS && err != ERROR_FILE_NOT_FOUND) {
+    printf(" RegDeleteKey failed, error=%ld\n", err);
+    return;
+  }
+  puts(" done");
 }
 
 
@@ -995,111 +924,128 @@ static int svcadm_setdesc(SC_HANDLE hs, const char * desc)
 static int svcadm_main(const char * ident, const daemon_winsvc_options * svc_opts,
                        int argc, char **argv                                      )
 {
-       int remove; long err;
-       SC_HANDLE hm, hs;
-
-       if (argc < 2)
-               return -1;
-       if (!strcmp(argv[1], "install"))
-               remove = 0;
-       else if (!strcmp(argv[1], "remove")) {
-               if (argc != 2) {
-                       printf("%s: no arguments allowed for command remove\n", ident);
-                       return 1;
-               }
-               remove = 1;
-       }
-       else
-               return -1;
-
-       printf("%s service %s:", (!remove?"Installing":"Removing"), ident); fflush(stdout);
-
-       // Open SCM
-       if (!(hm = OpenSCManager(NULL/*local*/, NULL/*default*/, SC_MANAGER_ALL_ACCESS))) {
-               if ((err = GetLastError()) == ERROR_ACCESS_DENIED)
-                       puts(" access to SCManager denied");
-               else if (err == ERROR_CALL_NOT_IMPLEMENTED)
-                       puts(" services not implemented on this version of Windows");
-               else
-                       printf(" cannot open SCManager, Error=%ld\n", err);
-               return 1;
-       }
-
-       if (!remove) {
-               char path[MAX_PATH+100];
-               int i;
-               // Get program path
-               if (!GetModuleFileNameA(NULL, path, MAX_PATH)) {
-                       printf(" unknown program path, Error=%ld\n", GetLastError());
-                       CloseServiceHandle(hm);
-                       return 1;
-               }
-               // Add quotes if necessary
-               if (strchr(path, ' ')) {
-                       i = strlen(path);
-                       path[i+1] = '"'; path[i+2] = 0;
-                       while (--i >= 0)
-                               path[i+1] = path[i];
-                       path[0] = '"';
-               }
-               // Append options
-               strcat(path, " "); strcat(path, svc_opts->cmd_opt);
-               for (i = 2; i < argc; i++) {
-                       const char * s = argv[i];
-                       if (strlen(path)+1+1+strlen(s)+1 >= sizeof(path))
-                               break;
-                       // Add quotes if necessary
-                       if (strchr(s, ' ') && !strchr(s, '"')) {
-                               strcat(path, " \""); strcat(path, s); strcat(path, "\"");
-                       }
-                       else {
-                               strcat(path, " "); strcat(path, s);
-                       }
-               }
-               // Create
-               if (!(hs = CreateService(hm,
-                       svc_opts->svcname, svc_opts->dispname,
-                       SERVICE_ALL_ACCESS,
-                       SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS,
-                       SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, path,
-                       NULL/*no load ordering*/, NULL/*no tag id*/,
-                       ""/*no depedencies*/, NULL/*local system account*/, NULL/*no pw*/))) {
-                       if ((err = GetLastError()) == ERROR_SERVICE_EXISTS)
-                               puts(" the service is already installed");
-                       else if (err == ERROR_SERVICE_MARKED_FOR_DELETE)
-                               puts(" service is still running and marked for deletion\n"
-                                    "Stop the service and retry install");
-                       else
-                               printf(" failed, Error=%ld\n", err);
-                       CloseServiceHandle(hm);
-                       return 1;
-               }
-               // Set optional description
-               if (svc_opts->descript)
-                       svcadm_setdesc(hs, svc_opts->descript);
-       }
-       else {
-               // Open
-               if (!(hs = OpenService(hm, svc_opts->svcname, SERVICE_ALL_ACCESS))) {
-                       puts(" not found");
-                       CloseServiceHandle(hm);
-                       return 1;
-               }
-               // TODO: Stop service if running
-               // Remove
-               if (!DeleteService(hs)) {
-                       if ((err = GetLastError()) == ERROR_SERVICE_MARKED_FOR_DELETE)
-                               puts(" service is still running and marked for deletion\n"
-                                    "Stop the service to remove it");
-                       else
-                               printf(" failed, Error=%ld\n", err);
-                       CloseServiceHandle(hs); CloseServiceHandle(hm);
-                       return 1;
-               }
-       }
-       puts(" done");
-       CloseServiceHandle(hs); CloseServiceHandle(hm);
-       return 0;
+  int remove; long err;
+  SC_HANDLE hm, hs;
+
+  if (argc < 2)
+    return -1;
+  if (!strcmp(argv[1], "install"))
+    remove = 0;
+  else if (!strcmp(argv[1], "remove")) {
+    if (argc != 2) {
+      printf("%s: no arguments allowed for command remove\n", ident);
+      return 1;
+    }
+    remove = 1;
+  }
+  else
+    return -1;
+
+  printf("%s service %s:", (!remove?"Installing":"Removing"), ident); fflush(stdout);
+
+  // Open SCM
+  if (!(hm = OpenSCManager(NULL/*local*/, NULL/*default*/, SC_MANAGER_ALL_ACCESS))) {
+    if ((err = GetLastError()) == ERROR_ACCESS_DENIED)
+      puts(" access to SCManager denied");
+    else
+      printf(" cannot open SCManager, Error=%ld\n", err);
+    return 1;
+  }
+
+  if (!remove) {
+    char path[MAX_PATH+100];
+    int i;
+    // Get program path
+    if (!GetModuleFileNameA(NULL, path, MAX_PATH)) {
+      printf(" unknown program path, Error=%ld\n", GetLastError());
+      CloseServiceHandle(hm);
+      return 1;
+    }
+    // Add quotes if necessary
+    if (strchr(path, ' ')) {
+      i = strlen(path);
+      path[i+1] = '"'; path[i+2] = 0;
+      while (--i >= 0)
+        path[i+1] = path[i];
+      path[0] = '"';
+    }
+    // Append options
+    strcat(path, " "); strcat(path, svc_opts->cmd_opt);
+    for (i = 2; i < argc; i++) {
+      const char * s = argv[i];
+      if (strlen(path)+1+1+strlen(s)+1 >= sizeof(path))
+        break;
+      // Add quotes if necessary
+      if (strchr(s, ' ') && !strchr(s, '"')) {
+        strcat(path, " \""); strcat(path, s); strcat(path, "\"");
+      }
+      else {
+        strcat(path, " "); strcat(path, s);
+      }
+    }
+    // Create
+    if (!(hs = CreateService(hm,
+      svc_opts->svcname, svc_opts->dispname,
+      SERVICE_ALL_ACCESS,
+      SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS,
+      SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, path,
+      NULL/*no load ordering*/, NULL/*no tag id*/,
+      ""/*no depedencies*/, NULL/*local system account*/, NULL/*no pw*/))) {
+      if ((err = GetLastError()) == ERROR_SERVICE_EXISTS)
+        puts(" the service is already installed");
+      else if (err == ERROR_SERVICE_MARKED_FOR_DELETE)
+        puts(" service is still running and marked for deletion\n"
+             "Stop the service and retry install");
+      else
+        printf(" failed, Error=%ld\n", err);
+      CloseServiceHandle(hm);
+      return 1;
+    }
+    // Set optional description
+    if (svc_opts->descript) {
+      SERVICE_DESCRIPTIONA sd = { const_cast<char *>(svc_opts->descript) };
+      ChangeServiceConfig2A(hs, SERVICE_CONFIG_DESCRIPTION, &sd);
+    }
+    // Enable delayed auto start if supported
+    OSVERSIONINFOA ver; ver.dwOSVersionInfoSize = sizeof(ver);
+    if (   GetVersionExA(&ver)
+        && ver.dwPlatformId == VER_PLATFORM_WIN32_NT
+        && ver.dwMajorVersion >= 6 /* Vista */      ) {
+      SERVICE_DELAYED_AUTO_START_INFO sdasi = { TRUE };
+      ChangeServiceConfig2A(hs, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, &sdasi);
+    }
+  }
+  else {
+    // Open
+    if (!(hs = OpenService(hm, svc_opts->svcname, SERVICE_ALL_ACCESS))) {
+      puts(" not found");
+      CloseServiceHandle(hm);
+      return 1;
+    }
+    // TODO: Stop service if running
+    // Remove
+    if (!DeleteService(hs)) {
+      if ((err = GetLastError()) == ERROR_SERVICE_MARKED_FOR_DELETE)
+        puts(" service is still running and marked for deletion\n"
+             "Stop the service to remove it");
+      else
+        printf(" failed, Error=%ld\n", err);
+      CloseServiceHandle(hs); CloseServiceHandle(hm);
+      return 1;
+    }
+  }
+  puts(" done");
+  CloseServiceHandle(hs); CloseServiceHandle(hm);
+
+  // Install/Remove event message file registry entry
+  if (!remove) {
+    inst_evtmsg(ident);
+  }
+  else {
+    uninst_evtmsg(ident);
+  }
+
+  return 0;
 }
 
 
@@ -1112,77 +1058,77 @@ static int svcadm_main(const char * ident, const daemon_winsvc_options * svc_opt
 int daemon_main(const char * ident, const daemon_winsvc_options * svc_opts,
                 int (*main_func)(int, char **), int argc, char **argv      )
 {
-       int rc;
+  int rc;
 #ifdef _DEBUG
-       // Enable Debug heap checks
-       _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)
-               |_CRTDBG_ALLOC_MEM_DF|_CRTDBG_CHECK_ALWAYS_DF|_CRTDBG_LEAK_CHECK_DF);
+  // Enable Debug heap checks
+  _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)
+    |_CRTDBG_ALLOC_MEM_DF|_CRTDBG_CHECK_ALWAYS_DF|_CRTDBG_LEAK_CHECK_DF);
 #endif
 
-       // Check for [status|stop|reload|restart|sigusr1|sigusr2] parameters
-       if ((rc = initd_main(ident, argc, argv)) >= 0)
-               return rc;
-       // Check for [install|remove] parameters
-       if (svc_opts && (rc = svcadm_main(ident, svc_opts, argc, argv)) >= 0)
-               return rc;
-
-       // Run as service if svc_opts.cmd_opt is given as first(!) argument
-       svc_mode = (svc_opts && argc >= 2 && !strcmp(argv[1], svc_opts->cmd_opt));
-
-       if (!svc_mode) {
-               // Daemon: Try to simulate a Unix-like daemon
-               HANDLE rev;
-               BOOL exists;
-
-               // Create main event to detect process type:
-               // 1. new: parent process => start child and wait for detach() or exit() of child.
-               // 2. exists && signaled: child process => do the real work, signal detach() to parent
-               // 3. exists && !signaled: already running => exit()
-               if (!(rev = create_event(EVT_RUNNING, TRUE/*signaled*/, TRUE, &exists)))
-                       return 100;
-
-               if (!exists && !debugging()) {
-                       // Event new => parent process
-                       return parent_main(rev);
-               }
-
-               if (WaitForSingleObject(rev, 0) == WAIT_OBJECT_0) {
-                       // Event was signaled => In child process
-                       return child_main(rev, main_func, argc, argv);
-               }
-
-               // Event no longer signaled => Already running!
-               daemon_help(stdout, ident, "already running");
-               CloseHandle(rev);
-               return 1;
-       }
-       else {
-               // Service: Start service_main() via SCM
-               SERVICE_TABLE_ENTRY service_table[] = {
-                       { (char*)svc_opts->svcname, service_main }, { NULL, NULL }
-               };
-
-               svc_main_func = main_func;
-               svc_main_argc = argc;
-               svc_main_argv = argv;
-               if (!StartServiceCtrlDispatcher(service_table)) {
-                       printf("%s: cannot dispatch service, Error=%ld\n"
-                               "Option \"%s\" cannot be used to start %s as a service from console.\n"
-                               "Use \"%s install ...\" to install the service\n"
-                               "and \"net start %s\" to start it.\n",
-                               ident, GetLastError(), svc_opts->cmd_opt, ident, ident, ident);
+  // Check for [status|stop|reload|restart|sigusr1|sigusr2] parameters
+  if ((rc = initd_main(ident, argc, argv)) >= 0)
+    return rc;
+  // Check for [install|remove] parameters
+  if (svc_opts && (rc = svcadm_main(ident, svc_opts, argc, argv)) >= 0)
+    return rc;
+
+  // Run as service if svc_opts.cmd_opt is given as first(!) argument
+  svc_mode = (svc_opts && argc >= 2 && !strcmp(argv[1], svc_opts->cmd_opt));
+
+  if (!svc_mode) {
+    // Daemon: Try to simulate a Unix-like daemon
+    HANDLE rev;
+    BOOL exists;
+
+    // Create main event to detect process type:
+    // 1. new: parent process => start child and wait for detach() or exit() of child.
+    // 2. exists && signaled: child process => do the real work, signal detach() to parent
+    // 3. exists && !signaled: already running => exit()
+    if (!(rev = create_event(EVT_RUNNING, TRUE/*signaled*/, TRUE, &exists)))
+      return 100;
+
+    if (!exists && !debugging()) {
+      // Event new => parent process
+      return parent_main(rev);
+    }
+
+    if (WaitForSingleObject(rev, 0) == WAIT_OBJECT_0) {
+      // Event was signaled => In child process
+      return child_main(rev, main_func, argc, argv);
+    }
+
+    // Event no longer signaled => Already running!
+    daemon_help(stdout, ident, "already running");
+    CloseHandle(rev);
+    return 1;
+  }
+  else {
+    // Service: Start service_main() via SCM
+    SERVICE_TABLE_ENTRY service_table[] = {
+      { (char*)svc_opts->svcname, service_main }, { NULL, NULL }
+    };
+
+    svc_main_func = main_func;
+    svc_main_argc = argc;
+    svc_main_argv = argv;
+    if (!StartServiceCtrlDispatcher(service_table)) {
+      printf("%s: cannot dispatch service, Error=%ld\n"
+        "Option \"%s\" cannot be used to start %s as a service from console.\n"
+        "Use \"%s install ...\" to install the service\n"
+        "and \"net start %s\" to start it.\n",
+        ident, GetLastError(), svc_opts->cmd_opt, ident, ident, ident);
 
 #ifdef _DEBUG
-                       if (debugging())
-                               service_main(argc, argv);
+      if (debugging())
+        service_main(argc, argv);
 #endif
-                       return 100;
-               }
-               Sleep(1000);
-               ExitThread(0); // Do not redo exit() processing
-               /*NOTREACHED*/
-               return 0;
-       }
+      return 100;
+    }
+    Sleep(1000);
+    ExitThread(0); // Do not redo exit() processing
+    /*NOTREACHED*/
+    return 0;
+  }
 }
 
 
@@ -1195,88 +1141,88 @@ static volatile sig_atomic_t caughtsig = 0;
 
 static void sig_handler(int sig)
 {
-       caughtsig = sig;
+  caughtsig = sig;
 }
 
 static void test_exit(void)
 {
-       printf("Main exit\n");
+  printf("Main exit\n");
 }
 
 int test_main(int argc, char **argv)
 {
-       int i;
-       int debug = 0;
-       char * cmd = 0;
-
-       printf("PID=%ld\n", GetCurrentProcessId());
-       for (i = 0; i < argc; i++) {
-               printf("%d: \"%s\"\n", i, argv[i]);
-               if (!strcmp(argv[i],"-d"))
-                       debug = 1;
-       }
-       if (argc > 1 && argv[argc-1][0] != '-')
-               cmd = argv[argc-1];
-
-       daemon_signal(SIGINT, sig_handler);
-       daemon_signal(SIGBREAK, sig_handler);
-       daemon_signal(SIGTERM, sig_handler);
-       daemon_signal(SIGHUP, sig_handler);
-       daemon_signal(SIGUSR1, sig_handler);
-       daemon_signal(SIGUSR2, sig_handler);
-
-       atexit(test_exit);
-
-       if (!debug) {
-               printf("Preparing to detach...\n");
-               Sleep(2000);
-               daemon_detach("test");
-               printf("Detached!\n");
-       }
-
-       for (;;) {
-               daemon_sleep(1);
-               printf("."); fflush(stdout);
-               if (caughtsig) {
-                       if (caughtsig == SIGUSR2) {
-                               debug ^= 1;
-                               if (debug)
-                                       daemon_enable_console("Daemon[Debug]");
-                               else
-                                       daemon_disable_console();
-                       }
-                       else if (caughtsig == SIGUSR1 && cmd) {
-                               char inpbuf[200], outbuf[1000]; int rc;
-                               strcpy(inpbuf, "Hello\nWorld!\n");
-                               rc = daemon_spawn(cmd, inpbuf, strlen(inpbuf), outbuf, sizeof(outbuf));
-                               if (!debug)
-                                       daemon_enable_console("Command output");
-                               printf("\"%s\" returns %d\n", cmd, rc);
-                               if (rc >= 0)
-                                       printf("output:\n%s.\n", outbuf);
-                               fflush(stdout);
-                               if (!debug) {
-                                       Sleep(10000); daemon_disable_console();
-                               }
-                       }
-                       printf("[PID=%ld: Signal=%d]", GetCurrentProcessId(), caughtsig); fflush(stdout);
-                       if (caughtsig == SIGTERM || caughtsig == SIGBREAK)
-                               break;
-                       caughtsig = 0;
-               }
-       }
-       printf("\nExiting on signal %d\n", caughtsig);
-       return 0;
+  int i;
+  int debug = 0;
+  char * cmd = 0;
+
+  printf("PID=%ld\n", GetCurrentProcessId());
+  for (i = 0; i < argc; i++) {
+    printf("%d: \"%s\"\n", i, argv[i]);
+    if (!strcmp(argv[i],"-d"))
+      debug = 1;
+  }
+  if (argc > 1 && argv[argc-1][0] != '-')
+    cmd = argv[argc-1];
+
+  daemon_signal(SIGINT, sig_handler);
+  daemon_signal(SIGBREAK, sig_handler);
+  daemon_signal(SIGTERM, sig_handler);
+  daemon_signal(SIGHUP, sig_handler);
+  daemon_signal(SIGUSR1, sig_handler);
+  daemon_signal(SIGUSR2, sig_handler);
+
+  atexit(test_exit);
+
+  if (!debug) {
+    printf("Preparing to detach...\n");
+    Sleep(2000);
+    daemon_detach("test");
+    printf("Detached!\n");
+  }
+
+  for (;;) {
+    daemon_sleep(1);
+    printf("."); fflush(stdout);
+    if (caughtsig) {
+      if (caughtsig == SIGUSR2) {
+        debug ^= 1;
+        if (debug)
+          daemon_enable_console("Daemon[Debug]");
+        else
+          daemon_disable_console();
+      }
+      else if (caughtsig == SIGUSR1 && cmd) {
+        char inpbuf[200], outbuf[1000]; int rc;
+        strcpy(inpbuf, "Hello\nWorld!\n");
+        rc = daemon_spawn(cmd, inpbuf, strlen(inpbuf), outbuf, sizeof(outbuf));
+        if (!debug)
+          daemon_enable_console("Command output");
+        printf("\"%s\" returns %d\n", cmd, rc);
+        if (rc >= 0)
+          printf("output:\n%s.\n", outbuf);
+        fflush(stdout);
+        if (!debug) {
+          Sleep(10000); daemon_disable_console();
+        }
+      }
+      printf("[PID=%ld: Signal=%d]", GetCurrentProcessId(), caughtsig); fflush(stdout);
+      if (caughtsig == SIGTERM || caughtsig == SIGBREAK)
+        break;
+      caughtsig = 0;
+    }
+  }
+  printf("\nExiting on signal %d\n", caughtsig);
+  return 0;
 }
 
 
 int main(int argc, char **argv)
 {
-       static const daemon_winsvc_options svc_opts = {
-       "-s", "test", "Test Service", "Service to test daemon_win32.c Module"
-       };
+  static const daemon_winsvc_options svc_opts = {
+  "-s", "test", "Test Service", "Service to test daemon_win32.c Module"
+  };
 
-       return daemon_main("testd", &svc_opts, test_main, argc, argv);
+  return daemon_main("testd", &svc_opts, test_main, argc, argv);
 }
 
 #endif