You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by pq...@apache.org on 2008/04/07 18:31:24 UTC

svn commit: r645594 [28/28] - in /httpd/sandbox/amsterdam/d: ./ build/ docs/conf/ docs/conf/extra/ docs/man/ docs/manual/ docs/manual/developer/ docs/manual/faq/ docs/manual/howto/ docs/manual/misc/ docs/manual/mod/ docs/manual/platform/ docs/manual/pr...

Modified: httpd/sandbox/amsterdam/d/support/logresolve.dsp
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/support/logresolve.dsp?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/support/logresolve.dsp (original)
+++ httpd/sandbox/amsterdam/d/support/logresolve.dsp Mon Apr  7 09:28:58 2008
@@ -49,8 +49,8 @@
 # ADD BASE BSC32 /nologo
 # ADD BSC32 /nologo
 LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console
-# ADD LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /debug /opt:ref
+# ADD BASE LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib shell32.lib /nologo /subsystem:console
+# ADD LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib shell32.lib /nologo /subsystem:console /debug /opt:ref
 # Begin Special Build Tool
 TargetPath=.\Release\logresolve.exe
 SOURCE="$(InputPath)"
@@ -79,8 +79,8 @@
 # ADD BASE BSC32 /nologo
 # ADD BSC32 /nologo
 LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /incremental:no /debug
-# ADD LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /incremental:no /debug
+# ADD BASE LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib shell32.lib /nologo /subsystem:console /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib shell32.lib /nologo /subsystem:console /incremental:no /debug
 # Begin Special Build Tool
 TargetPath=.\Debug\logresolve.exe
 SOURCE="$(InputPath)"

Modified: httpd/sandbox/amsterdam/d/support/rotatelogs.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/support/rotatelogs.c?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/support/rotatelogs.c (original)
+++ httpd/sandbox/amsterdam/d/support/rotatelogs.c Mon Apr  7 09:28:58 2008
@@ -31,6 +31,9 @@
  * interval.  NB: Using -l in an environment which changes the GMT offset
  * (such as for BST or DST) can lead to unpredictable results!
  *
+ * -f option added Feb, 2008. This causes rotatelog to open/create
+ *    the logfile as soon as it's started, not as soon as it sees
+ *    data.
  */
 
 
@@ -42,6 +45,7 @@
 #include "apr_file_info.h"
 #include "apr_general.h"
 #include "apr_time.h"
+#include "apr_getopt.h"
 
 #if APR_HAVE_STDLIB_H
 #include <stdlib.h>
@@ -60,6 +64,52 @@
 #define MAX_PATH        1024
 #endif
 
