You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by "Keijser, Jan Just" <KE...@logica.com> on 1999/10/06 23:19:13 UTC

[PATCH] Several patches for running Apache 1.3.9 on Win95

This patch is intended to fix/address PR2472, PR4125, PR1643 (suspended) and
PR2208 (suspended).

This patch does several things:
1. Adds support to run Apache as a service on Win95. This service will run
without any users logging on to the system and will continue to run until
the system is shutdown (PR2208);
2. Making sure that Apache is shut down when the system is shutdown. This is
done by spawning an extra thread, which monitors the system shutdown
messages; if this message is seen, it will shutdown Apache using
'send_signal( "shutdown" )' (PR1643, PR2472)
3. Installing/Uninstalling Apache on Win95 is done using the same syntax as
on NT  (i.e. apache -i/-u)
4. Pressing Ctrl-C in the Apache console window will cause Apache to clean
up nicely and then shut down. This is done using a ConsoleCtrlHandler;
5. Apache will try to close the console window when possible; in most cases
this will result in the console window disappearing after the successful
launch of Apache. The console window will NOT be closed if the user starts a
DOS box and then starts Apache from within that DOS box. This is required to
make Apache shut down cleanly when run on Windows 95, otherwise Apache seems
to prevent a system shutdown (PR4125)

Extra:
- The command "apache -s" will start Apache as a service on Win95; this is
necessary when installing Apache as a service, since there is no easy method
on Win95 for determining whether an app is run as a service or by a user.

All diffs are based on the Apache 1.3.9 Win32 source code.

*** main/http_main-old.c	Tue Aug 11 08:54:48 1999
--- main/http_main.c	Wed Oct 06 15:46:12 1999
***************
*** 1062,1067 ****
--- 1062,1068 ----
      fprintf(stderr, "  -k start         : tell Apache to start\n");
      fprintf(stderr, "  -i               : install an Apache service\n");
      fprintf(stderr, "  -u               : uninstall an Apache service\n");
+     fprintf(stderr, "  -s               : run Apache as a service (Win9x
only)\n");
  #endif
      exit(1);
  }
***************
*** 1262,1267 ****
--- 1263,1296 ----
      else
  	return (0);
  }
+ 
+ /* Control handler for processing Ctrl-C/Ctrl-Break and
+  * on Windows NT also user logoff and system shutdown
+  */
+ 
+ /* Is defined later in this file */
+ int send_signal(pool *p, char *signal);
+ 
+ BOOL WINAPI ap_control_handler( DWORD ctrl_type )
+ {
+ 	switch ( ctrl_type )
+ 	{
+ 	case CTRL_C_EVENT:
+ 		printf( "Caught Ctrl-Break, shutting down...\n" );
+ 	/* The following only work on NT, despite the manuals... */
+ 	case CTRL_CLOSE_EVENT:
+ 	case CTRL_LOGOFF_EVENT:
+ 	case CTRL_SHUTDOWN_EVENT:
+ 		/* for all known signals, shut down the server */
+ 		send_signal( pconf, "shutdown" );
+ 		/* Tell the system we have dealt with the signal */
+ 		return TRUE;
+ 		break;
+ 	}
+ 
+ 	/* We should never get here, but this is harmless */
+ 	return FALSE;
+ }
  #endif /* WIN32 */
  
  
***************
*** 5944,5949 ****
--- 5973,6064 ----
      }
  }
  
