]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Accept service names modified by the user in the Win/2000 Service Control
authorWilliam A. Rowe Jr <wrowe@apache.org>
Wed, 3 Oct 2001 20:56:00 +0000 (20:56 +0000)
committerWilliam A. Rowe Jr <wrowe@apache.org>
Wed, 3 Oct 2001 20:56:00 +0000 (20:56 +0000)
  Panel applet.  Allow the admin to specify -W dependency, where the given
  service will become a dependency for Apache when configured with the
  -k install and config options.  Finally, document -w and -W.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x@91265 13f79535-47bb-0310-9956-ffa450edef68

src/CHANGES
src/main/http_main.c
src/os/win32/registry.c
src/os/win32/service.c
src/os/win32/service.h

index ae188e8624bf4dbb8c7c3c8d3b59556803b0b586..27f61f8e5649feb3a8155bb14552a9e77f82d768 100644 (file)
@@ -1,5 +1,13 @@
 Changes with Apache 1.3.21
 
+  *) Handle user modification of WinNT/2K service display names.  Prior
+     versions of Apache only accepted identical internal and display names
+     (where internal service names were space-stripped.)  [William Rowe]
+
+  *) Introduce Win32 -W option for -k install/config to set up service
+     dependencies on the workstation, snmp and other services that given
+     modules or configurations might depend upon.  [William Rowe]
+
   *) Update the mime.types file to map video/vnd.mpegurl to mxu
      and add commonly used audio/x-mpegurl for m3u extensions.
      [Heiko Recktenwald <uzs106@uni-bonn.de>, Lars Eilebrecht]
index 91f33e9c70dcc3ae2ddb989542bb1d18f1e45770..10126c03116055ff53fc32ca5cf87fe92da6063c 100644 (file)
@@ -1310,6 +1310,8 @@ static void usage(char *bin)
     fprintf(stderr, "  -k install   | -i: install an Apache service\n");
     fprintf(stderr, "  -k config        : reconfigure an installed Apache service\n");
     fprintf(stderr, "  -k uninstall | -u: uninstall an Apache service\n");
+    fprintf(stderr, "  -W service       : after -k config|install; Apache starts after 'service'\n");
+    fprintf(stderr, "  -w               : holds the window open for 30 seconds for fatal errors.\n");
 #endif
 
 #if defined(NETWARE)
@@ -7059,7 +7061,7 @@ int REALMAIN(int argc, char *argv[])
         reparsed = 1;
     }
 
-    while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLz:Z:wiuStThk:n:")) != -1) {
+    while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLz:Z:wiuStThk:n:W:")) != -1) {
 #else /* !WIN32 */
     while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLsStTh")) != -1) {
 #endif
@@ -7125,6 +7127,19 @@ int REALMAIN(int argc, char *argv[])
             else
                 signal_to_send = optarg;
            break;
+        case 'W':
+            /* -With a dependent service */
+            if (install < 1) {
+               fprintf(stderr, "%s: invalid option: -W %s ignored\n"
+                        "\t-W only modifies -k install or -k config\n",
+                        argv[0], optarg);
+            }
+            else if (!isWindowsNT()) {
+                fprintf(stderr, "%s: invalid option: -W %s ignored\n"
+                        "\t-W is only supported for Windows NT/2000\n",
+                        argv[0], optarg);
+            }
+            break;
 #endif /* WIN32 */
 #ifdef NETWARE
         case 's':
@@ -7225,6 +7240,10 @@ int REALMAIN(int argc, char *argv[])
         service_name = DEFAULTSERVICENAME;
     }
 