+static void usage(const char *argv0, const char *reason)
+{
+    if (reason) {
+        fprintf(stderr, "%s\n", reason);
+    }
+    fprintf(stderr,
+            "Usage: %s [-l] [-f] <logfile> "
+            "{<rotation time in seconds>|<rotation size in megabytes>} "
+            "[offset minutes from UTC]\n\n",
+            argv0);
+#ifdef OS2
+    fprintf(stderr,
+            "Add this:\n\nTransferLog \"|%s.exe /some/where 86400\"\n\n",
+            argv0);
+#else
+    fprintf(stderr,
+            "Add this:\n\nTransferLog \"|%s /some/where 86400\"\n\n",
+            argv0);
+    fprintf(stderr,
+            "or \n\nTransferLog \"|%s /some/where 5M\"\n\n", argv0);
+#endif
+    fprintf(stderr,
+            "to httpd.conf. The generated name will be /some/where.nnnn "
+            "where nnnn is the\nsystem time at which the log nominally "
+            "starts (N.B. if using a rotation time,\nthe time will always "
+            "be a multiple of the rotation time, so you can synchronize\n"
+            "cron scripts with it). At the end of each rotation time or "
+            "when the file size\nis reached a new log is started.\n");
+    exit(1);
+}
+
+static int get_now(int use_localtime, int utc_offset)
+{
+    apr_time_t tNow = apr_time_now();
+    if (use_localtime) {
+        /* Check for our UTC offset before using it, since it might
+         * change if there's a switch between standard and daylight
+         * savings time.
+         */
+        apr_time_exp_t lt;
+        apr_time_exp_lt(&lt, tNow);
+        utc_offset = lt.tm_gmtoff;
+    }
+    return (int)apr_time_sec(tNow) + utc_offset;
+}
+
 int main (int argc, const char * const argv[])
 {
     char buf[BUFSIZE], buf2[MAX_PATH], errbuf[ERRMSGSZ];
@@ -69,74 +119,67 @@
     apr_size_t nRead, nWrite;
     int use_strftime = 0;
     int use_localtime = 0;
+    int bypass_io = 0;
     int now = 0;
     const char *szLogRoot;
     apr_file_t *f_stdin, *nLogFD = NULL, *nLogFDprev = NULL;
     apr_pool_t *pool;
+    apr_pool_t *pfile = NULL;
+    apr_pool_t *pfile_prev = NULL;
+    apr_getopt_t *opt;
+    apr_status_t rv;
+    char c;
+    const char *optarg;
     char *ptr = NULL;
-    int argBase = 0;
-    int argFile = 1;
-    int argIntv = 2;
-    int argOffset = 3;
 
     apr_app_initialize(&argc, &argv, NULL);
     atexit(apr_terminate);
 
     apr_pool_create(&pool, NULL);
-    if ((argc > 2) && (strcmp(argv[1], "-l") == 0)) {
-        argBase++;
-        argFile += argBase;
-        argIntv += argBase;
-        argOffset += argBase;
-        use_localtime = 1;
-    }
-    if (argc < (argBase + 3) || argc > (argBase + 4)) {
-        fprintf(stderr,
-                "Usage: %s [-l] <logfile> <rotation time in seconds> "
-                "[offset minutes from UTC] or <rotation size in megabytes>\n\n",
-                argv[0]);
-#ifdef OS2
-        fprintf(stderr,
-                "Add this:\n\nTransferLog \"|%s.exe /some/where 86400\"\n\n",
-                argv[0]);
-#else
-        fprintf(stderr,
-                "Add this:\n\nTransferLog \"|%s /some/where 86400\"\n\n",
-                argv[0]);
-        fprintf(stderr,
-                "or \n\nTransferLog \"|%s /some/where 5M\"\n\n", argv[0]);
-#endif
-        fprintf(stderr,
-                "to httpd.conf. The generated name will be /some/where.nnnn "
-                "where nnnn is the\nsystem time at which the log nominally "
-                "starts (N.B. if using a rotation time,\nthe time will always "
-                "be a multiple of the rotation time, so you can synchronize\n"
-                "cron scripts with it). At the end of each rotation time or "
-                "when the file size\nis reached a new log is started.\n");
-        exit(1);
+    apr_getopt_init(&opt, pool, argc, argv);
+    while ((rv = apr_getopt(opt, "lf", &c, &optarg)) == APR_SUCCESS) {
+        switch (c) {
+        case 'l':
+            use_localtime = 1;
+            break;
+        case 'f':
+            bypass_io = 1;
+            break;
+        }
     }
 
-    szLogRoot = argv[argFile];
+    if (rv != APR_EOF) {
+        usage(argv[0], NULL /* specific error message already issued */ );
+    }
+
+    if (opt->ind + 2 != argc && opt->ind + 3 != argc) {
+        usage(argv[0], "Incorrect number of arguments");
+    }
+
+    szLogRoot = argv[opt->ind++];
 
-    ptr = strchr(argv[argIntv], 'M');
-    if (ptr) {
+    ptr = strchr(argv[opt->ind], 'M');
+    if (ptr) { /* rotation based on file size */
         if (*(ptr+1) == '\0') {
-            sRotation = atoi(argv[argIntv]) * 1048576;
+            sRotation = atoi(argv[opt->ind]) * 1048576;
         }
         if (sRotation == 0) {
-            fprintf(stderr, "Invalid rotation size parameter\n");
-            exit(1);
+            usage(argv[0], "Invalid rotation size parameter");
         }
     }
-    else {
-        if (argc >= (argBase + 4)) {
-            utc_offset = atoi(argv[argOffset]) * 60;
-        }
-        tRotation = atoi(argv[argIntv]);
+    else { /* rotation based on elapsed time */
+        tRotation = atoi(argv[opt->ind]);
         if (tRotation <= 0) {
-            fprintf(stderr, "Rotation time must be > 0\n");
-            exit(6);
+            usage(argv[0], "Invalid rotation time parameter");
+        }
+    }
+    opt->ind++;
+
+    if (opt->ind < argc) { /* have UTC offset */
+        if (use_localtime) {
+            usage(argv[0], "UTC offset parameter is not valid with -l");
         }
+        utc_offset = atoi(argv[opt->ind]) * 60;
     }
 
     use_strftime = (strchr(szLogRoot, '%') != NULL);
@@ -147,21 +190,20 @@
 
     for (;;) {
         nRead = sizeof(buf);
-        if (apr_file_read(f_stdin, buf, &nRead) != APR_SUCCESS) {
-            exit(3);
+        /*
+         * Bypass reading stdin if we are forcing the logfile
+         * to be opened as soon as we start. Since we won't be
+         * writing anything, we just want to open the file.
+         * First time through is the only time we do this
+         * since we reset bypass_io after the 1st loop
+         */
+        if (!bypass_io) {
+            if (apr_file_read(f_stdin, buf, &nRead) != APR_SUCCESS) {
+                exit(3);
+            }
         }
         if (tRotation) {
-            /*
-             * Check for our UTC offset every time through the loop, since
-             * it might change if there's a switch between standard and
-             * daylight savings time.
-             */
-            if (use_localtime) {
-                apr_time_exp_t lt;
-                apr_time_exp_lt(&lt, apr_time_now());
-                utc_offset = lt.tm_gmtoff;
-            }
-            now = (int)(apr_time_now() / APR_USEC_PER_SEC) + utc_offset;
+            now = get_now(use_localtime, utc_offset);
             if (nLogFD != NULL && now >= tLogEnd) {
                 nLogFDprev = nLogFD;
                 nLogFD = NULL;
@@ -194,7 +236,7 @@
                 tLogStart = (now / tRotation) * tRotation;
             }
             else {
-                tLogStart = (int)apr_time_sec(apr_time_now());
+                tLogStart = get_now(use_localtime, utc_offset);
             }
 
             if (use_strftime) {
@@ -209,8 +251,10 @@
                 sprintf(buf2, "%s.%010d", szLogRoot, tLogStart);
             }
             tLogEnd = tLogStart + tRotation;
+            pfile_prev = pfile;
+            apr_pool_create(&pfile, pool);
             rv = apr_file_open(&nLogFD, buf2, APR_WRITE | APR_CREATE | APR_APPEND,
-                               APR_OS_DEFAULT, pool);
+                               APR_OS_DEFAULT, pfile);
             if (rv != APR_SUCCESS) {
                 char error[120];
 
@@ -225,6 +269,8 @@
                 }
                 else {
                     nLogFD = nLogFDprev;
+                    apr_pool_destroy(pfile);
+                    pfile = pfile_prev;
                     /* Try to keep this error message constant length
                      * in case it occurs several times. */
                     apr_snprintf(errbuf, sizeof errbuf,
@@ -241,26 +287,39 @@
             }
             else if (nLogFDprev) {
                 apr_file_close(nLogFDprev);
+                if (pfile_prev) {
+                    apr_pool_destroy(pfile_prev);
+                }
             }
             nMessCount = 0;
         }
-        nWrite = nRead;
-        apr_file_write(nLogFD, buf, &nWrite);
-        if (nWrite != nRead) {
-            nMessCount++;
-            sprintf(errbuf,
-                    "Error writing to log file. "
-                    "%10d messages lost.\n",
-                    nMessCount);
-            nWrite = strlen(errbuf);
-            apr_file_trunc(nLogFD, 0);
-            if (apr_file_write(nLogFD, errbuf, &nWrite) != APR_SUCCESS) {
-                fprintf(stderr, "Error writing to the file %s\n", buf2);
+        /*
+         * If we just bypassed reading stdin, due to bypass_io,
+         * then we have nothing to write, so skip this.
+         */
+        if (!bypass_io) {
+            nWrite = nRead;
+            apr_file_write(nLogFD, buf, &nWrite);
+            if (nWrite != nRead) {
+                nMessCount++;
+                sprintf(errbuf,
+                        "Error writing to log file. "
+                        "%10d messages lost.\n",
+                        nMessCount);
+                nWrite = strlen(errbuf);
+                apr_file_trunc(nLogFD, 0);
+                if (apr_file_write(nLogFD, errbuf, &nWrite) != APR_SUCCESS) {
+                    fprintf(stderr, "Error writing to the file %s\n", buf2);
                 exit(2);
+                }
+            }
+            else {
+                nMessCount++;
             }
         }
         else {
-            nMessCount++;
+           /* now worry about reading 'n writing all the time */
+           bypass_io = 0;
         }
     }
     /* Of course we never, but prevent compiler warnings */

Modified: httpd/sandbox/amsterdam/d/support/rotatelogs.dsp
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/support/rotatelogs.dsp?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/support/rotatelogs.dsp (original)
+++ httpd/sandbox/amsterdam/d/support/rotatelogs.dsp Mon Apr  7 09:28:58 2008
@@ -49,8 +49,8 @@
 # ADD BASE BSC32 /nologo
 # ADD BSC32 /nologo
 LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console
-# ADD LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /debug /opt:ref
+# ADD BASE LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib shell32.lib /nologo /subsystem:console
+# ADD LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib shell32.lib /nologo /subsystem:console /debug /opt:ref
 # Begin Special Build Tool
 TargetPath=.\Release\rotatelogs.exe
 SOURCE="$(InputPath)"
@@ -79,8 +79,8 @@
 # ADD BASE BSC32 /nologo
 # ADD BSC32 /nologo
 LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /incremental:no /debug
-# ADD LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /incremental:no /debug
+# ADD BASE LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib shell32.lib /nologo /subsystem:console /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib shell32.lib /nologo /subsystem:console /incremental:no /debug
 # Begin Special Build Tool
 TargetPath=.\Debug\rotatelogs.exe
 SOURCE="$(InputPath)"

Modified: httpd/sandbox/amsterdam/d/support/win32/ApacheMonitor.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/support/win32/ApacheMonitor.c?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/support/win32/ApacheMonitor.c (original)
+++ httpd/sandbox/amsterdam/d/support/win32/ApacheMonitor.c Mon Apr  7 09:28:58 2008
@@ -23,7 +23,7 @@
  * ====================================================================
  */
 
-#define _WIN32_WINNT 0x0400
+#define _WIN32_WINNT 0x0500
 #ifndef STRICT
 #define STRICT
 #endif
@@ -33,7 +33,6 @@
 
 #if defined(_MSC_VER) && _MSC_VER >= 1400
 #define _CRT_SECURE_NO_DEPRECATE
-#pragma warning(disable: 4996)
 #endif
 
 #include <windows.h>
@@ -43,8 +42,16 @@
 #include <shlobj.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <WtsApi32.h>
+#include <tchar.h>
 #include "ApacheMonitor.h"
 
+#ifndef AM_STRINGIFY
+/** Properly quote a value as a string in the C preprocessor */
+#define AM_STRINGIFY(n) AM_STRINGIFY_HELPER(n)
+/** Helper macro for AM_STRINGIFY */
+#define AM_STRINGIFY_HELPER(n) #n
+#endif
 
 #define OS_VERSION_WIN9X    1
 #define OS_VERSION_WINNT    2
@@ -68,24 +75,24 @@
 
 typedef struct _st_APACHE_SERVICE
 {
-    LPSTR    szServiceName;
-    LPSTR    szDisplayName;
-    LPSTR    szDescription;
-    LPSTR    szImagePath;
-    LPSTR    szComputerName;
+    LPTSTR   szServiceName;
+    LPTSTR   szDisplayName;
+    LPTSTR   szDescription;
+    LPTSTR   szImagePath;
+    LPTSTR   szComputerName;
     DWORD    dwPid;
 } ST_APACHE_SERVICE;
 
 typedef struct _st_MONITORED_COMPUTERS
 {
-    LPSTR   szComputerName;
+    LPTSTR  szComputerName;
     HKEY    hRegistry;
 } ST_MONITORED_COMP;
 
 /* Global variables */
 HINSTANCE         g_hInstance = NULL;
-CHAR             *g_szTitle;          /* The title bar text */
-CHAR             *g_szWindowClass;    /* Window Class Name  */
+TCHAR            *g_szTitle;          /* The title bar text */
+TCHAR            *g_szWindowClass;    /* Window Class Name  */
 HICON             g_icoStop;
 HICON             g_icoRun;
 UINT              g_bUiTaskbarCreated;
@@ -113,10 +120,10 @@
 LANGID            g_LangID;
 PROCESS_INFORMATION g_lpRedirectProc;
 CRITICAL_SECTION  g_stcSection;
-LPSTR             g_szLocalHost;
+LPTSTR            g_szLocalHost;
 
 /* locale language support */
-static CHAR *g_lpMsg[IDS_MSG_LAST - IDS_MSG_FIRST + 1];
+static TCHAR *g_lpMsg[IDS_MSG_LAST - IDS_MSG_FIRST + 1];
 
 
 void am_ClearServicesSt()
@@ -160,11 +167,11 @@
 }
 
 
-BOOL am_IsComputerConnected(LPSTR szComputerName)
+BOOL am_IsComputerConnected(LPTSTR szComputerName)
 {
     int i = 0;
     while (g_stComputers[i].szComputerName != NULL) {
-        if (strcmp(g_stComputers[i].szComputerName, szComputerName) == 0) {
+        if (_tcscmp(g_stComputers[i].szComputerName, szComputerName) == 0) {
             return TRUE;
         }
         ++i;
@@ -173,11 +180,11 @@
 }
 
 
-void am_DisconnectComputer(LPSTR szComputerName)
+void am_DisconnectComputer(LPTSTR szComputerName)
 {
     int i = 0, j;
     while (g_stComputers[i].szComputerName != NULL) {
-        if (strcmp(g_stComputers[i].szComputerName, szComputerName) == 0) {
+        if (_tcscmp(g_stComputers[i].szComputerName, szComputerName) == 0) {
             break;
         }
         ++i;
@@ -186,19 +193,16 @@
         free(g_stComputers[i].szComputerName);
         RegCloseKey(g_stComputers[i].hRegistry);
         for (j = i; j < MAX_APACHE_COMPUTERS - 1; j++) {
-            g_stComputers[i].szComputerName= g_stComputers[i+1].szComputerName;
-            g_stComputers[i].hRegistry = g_stComputers[i+1].hRegistry;
-        }
-        for (i = j; i < MAX_APACHE_COMPUTERS; i++) {
-            g_stComputers[i].szComputerName = NULL;
-            g_stComputers[i].hRegistry = NULL;
+            g_stComputers[j].szComputerName= g_stComputers[j+1].szComputerName;
+            g_stComputers[j].hRegistry = g_stComputers[j+1].hRegistry;
         }
+        g_stComputers[j].szComputerName = NULL;
+        g_stComputers[j].hRegistry = NULL;
     }
-
 }
 
 
-void ErrorMessage(LPCSTR szError, BOOL bFatal)
+void ErrorMessage(LPCTSTR szError, BOOL bFatal)
 {
     LPVOID lpMsgBuf = NULL;
     if (szError) {
@@ -210,8 +214,8 @@
                       FORMAT_MESSAGE_FROM_SYSTEM |
                       FORMAT_MESSAGE_IGNORE_INSERTS,
                       NULL, GetLastError(), g_LangID,
-                      (LPSTR) &lpMsgBuf, 0, NULL);
-        MessageBox(NULL, (LPCSTR)lpMsgBuf,
+                      (LPTSTR) &lpMsgBuf, 0, NULL);
+        MessageBox(NULL, (LPCTSTR)lpMsgBuf,
                    g_lpMsg[IDS_MSG_ERROR - IDS_MSG_FIRST],
                    MB_OK | (bFatal ? MB_ICONERROR : MB_ICONEXCLAMATION));
         LocalFree(lpMsgBuf);
@@ -222,14 +226,37 @@
 }
 
 
-BOOL am_ConnectComputer(LPSTR szComputerName)
+int am_RespawnAsUserAdmin(HWND hwnd, DWORD op, LPCTSTR szService, 
+                          LPCTSTR szComputerName)
+{
+    TCHAR args[MAX_PATH + MAX_COMPUTERNAME_LENGTH + 12];
+
+    if (g_dwOSVersion < OS_VERSION_WIN2K) {
+        ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST], FALSE);
+        return 0;
+    }
+
+    _sntprintf(args, sizeof(args) / sizeof(TCHAR), 
+               _T("%d \"%s\" \"%s\""), op, szService,
+               szComputerName ? szComputerName : _T(""));
+    if (!ShellExecute(hwnd, _T("runas"), __targv[0], args, NULL, SW_NORMAL)) {
+        ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST],
+                     FALSE);
+        return 0;
+    }
+
+    return 1;
+}
+
+
+BOOL am_ConnectComputer(LPTSTR szComputerName)
 {
     int i = 0;
     HKEY hKeyRemote;
-    char szTmp[MAX_PATH];
+    TCHAR szTmp[MAX_PATH];
 
     while (g_stComputers[i].szComputerName != NULL) {
-        if (strcmp(g_stComputers[i].szComputerName, szComputerName) == 0) {
+        if (_tcscmp(g_stComputers[i].szComputerName, szComputerName) == 0) {
             return FALSE;
         }
         ++i;
@@ -239,22 +266,23 @@
     }
     if (RegConnectRegistry(szComputerName, HKEY_LOCAL_MACHINE, &hKeyRemote)
             != ERROR_SUCCESS) {
-        sprintf(szTmp, g_lpMsg[IDS_MSG_ECONNECT - IDS_MSG_FIRST],
-                szComputerName);
+        _sntprintf(szTmp, sizeof(szTmp) / sizeof(TCHAR), 
+                   g_lpMsg[IDS_MSG_ECONNECT - IDS_MSG_FIRST],
+                   szComputerName);
         ErrorMessage(szTmp, FALSE);
         return FALSE;
     }
     else {
-        g_stComputers[i].szComputerName = strdup(szComputerName);
+        g_stComputers[i].szComputerName = _tcsdup(szComputerName);
         g_stComputers[i].hRegistry = hKeyRemote;
         return TRUE;
     }
 }
 
 
-LPSTR GetStringRes(int id)
+LPTSTR GetStringRes(int id)
 {
-    static CHAR buffer[MAX_PATH];
+    static TCHAR buffer[MAX_PATH];
 
     buffer[0] = 0;
     LoadString(GetModuleHandle(NULL), id, buffer, MAX_PATH);
@@ -330,22 +358,24 @@
         nid.hIcon = NULL;
     }
     if (n == i && n > 0) {
-        lstrcpy(nid.szTip, g_lpMsg[IDS_MSG_RUNNINGALL - IDS_MSG_FIRST]);
+        _tcscpy(nid.szTip, g_lpMsg[IDS_MSG_RUNNINGALL - IDS_MSG_FIRST]);
     }
     else if (n) {
-        sprintf(nid.szTip, g_lpMsg[IDS_MSG_RUNNING - IDS_MSG_FIRST], n, i);
+        _sntprintf(nid.szTip, sizeof(nid.szTip) / sizeof(TCHAR), 
+                  g_lpMsg[IDS_MSG_RUNNING - IDS_MSG_FIRST], n, i);
     }
     else if (i) {
-        sprintf(nid.szTip, g_lpMsg[IDS_MSG_RUNNINGNONE - IDS_MSG_FIRST], i);
+        _sntprintf(nid.szTip, sizeof(nid.szTip) / sizeof(TCHAR), 
+                  g_lpMsg[IDS_MSG_RUNNINGNONE - IDS_MSG_FIRST], i);
     }
     else {
-        lstrcpy(nid.szTip, g_lpMsg[IDS_MSG_NOSERVICES - IDS_MSG_FIRST]);
+        _tcscpy(nid.szTip, g_lpMsg[IDS_MSG_NOSERVICES - IDS_MSG_FIRST]);
     }
     Shell_NotifyIcon(dwMessage, &nid);
 }
 
 
-void appendMenuItem(HMENU hMenu, UINT uMenuId, LPSTR szName,
+void appendMenuItem(HMENU hMenu, UINT uMenuId, LPTSTR szName,
                     BOOL fDefault, BOOL fEnabled)
 {
     MENUITEMINFO mii;
@@ -353,7 +383,7 @@
     memset(&mii, 0, sizeof(MENUITEMINFO));
     mii.cbSize = sizeof(MENUITEMINFO);
     mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
-    if (lstrlen(szName))
+    if (_tcslen(szName))
     {
         mii.fType = MFT_STRING;
         mii.wID = uMenuId;
@@ -373,7 +403,7 @@
 
 
 void appendServiceMenu(HMENU hMenu, UINT uMenuId,
-                       LPSTR szServiceName, BOOL fRunning)
+                       LPTSTR szServiceName, BOOL fRunning)
 {
     MENUITEMINFO mii;
     HMENU smh;
@@ -418,7 +448,7 @@
                            g_lpMsg[IDS_MSG_MNUSERVICES - IDS_MSG_FIRST],
                            FALSE, TRUE);
         }
-        appendMenuItem(hMenu, 0, "", FALSE, TRUE);
+        appendMenuItem(hMenu, 0, _T(""), FALSE, TRUE);
         appendMenuItem(hMenu, IDM_EXIT,
                        g_lpMsg[IDS_MSG_MNUEXIT - IDS_MSG_FIRST],
                        FALSE, TRUE);
@@ -492,7 +522,7 @@
 }
 
 
-static void addListBoxItem(HWND hDlg, LPSTR lpStr, HBITMAP hBmp)
+static void addListBoxItem(HWND hDlg, LPTSTR lpStr, HBITMAP hBmp)
 {
     LRESULT nItem;
 
@@ -501,7 +531,7 @@
 }
 
 
-static void addListBoxString(HWND hListBox, LPSTR lpStr)
+static void addListBoxString(HWND hListBox, LPTSTR lpStr)
 {
     static int nItems = 0;
     if (!g_bDlgServiceOn) {
@@ -519,6 +549,32 @@
 }
 
 
+#ifndef UNICODE
+#define addListBoxStringA addListBoxString
+#else
+static void addListBoxStringA(HWND hListBox, LPSTR lpStr)
+{
+    static int nItems = 0;
+    TCHAR WStr[16384];
+
+    if (!g_bDlgServiceOn) {
+        return;
+    }
+    if (!MultiByteToWideChar(CP_ACP, 0, lpStr, (int)strlen(lpStr) + 1,
+                             WStr, (int) (sizeof(WStr) / sizeof(TCHAR))))
+        return;
+    ++nItems;
+    if (nItems > MAX_LOADSTRING)
+    {
+        SendMessage(hListBox, LB_RESETCONTENT, 0, 0);
+        nItems = 1;
+    }
+    ListBox_SetCurSel(hListBox,
+                      ListBox_AddString(hListBox, WStr));
+}
+#endif
+
+
 static DWORD WINAPI ConsoleOutputThread(LPVOID lpThreadParameter)
 {
     static BYTE lpBuffer[MAX_PATH+1];
@@ -533,7 +589,7 @@
             if (ch == '\n' || nPtr >= MAX_PATH)
             {
                 lpBuffer[nPtr] = '\0';
-                addListBoxString(g_hwndStdoutList, lpBuffer);
+                addListBoxStringA(g_hwndStdoutList, lpBuffer);
                 nPtr = 0;
             }
             else if (ch == '\t' && nPtr < (MAX_PATH - 4))
@@ -566,7 +622,7 @@
 }
 
 
-BOOL RunRedirectedConsole(LPSTR szCmdLine)
+BOOL RunRedirectedConsole(LPTSTR szCmdLine)
 {
     DWORD dwThreadId;
     HANDLE hProc;
@@ -633,7 +689,7 @@
 }
 
 
-BOOL RunAndForgetConsole(LPSTR szCmdLine, BOOL bRedirectConsole)
+BOOL RunAndForgetConsole(LPTSTR szCmdLine, BOOL bRedirectConsole)
 {
     STARTUPINFO stInfo;
     PROCESS_INFORMATION prInfo;
@@ -672,12 +728,12 @@
 }
 
 
-BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath,
-                         LPSTR szComputerName, DWORD dwCommand)
+BOOL ApacheManageService(LPCTSTR szServiceName, LPCTSTR szImagePath,
+                         LPTSTR szComputerName, DWORD dwCommand)
 {
-    CHAR szBuf[MAX_PATH];
-    CHAR szMsg[MAX_PATH];
-    LPSTR sPos;
+    TCHAR szBuf[MAX_PATH];
+    TCHAR szMsg[MAX_PATH];
+    LPTSTR sPos;
     BOOL retValue;
     BOOL serviceFlag = TRUE;
     SC_HANDLE schService;
@@ -687,32 +743,33 @@
 
     if (g_dwOSVersion == OS_VERSION_WIN9X)
     {
-        sPos = strstr(szImagePath, "-k start");
+        sPos = _tcsstr(szImagePath, _T("-k start"));
         if (sPos)
         {
-            lstrcpyn(szBuf, szImagePath, (int)(sPos - szImagePath));
+            _tcsncpy(szBuf, szImagePath, (int)(sPos - szImagePath));
             switch (dwCommand)
             {
             case SERVICE_CONTROL_STOP:
-                lstrcat(szBuf, " -k shutdown -n ");
+                _tcscat(szBuf, _T(" -k shutdown -n "));
                 break;
 
             case SERVICE_CONTROL_CONTINUE:
-                sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTART - IDS_MSG_FIRST],
-                        szServiceName);
+                _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR),
+                          g_lpMsg[IDS_MSG_SRVSTART - IDS_MSG_FIRST],
+                          szServiceName);
                 addListBoxString(g_hwndStdoutList, szMsg);
-                lstrcat(szBuf, " -k start -n ");
+                _tcscat(szBuf, _T(" -k start -n "));
                 serviceFlag = FALSE;
                 break;
 
             case SERVICE_APACHE_RESTART:
-                lstrcat(szBuf, " -k restart -n ");
+                _tcscat(szBuf, _T(" -k restart -n "));
                 break;
 
             default:
                 return FALSE;
             }
-            lstrcat(szBuf, szServiceName);
+            _tcscat(szBuf, szServiceName);
         }
         else {
             return FALSE;
@@ -728,8 +785,9 @@
         }
         else if (!serviceFlag)
         {
-            sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTARTED - IDS_MSG_FIRST],
-                    szServiceName);
+            _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), 
+                      g_lpMsg[IDS_MSG_SRVSTARTED - IDS_MSG_FIRST],
+                      szServiceName);
             addListBoxString(g_hwndStdoutList, szMsg);
             g_bConsoleRun = FALSE;
             SetCursor(g_hCursorArrow);
