From: William A. Rowe Jr Date: Wed, 3 Oct 2001 20:56:00 +0000 (+0000) Subject: Accept service names modified by the user in the Win/2000 Service Control X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d69b5e1e8d85b891cf1b774763e33cda82d60fb8;p=thirdparty%2Fapache%2Fhttpd.git Accept service names modified by the user in the Win/2000 Service Control 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 --- diff --git a/src/CHANGES b/src/CHANGES index ae188e8624b..27f61f8e564 100644 --- a/src/CHANGES +++ b/src/CHANGES @@ -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 , Lars Eilebrecht] diff --git a/src/main/http_main.c b/src/main/http_main.c index 91f33e9c70d..10126c03116 100644 --- a/src/main/http_main.c +++ b/src/main/http_main.c @@ -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 diff --git a/src/os/win32/registry.c b/src/os/win32/registry.c index 04ba810a810..882bc9974af 100755 --- a/src/os/win32/registry.c +++ b/src/os/win32/registry.c @@ -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); diff --git a/src/os/win32/service.c b/src/os/win32/service.c index b915782ed30..5de5f36a86d 100644 --- a/src/os/win32/service.c +++ b/src/os/win32/service.c @@ -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()) { diff --git a/src/os/win32/service.h b/src/os/win32/service.h index 93b9d004022..efbf5b506e2 100644 --- a/src/os/win32/service.h +++ b/src/os/win32/service.h @@ -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);