+ 
+ /* This is the WndProc procedure for our invisible window.
+  * When the user shuts down the system, this window is sent
+  * a signal WM_QUERYENDSESSION with lParam == 0 to indicate
+  * a system shutdown. We clean up by shutting down Apache and
+  * indicate to the system that the message was received and
+  * understood (return TRUE).
+  * If a user logs off, the window is sent WM_QUERYENDSESSION 
+  * as well, but with lParam != 0. We ignore this case.
+  */
+ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
lParam)
+ {
+ 	switch (message)
+ 	{
+ 		case WM_QUERYENDSESSION:
+ 			if ( lParam == 0 )
+ 			{
+ 				/* Tell Apache to shut down gracefully */
+ 				send_signal( pconf, "shutdown" );
+ 			}
+ 			return TRUE;
+ 			break;
+ 	}
+ 			
+ 	return (DefWindowProc(hWnd, message, wParam, lParam));
+ }
+ 
+ 
+ DWORD WINAPI WatchWindow( void *junk )
+ {
+ /* When running on Windows 9x, the ConsoleCtrlHandler is _NOT_ 
+  * called when the system is shutdown or the user logs off, nor 
+  * are there any other signals that console applications get. 
+  * So we create an invisible window and set up a WndProc for
+  * this window. Funny enough, this window DOES receive a signal
+  * when the user is logging off or the system is shutting down.
+  * We need to deal with both cases in our own WndProc routine.
+  */
+ 	WNDCLASS	wc;
+ 	HWND		hwndMain;
+ 
+     wc.style         = CS_GLOBALCLASS;
+ 	wc.lpfnWndProc   = (WNDPROC) WndProc; 
+     wc.cbClsExtra    = 0;
+ 	wc.cbWndExtra    = 0; 
+     wc.hInstance     = NULL;
+ 	wc.hIcon         = NULL;
+ 	wc.hCursor       = NULL;
+ 	wc.hbrBackground = NULL;
+ 	wc.lpszMenuName  = NULL;
+ 	wc.lpszClassName = "SleepyMonkey";
+ 	
+ 	if (RegisterClass(&wc)) 
+ 	{
+ 		/* Create an invisible window */
+ 		hwndMain = CreateWindow("SleepyMonkey", "Apache", 
+ 				WS_OVERLAPPEDWINDOW & ~WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 
+         		CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL,
NULL);
+ 		
+ 		if ( hwndMain )
+ 		{
+ 			MSG msg;
+ 
+ 			while (GetMessage(&msg, hwndMain, 0, 0)) 
+ 			{
+ 				TranslateMessage(&msg);
+ 				DispatchMessage(&msg);
+ 			}
+ 
+ 		}
+ 		else
+ 		{
+ 			ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR,
NULL,
+ 						"Could not create
WatchWindow");
+ 		}
+ 	}
+ 	else
+ 	{
+ 		ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ 					"Could not register window class for
WatchWindow");
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ 
  int master_main(int argc, char **argv)
  {
      /* returns NULL if invalid (Win95?) */
***************
*** 6002,6012 ****
      start_mutex = ap_create_mutex(signal_prefix_string);
      restart_pending = shutdown_pending = 0;
  
      do { /* restart-pending */
  	if (!is_graceful) {
  	    ap_restart_time = time(NULL);
  	}
!         copy_listeners(pconf);
  	ap_clear_pool(pconf);
  	pparent = ap_make_sub_pool(pconf);
  
--- 6117,6139 ----
      start_mutex = ap_create_mutex(signal_prefix_string);
      restart_pending = shutdown_pending = 0;
  
+ 	/* Create a thread for listening to WM_QUERYENDSESSION messages.
+ 	 * This is necessary on Win9x only, as the SetConsoleCtrlHandler
+ 	 * function does not work properly for Win9x
+ 	 */
+ 	if ( get_platform_id() == VER_PLATFORM_WIN32_WINDOWS )
+ 	{
+ 		DWORD thread_id;
+ 
+ 		CreateThread( NULL, 0, WatchWindow, NULL, 0, &thread_id );
+ 	}
+ 
      do { /* restart-pending */
  	if (!is_graceful) {
  	    ap_restart_time = time(NULL);
  	}
! 	copy_listeners(pconf);
! 
  	ap_clear_pool(pconf);
  	pparent = ap_make_sub_pool(pconf);
  
***************
*** 6158,6163 ****
--- 6285,6291 ----
      return (0);
  }
  
+ 
  /*
   * Send signal to a running Apache. On entry signal should contain
   * either "shutdown" or "restart"
***************
*** 6248,6253 ****
--- 6376,6382 ----
      char *s;
      char *service_name = NULL;
      int install = 0;
+ 	int run_as_service = 0;
      int conf_specified = 0;
      char *signal_to_send = NULL;
      char cwd[MAX_STRING_LEN];
***************
*** 6309,6322 ****
  	    ap_assert(start_mutex);
  	    child = 1;
  	    break;
!         case 'n':
!             service_name = ap_pstrdup(pcommands, optarg);
!             if (isValidService(optarg)) {
!                 ap_registry_get_service_conf(pconf, ap_server_confname,
sizeof(ap_server_confname),
!                                              optarg);
!                 conf_specified = 1;
!             }
!             break;
  	case 'i':
  	    install = 1;
  	    break;
--- 6438,6454 ----
  	    ap_assert(start_mutex);
  	    child = 1;
  	    break;
! 	case 'n':
! 		service_name = ap_pstrdup(pcommands, optarg);
! 		if (isValidService(optarg)) {
! 			ap_registry_get_service_conf(pconf,
ap_server_confname, sizeof(ap_server_confname),
!
optarg);
! 			conf_specified = 1;
! 		}
! 		break;
! 	case 's':
! 		run_as_service = 1;
! 		break;
  	case 'i':
  	    install = 1;
  	    break;
***************
*** 6450,6456 ****
  
      if (!child && !ap_dump_settings) { 
          ap_log_pid(pconf, ap_pid_fname);
!     }
  
      post_parse_init();
  
--- 6582,6588 ----
  
      if (!child && !ap_dump_settings) { 
          ap_log_pid(pconf, ap_pid_fname);
! 	    }
  
      post_parse_init();
  
***************
*** 6458,6465 ****
      printf("%s running...\n", ap_get_server_version());
  #endif
  #ifdef WIN32
      if (!child) {
! 	printf("%s running...\n", ap_get_server_version());
      }
  #endif
      if (one_process && !exit_event)
--- 6590,6609 ----
      printf("%s running...\n", ap_get_server_version());
  #endif
  #ifdef WIN32
+ 	if (run_as_service)	{
+ 		/* Close the bloody console window, if you can...
+ 		 *
+ 		 * At first I did this in the getopt switch statement,
+ 		 * but this caused problems with the file handles:
+ 		 * all output for access.log ended up in error.log.
+ 		 */
+ 		FreeConsole();
+ 	}
      if (!child) {
! 		/* Let's go fishing for some signals */
! 		SetConsoleCtrlHandler( ap_control_handler, TRUE );
! 
! 		printf("%s running...\n", ap_get_server_version());
      }
  #endif
      if (one_process && !exit_event)
***************
*** 6472,6485 ****
       * exits, it spawns off a new one
       */
      if (child || one_process) {
! 	if (!exit_event || !start_mutex)
! 	    exit(-1);
! 	worker_main();
! 	ap_destroy_mutex(start_mutex);
! 	destroy_event(exit_event);
!     }
!     else 
!         master_main(argc, argv);
  
      clean_parent_exit(0);
      return 0;	/* purely to avoid a warning */
--- 6616,6635 ----
       * exits, it spawns off a new one
       */
      if (child || one_process) {
! 		if (!exit_event || !start_mutex) {
! 			exit(-1);
! 		}
! 		worker_main();
! 		ap_destroy_mutex(start_mutex);
! 		destroy_event(exit_event);
!     } else {
! 		if (run_as_service)	{
! 			/* service_main will call master_main ! */
! 	        service_main(master_main, argc, argv);
! 		} else {
! 	        master_main(argc, argv);
! 		}
! 	}
  
      clean_parent_exit(0);
      return 0;	/* purely to avoid a warning */


*** os/win32/service-old.c	Thu Apr 08 16:04:48 1999
--- os/win32/service.c	Wed Oct 06 15:46:12 1999
***************
*** 32,60 ****
  static int ap_start_service(SC_HANDLE);
  static int ap_stop_service(SC_HANDLE);
  
  int service_main(int (*main_fn)(int, char **), int argc, char **argv )
  {
!     SERVICE_TABLE_ENTRY dispatchTable[] =
!     {
!         { "", service_main_fn },
!         { NULL, NULL }
!     };
! 
!     globdat.main_fn = main_fn;
!     globdat.stop_event = create_event(0, 0, "apache-signal");
!     globdat.connected = 1;
  
!     if(!StartServiceCtrlDispatcher(dispatchTable))
!     {
!         /* This is a genuine failure of the SCM. */
!         ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
!         "Error starting service control dispatcher");
!         return(globdat.exit_status);
!     }
!     else
!     {
!         return(globdat.exit_status);
!     }
  }
  
  void service_cd()
--- 32,128 ----
  static int ap_start_service(SC_HANDLE);
  static int ap_stop_service(SC_HANDLE);
  
+ DWORD platform_id = -1;
+ 
+ DWORD get_platform_id( void )
+ {
+ 	OSVERSIONINFO os_info;
+ 
+ 	if (platform_id == -1) {
+ 		/* Get the platform identifier */
+ 	    os_info.dwOSVersionInfoSize = sizeof(os_info);
+ 
+ 	    if (GetVersionEx(&os_info))	{
+ 			platform_id = os_info.dwPlatformId;
+ 		}
+ 	}
+ 
+ 	return platform_id;
+ }
+ 
  int service_main(int (*main_fn)(int, char **), int argc, char **argv )
  {
! /*
! 	printf( "Start of service_main:\n  main_fn  = %p\n", main_fn );
! */
! 
! 	switch ( get_platform_id() ) {
! 	case VER_PLATFORM_WIN32_NT:
! 		/* Windows NT */
! 		{
! 			SERVICE_TABLE_ENTRY dispatchTable[] =
! 			{
! 				{ "", service_main_fn },
! 				{ NULL, NULL }
! 			};
! 
! 			globdat.main_fn = main_fn;
! 			globdat.stop_event = create_event(0, 0,
"apache-signal");
! 			globdat.connected = 1;
! 
! 			if(!StartServiceCtrlDispatcher(dispatchTable)) {
! 				/* This is a genuine failure of the SCM. */
! 				ap_log_error(APLOG_MARK,
APLOG_ERR|APLOG_WIN32ERROR, NULL,
! 				"Error starting service control
dispatcher");
! 		        return(globdat.exit_status);
! 			} else {
! 				return(globdat.exit_status);
! 			}
! 			break;
! 		}
! 	case VER_PLATFORM_WIN32_WINDOWS:
! 		/* Windows 95/98 */
! 		{
! 			HINSTANCE kerneldll;
! 			DWORD (WINAPI *RegisterService)(DWORD, DWORD);
! 
! 			/* Obtain a handle to the kernel library */
! 			kerneldll = LoadLibrary( "KERNEL32.DLL" );
! 			if ( kerneldll == NULL ) {
! 				break;
! 			}
! 
! 			/* Find the RegisterServiceProcess function */
! 			RegisterService = (DWORD (WINAPI *)(DWORD, DWORD))
! 				GetProcAddress( kerneldll,
"RegisterServiceProcess" );
! 			if ( RegisterService == NULL ) {
! 				break;
! 			}
! 			
! 			/* Register this process as a service */
! 			if ( ! RegisterService( (DWORD)NULL, 1 ) ) {
! 				break;
! 			}
! 
! 			/* Run the service */
! 			globdat.exit_status = main_fn( argc, argv );
! 
! 			/* When the service quits, remove it from the 
! 			 system service table */
! 			RegisterService( (DWORD)NULL, 0 );
! 
! 			/* Free the kernel library */
! 			FreeLibrary( kerneldll );
! 
! 			/* We have to quit right here to avoid an invalid
page fault */
! 			exit( globdat.exit_status );
! 
! 			break;
! 		}
! 	}
  
! 	/* We should never get here... */
! 	return( -1 );
  }
  
  void service_cd()
***************
*** 123,129 ****
      {
          // Stop the service.
          //
!         case SERVICE_CONTROL_STOP:
              state = SERVICE_STOP_PENDING;
  	    ap_start_shutdown();
              break;
--- 191,197 ----
      {
          // Stop the service.
          //
! 		case SERVICE_CONTROL_STOP:
              state = SERVICE_STOP_PENDING;
  	    ap_start_shutdown();
              break;
***************
*** 185,329 ****
      return(1);
  }
  
  void InstallService(char *service_name, char *conf)
  {
-     SC_HANDLE   schService;
-     SC_HANDLE   schSCManager;
- 
      TCHAR szPath[512];
-     TCHAR szQuotedPath[512];
  
      printf("Installing the %s service to use %s\n", service_name, conf);
  
!     if (GetModuleFileName( NULL, szPath, 512 ) == 0)
!     {
          ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
          "GetModuleFileName failed");
          return;
      }
  
!     ap_snprintf(szQuotedPath, 512, "\"%s\"", szPath);
! 
!     schSCManager = OpenSCManager(
!                         NULL,                   // machine (NULL == local)
!                         NULL,                   // database (NULL ==
default)
!                         SC_MANAGER_ALL_ACCESS   // access required
!                         );
!    if (!schSCManager) {
!        ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
! 	   "OpenSCManager failed");
!     }
!     else {
!         schService = CreateService(
!             schSCManager,               // SCManager database
!             service_name,               // name of service
!             service_name,               // name to display
!             SERVICE_ALL_ACCESS,         // desired access
!             SERVICE_WIN32_OWN_PROCESS,  // service type
!             SERVICE_AUTO_START,       // start type
!             SERVICE_ERROR_NORMAL,       // error control type
!             szQuotedPath,               // service's binary
!             NULL,                       // no load ordering group
!             NULL,                       // no tag identifier
!             NULL,       // dependencies
!             NULL,                       // LocalSystem account
!             NULL);                      // no password
! 
!         if (schService) {
!             CloseServiceHandle(schService);
! 
!             /* Now store the server_root in the registry */
!             if(!ap_registry_set_service_conf(conf, service_name))
!                 printf("The %s service has been installed
successfully.\n", service_name );
!         }
!         else {
!             ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, 
! 		"CreateService failed");
!         }
! 
!         CloseServiceHandle(schSCManager);
!     }
  }
  
  
  void RemoveService(char *service_name)
  {
-     SC_HANDLE   schService;
-     SC_HANDLE   schSCManager;
- 
      printf("Removing the %s service\n", service_name);
  
!     schSCManager = OpenSCManager(
!                         NULL,                   // machine (NULL == local)
!                         NULL,                   // database (NULL ==
default)
!                         SC_MANAGER_ALL_ACCESS   // access required
!                         );
!     if (!schSCManager) {
!        ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
! 	   "OpenSCManager failed");
!     }
!     else {
!         schService = OpenService(schSCManager, service_name,
SERVICE_ALL_ACCESS);
! 
!         if (schService == NULL) {
!             /* Could not open the service */
!            ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
! 			"OpenService failed");
!         }
!         else {
!             /* try to stop the service */
!             ap_stop_service(schService);
! 
!             // now remove the service
!             if (DeleteService(schService) == 0)
! 		ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
! 		    "DeleteService failed");
!             else
!                 printf("The %s service has been removed successfully.\n",
service_name );
!             CloseServiceHandle(schService);
!         }
!         /* SCM removes registry parameters  */
!         CloseServiceHandle(schSCManager);
!     }
! 
  }
  
  /* A hack to determine if we're running as a service without waiting for
!  * the SCM to fail; if AllocConsole succeeds, we're a service.
   */
  
  BOOL isProcessService() {
!     if( !AllocConsole() ) 
!         return FALSE;
!     FreeConsole();
!     return TRUE;
  }
  
  /* Determine is service_name is a valid service
   */
  