@@ -741,13 +799,29 @@
         schSCManager = OpenSCManager(szComputerName, NULL,
                                      SC_MANAGER_CONNECT);
         if (!schSCManager) {
+            ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST],
+                         FALSE);
             return FALSE;
         }
 
         schService = OpenService(schSCManager, szServiceName,
                                  SERVICE_QUERY_STATUS | SERVICE_START |
                                  SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL);
-        if (schService != NULL)
+        if (schService == NULL)
+        {
+            /* Avoid recursion of ImagePath NULL (from this Respawn) */
+            if (szImagePath) {
+                am_RespawnAsUserAdmin(g_hwndMain, dwCommand, 
+                                      szServiceName, szComputerName);
+            }
+            else {
+                ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST],
+                             FALSE);
+            }
+            CloseServiceHandle(schSCManager);
+            return FALSE;
+        }
+        else
         {
             retValue = FALSE;
             g_bConsoleRun = TRUE;
@@ -755,8 +829,9 @@
             switch (dwCommand)
             {
             case SERVICE_CONTROL_STOP:
-                sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTOP - IDS_MSG_FIRST],
-                        szServiceName);
+                _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), 
+                          g_lpMsg[IDS_MSG_SRVSTOP - IDS_MSG_FIRST],
+                          szServiceName);
                 addListBoxString(g_hwndStdoutList, szMsg);
                 if (ControlService(schService, SERVICE_CONTROL_STOP,
                                    &schSStatus)) {
@@ -777,17 +852,18 @@
                     if (schSStatus.dwCurrentState == SERVICE_STOPPED)
                     {
                         retValue = TRUE;
-                        sprintf(szMsg,
-                                g_lpMsg[IDS_MSG_SRVSTOPPED - IDS_MSG_FIRST],
-                                szServiceName);
+                        _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), 
+                                  g_lpMsg[IDS_MSG_SRVSTOPPED - IDS_MSG_FIRST],
+                                  szServiceName);
                         addListBoxString(g_hwndStdoutList, szMsg);
                     }
                 }
                 break;
 
             case SERVICE_CONTROL_CONTINUE:
-                sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTART - IDS_MSG_FIRST],
-                        szServiceName);
+                _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR),
+                          g_lpMsg[IDS_MSG_SRVSTART - IDS_MSG_FIRST],
+                          szServiceName);
                 addListBoxString(g_hwndStdoutList, szMsg);
 
                 if (StartService(schService, 0, NULL))
@@ -809,17 +885,18 @@
                     if (schSStatus.dwCurrentState == SERVICE_RUNNING)
                     {
                         retValue = TRUE;
-                        sprintf(szMsg,
-                                g_lpMsg[IDS_MSG_SRVSTARTED - IDS_MSG_FIRST],
-                                szServiceName);
+                        _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), 
+                                  g_lpMsg[IDS_MSG_SRVSTARTED - IDS_MSG_FIRST],
+                                  szServiceName);
                         addListBoxString(g_hwndStdoutList, szMsg);
                     }
                 }
                 break;
 
             case SERVICE_APACHE_RESTART:
-                sprintf(szMsg, g_lpMsg[IDS_MSG_SRVRESTART - IDS_MSG_FIRST],
-                        szServiceName);
+                _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), 
+                          g_lpMsg[IDS_MSG_SRVRESTART - IDS_MSG_FIRST],
+                          szServiceName);
                 addListBoxString(g_hwndStdoutList, szMsg);
                 if (ControlService(schService, SERVICE_APACHE_RESTART,
                                    &schSStatus))
