You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by wr...@apache.org on 2015/05/23 07:25:22 UTC

svn commit: r1681266 - in /httpd/httpd/branches/2.2.x: ./ CHANGES STATUS server/mpm/winnt/service.c

Author: wrowe
Date: Sat May 23 05:25:22 2015
New Revision: 1681266

URL: http://svn.apache.org/r1681266
Log:
mpm_winnt: Accept utf-8 (Unicode) service names and descriptions for
internationalization.

Backports: 1611165,1611169
Reviewed by: wrowe, gsmith

Modified:
    httpd/httpd/branches/2.2.x/   (props changed)
    httpd/httpd/branches/2.2.x/CHANGES
    httpd/httpd/branches/2.2.x/STATUS
    httpd/httpd/branches/2.2.x/server/mpm/winnt/service.c

Propchange: httpd/httpd/branches/2.2.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sat May 23 05:25:22 2015
@@ -1,2 +1,2 @@
 /httpd/httpd/branches/2.4.x:1555538,1555559,1648845,1649003,1681034
-/httpd/httpd/trunk:290940,395552,417988,451572,501364,583817,583830,611483,630858,639005,639010,647395,657354,657459,660461,660566,664330,678761,680082,681190,682369,683626,685112,686805,686809,687099,687754,693120,693392,693727-693728,696006,697093,706318,707163,708902,711421,713575,719357,720250,729316-729317,729586,732414,732504,732816,732832,733127,733134,733218-733219,734710,743589,755190,756671,756675,756678,756683,757741,761329,763394,764239,768535,769809,771587,771610,776325,777042,777091,778438-778439,778531,778942,780648,780655,780692,780697,780699,785457,785661,790587,803704,819480,823536,823563,834378,835046,891282,900022,932791,942209,952823,953311,955966,981084,992625,1026743,1031551,1040304,1040373,1058192,1070096,1082189,1082196,1090645,1172732,1200040,1200372,1200374,1213380,1222335,1223048,1231446,1244211,1294306,1299738,1300171,1301111,1308862,1327036,1327080,1328133,1328325-1328326,1345319,1348656,1349905,1352912,1363183,1363186,1366344,1367778,1368131,1368396,13
 69568,1395225,1398066,1400700,1408402,1410681,1413732,1414094,1416889,1418752,1422234,1422253,1435178,1447426,1470940,1475878,1476604,1476621,1476642,1476644-1476645,1477530,1485409,1485668,1490994,1493330,1496429,1500323,1504276,1506714,1509872,1509875,1524192,1524770,1526168,1526189,1527291,1527295,1527925,1528718,1529559,1531505,1532816,1551714,1552227,1553204,1554276,1554281,1555240,1555555,1556428,1563420,1572092,1572198,1572543,1572611,1572630,1572655,1572663,1572668-1572671,1572896,1572911,1572967,1573224,1573229,1575400,1586745,1587594,1587639,1588851,1590509,1603156,1604353,1610207,1610311,1610491,1610501,1620932,1621453,1648840,1649001,1649043,1650310,1650320,1653997,1658765,1663647,1664205,1666363,1675533,1676654,1677462,1679182,1679470,1680895,1680900,1680942,1681037
