* registered HandlerRoutine.
*/
-/* #define DBG 1
- */
+#define DBG 1
#include <windows.h>
-/*
+/* Variables used within any process context:
+ * hookwndmsg is a shared message to send Win9xConHook signals
+ * origwndprop is a wndprop atom to store the orig wndproc of the tty
+ * hookwndprop is a wndprop atom to store the hwnd of the hidden child
+ * is_service reminds us to unmark this process on the way out
+ */
+static UINT hookwndmsg = 0;
+static LPCTSTR origwndprop;
+static LPCTSTR hookwndprop;
+static BOOL is_service = 0;
+
+/* 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
- * is_hooked is toggled to assure DllMain removes the subclass
+ * is_subclassed is toggled to assure DllMain removes the subclass on unload
*/
static int is_tty = -1;
static HWND hwtty = NULL;
static BOOL is_subclassed = 0;
+/* 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
+ * hhkGetMessage is the hook handle for catching Sent messages
+ * monitor_hwnd is the invisible window that handles our tty messages
+ * the tty_info strucure is used to pass args into the hidden window's thread
+ */
static HMODULE hmodHook = NULL;
static HHOOK hhkGetMessage;
static HHOOK hhkCallWndProc;
+static HWND monitor_hwnd = NULL;
-static LPCTSTR origwndprop = NULL;
-static LPCTSTR hookwndprop = NULL;
+typedef struct {
+ PHANDLER_ROUTINE phandler;
+ HINSTANCE instance;
+ HWND parent;
+ LPCSTR name;
+} tty_info;
-static HWND monitor_hwnd = NULL;
+/* These are the GetWindowLong offsets for the hidden window's internal info
+ * gwltty_phandler is the address of the app's HandlerRoutine
+ * gwltty_ttywnd is the tty this hidden window will handle messages from
+ */
+#define gwltty_phandler 0
+#define gwltty_ttywnd 4
+/* Forward declaration prototypes for internal functions
+ */
+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 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);
#ifdef DBG
static VOID DbgPrintf(LPTSTR fmt, ...);
#endif
-static BOOL CALLBACK EnumttyWindow(HWND wnd, LPARAM retwnd);
-
-LRESULT __declspec(dllexport) WINAPI RegisterWindows9xService(BOOL is_service)
-{
- static BOOL is_registered = FALSE;
- HINSTANCE hkernel;
- DWORD (WINAPI *register_service_process)(DWORD, DWORD);
- BOOL rv;
-
- if (is_service == is_registered)
- return 1;
-
- /* Obtain a handle to the kernel library */
- hkernel = LoadLibrary("KERNEL32.DLL");
- if (!hkernel)
- return 0;
-
- /* Find the RegisterServiceProcess function */
- register_service_process = (DWORD (WINAPI *)(DWORD, DWORD))
- GetProcAddress(hkernel, "RegisterServiceProcess");
- if (register_service_process == NULL) {
- FreeLibrary(hkernel);
- return 0;
- }
-
- /* Register this process as a service */
- rv = register_service_process(0, is_service != FALSE);
-
- /* Unload the kernel library */
- FreeLibrary(hkernel);
- return rv;
-}
+/* DllMain is invoked by every process in the entire system that is hooked
+ * 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)
{
if (ulReason == DLL_PROCESS_ATTACH)
{
+ if (!hookwndmsg) {
+ origwndprop = MAKEINTATOM(GlobalAddAtom("Win9xConHookOrigProc"));
+ hookwndprop = MAKEINTATOM(GlobalAddAtom("Win9xConHookThunkWnd"));
+ hookwndmsg = RegisterWindowMessage("Win9xConHookMsg");
+ }
#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) {
+ 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;
}
+ }
+ if (hmodHook)
+ {
+ if (hhkGetMessage) {
+ UnhookWindowsHookEx(hhkGetMessage);
+ hhkGetMessage = NULL;
+ }
+ if (hhkCallWndProc) {
+ UnhookWindowsHookEx(hhkCallWndProc);
+ hhkCallWndProc = NULL;
+ }
+ FreeLibrary(hmodHook);
+ hmodHook = NULL;
+ }
+ if (is_service)
RegisterWindows9xService(FALSE);
+ if (hookwndmsg) {
+ GlobalDeleteAtom((ATOM)origwndprop);
+ GlobalDeleteAtom((ATOM)hookwndprop);
+ hookwndmsg = 0;
+ }
+ }
+ return TRUE;
+}
+
+
+/* This group of functions are provided for the service/console app
+ * to register itself a HandlerRoutine to accept tty or service messages
+ */
+
+
+/* Exported function that creates a Win9x 'service' via a hidden window,
+ * that notifies the process via the HandlerRoutine messages.
+ */
+BOOL __declspec(dllexport) WINAPI Windows9xServiceCtrlHandler(
+ PHANDLER_ROUTINE phandler,
+ LPCSTR name)
+{
+ /* If we have not yet done so */
+ FreeConsole();
+
+ if (name)
+ {
+ DWORD tid;
+ HANDLE hThread;
+ /* NOTE: this is static so the module can continue to
+ * access these args while we go on to other things
+ */
+ static tty_info tty;
+ tty.instance = GetModuleHandle(NULL);
+ tty.phandler = phandler;
+ tty.parent = NULL;
+ tty.name = name;
+ RegisterWindows9xService(TRUE);
+ hThread = CreateThread(NULL, 0, ttyConsoleCtrlThread,
+ (LPVOID)&tty, 0, &tid);
+ if (hThread)
+ {
+ CloseHandle(hThread);
+ return TRUE;
}
+ }
+ else /* remove */
+ {
+ if (monitor_hwnd)
+ SendMessage(monitor_hwnd, WM_DESTROY, 0, 0);
+ RegisterWindows9xService(FALSE);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/* Exported function that registers a HandlerRoutine to accept missing
+ * Win9x CTRL_EVENTs from the tty window, as NT does without a hassle.
+ * If add is 1 or 2, register the handler, if 2 also mark it as a service.
+ * If add is 0 deregister the handler, and unmark if a service
+ */
+BOOL __declspec(dllexport) WINAPI FixConsoleCtrlHandler(
+ PHANDLER_ROUTINE phandler,
+ INT add)
+{
+ HWND parent;
+
+ if (add)
+ {
+ HANDLE hThread;
+ DWORD tid;
+ /* NOTE: this is static so the module can continue to
+ * access these args while we go on to other things
+ */
+ static tty_info tty;
EnumWindows(EnumttyWindow, (LPARAM)&parent);
- if (parent) {
- HWND child = (HWND)GetProp(parent, hookwndprop);
- if (child)
- SendMessage(child, WM_DESTROY, 0, 0);
+ if (!parent)
+ return FALSE;
+ tty.instance = GetModuleHandle(NULL);
+ tty.phandler = phandler;
+ tty.parent = parent;
+ if (add == 2) {
+ tty.name = "ttyService";
+ RegisterWindows9xService(TRUE);
+ }
+ else
+ tty.name = "ttyMonitor";
+ 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);
+ /* All is set ... wake up the tty window */
+ PostMessage(parent, hookwndmsg, add, 0);
+ 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)
{
FreeLibrary(hmodHook);
hmodHook = NULL;
}
- GlobalDeleteAtom((ATOM)origwndprop);
- GlobalDeleteAtom((ATOM)hookwndprop);
+ if (is_service)
+ RegisterWindows9xService(FALSE);
+ return TRUE;
}
- return TRUE;
+ return FALSE;
}
-typedef struct {
- PHANDLER_ROUTINE phandler;
- HINSTANCE instance;
- HWND parent;
- char *name;
-} tty_info;
+/* The following internal helpers are only used within the app's context
+ */
+/* ttyConsoleCreateThread is the process that runs within the user app's
+ * context. It creates and pumps the messages of a hidden monitor window,
+ * watching for messages from the system, or the associated subclassed tty
+ * window. Things can happen in our context that can't be done from the
+ * tty's context, and visa versa, so the subclass procedure and this hidden
+ * window work together to make it all happen.
+ */
+static DWORD WINAPI ttyConsoleCtrlThread(LPVOID tty)
+{
+ WNDCLASS wc;
+ 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;
+ if (((tty_info*)tty)->parent)
+ wc.lpszClassName = "ttyConHookChild";
+ else
+ wc.lpszClassName = "ApacheWin95ServiceMonitor";
+
+ if (!RegisterClass(&wc)) {
+#ifdef DBG
+ DbgPrintf("S Created ttyConHookChild class\r\n");
+#endif
+ return 0;
+ }
+
+ /* Create an invisible window */
+ monitor_hwnd = CreateWindow(wc.lpszClassName, ((tty_info*)tty)->name,
+ WS_OVERLAPPED & ~WS_VISIBLE,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL, NULL,
+ ((tty_info*)tty)->instance, tty);
+
+ if (!monitor_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);
+ }
+
+ /* Tag again as deleted, just in case we missed WM_DESTROY */
+ monitor_hwnd = NULL;
+ return 0;
+}
-#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.
+ * When our subclasssed tty window receives the WM_CLOSE, WM_ENDSESSION,
+ * or WM_QUERYENDSESSION messages, the message is dispatched to our hidden
+ * window (this message process), and we call the installed HandlerRoutine
+ * that was registered by the app.
*/
-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)
{
HWND parent = (HWND)GetWindowLong(hwnd, gwltty_ttywnd);
if (parent)
RemoveProp(parent, hookwndprop);
+ monitor_hwnd = NULL;
}
else if (msg == WM_CLOSE)
{
}
-DWORD WINAPI ttyConsoleCtrlThread(LPVOID tty)
+/* The following internal helpers are invoked by the hooked tty and our app
+ */
+
+
+/* Register or deregister the current process as a Windows9x style service.
+ * Experience shows this call is ignored across processes, so the second
+ * arg to RegisterServiceProcess (process group id) is effectively useless.
+ */
+static LRESULT WINAPI RegisterWindows9xService(BOOL set_service)
{
- /* 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;
- 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;
- if (((tty_info*)tty)->parent)
- wc.lpszClassName = "ttyConHookChild";
- else
- wc.lpszClassName = "ApacheWin95ServiceMonitor";
-
- if (!RegisterClass(&wc)) {
-#ifdef DBG
- DbgPrintf("S Created ttyConHookChild class\r\n");
-#endif
- return 0;
- }
+ HINSTANCE hkernel;
+ DWORD (WINAPI *register_service_process)(DWORD, DWORD);
+ BOOL rv;
- /* Create an invisible window */
- monitor_hwnd = CreateWindow(wc.lpszClassName, ((tty_info*)tty)->name,
- WS_OVERLAPPED & ~WS_VISIBLE,
- CW_USEDEFAULT, CW_USEDEFAULT,
- CW_USEDEFAULT, CW_USEDEFAULT,
- NULL, NULL,
- ((tty_info*)tty)->instance, tty);
+ if (set_service == is_service)
+ return 1;
- if (!monitor_hwnd) {
-#ifdef DBG
- DbgPrintf("S Error Creating ttyConHookChild:%d\r\n", GetLastError());
-#endif
+ /* Obtain a handle to the kernel library */
+ hkernel = LoadLibrary("KERNEL32.DLL");
+ if (!hkernel)
+ return 0;
+
+ /* Find the RegisterServiceProcess function */
+ register_service_process = (DWORD (WINAPI *)(DWORD, DWORD))
+ GetProcAddress(hkernel, "RegisterServiceProcess");
+ if (register_service_process == NULL) {
+ FreeLibrary(hkernel);
return 0;
}
-
- while (GetMessage(&msg, NULL, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return 0;
+
+ /* Register this process as a service */
+ rv = register_service_process(0, is_service != FALSE);
+ if (rv)
+ is_service = set_service;
+
+ /* Unload the kernel library */
+ FreeLibrary(hkernel);
+ return rv;
}
}
-/*
- * Exported function that sets up the fixup child window
- */
-BOOL __declspec(dllexport) WINAPI Windows9xServiceCtrlHandler(
- PHANDLER_ROUTINE phandler,
- BOOL add)
-{
- /* If we have not yet done so */
- FreeConsole();
-
- if (add)
- {
- DWORD tid;
- HANDLE hThread;
- /* NOTE: this is static so the module can continue to
- * access these args while we go on to other things
- */
- static tty_info tty;
- tty.instance = GetModuleHandle(NULL);
- tty.phandler = phandler;
- tty.parent = NULL;
- tty.name = "Apache Service";
- RegisterWindows9xService(TRUE);
- hThread = CreateThread(NULL, 0, ttyConsoleCtrlThread,
- (LPVOID)&tty, 0, &tid);
- if (hThread)
- {
- CloseHandle(hThread);
- return TRUE;
- }
- }
- else /* remove */
- {
- HWND child = FindWindowEx(NULL, NULL, "ttyConHookChild", NULL);
- if (monitor_hwnd)
- SendMessage(monitor_hwnd, WM_DESTROY, 0, 0);
- RegisterWindows9xService(FALSE);
- return TRUE;
- }
- return FALSE;
-}
-
-
-/*
- * Exported function that sets up the fixup child window and dispatch
+/* The remaining code all executes --in the tty's own process context--
+ *
+ * That means special attention must be paid to what it's doing...
*/
-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.instance = GetModuleHandle(NULL);
- tty.phandler = phandler;
- tty.parent = parent;
- tty.name = "ttyListener";
- 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;
- }
- if (hhkCallWndProc) {
- UnhookWindowsHookEx(hhkCallWndProc);
- hhkCallWndProc = NULL;
- }
- FreeLibrary(hmodHook);
- hmodHook = NULL;
- }
- return TRUE;
- }
- return FALSE;
-}
-
-
-/*
- * Subclass message process for the tty window
+/* Subclass message process for the tty window
+ *
+ * This code -handles- WM_CLOSE, WM_ENDSESSION and WM_QUERYENDSESSION
+ * by dispatching them to the window identified by the hookwndprop
+ * property atom set against our window. Messages are then dispatched
+ * to origwndprop property atom we set against the window when we
+ * injected this subclass. This trick did not work with simply a hook.
*/
-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;
- switch (msg)
+ if (msg == WM_NCDESTROY || msg == hookwndmsg)
{
- case WM_NCDESTROY:
#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
- is_subclassed = FALSE;
- RegisterWindows9xService(FALSE);
+ if (is_subclassed) {
+ if (is_service)
+ RegisterWindows9xService(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);
+ RemoveProp(hwnd, hookwndprop);
+ is_subclassed = FALSE;
+ }
+ }
+ else if (msg == WM_CLOSE || msg == WM_ENDSESSION
+ || msg == WM_QUERYENDSESSION)
+ {
+ HWND child = (HWND)GetProp(hwnd, hookwndprop);
#ifdef DBG
- DbgPrintf("W Proc %08x hwnd:%08x msg:%d\r\n",
- GetCurrentProcessId(), hwnd, msg);
+ DbgPrintf("W Proc %08x hwnd:%08x msg:%d\r\n",
+ GetCurrentProcessId(), hwnd, msg);
#endif
- if (!child)
- break;
+ if (child)
return SendMessage(child, msg, wParam, lParam);
- }
}
return CallWindowProc(origproc, hwnd, msg, wParam, lParam);
}
+/* HookProc, once installed, is responsible for subclassing the system
+ * tty windows. It generally does nothing special itself, since
+ * research indicates that it cannot deal well with the messages we are
+ * interested in, that is, WM_CLOSE, WM_QUERYSHUTDOWN and WM_SHUTDOWN
+ * of the tty process.
+ *
+ * Respond and subclass only when a WM_NULL is received by the window.
+ */
int HookProc(int hc, HWND *hwnd, UINT *msg, WPARAM *wParam, LPARAM *lParam)
{
if (is_tty == -1 && *hwnd)
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
- RegisterWindows9xService(TRUE);
- }
#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 == hookwndmsg && is_tty)
{
- if ((*msg == WM_CLOSE)
- || (*msg == WM_ENDSESSION)) {
- DWORD apppid, ttypid = GetCurrentProcessId();
- GetWindowThreadProcessId(*hwnd, &apppid);
+ WNDPROC origproc = (WNDPROC)GetWindowLong(hwtty, GWL_WNDPROC);
+ SetProp(hwtty, origwndprop, origproc);
+ SetWindowLong(hwtty, GWL_WNDPROC, (LONG)WndProc);
+ is_subclassed = TRUE;
#ifdef DBG
- DbgPrintf("H Proc %08x hwnd:%08x owned by %08x msg:%d\r\n", ttypid, *hwnd, apppid, *msg);
+ DbgPrintf("W Proc %08x hwnd:%08x Subclassed\r\n",
+ GetCurrentProcessId(), hwtty);
#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;
- }
+ if (*wParam == 2)
+ RegisterWindows9xService(TRUE);
}
+
return -1;
}