--- service.c.old	Fri Aug 17 19:25:26 2001
+++ service.c	Thu Sep 13 20:26:04 2001
@@ -69,6 +69,7 @@
 #include "mpm_winnt.h"
 #include "apr_strings.h"
 #include "apr_lib.h"
+#include "Win9xConHook.h"
 
 #ifdef NOUSER
 #undef NOUSER
@@ -171,103 +172,31 @@
 }
 
 static BOOL  die_on_logoff = FALSE;
+static HWND  console_wnd = NULL;
 
-static LRESULT CALLBACK monitor_service_9x_proc(HWND hWnd, UINT msg, 
-                                                WPARAM wParam, LPARAM lParam)
-{
-/* This is the WndProc procedure for our invisible window.
- * When the user shuts down the system, this window is sent
- * a signal WM_ENDSESSION. We clean up by signaling Apache
- * to shut down, and idle until Apache's primary thread quits.
+/* Once we are running a child process in our tty, it can no longer 
+ * determine which console window is our own, since the window
+ * reports that it is owned by the child process.
  */
-    if ((msg == WM_ENDSESSION) 
-            && (die_on_logoff || (lParam != ENDSESSION_LOGOFF)))
-    {
-        signal_parent(0);
-	if (wParam)
-            /* Don't leave this message until we are dead! */
-	    WaitForSingleObject(globdat.mpm_thread, 30000);
-        return 0;
-    }
-    return (DefWindowProc(hWnd, msg, wParam, lParam));
-}
-
-static DWORD WINAPI monitor_service_9x_thread(void *service_name)
-{
-    /* When running as a service under Windows 9x, there is no console
-     * window present, and no ConsoleCtrlHandler to call when the system 
-     * is shutdown.  If the WatchWindow thread is created with a NULL
-     * service_name argument, then the ...SystemMonitor window class is
-     * used to create the "Apache" window to watch for logoff and shutdown.
-     * If the service_name is provided, the ...ServiceMonitor window class
-     * is used to create the window named by the service_name argument,
-     * and the logoff message is ignored.
-     */
-    WNDCLASS wc;
-    HWND hwndMain;
-    MSG msg;
-    
-    wc.style         = CS_GLOBALCLASS;
-    wc.lpfnWndProc   = monitor_service_9x_proc; 
-    wc.cbClsExtra    = 0;
-    wc.cbWndExtra    = 0; 
-    wc.hInstance     = NULL;
-    wc.hIcon         = NULL;
-    wc.hCursor       = NULL;
-    wc.hbrBackground = NULL;
-    wc.lpszMenuName  = NULL;
-    if (service_name)
-	wc.lpszClassName = "ApacheWin95ServiceMonitor";
+static BOOL CALLBACK EnumttyWindow(HWND wnd, LPARAM retwnd)
+{
+    char tmp[20], *tty;
+    if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
+        tty = "ConsoleWindowClass";
     else
-	wc.lpszClassName = "ApacheWin95SystemMonitor";
- 
-    die_on_logoff = service_name ? FALSE : TRUE;
-
-    if (!RegisterClass(&wc)) 
-    {
-        ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(), 
-                     NULL, "Could not register window class for WatchWindow");
-        SetEvent(globdat.signal_monitor);
-        globdat.service_thread_id = 0;
-        return 0;
-    }
-    
-    /* Create an invisible window */
-    hwndMain = CreateWindow(wc.lpszClassName, 
-                            service_name ? (char *) service_name : "Apache",
- 	                    WS_OVERLAPPEDWINDOW & ~WS_VISIBLE, 
-                            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 
-                            CW_USEDEFAULT, NULL, NULL, NULL, NULL);
-                            
-    if (!hwndMain)
+        tty = "tty";
+    if (GetClassName(wnd, tmp, sizeof(tmp)) && !strcmp(tmp, tty)) 
     {
-        ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(), 
-                     NULL, "Could not create WatchWindow");
-        SetEvent(globdat.signal_monitor);
-        globdat.service_thread_id = 0;
-        return 0;
-    }
-
-    /* If we succeed, eliminate the console window.
-     * Signal the parent we are all set up, and
-     * watch the message queue while the window lives.
-     */
-    FreeConsole();
-    SetEvent((HANDLE) globdat.signal_monitor);
-    while (GetMessage(&msg, NULL, 0, 0)) 
-    {
-        if (msg.message == WM_CLOSE)
-            DestroyWindow(hwndMain); 
-        else {
-	    TranslateMessage(&msg);
-	    DispatchMessage(&msg);
+        DWORD wndproc, thisproc = GetCurrentProcessId();
+        GetWindowThreadProcessId(wnd, &wndproc);
+        if (wndproc == thisproc) {
+            *((HWND*)retwnd) = wnd;
+            return FALSE;
         }
     }
-    globdat.service_thread_id = 0;
-    return 0;
+    return TRUE;
 }
 