@@ -844,9 +921,9 @@
                 if (schSStatus.dwCurrentState == SERVICE_RUNNING)
                 {
                     retValue = TRUE;
-                    sprintf(szMsg,
-                            g_lpMsg[IDS_MSG_SRVRESTARTED - IDS_MSG_FIRST],
-                            szServiceName);
+                    _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), 
+                              g_lpMsg[IDS_MSG_SRVRESTARTED - IDS_MSG_FIRST],
+                              szServiceName);
                     addListBoxString(g_hwndStdoutList, szMsg);
                 }
                 break;
@@ -861,10 +938,6 @@
             SetCursor(g_hCursorArrow);
             return retValue;
         }
-        else {
-            g_bRescanServices = TRUE;
-        }
-        CloseServiceHandle(schSCManager);
         return FALSE;
     }
 
@@ -872,7 +945,7 @@
 }
 
 
-BOOL IsServiceRunning(LPCSTR szServiceName, LPCSTR szComputerName,
+BOOL IsServiceRunning(LPCTSTR szServiceName, LPCTSTR szComputerName,
                       LPDWORD lpdwPid)
 {
     DWORD dwPid;
@@ -883,7 +956,7 @@
 
     if (g_dwOSVersion == OS_VERSION_WIN9X)
     {
-        hWnd = FindWindow("ApacheWin95ServiceMonitor", szServiceName);
+        hWnd = FindWindow(_T("ApacheWin95ServiceMonitor"), szServiceName);
         if (hWnd && GetWindowThreadProcessId(hWnd, &dwPid))
         {
             *lpdwPid = 1;
@@ -952,11 +1025,11 @@
 
 BOOL GetApacheServicesStatus()
 {
-    CHAR szKey[MAX_PATH];
-    CHAR achKey[MAX_PATH];
-    CHAR szImagePath[MAX_PATH];
-    CHAR szBuf[MAX_PATH];
-    CHAR szTmp[MAX_PATH];
+    TCHAR szKey[MAX_PATH];
+    TCHAR achKey[MAX_PATH];
+    TCHAR szImagePath[MAX_PATH];
+    TCHAR szBuf[MAX_PATH];
+    TCHAR szTmp[MAX_PATH];
     HKEY hKey, hSubKey, hKeyRemote;
     DWORD retCode, rv, dwKeyType;
     DWORD dwBufLen = MAX_PATH;
@@ -969,7 +1042,7 @@
     while (g_stComputers[computers].szComputerName != NULL) {
         hKeyRemote = g_stComputers[computers].hRegistry;
         retCode = RegOpenKeyEx(hKeyRemote,
-                               "System\\CurrentControlSet\\Services\\",
+                               _T("System\\CurrentControlSet\\Services\\"),
                                0, KEY_READ, &hKey);
         if (retCode != ERROR_SUCCESS)
         {
@@ -981,60 +1054,57 @@
             retCode = RegEnumKey(hKey, i, achKey, MAX_PATH);
             if (retCode == ERROR_SUCCESS)
             {
-                lstrcpy(szKey, "System\\CurrentControlSet\\Services\\");
-                lstrcat(szKey, achKey);
+                _tcscpy(szKey, _T("System\\CurrentControlSet\\Services\\"));
+                _tcscat(szKey, achKey);
 
                 if (RegOpenKeyEx(hKeyRemote, szKey, 0,
                                  KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS)
                 {
                     dwBufLen = MAX_PATH;
-                    rv = RegQueryValueEx(hSubKey, "ImagePath", NULL,
-                                         &dwKeyType, szImagePath, &dwBufLen);
+                    rv = RegQueryValueEx(hSubKey, _T("ImagePath"), NULL,
+                                         &dwKeyType, (LPBYTE)szImagePath, &dwBufLen);
 
                     if (rv == ERROR_SUCCESS
                             && (dwKeyType == REG_SZ
                              || dwKeyType == REG_EXPAND_SZ)
                             && dwBufLen)
                     {
-                        lstrcpy(szBuf, szImagePath);
+                        _tcscpy(szBuf, szImagePath);
                         CharLower(szBuf);
                         /* the service name could be httpd*.exe or Apache*.exe */
-                        if (((strstr(szBuf, "\\apache") != NULL)
-                             || (strstr(szBuf, "\\httpd") != NULL))
-                                && strstr(szBuf, ".exe")
-                                && (strstr(szBuf, "--ntservice") != NULL
-                                       || strstr(szBuf, "-k ") != NULL))
+                        if (((_tcsstr(szBuf, _T("\\apache")) != NULL)
+                             || (_tcsstr(szBuf, _T("\\httpd")) != NULL))
+                                && _tcsstr(szBuf, _T(".exe"))
+                                && (_tcsstr(szBuf, _T("--ntservice")) != NULL
+                                       || _tcsstr(szBuf, _T("-k ")) != NULL))
                         {
-                            g_stServices[stPos].szServiceName = strdup(achKey);
-                            g_stServices[stPos].szImagePath =
-                                                           strdup(szImagePath);
+                            g_stServices[stPos].szServiceName = _tcsdup(achKey);
+                            g_stServices[stPos].szImagePath = _tcsdup(szImagePath);
                             g_stServices[stPos].szComputerName =
-                               strdup(g_stComputers[computers].szComputerName);
+                                _tcsdup(g_stComputers[computers].szComputerName);
                             dwBufLen = MAX_PATH;
-                            if (RegQueryValueEx(hSubKey, "Description", NULL,
-                                                &dwKeyType, szBuf, &dwBufLen)
+                            if (RegQueryValueEx(hSubKey, _T("Description"), NULL,
+                                                &dwKeyType, (LPBYTE)szBuf, &dwBufLen)
                                     == ERROR_SUCCESS) {
-                                g_stServices[stPos].szDescription =
-                                                                 strdup(szBuf);
+                                g_stServices[stPos].szDescription = _tcsdup(szBuf);
                             }
                             dwBufLen = MAX_PATH;
-                            if (RegQueryValueEx(hSubKey, "DisplayName", NULL,
-                                                &dwKeyType, szBuf, &dwBufLen)
+                            if (RegQueryValueEx(hSubKey, _T("DisplayName"), NULL,
+                                                &dwKeyType, (LPBYTE)szBuf, &dwBufLen)
                                     == ERROR_SUCCESS)
                             {
-                                if (strcmp(g_stComputers[computers]
+                                if (_tcscmp(g_stComputers[computers]
                                         .szComputerName, g_szLocalHost) != 0)
                                 {
-                                    strcpy(szTmp, g_stComputers[computers]
+                                    _tcscpy(szTmp, g_stComputers[computers]
                                                       .szComputerName + 2);
-                                    strcat(szTmp, "@");
-                                    strcat(szTmp, szBuf);
+                                    _tcscat(szTmp, _T("@"));
+                                    _tcscat(szTmp, szBuf);
                                 }
                                 else {
-                                    strcpy(szTmp, szBuf);
+                                    _tcscpy(szTmp, szBuf);
                                 }
-                                g_stServices[stPos].szDisplayName
-                                                        = strdup(szTmp);
+                                g_stServices[stPos].szDisplayName = _tcsdup(szTmp);
 
                             }
                             ++stPos;
@@ -1048,8 +1118,8 @@
             }
         }
         ++computers;
+        RegCloseKey(hKey);
     }
-    RegCloseKey(hKey);
     FindRunningServices();
     return TRUE;
 }
@@ -1058,7 +1128,7 @@
 LRESULT CALLBACK ConnectDlgProc(HWND hDlg, UINT message,
                                 WPARAM wParam, LPARAM lParam)
 {
-    CHAR szCmp[MAX_COMPUTERNAME_LENGTH+4];
+    TCHAR szCmp[MAX_COMPUTERNAME_LENGTH+4];
     switch (message)
     {
     case WM_INITDIALOG:
@@ -1073,14 +1143,14 @@
         switch (LOWORD(wParam))
         {
         case IDOK:
-            memset(szCmp, 0, MAX_COMPUTERNAME_LENGTH+4);
-            strcpy(szCmp, "\\\\");
+            memset(szCmp, 0, sizeof(szCmp));
+            _tcscpy(szCmp, _T("\\\\"));
             SendMessage(GetDlgItem(hDlg, IDC_COMPUTER), WM_GETTEXT,
                         (WPARAM) MAX_COMPUTERNAME_LENGTH,
                         (LPARAM) szCmp+2);
 
-            strupr(szCmp);
-            if (strlen(szCmp) < 3) {
+            _tcsupr(szCmp);
+            if (_tcslen(szCmp) < 3) {
                 EndDialog(hDlg, TRUE);
                 return TRUE;
             }
@@ -1099,7 +1169,7 @@
             memset(&bi, 0, sizeof(BROWSEINFO));
             SHGetSpecialFolderLocation(hDlg, CSIDL_NETWORK, &il);
 
-            bi.lpszTitle      = "ApacheMonitor :\nSelect Network Computer!";
+            bi.lpszTitle      = _T("ApacheMonitor :\nSelect Network Computer!");
             bi.pszDisplayName = szCmp;
             bi.hwndOwner =      hDlg;
             bi.ulFlags =        BIF_BROWSEFORCOMPUTER;
@@ -1138,7 +1208,7 @@
 LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message,
                                 WPARAM wParam, LPARAM lParam)
 {
-    CHAR szBuf[MAX_PATH];
+    TCHAR szBuf[MAX_PATH];
     HWND hListBox;
     static HWND hStatusBar;
     TEXTMETRIC tm;
@@ -1149,7 +1219,7 @@
     LPMEASUREITEMSTRUCT lpmis;
     LPDRAWITEMSTRUCT lpdis;
 
-    memset(szBuf, 0, MAX_PATH);
+    memset(szBuf, 0, sizeof(szBuf));
     switch (message)
     {
     case WM_INITDIALOG:
@@ -1182,7 +1252,7 @@
         g_hwndStdoutList = GetDlgItem(hDlg, IDL_STDOUT);
         hStatusBar = CreateStatusWindow(0x0800 /* SBT_TOOLTIPS */
                                       | WS_CHILD | WS_VISIBLE,
-                                        "", hDlg, IDC_STATBAR);
+                                        _T(""), hDlg, IDC_STATBAR);
         if (GetApacheServicesStatus())
         {
             i = 0;
@@ -1213,7 +1283,7 @@
     case WM_UPDATEMESSAGE:
         hListBox = GetDlgItem(hDlg, IDL_SERVICES);
         SendMessage(hListBox, LB_RESETCONTENT, 0, 0);
-        SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)"");
+        SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)_T(""));
         Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
         Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
         Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
@@ -1302,7 +1372,7 @@
                     Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
                     Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
                 }
-                if (strcmp(g_stServices[lpdis->itemID].szComputerName,
+                if (_tcscmp(g_stServices[lpdis->itemID].szComputerName,
                            g_szLocalHost) == 0) {
                     Button_Enable(GetDlgItem(hDlg, IDC_SDISCONN), FALSE);
                 }
@@ -1315,7 +1385,7 @@
                             (LPARAM)g_stServices[lpdis->itemID].szDescription);
                 }
                 else {
-                    SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)"");
+                    SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)_T(""));
                 }
                 SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
                 SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
@@ -1327,7 +1397,7 @@
                SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW));
                FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_WINDOW+1));
             }
-            TextOut(lpdis->hDC, XBITMAP + 6, y, szBuf, (int)strlen(szBuf));
+            TextOut(lpdis->hDC, XBITMAP + 6, y, szBuf, (int)_tcslen(szBuf));
             break;
 
         case ODA_FOCUS:
@@ -1402,7 +1472,7 @@
 
         case IDC_SMANAGER:
             if (g_dwOSVersion >= OS_VERSION_WIN2K) {
-                ShellExecute(hDlg, "open", "services.msc", "/s",
+                ShellExecute(hDlg, _T("open"), _T("services.msc"), _T("/s"),
                              NULL, SW_NORMAL);
             }
             else {
@@ -1615,7 +1685,7 @@
 
         case IDC_SMANAGER:
             if (g_dwOSVersion >= OS_VERSION_WIN2K) {
-                ShellExecute(NULL, "open", "services.msc", "/s",
+                ShellExecute(NULL, _T("open"), _T("services.msc"), _T("/s"),
                              NULL, SW_NORMAL);
             }
             else {
@@ -1637,18 +1707,86 @@
 }
 
 
+static int KillAWindow(HWND appwindow)
+{
+    HANDLE appproc;
+    DWORD procid;
+    BOOL postres;
+
+    SetLastError(0);
+    GetWindowThreadProcessId(appwindow, &procid);
+    if (GetLastError())
+        return(2);
+
+    appproc = OpenProcess(SYNCHRONIZE, 0, procid);
+    postres = PostMessage(appwindow, WM_COMMAND, IDM_EXIT, 0);
+    if (appproc && postres) {
+        if (WaitForSingleObject(appproc, 10 /* seconds */ * 1000)
+                == WAIT_OBJECT_0) {
+            CloseHandle(appproc);
+            return (0);
+        }
+    }
+    if (appproc)
+        CloseHandle(appproc);
+
+    if ((appproc = OpenProcess(PROCESS_TERMINATE, 0, procid)) != NULL) {
+        if (TerminateProcess(appproc, 0)) {
+            CloseHandle(appproc);
+            return (0);
+        }
+        CloseHandle(appproc);
+    }
+
+    /* Perhaps we were short of permissions? */
+    return (2);
+}
+
+
+static int KillAllMonitors(void)
+{
+    HWND appwindow;
+    int exitcode = 0;
+    PWTS_PROCESS_INFO tsProcs;
+    DWORD tsProcCount, i;
+    DWORD thisProcId; 
+
+    /* This is graceful, close our own Window, clearing the icon */
+    if ((appwindow = FindWindow(g_szWindowClass, g_szTitle)) != NULL)
+        exitcode = KillAWindow(appwindow);
+
+    if (g_dwOSVersion < OS_VERSION_WIN2K)
+        return exitcode;
+
+    thisProcId = GetCurrentProcessId();
+
+    if (!WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1,
+                               &tsProcs, &tsProcCount))
+        return exitcode;
+
+    /* This is ungraceful; close other Windows, with a lingering icon.
+     * Since on terminal server it's not possible to post the message
+     * to exit across sessions, we have to suffer this side effect
+     * of a taskbar 'icon' which will evaporate the next time that
+     * the user hovers over it or when the taskbar area is updated.
+     */
+    for (i = 0; i < tsProcCount; ++i) {
+        if (_tcscmp(tsProcs[i].pProcessName, _T(AM_STRINGIFY(BIN_NAME))) == 0
+                && tsProcs[i].ProcessId != thisProcId)
+            WTSTerminateProcess(WTS_CURRENT_SERVER_HANDLE, 
+                                tsProcs[i].ProcessId, 1);
+    }
+    WTSFreeMemory(tsProcs);
+    return exitcode;
+}
+
+
 /* Create main invisible window */
 HWND CreateMainWindow(HINSTANCE hInstance)
 {
     HWND hWnd = NULL;
     WNDCLASSEX wcex;
 
-    if (!GetSystemOSVersion(&g_dwOSVersion))
-    {
-        ErrorMessage(NULL, TRUE);
-        return hWnd;
-    }
-
     wcex.cbSize = sizeof(WNDCLASSEX);
 
     wcex.style          = CS_HREDRAW | CS_VREDRAW;
@@ -1671,42 +1809,89 @@
                             NULL, NULL, hInstance, NULL);
     }
     return hWnd;
-
 }
 
 
+#ifndef UNICODE
+/* Borrowed from CRT internal.h for _MBCS argc/argv parsing in this GUI app */
+int  __CRTDECL _setargv(void);
+#endif
+
 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine, int nCmdShow)
 {
-    CHAR szTmp[MAX_LOADSTRING];
-    CHAR szCmp[MAX_COMPUTERNAME_LENGTH+4];
+    TCHAR szTmp[MAX_LOADSTRING];
+    TCHAR szCmp[MAX_COMPUTERNAME_LENGTH+4];
     MSG msg;
-    /* single instance mutex */
-    HANDLE hMutex;
+    /* existing window */
+    HWND appwindow;
+    DWORD dwControl;
     int i;
     DWORD d;
 
+    if (!GetSystemOSVersion(&g_dwOSVersion))
+    {
+        ErrorMessage(NULL, TRUE);
+        return 1;
+    }
+
     g_LangID = GetUserDefaultLangID();
     if ((g_LangID & 0xFF) != LANG_ENGLISH) {
         g_LangID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
     }
     for (i = IDS_MSG_FIRST; i <= IDS_MSG_LAST; ++i) {
         LoadString(hInstance, i, szTmp, MAX_LOADSTRING);
-        g_lpMsg[i - IDS_MSG_FIRST] = strdup(szTmp);
+        g_lpMsg[i - IDS_MSG_FIRST] = _tcsdup(szTmp);
     }
     LoadString(hInstance, IDS_APMONITORTITLE, szTmp, MAX_LOADSTRING);
     d = MAX_COMPUTERNAME_LENGTH+1;
-    strcpy(szCmp, "\\\\");
+    _tcscpy(szCmp, _T("\\\\"));
     GetComputerName(szCmp + 2, &d);
-    strupr(szCmp);
-    g_szLocalHost = strdup(szCmp);
+    _tcsupr(szCmp);
+    g_szLocalHost = _tcsdup(szCmp);
 
     memset(g_stComputers, 0, sizeof(ST_MONITORED_COMP) * MAX_APACHE_COMPUTERS);
-    g_stComputers[0].szComputerName = strdup(szCmp);
+    g_stComputers[0].szComputerName = _tcsdup(szCmp);
     g_stComputers[0].hRegistry = HKEY_LOCAL_MACHINE;
-    g_szTitle = strdup(szTmp);
+    g_szTitle = _tcsdup(szTmp);
     LoadString(hInstance, IDS_APMONITORCLASS, szTmp, MAX_LOADSTRING);
-    g_szWindowClass = strdup(szTmp);
+    g_szWindowClass = _tcsdup(szTmp);
+
+    appwindow = FindWindow(g_szWindowClass, g_szTitle);
+
+#ifdef UNICODE
+    __wargv = CommandLineToArgvW(GetCommandLineW(), &__argc);
+#else
+    _setargv();
+#endif
+
+    if ((__argc == 2) && (_tcscmp(__targv[1], _T("--kill")) == 0))
+    {
+        /* Off to chase and close up every ApacheMonitor taskbar window */
+        return KillAllMonitors();
+    }
+    else if ((__argc == 4) && (g_dwOSVersion >= OS_VERSION_WIN2K))
+    {
+        dwControl = _tstoi(__targv[1]);
+        if ((dwControl != SERVICE_CONTROL_CONTINUE) &&
+            (dwControl != SERVICE_APACHE_RESTART) &&
+            (dwControl != SERVICE_CONTROL_STOP))
+        {
+            return 1;
+        }
+
+        /* Chase down and close up our session's previous window */
+        if ((appwindow) != NULL)
+            KillAWindow(appwindow);
+    }
+    else if (__argc != 1) {
+        return 1;
+    }
+    else if (appwindow)
+    {
+        ErrorMessage(g_lpMsg[IDS_MSG_APPRUNNING - IDS_MSG_FIRST], FALSE);
+        return 0;
+    }
 
     g_icoStop          = LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICOSTOP),
                                    IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
@@ -1725,26 +1910,20 @@
                                    IMAGE_BITMAP, XBITMAP, YBITMAP,
                                    LR_DEFAULTCOLOR);
 
-    hMutex = CreateMutex(NULL, FALSE, "APSRVMON_MUTEX");
-    if ((hMutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS))
-    {
-        ErrorMessage(g_lpMsg[IDS_MSG_APPRUNNING - IDS_MSG_FIRST], FALSE);
-        if (hMutex) {
-            CloseHandle(hMutex);
-        }
-        return 0;
-    }
-
     memset(g_stServices, 0, sizeof(ST_APACHE_SERVICE) * MAX_APACHE_SERVICES);
     CoInitialize(NULL);
     InitCommonControls();
     g_hInstance = hInstance;
     g_hwndMain = CreateMainWindow(hInstance);
-    g_bUiTaskbarCreated = RegisterWindowMessage("TaskbarCreated");
+    g_bUiTaskbarCreated = RegisterWindowMessage(_T("TaskbarCreated"));
     InitializeCriticalSection(&g_stcSection);
     g_hwndServiceDlg = NULL;
     if (g_hwndMain != NULL)
     {
+        /* To avoid recursion, pass ImagePath NULL (a noop on NT and later) */
+        if ((__argc == 4) && (g_dwOSVersion >= OS_VERSION_WIN2K))
+            ApacheManageService(__targv[2], NULL, __targv[3], dwControl);
+
         while (GetMessage(&msg, NULL, 0, 0) == TRUE)
         {
             TranslateMessage(&msg);
@@ -1754,7 +1933,6 @@
     }
     am_ClearComputersSt();
     DeleteCriticalSection(&g_stcSection);
-    CloseHandle(hMutex);
     DestroyIcon(g_icoStop);
     DestroyIcon(g_icoRun);
     DestroyCursor(g_hCursorHourglass);
@@ -1764,3 +1942,4 @@
     CoUninitialize();
     return 0;
 }
+

Modified: httpd/sandbox/amsterdam/d/support/win32/ApacheMonitor.dsp
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/support/win32/ApacheMonitor.dsp?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/support/win32/ApacheMonitor.dsp (original)
+++ httpd/sandbox/amsterdam/d/support/win32/ApacheMonitor.dsp Mon Apr  7 09:28:58 2008
@@ -52,8 +52,8 @@
 # ADD BASE BSC32 /nologo
 # ADD BSC32 /nologo
 LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib /nologo /subsystem:windows
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib /nologo /subsystem:windows /debug /opt:ref
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib wtsapi32.lib /nologo /subsystem:windows
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib wtsapi32.lib /nologo /subsystem:windows /debug /opt:ref
 # Begin Special Build Tool
 TargetPath=.\Release\ApacheMonitor.exe
 SOURCE="$(InputPath)"
@@ -84,8 +84,8 @@
 # ADD BASE BSC32 /nologo
 # ADD BSC32 /nologo
 LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib /nologo /subsystem:windows /debug
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib /nologo /subsystem:windows /incremental:no /debug
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib wtsapi32.lib /nologo /subsystem:windows /debug
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib wtsapi32.lib /nologo /subsystem:windows /incremental:no /debug
 # Begin Special Build Tool
 TargetPath=.\Debug\ApacheMonitor.exe
 SOURCE="$(InputPath)"

Modified: httpd/sandbox/amsterdam/d/support/win32/ApacheMonitor.h
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/support/win32/ApacheMonitor.h?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/support/win32/ApacheMonitor.h (original)
+++ httpd/sandbox/amsterdam/d/support/win32/ApacheMonitor.h Mon Apr  7 09:28:58 2008
@@ -18,6 +18,7 @@
  * @file  ApacheMonitor.h
  * @brief Resource definitions for ApacheMonitor.rc and ApacheMonitor.c
  */
+#define BIN_NAME  ApacheMonitor.exe
 
 #define IDD_DLGSERVICES                 101
 #define IDS_APMONITORTITLE              102

Modified: httpd/sandbox/amsterdam/d/support/win32/ApacheMonitor.rc
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/support/win32/ApacheMonitor.rc?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/support/win32/ApacheMonitor.rc (original)
+++ httpd/sandbox/amsterdam/d/support/win32/ApacheMonitor.rc Mon Apr  7 09:28:58 2008
@@ -19,7 +19,6 @@
 #include "ApacheMonitor.h"
 
 #define LONG_NAME Apache HTTP Server Monitor
-#define BIN_NAME  ApacheMonitor.exe
 
 #include "../../build/win32/httpd.rc"
 

Modified: httpd/sandbox/amsterdam/d/support/win32/wintty.dsp
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/support/win32/wintty.dsp?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/support/win32/wintty.dsp (original)
+++ httpd/sandbox/amsterdam/d/support/win32/wintty.dsp Mon Apr  7 09:28:58 2008
@@ -49,8 +49,8 @@
 # ADD BASE BSC32 /nologo
 # ADD BSC32 /nologo
 LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console
-# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /debug /opt:ref
+# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console
+# ADD LINK32 kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /opt:ref
 # Begin Special Build Tool
 TargetPath=.\Release\wintty.exe
 SOURCE="$(InputPath)"
@@ -79,8 +79,8 @@
 # ADD BASE BSC32 /nologo
 # ADD BSC32 /nologo
 LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /incremental:no /debug
-# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /incremental:no /debug
+# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /incremental:no /debug
+# ADD LINK32 kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /incremental:no /debug
 # Begin Special Build Tool
 TargetPath=.\Debug\wintty.exe
 SOURCE="$(InputPath)"