Return-Path: Delivered-To: apmail-apache-cvs-archive@apache.org Received: (qmail 36735 invoked by uid 500); 12 Dec 2000 06:02:01 -0000 Mailing-List: contact apache-cvs-help@apache.org; run by ezmlm Precedence: bulk Reply-To: new-httpd@apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list apache-cvs@apache.org Received: (qmail 36676 invoked by uid 500); 12 Dec 2000 06:02:00 -0000 Delivered-To: apmail-apache-1.3-cvs@apache.org Date: 12 Dec 2000 06:01:59 -0000 Message-ID: <20001212060159.36644.qmail@locus.apache.org> From: wrowe@locus.apache.org To: apache-1.3-cvs@apache.org Subject: cvs commit: apache-1.3/src/os/win32/win9xconhook Win9xConHook.c wrowe 00/12/11 22:01:59 Modified: src/os/win32 service.c src/os/win32/win9xconhook Win9xConHook.c Log: Here's what should work flawlessly... WinNT/2K as a service or a console app, Win9x as a console app or hidden service, the ctrl+c, ctrl+break and close button on all platforms. Now the rough part, Win9x, while the processes set themselves up as services, are dieing on logoff. My guess, the hooks are deregistered regardless on logoff, unloading the 'partner' .dll that is sitting in WinOldAp's process. Anyway, before rebooting 1,000 more times, and possibly loosing some fruits of my effort, here is the working code. Revision Changes Path 1.34 +24 -20 apache-1.3/src/os/win32/service.c Index: service.c =================================================================== RCS file: /home/cvs/apache-1.3/src/os/win32/service.c,v retrieving revision 1.33 retrieving revision 1.34 diff -u -r1.33 -r1.34 --- service.c 2000/12/11 16:48:27 1.33 +++ service.c 2000/12/12 06:01:57 1.34 @@ -189,7 +189,8 @@ case CTRL_LOGOFF_EVENT: if (!die_on_logoff) - return FALSE; + return TRUE; + /* or fall through... */ case CTRL_CLOSE_EVENT: case CTRL_SHUTDOWN_EVENT: @@ -234,8 +235,7 @@ void stop_child_monitor(void) { - if (!isWindowsNT()) - FixConsoleCtrlHandler(ap_control_handler, 0); + FixConsoleCtrlHandler(ap_control_handler, 0); } /* @@ -255,8 +255,8 @@ /* Prevent holding open the (hidden) console */ real_exit_code = 0; - if (!is_child_of_service) - die_on_logoff = TRUE; + /* We only die on logoff if we not a service's child */ + die_on_logoff = !is_child_of_service; if (isWindowsNT()) { if (!is_child_of_service) { @@ -285,34 +285,37 @@ return; } - FreeConsole(); - AllocConsole(); - while (maxwait-- > 0) { + if (!is_child_of_service) { + FreeConsole(); + AllocConsole(); + } + while (!console_wnd && maxwait-- > 0) { EnumWindows(EnumttyWindow, (long)(&console_wnd)); - if (console_wnd) { - ShowWindow(console_wnd, SW_HIDE); - break; - } Sleep(100); } - - FixConsoleCtrlHandler(ap_control_handler, die_on_logoff ? 1 : 2); + if (console_wnd) { + FixConsoleCtrlHandler(ap_control_handler, die_on_logoff ? 1 : 2); + ShowWindow(console_wnd, SW_HIDE); + atexit(stop_child_monitor); + } } void stop_console_monitor(void) { - if (!isWindowsNT) - FixConsoleCtrlHandler(ap_control_handler, 0); - /* Remove the control handler at the end of the day. */ SetConsoleCtrlHandler(ap_control_handler, FALSE); + + if (!isWindowsNT()) + FixConsoleCtrlHandler(ap_control_handler, 0); } void ap_start_console_monitor(void) { HANDLE console_input; - + + die_on_logoff = TRUE; + is_service = 0; console_input = GetStdHandle(STD_INPUT_HANDLE); @@ -341,11 +344,11 @@ } } - SetConsoleCtrlHandler(ap_control_handler, TRUE); - if (!isWindowsNT()) FixConsoleCtrlHandler(ap_control_handler, die_on_logoff ? 1 : 2); + SetConsoleCtrlHandler(ap_control_handler, TRUE); + atexit(stop_console_monitor); } @@ -361,6 +364,7 @@ char *service_name; is_service = 1; + die_on_logoff = FALSE; /* Set up the Win9x server name, as WinNT would */ ap_server_argv0 = globdat.name = display_name; 1.4 +132 -83 apache-1.3/src/os/win32/win9xconhook/Win9xConHook.c Index: Win9xConHook.c =================================================================== RCS file: /home/cvs/apache-1.3/src/os/win32/win9xconhook/Win9xConHook.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- Win9xConHook.c 2000/12/11 16:48:28 1.3 +++ Win9xConHook.c 2000/12/12 06:01:58 1.4 @@ -94,16 +94,23 @@ static LPCTSTR origwndprop; static LPCTSTR hookwndprop; static BOOL is_service = 0; +//static HMODULE hmodThis = NULL; /* Variables used within the tty processes' context: * is_tty flags this process; -1 == unknown, 1 == if tty, 0 == if not * hw_tty is the handle of the top level tty in this process context * is_subclassed is toggled to assure DllMain removes the subclass on unload + * hmodLock is there to try and prevent this dll from being unloaded if the + * hook is removed while we are subclassed */ static int is_tty = -1; static HWND hwtty = NULL; static BOOL is_subclassed = 0; +// This simply causes a gpfault the moment it tries to FreeLibrary within +// the subclass procedure ... not good. +//static HMODULE hmodLock = NULL; + /* Variables used within the service or console app's context: * hmodHook is the instance handle of this module for registering the hooks * hhkGetMessage is the hook handle for catching Posted messages @@ -113,13 +120,14 @@ */ static HMODULE hmodHook = NULL; static HHOOK hhkGetMessage; -static HHOOK hhkCallWndProc; +//static HHOOK hhkCallWndProc; static HWND monitor_hwnd = NULL; typedef struct { PHANDLER_ROUTINE phandler; HINSTANCE instance; HWND parent; + INT type; LPCSTR name; } tty_info; @@ -134,10 +142,13 @@ */ static BOOL CALLBACK EnumttyWindow(HWND wnd, LPARAM retwnd); static LRESULT WINAPI RegisterWindows9xService(BOOL set_service); -static LRESULT CALLBACK ttyConsoleCtrlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +static LRESULT CALLBACK ttyConsoleCtrlWndProc(HWND hwnd, UINT msg, + WPARAM wParam, LPARAM lParam); static DWORD WINAPI ttyConsoleCtrlThread(LPVOID tty); -static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); -static int HookProc(int hc, HWND *hwnd, UINT *msg, WPARAM *wParam, LPARAM *lParam); +static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, + WPARAM wParam, LPARAM lParam); +static int HookProc(int hc, HWND *hwnd, UINT *msg, + WPARAM *wParam, LPARAM *lParam); #ifdef DBG static VOID DbgPrintf(LPTSTR fmt, ...); #endif @@ -147,50 +158,41 @@ * by our window hooks, notably the tty processes' context, and by the user * who wants tty messages (the app). Keep it light and simple. */ -BOOL __declspec(dllexport) APIENTRY DllMain(PVOID hModule, ULONG ulReason, PCONTEXT pctx) +BOOL __declspec(dllexport) APIENTRY DllMain(HINSTANCE hModule, ULONG ulReason, + LPVOID pctx) { if (ulReason == DLL_PROCESS_ATTACH) { + //hmodThis = hModule; if (!hookwndmsg) { origwndprop = MAKEINTATOM(GlobalAddAtom("Win9xConHookOrigProc")); hookwndprop = MAKEINTATOM(GlobalAddAtom("Win9xConHookThunkWnd")); hookwndmsg = RegisterWindowMessage("Win9xConHookMsg"); } #ifdef DBG - DbgPrintf("H ProcessAttach:%8.8x\r\n", GetCurrentProcessId()); +// DbgPrintf("H ProcessAttach:%8.8x\r\n", +// GetCurrentProcessId()); #endif } else if ( ulReason == DLL_PROCESS_DETACH ) { #ifdef DBG - DbgPrintf("H ProcessDetach:%8.8x\r\n", GetCurrentProcessId()); +// DbgPrintf("H ProcessDetach:%8.8x\r\n", GetCurrentProcessId()); #endif if (monitor_hwnd) SendMessage(monitor_hwnd, WM_DESTROY, 0, 0); if (is_subclassed) - { - WNDPROC origproc = (WNDPROC) GetProp(hwtty, origwndprop); - HWND child = (HWND) GetProp(hwtty, hookwndprop); - if (child) { - RemoveProp(hwtty, hookwndprop); - PostMessage(child, WM_DESTROY, 0, 0); - } - if (origproc) { - SetWindowLong(hwtty, GWL_WNDPROC, (LONG)origproc); - RemoveProp(hwtty, origwndprop); - is_subclassed = 0; - } - } + SendMessage(hwtty, hookwndmsg, 0, (LPARAM)hwtty); if (hmodHook) { if (hhkGetMessage) { UnhookWindowsHookEx(hhkGetMessage); hhkGetMessage = NULL; } - if (hhkCallWndProc) { - UnhookWindowsHookEx(hhkCallWndProc); - hhkCallWndProc = NULL; - } + //if (hhkCallWndProc) { + // UnhookWindowsHookEx(hhkCallWndProc); + // hhkCallWndProc = NULL; + //} FreeLibrary(hmodHook); hmodHook = NULL; } @@ -233,6 +235,7 @@ tty.phandler = phandler; tty.parent = NULL; tty.name = name; + tty.type = 2; RegisterWindows9xService(TRUE); hThread = CreateThread(NULL, 0, ttyConsoleCtrlThread, (LPVOID)&tty, 0, &tid); @@ -273,41 +276,40 @@ */ static tty_info tty; EnumWindows(EnumttyWindow, (LPARAM)&parent); - if (!parent) + if (!parent) { +#ifdef DBG + DbgPrintf("A EnumttyWindow failed (%d)\r\n", GetLastError()); +#endif return FALSE; + } tty.instance = GetModuleHandle(NULL); tty.phandler = phandler; tty.parent = parent; + tty.type = add; if (add == 2) { tty.name = "ttyService"; RegisterWindows9xService(TRUE); } else tty.name = "ttyMonitor"; + hThread = CreateThread(NULL, 0, ttyConsoleCtrlThread, + (LPVOID)&tty, 0, &tid); + if (!hThread) + return FALSE; + CloseHandle(hThread); hmodHook = LoadLibrary("Win9xConHook.dll"); if (hmodHook) { hhkGetMessage = SetWindowsHookEx(WH_GETMESSAGE, - (HOOKPROC)GetProcAddress(hmodHook, "GetMsgProc"), hmodHook, 0); - hhkCallWndProc = SetWindowsHookEx(WH_CALLWNDPROC, - (HOOKPROC)GetProcAddress(hmodHook, "CallWndProc"), hmodHook, 0); + (HOOKPROC)GetProcAddress(hmodHook, "GetMsgProc"), hmodHook, 0); + //hhkCallWndProc = SetWindowsHookEx(WH_CALLWNDPROC, + // (HOOKPROC)GetProcAddress(hmodHook, "CallWndProc"), hmodHook, 0); } - hThread = CreateThread(NULL, 0, ttyConsoleCtrlThread, - (LPVOID)&tty, 0, &tid); - if (hThread) - { - CloseHandle(hThread); - /* All is set ... wake up the tty window */ - PostMessage(parent, hookwndmsg, add, 0); - return TRUE; - } + return TRUE; } else /* remove */ { if (monitor_hwnd) { - parent = (HWND) GetWindowLong(monitor_hwnd, gwltty_ttywnd); - if (parent) - PostMessage(parent, hookwndmsg, add, 0); SendMessage(monitor_hwnd, WM_DESTROY, 0, 0); } if (hmodHook) @@ -315,11 +317,11 @@ if (hhkGetMessage) { UnhookWindowsHookEx(hhkGetMessage); hhkGetMessage = NULL; - } - if (hhkCallWndProc) { - UnhookWindowsHookEx(hhkCallWndProc); - hhkCallWndProc = NULL; } + //if (hhkCallWndProc) { + // UnhookWindowsHookEx(hhkCallWndProc); + // hhkCallWndProc = NULL; + //} FreeLibrary(hmodHook); hmodHook = NULL; } @@ -361,7 +363,8 @@ if (!RegisterClass(&wc)) { #ifdef DBG - DbgPrintf("S Created ttyConHookChild class\r\n"); + DbgPrintf("A proc %8.8x Error creating class %s (%d)\r\n", + GetCurrentProcessId(), wc.lpszClassName, GetLastError()); #endif return 0; } @@ -376,7 +379,9 @@ if (!monitor_hwnd) { #ifdef DBG - DbgPrintf("S Error Creating ttyConHookChild:%d\r\n", GetLastError()); + DbgPrintf("A proc %8.8x Error creating window %s %s (%d)\r\n", + GetCurrentProcessId(), wc.lpszClassName, + ((tty_info*)tty)->name, GetLastError()); #endif return 0; } @@ -399,7 +404,8 @@ * window (this message process), and we call the installed HandlerRoutine * that was registered by the app. */ -static LRESULT CALLBACK ttyConsoleCtrlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +static LRESULT CALLBACK ttyConsoleCtrlWndProc(HWND hwnd, UINT msg, + WPARAM wParam, LPARAM lParam) { if (msg == WM_CREATE) { @@ -407,50 +413,69 @@ SetWindowLong(hwnd, gwltty_phandler, (LONG)tty->phandler); SetWindowLong(hwnd, gwltty_ttywnd, (LONG)tty->parent); #ifdef DBG - DbgPrintf("S Created ttyConHookChild:%8.8x\r\n", hwnd); -#endif - if (((tty_info*)tty)->parent) - SetProp(((tty_info*)tty)->parent, hookwndprop, hwnd); + DbgPrintf("A proc %8.8x created %8.8x %s for tty wnd %8.8x\r\n", + GetCurrentProcessId(), hwnd, + tty->name, tty->parent); +#endif + if (tty->parent) { + SetProp(tty->parent, hookwndprop, hwnd); + PostMessage(tty->parent, hookwndmsg, + tty->type, (LPARAM)tty->parent); + } return 0; } else if (msg == WM_DESTROY) { HWND parent = (HWND)GetWindowLong(hwnd, gwltty_ttywnd); - if (parent) +#ifdef DBG + DbgPrintf("A proc %8.8x destroyed %8.8x ttyConHookChild\r\n", + GetCurrentProcessId(), hwnd); +#endif + if (parent) { RemoveProp(parent, hookwndprop); + SendMessage(parent, hookwndmsg, 0, (LPARAM)parent); + } monitor_hwnd = NULL; } else if (msg == WM_CLOSE) { PHANDLER_ROUTINE phandler = (PHANDLER_ROUTINE)GetWindowLong(hwnd, gwltty_phandler); + LRESULT rv = phandler(CTRL_CLOSE_EVENT); #ifdef DBG - DbgPrintf("S Invoking CTRL_CLOSE_EVENT:%8.8x\r\n", - GetCurrentProcessId()); + DbgPrintf("A proc %8.8x invoked CTRL_CLOSE_EVENT " + "returning %d\r\n", + GetCurrentProcessId(), rv); #endif - return !phandler(CTRL_CLOSE_EVENT); + if (rv) + return !rv; } - else if (msg == WM_QUERYENDSESSION) + else if ((msg == WM_QUERYENDSESSION) || (msg == WM_ENDSESSION)) { if (lParam & ENDSESSION_LOGOFF) { PHANDLER_ROUTINE phandler = (PHANDLER_ROUTINE)GetWindowLong(hwnd, gwltty_phandler); + LRESULT rv = phandler(CTRL_LOGOFF_EVENT); #ifdef DBG - DbgPrintf("S Invoking CTRL_LOGOFF_EVENT:%8.8x\r\n", - GetCurrentProcessId()); + DbgPrintf("A proc %8.8x invoked CTRL_LOGOFF_EVENT " + "returning %d\r\n", + GetCurrentProcessId(), rv); #endif - return !phandler(CTRL_LOGOFF_EVENT); + if (rv) + return ((msg == WM_QUERYENDSESSION) ? rv : !rv); } else { PHANDLER_ROUTINE phandler = (PHANDLER_ROUTINE)GetWindowLong(hwnd, gwltty_phandler); + LRESULT rv = phandler(CTRL_SHUTDOWN_EVENT); #ifdef DBG - DbgPrintf("S Invoking CTRL_SHUTDOWN_EVENT:%8.8x\r\n", - GetCurrentProcessId()); + DbgPrintf("A proc %8.8x invoked CTRL_SHUTDOWN_EVENT " + "returning %d\r\n", GetCurrentProcessId(), rv); #endif - return !phandler(CTRL_SHUTDOWN_EVENT); + if (rv) + return ((msg == WM_QUERYENDSESSION) ? rv : !rv); } } return (DefWindowProc(hwnd, msg, wParam, lParam)); @@ -474,6 +499,12 @@ if (set_service == is_service) return 1; +#ifdef DBG + DbgPrintf("R %s proc %8.8x as a service\r\n", + set_service ? "installing" : "removing", + GetCurrentProcessId()); +#endif + /* Obtain a handle to the kernel library */ hkernel = LoadLibrary("KERNEL32.DLL"); if (!hkernel) @@ -505,7 +536,7 @@ */ static BOOL CALLBACK EnumttyWindow(HWND wnd, LPARAM retwnd) { - char tmp[4]; + char tmp[8]; if (GetClassName(wnd, tmp, sizeof(tmp)) && !strcmp(tmp, "tty")) { DWORD wndproc, thisproc = GetCurrentProcessId(); @@ -532,37 +563,43 @@ * to origwndprop property atom we set against the window when we * injected this subclass. This trick did not work with simply a hook. */ -static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, + WPARAM wParam, LPARAM lParam) { WNDPROC origproc = (WNDPROC) GetProp(hwnd, origwndprop); if (!origproc) return 0; - if (msg == WM_NCDESTROY || msg == hookwndmsg) + if (msg == WM_NCDESTROY + || (msg == hookwndmsg && !LOWORD(wParam) && (HWND)lParam == hwnd)) { + if (is_subclassed) { #ifdef DBG - DbgPrintf("W Proc %08x hwnd:%08x Subclass removed\r\n", - GetCurrentProcessId(), hwnd); + DbgPrintf("W proc %08x hwnd:%08x Subclass removed\r\n", + GetCurrentProcessId(), hwnd); #endif - if (is_subclassed) { if (is_service) RegisterWindows9xService(FALSE); SetWindowLong(hwnd, GWL_WNDPROC, (LONG)origproc); RemoveProp(hwnd, origwndprop); RemoveProp(hwnd, hookwndprop); is_subclassed = FALSE; + //if (hmodLock) + // FreeLibrary(hmodLock); + //hmodLock = NULL; } } else if (msg == WM_CLOSE || msg == WM_ENDSESSION || msg == WM_QUERYENDSESSION) { HWND child = (HWND)GetProp(hwnd, hookwndprop); + if (child) { #ifdef DBG - DbgPrintf("W Proc %08x hwnd:%08x msg:%d\r\n", - GetCurrentProcessId(), hwnd, msg); + DbgPrintf("W proc %08x hwnd:%08x forwarded msg:%d\r\n", + GetCurrentProcessId(), hwnd, msg); #endif - if (child) return SendMessage(child, msg, wParam, lParam); + } } return CallWindowProc(origproc, hwnd, msg, wParam, lParam); } @@ -580,7 +617,7 @@ { if (is_tty == -1 && *hwnd) { - char ttybuf[4]; + char ttybuf[8]; HWND htty; hwtty = *hwnd; while (htty = GetParent(hwtty)) @@ -588,22 +625,26 @@ is_tty = (GetClassName(hwtty, ttybuf, sizeof(ttybuf)) && !strcmp(ttybuf, "tty")); #ifdef DBG - DbgPrintf("H Proc %08x %s %08x\r\n", GetCurrentProcessId(), - is_tty ? "tracking" : "ignoring", hwtty); + if (is_tty) + DbgPrintf("H proc %08x tracking hwnd %08x\r\n", + GetCurrentProcessId(), hwtty); #endif } - if (*msg == hookwndmsg && is_tty) + if (*msg == hookwndmsg && *wParam && *lParam == (LPARAM)hwtty && is_tty) { WNDPROC origproc = (WNDPROC)GetWindowLong(hwtty, GWL_WNDPROC); + //char myname[MAX_PATH]; + //if (GetModuleFileName(hmodThis, myname, sizeof(myname))) + // hmodLock = LoadLibrary(myname); SetProp(hwtty, origwndprop, origproc); SetWindowLong(hwtty, GWL_WNDPROC, (LONG)WndProc); is_subclassed = TRUE; #ifdef DBG - DbgPrintf("W Proc %08x hwnd:%08x Subclassed\r\n", + DbgPrintf("H proc %08x hwnd:%08x Subclassed\r\n", GetCurrentProcessId(), hwtty); #endif - if (*wParam == 2) + if (LOWORD(*wParam) == 2) RegisterWindows9xService(TRUE); } @@ -614,14 +655,16 @@ /* * PostMessage Hook: */ -LRESULT __declspec(dllexport) CALLBACK GetMsgProc(INT hc, WPARAM wParam, LPARAM lParam) +LRESULT __declspec(dllexport) CALLBACK GetMsgProc(INT hc, WPARAM wParam, + LPARAM lParam) { PMSG pmsg; pmsg = (PMSG)lParam; if (pmsg) { - int rv = HookProc(hc, &pmsg->hwnd, &pmsg->message, &pmsg->lParam, &pmsg->wParam); + int rv = HookProc(hc, &pmsg->hwnd, &pmsg->message, + &pmsg->wParam, &pmsg->lParam); if (rv != -1) return rv; } @@ -635,12 +678,14 @@ /* * SendMessage Hook: */ -LRESULT __declspec(dllexport) CALLBACK CallWndProc(INT hc, WPARAM wParam, LPARAM lParam) +LRESULT __declspec(dllexport) CALLBACK CallWndProc(INT hc, WPARAM wParam, + LPARAM lParam) { PCWPSTRUCT pcwps = (PCWPSTRUCT)lParam; if (pcwps) { - int rv = HookProc(hc, &pcwps->hwnd, &pcwps->message, &pcwps->wParam, &pcwps->lParam); + int rv = HookProc(hc, &pcwps->hwnd, &pcwps->message, + &pcwps->wParam, &pcwps->lParam); if (rv != -1) return rv; } @@ -657,6 +702,7 @@ ... ) { + static HANDLE mutex; va_list marker; TCHAR szBuf[256]; DWORD t; @@ -666,11 +712,14 @@ wvsprintf(szBuf, fmt, marker); va_end(marker); - gDbgOut = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, + if (!mutex) + mutex = CreateMutex(NULL, FALSE, "Win9xConHookDbgOut"); + WaitForSingleObject(mutex, INFINITE); + gDbgOut = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL); WriteFile(gDbgOut, szBuf, strlen(szBuf), &t, NULL); CloseHandle(gDbgOut); + ReleaseMutex(mutex); } #endif