From: William A. Rowe Jr Date: Thu, 30 Nov 2000 01:39:32 +0000 (+0000) Subject: This is the Win9x console hook handler ... much code to be pulled now X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bdf180c3b67ec5a6c3c44ee03e052b2bbcf10eeb;p=apache This is the Win9x console hook handler ... much code to be pulled now from the src/os/win32/services.c for Win9x. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@87137 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/server/mpm/winnt/Win9xConHook.c b/server/mpm/winnt/Win9xConHook.c new file mode 100644 index 0000000000..7f1224ab6a --- /dev/null +++ b/server/mpm/winnt/Win9xConHook.c @@ -0,0 +1,517 @@ +/* ==================================================================== + * Copyright (c) 1995-2000 The Apache Group. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://httpd.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://httpd.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + + +/* + * Win9xConHook.dll - a hook proc to clean up Win95/98 console behavior. + * + * It is well(?) documented by Microsoft that the Win9x HandlerRoutine + * hooked by the SetConsoleCtrlHandler never receives the CTRL_CLOSE_EVENT, + * CTRL_LOGOFF_EVENT or CTRL_SHUTDOWN_EVENT signals. + * + * It is possible to have a second window to monitor the WM_ENDSESSION + * message, but the close button still fails.. + * + * There is a 16bit polling method for the close window option, but this + * is CPU intensive and requires thunking. + * + * Attempts to subclass the 'tty' console fail, since that message thread + * is actually owned by the 16 bit winoldap.mod process, although the + * window reports it is owned by the process/thread of the console app. + * + * Win9xConHook is thunks the WM_CLOSE and WM_ENDSESSION messages, + * first through a window hook procedure in the winoldap context, into + * a subclass WndProc, and on to a second hidden monitor window in the + * console application's context that dispatches them to the console app's + * registered HandlerRoutine. + */ + +#define DBG 1 + +#include + +/* + * 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 + * is_hooked is toggled to assure DllMain removes the subclass + */ +static int is_tty = -1; +static HWND hwtty = NULL; +static BOOL is_subclassed = 0; + +static HMODULE hmodHook = NULL; +static HHOOK hhkGetMessage; +//static HHOOK hhkCallWndProc; + +static LPCTSTR origwndprop = NULL; +static LPCTSTR hookwndprop = NULL; + +#ifdef DBG +static VOID DbgPrintf(LPTSTR fmt, ...); +#endif + +static BOOL CALLBACK EnumttyWindow(HWND wnd, LPARAM retwnd); + + +BOOL __declspec(dllexport) APIENTRY DllMain(PVOID hModule, ULONG ulReason, PCONTEXT pctx) +{ + if (ulReason == DLL_PROCESS_ATTACH) + { +#ifdef DBG + DbgPrintf("H ProcessAttach:%8.8x\r\n", GetCurrentProcessId()); +#endif + origwndprop = MAKEINTATOM(GlobalAddAtom("Win9xConHookOrigProc")); + hookwndprop = MAKEINTATOM(GlobalAddAtom("Win9xConHookThunkWnd")); + } + else if ( ulReason == DLL_PROCESS_DETACH ) + { + HWND parent; +#ifdef DBG + DbgPrintf("H ProcessDetach:%8.8x\r\n", GetCurrentProcessId()); +#endif + if (is_subclassed) { + WNDPROC origproc = (WNDPROC) GetProp(hwtty, origwndprop); + if (origproc) { + SetWindowLong(hwtty, GWL_WNDPROC, (LONG)origproc); + RemoveProp(hwtty, origwndprop); + } + } + EnumWindows(EnumttyWindow, (LPARAM)&parent); + if (parent) { + HWND child = (HWND)GetProp(parent, hookwndprop); + if (child) + SendMessage(child, WM_DESTROY, 0, 0); + } + if (hmodHook) + { + if (hhkGetMessage) { + UnhookWindowsHookEx(hhkGetMessage); + hhkGetMessage = NULL; + } + FreeLibrary(hmodHook); + hmodHook = NULL; + } + GlobalDeleteAtom((ATOM)origwndprop); + GlobalDeleteAtom((ATOM)hookwndprop); + } + return TRUE; +} + + +typedef struct { + PHANDLER_ROUTINE phandler; + HINSTANCE instance; + HWND parent; +} tty_info; + + +#define gwltty_phandler 0 +#define gwltty_ttywnd 4 + +/* This is the WndProc procedure for our invisible window. + * When our tty subclass WndProc recieves the WM_CLOSE, + * or WM_QUERYENDSESSION messages, we call the installed + * HandlerRoutine that was registered with + * If a user logs off, the window is sent WM_QUERYENDSESSION + * as well, but with lParam != 0. We ignore this case. + */ +LRESULT CALLBACK ttyConsoleCtrlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (msg == WM_CREATE) + { + tty_info *tty = (tty_info*)(((LPCREATESTRUCT)lParam)->lpCreateParams); + 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 + SetProp(((tty_info*)tty)->parent, hookwndprop, hwnd); + return 0; + } + else if (msg == WM_DESTROY) + { + HWND parent = (HWND)GetWindowLong(hwnd, gwltty_ttywnd); + RemoveProp(parent, hookwndprop); + } + else if (msg == WM_CLOSE) + { + PHANDLER_ROUTINE phandler = + (PHANDLER_ROUTINE)GetWindowLong(hwnd, gwltty_phandler); +#ifdef DBG + DbgPrintf("S Invoking CTRL_CLOSE_EVENT:%8.8x\r\n", + GetCurrentProcessId()); +#endif + return !phandler(CTRL_CLOSE_EVENT); + } + else if (msg == WM_QUERYENDSESSION) + { + if (lParam & ENDSESSION_LOGOFF) + { + PHANDLER_ROUTINE phandler = + (PHANDLER_ROUTINE)GetWindowLong(hwnd, gwltty_phandler); +#ifdef DBG + DbgPrintf("S Invoking CTRL_LOGOFF_EVENT:%8.8x\r\n", + GetCurrentProcessId()); +#endif + return !phandler(CTRL_LOGOFF_EVENT); + } + else + { + PHANDLER_ROUTINE phandler = + (PHANDLER_ROUTINE)GetWindowLong(hwnd, gwltty_phandler); +#ifdef DBG + DbgPrintf("S Invoking CTRL_SHUTDOWN_EVENT:%8.8x\r\n", + GetCurrentProcessId()); +#endif + return !phandler(CTRL_SHUTDOWN_EVENT); + } + } + return (DefWindowProc(hwnd, msg, wParam, lParam)); +} + + +DWORD WINAPI ttyConsoleCtrlThread(LPVOID tty) +{ + /* When running as a service under Windows 9x, ConsoleCtrlHandler + * does not respond properly when the user logs off or 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 hwnd; + MSG msg; + wc.style = CS_GLOBALCLASS; + wc.lpfnWndProc = ttyConsoleCtrlWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 8; + wc.hInstance = NULL; + wc.hIcon = NULL; + wc.hCursor = NULL; + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = "ttyConHookChild"; + + if (!RegisterClass(&wc)) { +#ifdef DBG + DbgPrintf("S Created ttyConHookChild class\r\n"); +#endif + return 0; + } + + /* Create an invisible window */ + hwnd = CreateWindow(wc.lpszClassName, "", + WS_OVERLAPPED & ~WS_VISIBLE, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL, + ((tty_info*)tty)->instance, tty); + + if (!hwnd) { +#ifdef DBG + DbgPrintf("S Error Creating ttyConHookChild:%d\r\n", GetLastError()); +#endif + return 0; + } + + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + if (msg.message == WM_DESTROY) + DestroyWindow(hwnd); + } + return 0; +} + + +/* + * This function only works when this process is the active process + * (e.g. once it is running a child process, it can no longer determine + * which console window is its own.) + */ +static BOOL CALLBACK EnumttyWindow(HWND wnd, LPARAM retwnd) +{ + char tmp[4]; + if (GetClassName(wnd, tmp, sizeof(tmp)) && !strcmp(tmp, "tty")) + { + DWORD wndproc, thisproc = GetCurrentProcessId(); + GetWindowThreadProcessId(wnd, &wndproc); + if (wndproc == thisproc) { + *((HWND*)retwnd) = wnd; + return FALSE; + } + } + return TRUE; +} + + +/* + * Exported function that sets up the fixup child window and dispatch + */ +BOOL __declspec(dllexport) WINAPI FixConsoleCtrlHandler( + PHANDLER_ROUTINE phandler, + BOOL add) +{ + HWND parent; + EnumWindows(EnumttyWindow, (LPARAM)&parent); + + if (!parent) + return FALSE; + + if (add) + { + HANDLE hThread; + DWORD tid; + static tty_info tty; + tty.phandler = phandler; + tty.parent = parent; + tty.instance = GetModuleHandle(NULL); + + 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); + } + + hThread = CreateThread(NULL, 0, ttyConsoleCtrlThread, + (LPVOID)&tty, 0, &tid); + if (hThread) + { + CloseHandle(hThread); + return TRUE; + } + } + else /* remove */ + { + HWND child = FindWindowEx(parent, NULL, "ttyConHookChild", NULL); + if (child) + SendMessage(child, WM_DESTROY, 0, 0); + if (hmodHook) + { + if (hhkGetMessage) { + UnhookWindowsHookEx(hhkGetMessage); + hhkGetMessage = NULL; + } + FreeLibrary(hmodHook); + hmodHook = NULL; + } + return TRUE; + } + return FALSE; +} + + +/* + * Subclass message process for the tty window + */ +LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WNDPROC origproc = (WNDPROC) GetProp(hwnd, origwndprop); + if (!origproc) + return 0; + + switch (msg) + { + case WM_NCDESTROY: +#ifdef DBG + DbgPrintf("W Proc %08x hwnd:%08x Subclass removed\r\n", + GetCurrentProcessId(), hwnd); +#endif + is_subclassed = FALSE; + SetWindowLong(hwnd, GWL_WNDPROC, (LONG)origproc); + RemoveProp(hwnd, origwndprop); + break; + + case WM_CLOSE: + case WM_ENDSESSION: + case WM_QUERYENDSESSION: + { + HWND child = (HWND)GetProp(hwnd, hookwndprop); +#ifdef DBG + DbgPrintf("W Proc %08x hwnd:%08x msg:%d\r\n", + GetCurrentProcessId(), hwnd, msg); +#endif + if (!child) + break; + return SendMessage(child, msg, wParam, lParam); + } + } + return CallWindowProc(origproc, hwnd, msg, wParam, lParam); +} + + +int HookProc(int hc, HWND *hwnd, UINT *msg, WPARAM *wParam, LPARAM *lParam) +{ + if (is_tty == -1 && *hwnd) + { + char ttybuf[4]; + HWND htty; + hwtty = *hwnd; + while (htty = GetParent(hwtty)) + hwtty = htty; + is_tty = (GetClassName(hwtty, ttybuf, sizeof(ttybuf)) + && !strcmp(ttybuf, "tty")); + if (is_tty) + { + WNDPROC origproc = (WNDPROC)GetWindowLong(hwtty, GWL_WNDPROC); + SetProp(hwtty, origwndprop, origproc); + SetWindowLong(hwtty, GWL_WNDPROC, (LONG)WndProc); + is_subclassed = TRUE; +#ifdef DBG + DbgPrintf("W Proc %08x hwnd:%08x Subclassed\r\n", + GetCurrentProcessId(), hwtty); +#endif + } +#ifdef DBG + DbgPrintf("H Proc %08x %s %08x\r\n", GetCurrentProcessId(), + is_tty ? "tracking" : "ignoring", hwtty); +#endif + } + + if (hc >= 0 && is_tty && *hwnd == hwtty) + { + if ((*msg == WM_CLOSE) + || (*msg == WM_ENDSESSION)) { + DWORD apppid, ttypid = GetCurrentProcessId(); + GetWindowThreadProcessId(*hwnd, &apppid); +#ifdef DBG + DbgPrintf("H Proc %08x hwnd:%08x owned by %08x msg:%d\r\n", ttypid, *hwnd, apppid, *msg); +#endif + //*msg = WM_NULL; + /* + * Experimental, return 0 or 1 will bypass the next hook and return that + * value from the hook procedure, -1 continues to call the next hook. + */ + return -1; + } + } + return -1; +} + + +/* + * PostMessage Hook: + */ +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); + if (rv != -1) + return rv; + } + /* + * CallNextHookEx apparently ignores the hhook argument, so pass NULL + */ + return CallNextHookEx(NULL, hc, wParam, lParam); +} + + +/* + * SendMessage Hook: + */ +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); + if (rv != -1) + return rv; + } + /* + * CallNextHookEx apparently ignores the hhook argument, so pass NULL + */ + return CallNextHookEx(NULL, hc, wParam, lParam); +} + + +#ifdef DBG +VOID DbgPrintf( + LPTSTR fmt, + ... + ) +{ + va_list marker; + TCHAR szBuf[256]; + DWORD t; + HANDLE gDbgOut; + + va_start(marker, fmt); + wvsprintf(szBuf, fmt, marker); + va_end(marker); + + gDbgOut = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL); + WriteFile(gDbgOut, szBuf, strlen(szBuf), &t, NULL); + CloseHandle(gDbgOut); +} +#endif + + diff --git a/server/mpm/winnt/Win9xConHook.def b/server/mpm/winnt/Win9xConHook.def new file mode 100644 index 0000000000..689eb75a2c --- /dev/null +++ b/server/mpm/winnt/Win9xConHook.def @@ -0,0 +1,9 @@ +LIBRARY Win9xConHook + +EXETYPE WINDOWS + +EXPORTS + DllMain + GetMsgProc + CallWndProc + FixConsoleCtrlHandler \ No newline at end of file diff --git a/server/mpm/winnt/Win9xConHook.dsp b/server/mpm/winnt/Win9xConHook.dsp new file mode 100644 index 0000000000..3704f5b62e --- /dev/null +++ b/server/mpm/winnt/Win9xConHook.dsp @@ -0,0 +1,103 @@ +# Microsoft Developer Studio Project File - Name="Win9xConHook" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=Win9xConHook - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Win9xConHook.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Win9xConHook.mak" CFG="Win9xConHook - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Win9xConHook - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Win9xConHook - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Win9xConHook - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Release" +# PROP BASE Intermediate_Dir ".\Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Win9xConHookR" +# PROP Intermediate_Dir "Win9xConHookR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /c +# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /base:@"BaseAddr.ref",mod_status +# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /base:"0x1c0f0000" /subsystem:windows /dll /map /machine:I386 + +!ELSEIF "$(CFG)" == "Win9xConHook - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\Debug" +# PROP BASE Intermediate_Dir ".\Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Win9xConHookD" +# PROP Intermediate_Dir "Win9xConHookD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /base:@"BaseAddr.ref",mod_status +# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /base:"0x1c0f0000" /subsystem:windows /dll /incremental:no /map /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "Win9xConHook - Win32 Release" +# Name "Win9xConHook - Win32 Debug" +# Begin Source File + +SOURCE=.\Win9xConHook.c +# End Source File +# Begin Source File + +SOURCE=.\Win9xConHook.def +# End Source File +# Begin Source File + +SOURCE=.\Win9xConHook.h +# End Source File +# End Target +# End Project diff --git a/server/mpm/winnt/Win9xConHook.h b/server/mpm/winnt/Win9xConHook.h new file mode 100644 index 0000000000..107cdbe2f5 --- /dev/null +++ b/server/mpm/winnt/Win9xConHook.h @@ -0,0 +1,24 @@ + + + +/* + * FixConsoleControlHandler will register a handler routine with the + * Win9xConHook.dll, creating a hidden window and forwarding the + * WM_ENDSESSION and WM_CLOSE messages to the registered handler + * as CTRL_SHUTDOWN_EVENT, CTRL_LOGOFF_EVENT and CTRL_CLOSE_EVENT. + */ +BOOL WINAPI FixConsoleCtrlHandler( + PHANDLER_ROUTINE phandler, + BOOL add); + +/* + * PostMessage Hook: + */ +LRESULT CALLBACK GetMsgProc(INT hc, WPARAM wParam, LPARAM lParam); + + +/* + * SendMessage Hook: + */ +LRESULT CALLBACK CallWndProc(INT hc, WPARAM wParam, LPARAM lParam); +