! BOOL isValidService(char *service_name) {
!     SC_HANDLE schSCM, schSVC;
!     int Err;
! 
!     if (!(schSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) {
!         ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
!         "OpenSCManager failed");
!        return FALSE;
!     }
! 
!     if ((schSVC = OpenService(schSCM, service_name, SERVICE_ALL_ACCESS)))
{
!         CloseServiceHandle(schSVC);
!         CloseServiceHandle(schSCM);
!         return TRUE;
!     }
! 
!     Err = GetLastError();
!     if (Err != ERROR_SERVICE_DOES_NOT_EXIST && Err != ERROR_INVALID_NAME)
!         ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
!         "OpenService failed");
  
!     return FALSE;
  }
  
  int send_signal_to_service(char *service_name, char *sig) {
--- 253,496 ----
      return(1);
  }
  
+ 
  void InstallService(char *service_name, char *conf)
  {
      TCHAR szPath[512];
  
      printf("Installing the %s service to use %s\n", service_name, conf);
  
!     if (GetModuleFileName( NULL, szPath, 512 ) == 0) {
          ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
          "GetModuleFileName failed");
          return;
      }
  
! 	switch ( get_platform_id() )
! 	{
! 	case VER_PLATFORM_WIN32_NT:
! 		/* Windows NT */
! 		{
! 			TCHAR		szQuotedPath[512];
! 			SC_HANDLE   schService;
! 			SC_HANDLE   schSCManager;
! 
! 			ap_snprintf(szQuotedPath, 512, "\"%s\"", szPath);
! 
! 		    schSCManager = OpenSCManager(
! 							NULL,
// machine (NULL == local)
! 							NULL,
// database (NULL == default)
!
SC_MANAGER_ALL_ACCESS   // access required
! 							);
! 			 if (!schSCManager) {
! 				 ap_log_error(APLOG_MARK,
APLOG_ERR|APLOG_WIN32ERROR, NULL,
! 							 "OpenSCManager
failed");
! 			 } else {
! 				 schService = CreateService(
!
schSCManager,               // SCManager database
!
service_name,               // name of service
!
service_name,               // name to display
!
SERVICE_ALL_ACCESS,         // desired access
!
SERVICE_WIN32_OWN_PROCESS,  // service type
!
SERVICE_AUTO_START,			// start type
!
SERVICE_ERROR_NORMAL,       // error control type
!
szQuotedPath,               // service's binary
! 								NULL,
// no load ordering group
! 								NULL,
// no tag identifier
! 								NULL,
// dependencies
! 								NULL,
// LocalSystem account
! 								NULL);
// no password
! 
! 				 if (schService) {
! 					CloseServiceHandle(schService);
! 
! 					/* Now store the server_root in the
registry */
!
if(!ap_registry_set_service_conf(conf, service_name)) {
! 						printf("The %s service has
been installed successfully.\n", service_name );
! 					}
! 				 } else {
! 					ap_log_error(APLOG_MARK,
APLOG_ERR|APLOG_WIN32ERROR, NULL, 
!
"CreateService failed");
! 				}
! 
! 				CloseServiceHandle(schSCManager);
! 			}
! 
! 			break;
! 		}
! 	case VER_PLATFORM_WIN32_WINDOWS:
! 		/* Windows 95/98 */
! 		{
! 			TCHAR		szServicePath[512];
! 			HKEY		runservices;
! 
! 			ap_snprintf(szServicePath, 512, "%s -s", szPath);
! 	
! 			/* Create/Find the RunServices key */
! 			if ( RegCreateKey (HKEY_LOCAL_MACHINE, 
!
"Software\\Microsoft\\Windows\\CurrentVersion\\RunServices",
! 					&runservices ) != ERROR_SUCCESS ) {
! 				ap_log_error(APLOG_MARK,
APLOG_ERR|APLOG_WIN32ERROR, NULL,
! 							 "Could not
create/find RunServices registry key");
! 				break;
! 			}
! 
! 			/* Attempt to add a key for our service */
! 			if (RegSetValueEx(runservices, 
! 							  service_name, 
! 							  0, 
! 							  REG_SZ, 
! 							  (unsigned char
*)szServicePath, 
! 							  strlen(
szServicePath )+1
! 							  ) !=
ERROR_SUCCESS) {
! 				ap_log_error(APLOG_MARK,
APLOG_ERR|APLOG_WIN32ERROR, NULL,
! 							 "Unable to install
service: Could not add registry key");
! 				RegCloseKey( runservices );
! 				break;
! 			}
! 
! 			RegCloseKey( runservices );
! 		
! 			/* Now store the server_root in the registry */
! 			if ( !ap_registry_set_service_conf( conf,
service_name ) ) {
! 				printf("The %s service has been installed
successfully.\n", service_name );
! 			}
! 
! 			break;
! 		}
! 	}
  }
  
  
  void RemoveService(char *service_name)
  {
      printf("Removing the %s service\n", service_name);
  
! 	switch ( get_platform_id() ) 
! 	{
! 	case VER_PLATFORM_WIN32_NT:
! 		/* Windows NT */
! 		{
! 		    SC_HANDLE   schService;
! 			SC_HANDLE   schSCManager;
! 
! 			schSCManager = OpenSCManager(
! 				            NULL,                   //
machine (NULL == local)
! 					        NULL,                   //
database (NULL == default)
! 						    SC_MANAGER_ALL_ACCESS
// access required
! 							);
! 			if (!schSCManager)
! 			{
! 				ap_log_error(APLOG_MARK,
APLOG_ERR|APLOG_WIN32ERROR, NULL,
! 							"OpenSCManager
failed");
! 			} else {
! 				schService = OpenService(schSCManager,
service_name, SERVICE_ALL_ACCESS);
! 				if (schService == NULL) {
! 					/* Could not open the service */
! 					ap_log_error(APLOG_MARK,
APLOG_ERR|APLOG_WIN32ERROR, NULL,
! 								"OpenService
failed");
! 				} else {
! 					/* try to stop the service */
! 					ap_stop_service(schService);
! 
! 					/* now remove the service */
! 					if (DeleteService(schService) == 0)
{
! 						ap_log_error(APLOG_MARK,
APLOG_ERR|APLOG_WIN32ERROR, NULL,
!
"DeleteService failed");
! 					} else {
! 						printf("The %s service has
been removed successfully.\n", service_name );
! 					}
!             
! 					CloseServiceHandle(schService);
! 				}
! 				/* SCM removes registry parameters  */
! 				CloseServiceHandle(schSCManager);
! 			}
! 
! 			break;
! 		}
! 	case VER_PLATFORM_WIN32_WINDOWS:
! 		/* Windows 95/98 */
! 		{
! 			HKEY runservices;
! 
! 			/* Open the RunServices key */
! 			if (RegOpenKey(HKEY_LOCAL_MACHINE, 
!
"Software\\Microsoft\\Windows\\CurrentVersion\\RunServices",
! 						   &runservices) !=
ERROR_SUCCESS) {
! 				ap_log_error(APLOG_MARK,
APLOG_ERR|APLOG_WIN32ERROR, NULL,
! 							 "Could not open
RunServices registry key");
! 			} else {
! 				/* Delete the registry key for this service
*/
! 				if ( RegDeleteValue( runservices,
service_name ) != ERROR_SUCCESS )	{
! 					ap_log_error(APLOG_MARK,
APLOG_ERR|APLOG_WIN32ERROR, NULL,
! 								 "Unable to
remove service: Could not delete registry key");
! 				}
! 
! 				RegCloseKey(runservices);
! 			}
! 
! 			break;
! 		}
! 	}
  }
  
  /* A hack to determine if we're running as a service without waiting for
!  * the SCM to fail:
!      if we can't get a handle for stdin, then we're a service.
   */
  
  BOOL isProcessService() {
!     HANDLE h;
! 
! 	h = GetStdHandle( STD_INPUT_HANDLE );
!     return( h == INVALID_HANDLE_VALUE );
  }
  
  /* Determine is service_name is a valid service
   */
  
! BOOL isValidService(char *service_name) 
! {
!     switch ( get_platform_id() )
! 	{
! 	case VER_PLATFORM_WIN32_NT:
! 		/* Windows NT */
! 		{
! 			SC_HANDLE schSCM, schSVC;
! 			int Err;
! 
! 			if (!(schSCM = OpenSCManager(NULL, NULL,
SC_MANAGER_ALL_ACCESS))) 
! 			{
! 				ap_log_error(APLOG_MARK,
APLOG_ERR|APLOG_WIN32ERROR, NULL,
! 							"OpenSCManager
failed");
! 				return FALSE;
! 			}
! 
! 			if ((schSVC = OpenService(schSCM, service_name,
SERVICE_ALL_ACCESS))) 
! 			{
! 				CloseServiceHandle(schSVC);
! 				CloseServiceHandle(schSCM);
! 				return TRUE;
! 			}
! 	
! 			Err = GetLastError();
! 			if (Err != ERROR_SERVICE_DOES_NOT_EXIST && Err !=
ERROR_INVALID_NAME)
! 				ap_log_error(APLOG_MARK,
APLOG_ERR|APLOG_WIN32ERROR, NULL,
! 							"OpenService
failed");
! 
! 			break;
! 		}
! 	case VER_PLATFORM_WIN32_WINDOWS:
! 		/* Windows 95/98 */
! 		{
! 			/* I couldn't think of a valid check... */
! 			return TRUE;
! 			break;
! 		}
! 	}
  
! 	return FALSE;
  }
  
  int send_signal_to_service(char *service_name, char *sig) {


*** os/win32/service-old.h	Thu Apr 08 16:04:48 1999
--- os/win32/service.h	Fri Sep 24 11:34:32 1999
***************
*** 3,8 ****
--- 3,9 ----
  #define SERVICE_H
  
  #ifdef WIN32
+ DWORD get_platform_id( void );
  int service_main(int (*main_fn)(int, char **), int argc, char **argv);
  void service_set_status(int status);
  void service_cd();

Re: [PATCH] Several patches for running Apache 1.3.9 on Win95

Posted by Bill Stoddard <st...@raleigh.ibm.com>.
Thanks for your contribution. Always good to see some fellow Apache for
Windows developers :-).  Not sure when I can get around to reviewing these
(spending most of my time doing Apache 2.0 development),  but I will update
the STATUS file with your patches so we will not loose track of them.

Bill