-
 static BOOL CALLBACK console_control_handler(DWORD ctrl_type)
 {
     switch (ctrl_type)
@@ -285,8 +214,12 @@
             signal_parent(0);
             return TRUE;
 
+       case CTRL_LOGOFF_EVENT:
+            if (!die_on_logoff)
+                return TRUE;
+            /* or fall through... */
+
         case CTRL_CLOSE_EVENT:
-        case CTRL_LOGOFF_EVENT:
         case CTRL_SHUTDOWN_EVENT:
             /* for Terminate signals, shut down the server.
              * Wait for Apache to terminate, but respond
@@ -308,11 +241,15 @@
 static void stop_console_handler(void)
 {
     SetConsoleCtrlHandler(console_control_handler, FALSE);
+    if (osver.dwPlatformId < VER_PLATFORM_WIN32_NT)
+        FixConsoleCtrlHandler(console_control_handler, 0);
 }
 
 
 void mpm_start_console_handler(void)
 {
+    if (osver.dwPlatformId < VER_PLATFORM_WIN32_NT)
+        FixConsoleCtrlHandler(console_control_handler, die_on_logoff ? 1 : 2);
     SetConsoleCtrlHandler(console_control_handler, TRUE);
     atexit(stop_console_handler);
 }
@@ -365,6 +302,7 @@
     else
     {
         SetConsoleCtrlHandler(child_control_handler, TRUE);
+        FreeConsole();
         atexit(stop_child_console_handler);
     }
 }
@@ -802,8 +740,7 @@
         }
         else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */
         {
-            RegisterServiceProcess(0, 0);
-            PostThreadMessage(globdat.service_thread_id, WM_CLOSE, 0, 0);
+            Windows9xServiceCtrlHandler(console_control_handler, NULL);
         }
 
         WaitForSingleObject(globdat.service_thread, 5000);
@@ -826,30 +763,29 @@
                                                   service_nt_dispatch_thread, 
                                                   NULL, 0, 
                                                   &globdat.service_thread_id);
+        
+        if (globdat.signal_monitor && globdat.service_thread) 
+        {
+            waitfor[0] = globdat.signal_monitor;
+            waitfor[1] = globdat.service_thread;
+    
+            /* SetEvent(globdat.signal_monitor) to clean up the SCM thread */
+            if (WaitForMultipleObjects(2, waitfor, FALSE, 10000) != WAIT_OBJECT_0) {
+                CloseHandle(globdat.service_thread);
+                return APR_ENOTHREAD;
+            }
+        }
     }
     else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */
     {
-        if (!RegisterServiceProcess(0, 1)) 
-            return GetLastError();
+
+        die_on_logoff = mpm_service_name ? FALSE : TRUE;
 
         globdat.signal_monitor = CreateEvent(NULL, FALSE, FALSE, NULL);
-        if (globdat.signal_monitor)
-            globdat.service_thread = CreateThread(NULL, 0,
-                                                  monitor_service_9x_thread, 
-                                                  (LPVOID) mpm_service_name, 0, 
-                                                  &globdat.service_thread_id);
-    }
 
-    if (globdat.signal_monitor && globdat.service_thread) 
-    {
-        waitfor[0] = globdat.signal_monitor;
-        waitfor[1] = globdat.service_thread;
-    
-        /* SetEvent(globdat.signal_monitor) to clean up the SCM thread */
-        if (WaitForMultipleObjects(2, waitfor, FALSE, 10000) != WAIT_OBJECT_0) {
-            CloseHandle(globdat.service_thread);
-            return APR_ENOTHREAD;
-        }
+        if (globdat.signal_monitor)
+            Windows9xServiceCtrl2Handler(console_control_handler, mpm_display_name,
+                                         &globdat.service_thread, &globdat.service_thread_id);
     }
 
     if (globdat.service_thread_id)
@@ -870,6 +806,22 @@
         ReportStatusToSCMgr(SERVICE_RUNNING,    // service state
                             NO_ERROR,           // exit code
                             0);                 // wait hint
+    }
+    else
+    {
+        int maxwait = 100;
+
+        FreeConsole();
+        AllocConsole();              
+
+        while (!console_wnd && maxwait-- > 0) { 
+                EnumWindows(EnumttyWindow, (long)(&console_wnd));
+                Sleep(100);
+        }
+        if (console_wnd) {
+            FixConsoleCtrlHandler(console_control_handler, die_on_logoff ? 1 : 2);
+            ShowWindow(console_wnd, SW_HIDE);
+        }
     }
     return APR_SUCCESS;
 }