+    if (service_name) {
+        service_name = get_display_name(service_name);
+    }
+
     if (service_name && isValidService(service_name)) 
     {
         if (install == 2) {
@@ -7314,8 +7333,6 @@ int REALMAIN(int argc, char *argv[])
     }
 
     if (install) {
-        if (!service_name)
-            service_name = ap_pstrdup(pconf, DEFAULTSERVICENAME);
         if (install > 0) 
             InstallService(pconf, service_name, argc, argv, install == 1);
         else
index 04ba810a810cac20e5b11ca2f482eb4cac656913..882bc9974af9a4423cd0d1aa537d3c1201d299f7 100755 (executable)
@@ -89,6 +89,7 @@
 
 #include "httpd.h"
 #include "http_log.h"
+#include "service.h"
 
 /* Define where the Apache values are stored in the registry. In general
  * VERSION will be the same across all beta releases for a particular
@@ -279,9 +280,8 @@ API_EXPORT(char *) ap_get_service_key(char *display_name)
     if (display_name == NULL)
         return strdup("");
 
-    service_name = strdup(display_name);
-    ap_remove_spaces(service_name, display_name);
-
+    service_name = get_service_name(display_name);
+    
     key = malloc(strlen(SERVICEKEYPRE) +
                  strlen(service_name) +
                  strlen(SERVICEKEYPOST) + 1);
index b915782ed30142144d6f5e8d9c903d6055f9786e..5de5f36a86d12921e96f2bb59d5f064012e9f7b9 100644 (file)
@@ -668,7 +668,6 @@ void __stdcall service_main_fn(DWORD argc, LPTSTR *argv)
     globdat.exit_status = globdat.main_fn( argc, argv );
 }
 
-
 /* Set the service description regardless of platform.
  * We revert to set_service_description_string on NT/9x, the
  * very long way so any Apache management program can grab the
@@ -696,6 +695,55 @@ static void set_service_description_string(const char *description)
 }
 
 
+char *get_service_name(char *display_name)
+{
+    /* Get the service's true name from the SCM on NT/2000, since it
+     * can be changed by the user on 2000, especially, from the
+     * service control panel.  We can't trust the service name to 
+     * match a space-collapsed display name.
+     */
+    char service_name[MAX_PATH];
+    if (isWindowsNT())
+    {
+        SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
+        DWORD namelen = sizeof(service_name);
+        if (scm) {
+            BOOL ok = GetServiceKeyName(scm, display_name, service_name, 
+                                        &namelen);
+            CloseServiceHandle(scm);
+            if (ok)
+                return strdup(service_name);
+        }
+    }
+    ap_remove_spaces(service_name, display_name);
+    return strdup(service_name);
+}
+
+
+char *get_display_name(char *service_name)
+{
+    /* Get the service's display name from the SCM on NT/2000, since it
+     * can be changed by the user on 2000, especially, from the
+     * service control panel.  We can't trust the service name as
+     * provided by the user.
+     */
+    if (isWindowsNT())
+    {
+        char display_name[MAX_PATH];
+        SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
+        DWORD namelen = sizeof(display_name);
+        if (scm) {
+            BOOL ok = GetServiceDisplayName(scm, service_name, display_name,
+                                            &namelen);
+            CloseServiceHandle(scm);
+            if (ok)
+                return strdup(display_name);
+        }
+    }
+    return service_name;
+}
+
+
 /* ChangeServiceConfig2() prototype:
  */
 typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID);