+/httpd/httpd/trunk:290940,395552,417988,451572,501364,583817,583830,611483,630858,639005,639010,647395,657354,657459,660461,660566,664330,678761,680082,681190,682369,683626,685112,686805,686809,687099,687754,693120,693392,693727-693728,696006,697093,706318,707163,708902,711421,713575,719357,720250,729316-729317,729586,732414,732504,732816,732832,733127,733134,733218-733219,734710,743589,755190,756671,756675,756678,756683,757741,761329,763394,764239,768535,769809,771587,771610,776325,777042,777091,778438-778439,778531,778942,780648,780655,780692,780697,780699,785457,785661,790587,803704,819480,823536,823563,834378,835046,891282,900022,932791,942209,952823,953311,955966,981084,992625,1026743,1031551,1040304,1040373,1058192,1070096,1082189,1082196,1090645,1172732,1200040,1200372,1200374,1213380,1222335,1223048,1231446,1244211,1294306,1299738,1300171,1301111,1308862,1327036,1327080,1328133,1328325-1328326,1345319,1348656,1349905,1352912,1363183,1363186,1366344,1367778,1368131,1368396,13
 69568,1395225,1398066,1400700,1408402,1410681,1413732,1414094,1416889,1418752,1422234,1422253,1435178,1447426,1470940,1475878,1476604,1476621,1476642,1476644-1476645,1477530,1485409,1485668,1490994,1493330,1496429,1500323,1504276,1506714,1509872,1509875,1524192,1524770,1526168,1526189,1527291,1527295,1527925,1528718,1529559,1531505,1532816,1551714,1552227,1553204,1554276,1554281,1555240,1555555,1556428,1563420,1572092,1572198,1572543,1572611,1572630,1572655,1572663,1572668-1572671,1572896,1572911,1572967,1573224,1573229,1575400,1586745,1587594,1587639,1588851,1590509,1603156,1604353,1610207,1610311,1610491,1610501,1611165,1611169,1620932,1621453,1648840,1649001,1649043,1650310,1650320,1653997,1658765,1663647,1664205,1666363,1675533,1676654,1677462,1679182,1679470,1680895,1680900,1680942,1681037

Modified: httpd/httpd/branches/2.2.x/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/CHANGES?rev=1681266&r1=1681265&r2=1681266&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/CHANGES [utf-8] (original)
+++ httpd/httpd/branches/2.2.x/CHANGES [utf-8] Sat May 23 05:25:22 2015
@@ -1,6 +1,9 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.2.30
 
+  *) mpm_winnt: Accept utf-8 (Unicode) service names and descriptions for
+     internationalization.  [William Rowe]
+
   *) mod_log_config: Add "%{UNIT}T" format to output request duration in
      seconds, milliseconds or microseconds depending on UNIT ("s", "ms", "us").
      [Ben Reser, Rainer Jung]

Modified: httpd/httpd/branches/2.2.x/STATUS
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/STATUS?rev=1681266&r1=1681265&r2=1681266&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/STATUS (original)
+++ httpd/httpd/branches/2.2.x/STATUS Sat May 23 05:25:22 2015
@@ -101,12 +101,6 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
-   * mpm_winnt service.c: Accept utf-8 service names/descriptions for i18n.
-     trunk patches: http://svn.apache.org/r1611165
-                    http://svn.apache.org/r1611169
-     2.2.x patch: http://people.apache.org/~wrowe/httpd-2.2-utf8-servicename.patch
-     +1: wrowe, gsmith
-
    * mod_log_config: Backport get_request_end_time().
      This makes data consistent if a log format uses multiple %{...}T
      and/or %D. The end time of a request is only taken once and the

Modified: httpd/httpd/branches/2.2.x/server/mpm/winnt/service.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/server/mpm/winnt/service.c?rev=1681266&r1=1681265&r2=1681266&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/server/mpm/winnt/service.c (original)
+++ httpd/httpd/branches/2.2.x/server/mpm/winnt/service.c Sat May 23 05:25:22 2015
@@ -22,11 +22,18 @@
 #define CORE_PRIVATE
 #define _WINUSER_
 
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+#if APR_HAS_UNICODE_FS
+#include "arch/win32/apr_arch_utf8.h"
+#include "arch/win32/apr_arch_misc.h"
+#include <wchar.h>
+#endif
+
 #include "httpd.h"
 #include "http_log.h"
 #include "mpm_winnt.h"
-#include "apr_strings.h"
-#include "apr_lib.h"
 #include "ap_regkey.h"
 
 #ifdef NOUSER
@@ -39,6 +46,10 @@
 static char *mpm_service_name = NULL;
 static char *mpm_display_name = NULL;
 