@@ -854,7 +902,11 @@ void InstallService(pool *p, char *display_name, int argc, char **argv, int reco
     TCHAR szQuotedPath[512];
     char *service_name;
     int regargc = 0;
-    char **regargv = malloc((argc + 4) * sizeof(char*)), **newelem = regargv;
+    char default_depends[] = "Tcpip\0Afd\0";
+    char *depends = default_depends;
+    size_t depends_len = sizeof(default_depends);
+    char **regargv = malloc((argc + 4) * sizeof(char*));
+    char **newelem = regargv;
 
     regargc += 4;
     *(newelem++) = "-d";
@@ -865,10 +917,28 @@ void InstallService(pool *p, char *display_name, int argc, char **argv, int reco
     while (++argv, --argc) {
         if ((**argv == '-') && strchr("kndf", argv[0][1]))
             --argc, ++argv; /* Skip already handled -k -n -d -f options */
+        else if ((**argv == '-') && (argv[0][1] == 'W')) 
+        {
+            /* Catch this service -W dependency 
+             * the depends list is null seperated, double-null terminated
+             */
+            char *service = get_service_name(*(argv + 1));
+            size_t add_len = strlen(service) + 1;
+            char *more_depends = malloc(depends_len + add_len);
+            memcpy (more_depends, depends, depends_len - 1);
+            memcpy (more_depends + depends_len - 1, service, add_len);
+            depends_len += add_len;
+            depends = more_depends;
+            depends[depends_len - 1] = '\0';
+            ++argv, --argc;
+        }
         else if ((**argv != '-') || !strchr("iuw", argv[0][1]))
             *(newelem++) = *argv, ++regargc;  /* Ignoring -i -u -w options */
     }
 
+    /* Remove spaces from display name to create service name */
+    service_name = get_service_name(display_name);
+    
     printf(reconfig ? "Reconfiguring the %s service\n"
                     : "Installing the %s service\n", 
            display_name);
@@ -880,10 +950,6 @@ void InstallService(pool *p, char *display_name, int argc, char **argv, int reco
         return;
     }
 
-    /* Remove spaces from display name to create service name */
-    service_name = strdup(display_name);
-    ap_remove_spaces(service_name, display_name);
-
     if (isWindowsNT())
     {
         SC_HANDLE schService;
@@ -909,6 +975,12 @@ void InstallService(pool *p, char *display_name, int argc, char **argv, int reco
          * required for DCOM communication.  I am far from
          * convinced we should toggle this, but be warned that
          * future apache modules or ISAPI dll's may depend on it.
+         * Also UNC share users may need the networking service 
+         * started (usually "LanmanWorkstation").  "ProtectedStorage" 
+         * may be needed depending on how files and registry keys are 
+         * stored.  And W3SVC may be needed to wait until IIS has
+         * glommed and released 0.0.0.0:80 if the admin allocates 
+         * two different IP's to Apache and IIS on the same port.
          */
         if (reconfig) 
         {
@@ -925,7 +997,7 @@ void InstallService(pool *p, char *display_name, int argc, char **argv, int reco
                         szQuotedPath,               // service's binary
                         NULL,                       // no load ordering group
                         NULL,                       // no tag identifier
-                        "Tcpip\0Afd\0",             // dependencies
+                        depends,                    // dependencies
                         NULL,                       // user account
                         NULL,                       // account password
                         display_name)) {            // service display name
@@ -949,7 +1021,7 @@ void InstallService(pool *p, char *display_name, int argc, char **argv, int reco
                         szQuotedPath,               // service's binary
                         NULL,                       // no load ordering group
                         NULL,                       // no tag identifier
-                        "Tcpip\0Afd\0",             // dependencies
+                        depends,                    // dependencies
                         NULL,                       // user account
                         NULL);                      // account password
             if (!schService)
@@ -1056,9 +1128,8 @@ void RemoveService(char *display_name)
     printf("Removing the %s service\n", display_name);
 
     /* Remove spaces from display name to create service name */
-    service_name = strdup(display_name);
-    ap_remove_spaces(service_name, display_name);
-
+    service_name = get_service_name(display_name);
+    
     if (isWindowsNT())
     {
         SC_HANDLE   schService;
@@ -1172,6 +1243,25 @@ void RemoveService(char *display_name)
                display_name);
 }
 
+
+BOOL isWindowsNT(void)
+{
+    static BOOL once = FALSE;
+    static BOOL isNT = FALSE;
+    
+    if (!once)
+    {
+        OSVERSIONINFO osver;
+        osver.dwOSVersionInfoSize = sizeof(osver);
+        if (GetVersionEx(&osver))
+            if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
+                isNT = TRUE;
+        once = TRUE;
+    }
+    return isNT;
+}
+
+
 /*
  * A hack to determine if we're running as a service without waiting for
  * the SCM to fail.
@@ -1202,8 +1292,8 @@ BOOL isValidService(char *display_name) {
     
     /* Remove spaces from display name to create service name */
     strcpy(service_key, "System\\CurrentControlSet\\Services\\");
-    service_name = strchr(service_key, '\0');
-    ap_remove_spaces(service_name, display_name);
+    service_name = get_service_name(display_name);
+    strcat(service_key, service_name);
 
     if (RegOpenKey(HKEY_LOCAL_MACHINE, service_key, &hkey) != ERROR_SUCCESS) {
         return FALSE;
@@ -1212,22 +1302,6 @@ BOOL isValidService(char *display_name) {
     return TRUE;
 }
 
-BOOL isWindowsNT(void)
-{
-    static BOOL once = FALSE;
-    static BOOL isNT = FALSE;
-    
-    if (!once)
-    {
-        OSVERSIONINFO osver;
-        osver.dwOSVersionInfoSize = sizeof(osver);
-        if (GetVersionEx(&osver))
-            if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
-                isNT = TRUE;
-        once = TRUE;
-    }
-    return isNT;
-}
 
 int send_signal_to_service(char *display_name, char *sig, 
                            int argc, char **argv)
@@ -1253,9 +1327,7 @@ int send_signal_to_service(char *display_name, char *sig,
         return FALSE;
     }
 
-    /* Remove spaces from display name to create service name */
-    service_name = strdup(display_name);
-    ap_remove_spaces(service_name, display_name);
+    service_name = get_service_name(display_name);
 
     if (isWindowsNT()) 
     {
index 93b9d0040223cfebcde83c6cbeb0b5b8b2582ab0..efbf5b506e2e5be932ad9e95ca62e0f514f5f410 100644 (file)
@@ -79,6 +79,8 @@ int service95_main(int (*main_fn)(int, char **), int argc, char **argv,
                   char *display_name);
 void service_set_status(int status);
 void service_cd();
+char *get_service_name(char *display_name);
+char *get_display_name(char *service_name);
 BOOL isProcessService();
 BOOL isValidService(char *display_name);
 void InstallService(pool *p, char *display_name, int argc, char **argv, int reconfig);