+#if APR_HAS_UNICODE_FS
+static apr_wchar_t *mpm_service_name_w;
+#endif
+
 static struct
 {
     HANDLE mpm_thread;       /* primary thread handle of the apache server */
@@ -53,6 +64,33 @@ static struct
 static int ReportStatusToSCMgr(int currentState, int exitCode, int waitHint);
 
 
+/* Rather than repeat this logic throughout, create an either-or wide or narrow
+ * implementation because we don't actually pass strings to OpenSCManager.
+ * This election is based on build time defines and runtime os version test.
+ */
+#undef OpenSCManager
+typedef SC_HANDLE (WINAPI *fpt_OpenSCManager)(const void *lpMachine,
+                                              const void *lpDatabase,
+                                              DWORD dwAccess);
+static fpt_OpenSCManager pfn_OpenSCManager = NULL;
+static APR_INLINE SC_HANDLE OpenSCManager(const void *lpMachine,
+                                          const void *lpDatabase,
+                                          DWORD dwAccess)
+{
+    if (!pfn_OpenSCManager) {
+#if APR_HAS_UNICODE_FS
+        IF_WIN_OS_IS_UNICODE
+            pfn_OpenSCManager = (fpt_OpenSCManager)OpenSCManagerW;
+#endif
+#if APR_HAS_ANSI_FS
+        ELSE_WIN_OS_IS_ANSI
+            pfn_OpenSCManager = (fpt_OpenSCManager)OpenSCManagerA;
+#endif
+    }
+    return (*(pfn_OpenSCManager))(lpMachine, lpDatabase, dwAccess); 
+}
+
+
 /* The service configuration's is stored under the following trees:
  *
  * HKLM\System\CurrentControlSet\Services\[service name]
@@ -408,18 +446,50 @@ static void set_service_description(void
           && (ChangeServiceConfig2)
           && (schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT)))
     {
-        SC_HANDLE schService = OpenService(schSCManager, mpm_service_name,
-                                           SERVICE_CHANGE_CONFIG);
+        SC_HANDLE schService;
+
+#if APR_HAS_UNICODE_FS
+        IF_WIN_OS_IS_UNICODE
+        {
+            schService = OpenServiceW(schSCManager, mpm_service_name_w,
+                                      SERVICE_CHANGE_CONFIG);
+        }
+#endif /* APR_HAS_UNICODE_FS */
+#if APR_HAS_ANSI_FS
+        ELSE_WIN_OS_IS_ANSI
+        {
+            schService = OpenService(schSCManager, mpm_service_name,
+                                     SERVICE_CHANGE_CONFIG);
+        }
+#endif
         if (schService) {
             /* Cast is necessary, ChangeServiceConfig2 handles multiple
              * object types, some volatile, some not.
              */
-            /* ###: utf-ize */
-            if (ChangeServiceConfig2(schService,
-                                     1 /* SERVICE_CONFIG_DESCRIPTION */,
-                                     (LPVOID) &full_description)) {
-                full_description = NULL;
+#if APR_HAS_UNICODE_FS
+            IF_WIN_OS_IS_UNICODE
+            {
+                apr_size_t slen = strlen(full_description) + 1;
+                apr_size_t wslen = slen;
+                apr_wchar_t *full_description_w = apr_palloc(pconf, wslen * sizeof(apr_wchar_t));
+                apr_status_t rv = apr_conv_utf8_to_ucs2(full_description, &slen,
+                                                        full_description_w, &wslen);
+                if ((rv != APR_SUCCESS) || slen
+                        || ChangeServiceConfig2W(schService,
+                                                 1 /* SERVICE_CONFIG_DESCRIPTION */,
+                                                 (LPVOID) &full_description_w))
+                    full_description = NULL;
             }
+#endif /* APR_HAS_UNICODE_FS */
+#if APR_HAS_ANSI_FS
+            ELSE_WIN_OS_IS_ANSI
+            {
+                if (ChangeServiceConfig2(schService,
+                                         1 /* SERVICE_CONFIG_DESCRIPTION */,
+                                         (LPVOID) &full_description))
+                    full_description = NULL;
+            }
+#endif
             CloseServiceHandle(schService);
         }
         CloseServiceHandle(schSCManager);
@@ -473,8 +543,82 @@ static VOID WINAPI service_nt_ctrl(DWORD
  */
 extern apr_array_header_t *mpm_new_argv;
 
-/* ###: utf-ize */
-static void __stdcall service_nt_main_fn(DWORD argc, LPTSTR *argv)
+#if APR_HAS_UNICODE_FS
+static void __stdcall service_nt_main_fn_w(DWORD argc, LPWSTR *argv)
+{
+    const char *ignored;
+    char *service_name;
+    apr_size_t wslen = wcslen(argv[0]) + 1;
+    apr_size_t slen = wslen * 3 - 2;
+
+    service_name = malloc(slen);
+    (void)apr_conv_ucs2_to_utf8(argv[0], &wslen, service_name, &slen);
+
+    /* args and service names live in the same pool */
+    mpm_service_set_name(mpm_new_argv->pool, &ignored, service_name);
+
+    memset(&globdat.ssStatus, 0, sizeof(globdat.ssStatus));
+    globdat.ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+    globdat.ssStatus.dwCurrentState = SERVICE_START_PENDING;
+    globdat.ssStatus.dwCheckPoint = 1;
+
+    if (!(globdat.hServiceStatus = RegisterServiceCtrlHandlerW(argv[0], service_nt_ctrl)))
+    {
+        ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(),
+                     NULL, "Failure registering service handler");
+        return;
+    }
+
+    /* Report status, no errors, and buy 3 more seconds */
+    ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 30000);
+
+    /* We need to append all the command arguments passed via StartService()
+     * to our running service... which just got here via the SCM...
+     * but we have no interest in argv[0] for the mpm_new_argv list.
+     */
+    if (argc > 1)
+    {
+        char **cmb_data, **cmb;
+        DWORD i;
+
+        mpm_new_argv->nalloc = mpm_new_argv->nelts + argc - 1;
+        cmb_data = malloc(mpm_new_argv->nalloc * sizeof(const char *));
+
+        /* mpm_new_argv remains first (of lower significance) */
+        memcpy (cmb_data, mpm_new_argv->elts,
+                mpm_new_argv->elt_size * mpm_new_argv->nelts);
+
+        /* Service args follow from StartService() invocation */
+        memcpy (cmb_data + mpm_new_argv->nelts, argv + 1,
+                mpm_new_argv->elt_size * (argc - 1));
+
+        cmb = cmb_data + mpm_new_argv->nelts;
+
+        for (i = 1; i < argc; ++i)
+        {
+            wslen = wcslen(argv[i]) + 1;
+            slen = wslen * 3 - 2;
+            service_name = malloc(slen);
+            (void)apr_conv_ucs2_to_utf8(argv[i], &wslen, *(cmb++), &slen);
+        }
+
+        /* The replacement arg list is complete */
+        mpm_new_argv->elts = (char *)cmb_data;
+        mpm_new_argv->nelts = mpm_new_argv->nalloc;
+    }
+
+    /* Let the main thread continue now... but hang on to the
+     * signal_monitor event so we can take further action
+     */
+    SetEvent(globdat.service_init);
+
+    WaitForSingleObject(globdat.service_term, INFINITE);
+}
+#endif /* APR_HAS_UNICODE_FS */
+
+
+#if APR_HAS_ANSI_FS
+static void __stdcall service_nt_main_fn(DWORD argc, LPSTR *argv)
 {
     const char *ignored;
 
@@ -486,8 +630,7 @@ static void __stdcall service_nt_main_fn
     globdat.ssStatus.dwCurrentState = SERVICE_START_PENDING;
     globdat.ssStatus.dwCheckPoint = 1;
 
-    /* ###: utf-ize */
-    if (!(globdat.hServiceStatus = RegisterServiceCtrlHandler(argv[0], service_nt_ctrl)))
+    if (!(globdat.hServiceStatus = RegisterServiceCtrlHandlerA(argv[0], service_nt_ctrl)))
     {
         ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(),
                      NULL, "Failure registering service handler");
@@ -499,7 +642,7 @@ static void __stdcall service_nt_main_fn
 
     /* We need to append all the command arguments passed via StartService()
      * to our running service... which just got here via the SCM...
-     * but we hvae no interest in argv[0] for the mpm_new_argv list.
+     * but we have no interest in argv[0] for the mpm_new_argv list.
      */
     if (argc > 1)
     {
@@ -528,27 +671,44 @@ static void __stdcall service_nt_main_fn
 
     WaitForSingleObject(globdat.service_term, INFINITE);
 }
+#endif
 
 
 static DWORD WINAPI service_nt_dispatch_thread(LPVOID nada)
 {
-    apr_status_t rv = APR_SUCCESS;
-
-    SERVICE_TABLE_ENTRY dispatchTable[] =
+#if APR_HAS_UNICODE_FS
+    SERVICE_TABLE_ENTRYW dispatchTable_w[] =
+    {
+        { L"", service_nt_main_fn_w },
+        { NULL, NULL }
+    };
+#endif /* APR_HAS_UNICODE_FS */
+#if APR_HAS_ANSI_FS
+    SERVICE_TABLE_ENTRYA dispatchTable[] =
     {
         { "", service_nt_main_fn },
         { NULL, NULL }
     };
+#endif
+    apr_status_t rv;
 
-    /* ###: utf-ize */
-    if (!StartServiceCtrlDispatcher(dispatchTable))
-    {
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+        rv = StartServiceCtrlDispatcherW(dispatchTable_w);
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+         rv = StartServiceCtrlDispatcherA(dispatchTable);
+#endif
+    if (rv) {
+        apr_status_t rv = APR_SUCCESS;
+    }
+    else {
         /* This is a genuine failure of the SCM. */
         rv = apr_get_os_error();
         ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
                      "Error starting service control dispatcher");
     }
-
     return (rv);
 }
 
@@ -566,6 +726,21 @@ apr_status_t mpm_service_set_name(apr_po
      */
     mpm_service_name = apr_palloc(p, strlen(set_name) + 1);
     apr_collapse_spaces((char*) mpm_service_name, set_name);
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        apr_size_t slen = strlen(mpm_service_name) + 1;
+        apr_size_t wslen = slen;
+        mpm_service_name_w = apr_palloc(p, wslen * sizeof(apr_wchar_t));
+        rv = apr_conv_utf8_to_ucs2(mpm_service_name, &slen,
+                                   mpm_service_name_w, &wslen);
+        if (rv != APR_SUCCESS)
+            return rv;
+        else if (slen)
+            return APR_ENAMETOOLONG;
+    }
+#endif /* APR_HAS_UNICODE_FS */
+
     apr_snprintf(key_name, sizeof(key_name), SERVICECONFIG, mpm_service_name);
     rv = ap_regkey_open(&key, AP_REGKEY_LOCAL_MACHINE, key_name, APR_READ, pconf);
     if (rv == APR_SUCCESS) {
@@ -577,6 +752,7 @@ apr_status_t mpm_service_set_name(apr_po
         mpm_display_name = apr_pstrdup(p, set_name);
     }
     *display_name = mpm_display_name;
+
     return rv;
 }
 
@@ -756,27 +932,55 @@ apr_status_t mpm_service_install(apr_poo
                                  const char * const * argv, int reconfig)
 {
     char key_name[MAX_PATH];
-    char exe_path[MAX_PATH];
-    char *launch_cmd;
     ap_regkey_t *key;
+    char        *launch_cmd;
     apr_status_t rv;
 
     fprintf(stderr,reconfig ? "Reconfiguring the %s service\n"
                    : "Installing the %s service\n", mpm_display_name);
 
-    /* ###: utf-ize */
-    if (GetModuleFileName(NULL, exe_path, sizeof(exe_path)) == 0)
-    {
-        apr_status_t rv = apr_get_os_error();
-        ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
-                     "GetModuleFileName failed");
-        return rv;
-    }
-
     if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
     {
         SC_HANDLE   schService;
         SC_HANDLE   schSCManager;
+        DWORD       rc;
+#if APR_HAS_UNICODE_FS
+        apr_wchar_t *display_name_w;
+        apr_wchar_t *launch_cmd_w;
+
+        IF_WIN_OS_IS_UNICODE
+        {
+            apr_size_t slen = strlen(mpm_display_name) + 1;
+            apr_size_t wslen = slen;
+            display_name_w = apr_palloc(ptemp, wslen * sizeof(apr_wchar_t));
+            rv = apr_conv_utf8_to_ucs2(mpm_display_name, &slen,
+                                       display_name_w, &wslen);
+            if (rv != APR_SUCCESS)
+                return rv;
+            else if (slen)
+                return APR_ENAMETOOLONG;
+
+            launch_cmd_w = apr_palloc(ptemp, (MAX_PATH + 17) * sizeof(apr_wchar_t));
+            launch_cmd_w[0] = L'"';
+            rc = GetModuleFileNameW(NULL, launch_cmd_w + 1, MAX_PATH);
+            wcscpy(launch_cmd_w + rc + 1, L"\" -k runservice");
+        }
+#endif /* APR_HAS_UNICODE_FS */
+#if APR_HAS_ANSI_FS
+        ELSE_WIN_OS_IS_ANSI
+        {
+            launch_cmd = apr_palloc(ptemp, MAX_PATH + 17);
+            launch_cmd[0] = '"';
+            rc = GetModuleFileName(NULL, launch_cmd + 1, MAX_PATH);
+            strcpy(launch_cmd + rc + 1, "\" -k runservice");
+        }
+#endif
+        if (rc == 0) {
+            rv = apr_get_os_error();
+            ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
+                         "GetModuleFileName failed");
+            return rv;
+        }
 
         schSCManager = OpenSCManager(NULL, NULL, /* local, default database */
                                      SC_MANAGER_CREATE_SERVICE);
@@ -787,31 +991,59 @@ apr_status_t mpm_service_install(apr_poo
             return (rv);
         }
 
-        launch_cmd = apr_psprintf(ptemp, "\"%s\" -k runservice", exe_path);
-
         if (reconfig) {
-            /* ###: utf-ize */
-            schService = OpenService(schSCManager, mpm_service_name,
-                                     SERVICE_CHANGE_CONFIG);
+#if APR_HAS_UNICODE_FS
+            IF_WIN_OS_IS_UNICODE
+            {
+                schService = OpenServiceW(schSCManager, mpm_service_name_w,
+                                      SERVICE_CHANGE_CONFIG);
+            }
+#endif /* APR_HAS_UNICODE_FS */
+#if APR_HAS_ANSI_FS
+            ELSE_WIN_OS_IS_ANSI
+            {
+                schService = OpenService(schSCManager, mpm_service_name,
+                                         SERVICE_CHANGE_CONFIG);
+            }
+#endif
             if (!schService) {
                 ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_ERR,
                              apr_get_os_error(), NULL,
                              "OpenService failed");
             }
-            /* ###: utf-ize */
-            else if (!ChangeServiceConfig(schService,
-                                          SERVICE_WIN32_OWN_PROCESS,
-                                          SERVICE_AUTO_START,
-                                          SERVICE_ERROR_NORMAL,
-                                          launch_cmd, NULL, NULL,
-                                          "Tcpip\0Afd\0", NULL, NULL,
-                                          mpm_display_name)) {
-                ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_ERR,
-                             apr_get_os_error(), NULL,
-                             "ChangeServiceConfig failed");
-                /* !schService aborts configuration below */
-                CloseServiceHandle(schService);
-                schService = NULL;
+            else {
+#if APR_HAS_UNICODE_FS
+                IF_WIN_OS_IS_UNICODE
+                {
+                    rc = ChangeServiceConfigW(schService,
+                                              SERVICE_WIN32_OWN_PROCESS,
+                                              SERVICE_AUTO_START,
+                                              SERVICE_ERROR_NORMAL,
+                                              launch_cmd_w, NULL, NULL,
+                                              L"Tcpip\0Afd\0", NULL, NULL,
+                                              display_name_w);
+                }
+#endif /* APR_HAS_UNICODE_FS */
+#if APR_HAS_ANSI_FS
+                ELSE_WIN_OS_IS_ANSI
+                {
+                    rc = ChangeServiceConfig(schService,
+                                             SERVICE_WIN32_OWN_PROCESS,
+                                             SERVICE_AUTO_START,
+                                             SERVICE_ERROR_NORMAL,
+                                             launch_cmd, NULL, NULL,
+                                             "Tcpip\0Afd\0", NULL, NULL,
+                                             mpm_display_name);
+                }
+#endif
+                if (!rc) {
+                    ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_ERR,
+                                 apr_get_os_error(), NULL,
+                                 "ChangeServiceConfig failed");
+                    /* !schService aborts configuration below */
+                    CloseServiceHandle(schService);
+                    schService = NULL;
+                }
             }
         }
         else {
@@ -821,21 +1053,43 @@ apr_status_t mpm_service_install(apr_poo
              * be warned that future apache modules or ISAPI dll's may
              * depend on it.
              */
-            /* ###: utf-ize */
-            schService = CreateService(schSCManager,         // SCManager database
-                                   mpm_service_name,     // name of service
-                                   mpm_display_name,     // name to display
-                                   SERVICE_ALL_ACCESS,   // access required
-                                   SERVICE_WIN32_OWN_PROCESS,  // service type
-                                   SERVICE_AUTO_START,   // start type
-                                   SERVICE_ERROR_NORMAL, // error control type
-                                   launch_cmd,           // service's binary
-                                   NULL,                 // no load svc group
-                                   NULL,                 // no tag identifier
-                                   "Tcpip\0Afd\0",       // dependencies
-                                   NULL,                 // use SYSTEM account
-                                   NULL);                // no password
 
+#if APR_HAS_UNICODE_FS
+            IF_WIN_OS_IS_UNICODE
+            {
+                schService = CreateServiceW(schSCManager,    // SCManager database
+                                 mpm_service_name_w,   // name of service
+                                 display_name_w,   // name to display
+                                 SERVICE_ALL_ACCESS,   // access required
+                                 SERVICE_WIN32_OWN_PROCESS,  // service type
+                                 SERVICE_AUTO_START,   // start type
+                                 SERVICE_ERROR_NORMAL, // error control type
+                                 launch_cmd_w,         // service's binary
+                                 NULL,                 // no load svc group
+                                 NULL,                 // no tag identifier
+                                 L"Tcpip\0Afd\0",      // dependencies
+                                 NULL,                 // use SYSTEM account
+                                 NULL);                // no password
+            }
+#endif /* APR_HAS_UNICODE_FS */
+#if APR_HAS_ANSI_FS
+            ELSE_WIN_OS_IS_ANSI
+            {
+                schService = CreateService(schSCManager,     // SCManager database
+                                 mpm_service_name,     // name of service
+                                 mpm_display_name,     // name to display
+                                 SERVICE_ALL_ACCESS,   // access required
+                                 SERVICE_WIN32_OWN_PROCESS,  // service type
+                                 SERVICE_AUTO_START,   // start type
+                                 SERVICE_ERROR_NORMAL, // error control type
+                                 launch_cmd,           // service's binary
+                                 NULL,                 // no load svc group
+                                 NULL,                 // no tag identifier
+                                 "Tcpip\0Afd\0",       // dependencies
+                                 NULL,                 // use SYSTEM account
+                                 NULL);                // no password
+            }
+#endif
             if (!schService)
             {
                 rv = apr_get_os_error();
@@ -851,6 +1105,16 @@ apr_status_t mpm_service_install(apr_poo
     }
     else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */
     {
+        char exe_path[MAX_PATH];
+
+        if (GetModuleFileName(NULL, exe_path, sizeof(exe_path)) == 0)
+        {
+            apr_status_t rv = apr_get_os_error();
+            ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
+                         "GetModuleFileName failed");
+            return rv;
+        }
+
         /* Store the launch command in the registry */
         launch_cmd = apr_psprintf(ptemp, "\"%s\" -n %s -k runservice",
                                  exe_path, mpm_service_name);
@@ -939,9 +1203,18 @@ apr_status_t mpm_service_uninstall(void)
             return (rv);
         }
 
-        /* ###: utf-ize */
-        schService = OpenService(schSCManager, mpm_service_name, DELETE);
-
+#if APR_HAS_UNICODE_FS
+        IF_WIN_OS_IS_UNICODE
+        {
+            schService = OpenServiceW(schSCManager, mpm_service_name_w, DELETE);
+        }
+#endif /* APR_HAS_UNICODE_FS */
+#if APR_HAS_ANSI_FS
+        ELSE_WIN_OS_IS_ANSI
+        {
+            schService = OpenService(schSCManager, mpm_service_name, DELETE);
+        }
+#endif
         if (!schService) {
            rv = apr_get_os_error();
            ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
@@ -1040,7 +1313,6 @@ apr_status_t mpm_service_start(apr_pool_
 
     if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
     {
-        CHAR **start_argv;
         SC_HANDLE   schService;
         SC_HANDLE   schSCManager;
 
@@ -1053,9 +1325,20 @@ apr_status_t mpm_service_start(apr_pool_
             return (rv);
         }
 
-        /* ###: utf-ize */
-        schService = OpenService(schSCManager, mpm_service_name,
-                                 SERVICE_START | SERVICE_QUERY_STATUS);
+#if APR_HAS_UNICODE_FS
+        IF_WIN_OS_IS_UNICODE
+        {
+            schService = OpenServiceW(schSCManager, mpm_service_name_w,
+                                     SERVICE_START | SERVICE_QUERY_STATUS);
+        }
+#endif /* APR_HAS_UNICODE_FS */
+#if APR_HAS_ANSI_FS
+        ELSE_WIN_OS_IS_ANSI
+        {
+            schService = OpenService(schSCManager, mpm_service_name,
+                                     SERVICE_START | SERVICE_QUERY_STATUS);
+        }
+#endif
         if (!schService) {
             rv = apr_get_os_error();
             ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
@@ -1073,18 +1356,47 @@ apr_status_t mpm_service_start(apr_pool_
             return 0;
         }
 
-        start_argv = malloc((argc + 1) * sizeof(const char **));
-        memcpy(start_argv, argv, argc * sizeof(const char **));
-        start_argv[argc] = NULL;
-
         rv = APR_EINIT;
-        /* ###: utf-ize */
-        if (StartService(schService, argc, start_argv)
-            && signal_service_transition(schService, 0, /* test only */
-                                         SERVICE_START_PENDING,
-                                         SERVICE_RUNNING))
-                rv = APR_SUCCESS;
+#if APR_HAS_UNICODE_FS
+        IF_WIN_OS_IS_UNICODE
+        {
+            LPWSTR *start_argv_w = malloc((argc + 1) * sizeof(LPCWSTR));
+            int i;
 
+            for (i = 0; i < argc; ++i)
+            {
+                apr_size_t slen = strlen(argv[i]) + 1;
+                apr_size_t wslen = slen;
+                start_argv_w[i] = malloc(wslen * sizeof(WCHAR));
+                rv = apr_conv_utf8_to_ucs2(argv[i], &slen, start_argv_w[i], &wslen);
+                if (rv != APR_SUCCESS)
+                    return rv;
+                else if (slen)
+                    return APR_ENAMETOOLONG;
+            }
+            start_argv_w[argc] = NULL;
+
+            if (StartServiceW(schService, argc, start_argv_w)
+                && signal_service_transition(schService, 0, /* test only */
+                                             SERVICE_START_PENDING,
+                                             SERVICE_RUNNING))
+                    rv = APR_SUCCESS;
+        }
+#endif /* APR_HAS_UNICODE_FS */
+#if APR_HAS_ANSI_FS
+        ELSE_WIN_OS_IS_ANSI
+        {
+            char **start_argv = malloc((argc + 1) * sizeof(const char *));
+            memcpy(start_argv, argv, argc * sizeof(const char *));
+            start_argv[argc] = NULL;
+
+            if (StartService(schService, argc, start_argv)
+                && signal_service_transition(schService, 0, /* test only */
+                                             SERVICE_START_PENDING,
+                                             SERVICE_RUNNING))
+                    rv = APR_SUCCESS;
+        }
+#endif
         if (rv != APR_SUCCESS)
             rv = apr_get_os_error();
 
@@ -1193,12 +1505,24 @@ void mpm_signal_service(apr_pool_t *ptem
             return;
         }
 
-        /* ###: utf-ize */
-        schService = OpenService(schSCManager, mpm_service_name,
-                                 SERVICE_INTERROGATE | SERVICE_QUERY_STATUS |
-                                 SERVICE_USER_DEFINED_CONTROL |
-                                 SERVICE_START | SERVICE_STOP);
-
+#if APR_HAS_UNICODE_FS
+        IF_WIN_OS_IS_UNICODE
+        {
+            schService = OpenServiceW(schSCManager, mpm_service_name_w,
+                                      SERVICE_INTERROGATE | SERVICE_QUERY_STATUS |
+                                      SERVICE_USER_DEFINED_CONTROL |
+                                      SERVICE_START | SERVICE_STOP);
+        }
+#endif /* APR_HAS_UNICODE_FS */
+#if APR_HAS_ANSI_FS
+        ELSE_WIN_OS_IS_ANSI
+        {
+            schService = OpenService(schSCManager, mpm_service_name,
+                                     SERVICE_INTERROGATE | SERVICE_QUERY_STATUS |
+                                     SERVICE_USER_DEFINED_CONTROL |
+                                     SERVICE_START | SERVICE_STOP);
+        }
+#endif
         if (schService == NULL) {
             /* Could not open the service */
             ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(), NULL,