diff --git a/reactos/dll/win32/user32/windows/hook.c b/reactos/dll/win32/user32/windows/hook.c index b848225741b..c2c8f3efd65 100644 --- a/reactos/dll/win32/user32/windows/hook.c +++ b/reactos/dll/win32/user32/windows/hook.c @@ -154,49 +154,18 @@ CallMsgFilterA( LPMSG lpMsg, int nCode) { - BOOL ret = FALSE; - - if (nCode != HCBT_CREATEWND) ret = NtUserCallMsgFilter((LPMSG) lpMsg, nCode); - else + MSG Msg; + if (NtCurrentTeb()->Win32ThreadInfo && IsThreadHooked(GetWin32ClientInfo())) + { + if ( lpMsg->message & ~WM_MAXIMUM ) { - UNICODE_STRING usBuffer; - CBT_CREATEWNDA *cbtcwA = (CBT_CREATEWNDA *)lpMsg->lParam; - CBT_CREATEWNDW cbtcwW; - CREATESTRUCTW csW; - MSG Msg; - - Msg.hwnd = lpMsg->hwnd; - Msg.message = lpMsg->message; - Msg.time = lpMsg->time; - Msg.pt = lpMsg->pt; - Msg.wParam = lpMsg->wParam; - - cbtcwW.lpcs = &csW; - cbtcwW.hwndInsertAfter = cbtcwA->hwndInsertAfter; - csW = *(CREATESTRUCTW *)cbtcwA->lpcs; - - if (HIWORD(cbtcwA->lpcs->lpszName)) - { - RtlCreateUnicodeStringFromAsciiz(&usBuffer,cbtcwA->lpcs->lpszName); - csW.lpszName = usBuffer.Buffer; - } - if (HIWORD(cbtcwA->lpcs->lpszClass)) - { - RtlCreateUnicodeStringFromAsciiz(&usBuffer,cbtcwA->lpcs->lpszClass); - csW.lpszClass = usBuffer.Buffer; - } - Msg.lParam =(LPARAM) &cbtcwW; - - ret = NtUserCallMsgFilter((LPMSG)&Msg, nCode); - - lpMsg->time = Msg.time; - lpMsg->pt = Msg.pt; - - cbtcwA->hwndInsertAfter = cbtcwW.hwndInsertAfter; - if (HIWORD(csW.lpszName)) HeapFree( GetProcessHeap(), 0, (LPWSTR)csW.lpszName ); - if (HIWORD(csW.lpszClass)) HeapFree( GetProcessHeap(), 0, (LPWSTR)csW.lpszClass ); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; } - return ret; + RtlCopyMemory(&Msg, lpMsg, sizeof(MSG)); + return NtUserCallMsgFilter( &Msg, nCode); + } + return FALSE; } @@ -209,7 +178,18 @@ CallMsgFilterW( LPMSG lpMsg, int nCode) { - return NtUserCallMsgFilter((LPMSG) lpMsg, nCode); + MSG Msg; + if (NtCurrentTeb()->Win32ThreadInfo && IsThreadHooked(GetWin32ClientInfo())) + { + if ( lpMsg->message & ~WM_MAXIMUM ) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + RtlCopyMemory(&Msg, lpMsg, sizeof(MSG)); + return NtUserCallMsgFilter( &Msg, nCode); + } + return FALSE; } @@ -454,7 +434,7 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL; KBDLLHOOKSTRUCT KeyboardLlData, *pKeyboardLlData; MSLLHOOKSTRUCT MouseLlData, *pMouseLlData; - MSG Msg, *pMsg; + MSG *pcMsg, *pMsg; PMOUSEHOOKSTRUCT pMHook; CWPSTRUCT CWP, *pCWP; CWPRETSTRUCT CWPR, *pCWPR; @@ -476,13 +456,12 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) case HCBT_CREATEWND: CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS) ((PCHAR) Common + Common->lParam); - Csw = CbtCreatewndExtra->Cs; - Csw.lpszName = CbtCreatewndExtra->Cs.lpszName; - Csw.lpszClass = CbtCreatewndExtra->Cs.lpszClass; - wParam = Common->wParam; + RtlCopyMemory(&Csw, &CbtCreatewndExtra->Cs, sizeof(CREATESTRUCTW)); CbtCreatewndw.lpcs = &Csw; CbtCreatewndw.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter; + wParam = Common->wParam; lParam = (LPARAM) &CbtCreatewndw; + ERR("HCBT_CREATEWND: hWnd 0x%x Name 0x%x Class 0x%x\n", Common->wParam, Csw.lpszName, Csw.lpszClass); break; case HCBT_CLICKSKIPPED: pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam); @@ -524,7 +503,7 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) } else { - ERR("Common = 0x%x, Proc = 0x%x\n",Common,Common->Proc); + ERR("Null Proc! Common = 0x%x, Proc = 0x%x\n",Common,Common->Proc); } switch(Common->Code) { @@ -545,6 +524,7 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &KeyboardLlData); break; case WH_MOUSE_LL: + ERR("WH_MOUSE_LL: Code %d, wParam %d\n",Common->Code,Common->wParam); pMouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam); RtlCopyMemory(&MouseLlData, pMouseLlData, sizeof(MSLLHOOKSTRUCT)); Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &MouseLlData); @@ -562,7 +542,7 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) _SEH2_END; break; case WH_CALLWNDPROC: - ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common->Code,Common->wParam); +// ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common->Code,Common->wParam); pCWP = (PCWPSTRUCT)((PCHAR) Common + Common->lParam); RtlCopyMemory(&CWP, pCWP, sizeof(CWPSTRUCT)); Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &CWP); @@ -573,14 +553,15 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &CWPR); break; case WH_MSGFILTER: /* All SEH support */ - ERR("WH_MSGFILTER: Code %d, wParam %d\n",Common->Code,Common->wParam); case WH_SYSMSGFILTER: case WH_GETMESSAGE: pMsg = (PMSG)((PCHAR) Common + Common->lParam); - RtlCopyMemory(&Msg, pMsg, sizeof(MSG)); + pcMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MSG)); + RtlCopyMemory(pcMsg, pMsg, sizeof(MSG)); +// ERR("pMsg %d pcMsg %d\n",pMsg->message, pcMsg->message); _SEH2_TRY { - Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &Msg); + Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pcMsg); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -588,11 +569,14 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) } _SEH2_END; if (!Hit && Common->HookId == WH_GETMESSAGE) - RtlCopyMemory(pMsg, &Msg, sizeof(MSG)); + RtlCopyMemory(pMsg, pcMsg, sizeof(MSG)); + HeapFree( GetProcessHeap(), 0, pcMsg ); break; - case WH_FOREGROUNDIDLE: /* <-- SEH support */ case WH_KEYBOARD: case WH_SHELL: + Result = Common->Proc(Common->Code, Common->wParam, Common->lParam); + break; + case WH_FOREGROUNDIDLE: /* <-- SEH support */ _SEH2_TRY { Result = Common->Proc(Common->Code, Common->wParam, Common->lParam); diff --git a/reactos/include/reactos/win32k/callback.h b/reactos/include/reactos/win32k/callback.h index fc7c0bb95e2..76792380bd2 100644 --- a/reactos/include/reactos/win32k/callback.h +++ b/reactos/include/reactos/win32k/callback.h @@ -48,8 +48,6 @@ typedef struct _HOOKPROC_CALLBACK_ARGUMENTS LPARAM lParam; HOOKPROC Proc; BOOLEAN Ansi; - UINT ModuleNameLength; - WCHAR ModuleName[1]; } HOOKPROC_CALLBACK_ARGUMENTS, *PHOOKPROC_CALLBACK_ARGUMENTS; typedef struct _HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS diff --git a/reactos/subsystems/win32/win32k/main/dllmain.c b/reactos/subsystems/win32/win32k/main/dllmain.c index dd25b2efefe..42efcf9ea0e 100644 --- a/reactos/subsystems/win32/win32k/main/dllmain.c +++ b/reactos/subsystems/win32/win32k/main/dllmain.c @@ -252,17 +252,41 @@ Win32kThreadCallback(struct _ETHREAD *Thread, } } } + else + { + DPRINT1("No Desktop handle for this Thread!\n"); + } Win32Thread->TIF_flags &= ~TIF_INCLEANUP; co_IntDestroyCaret(Win32Thread); Win32Thread->ppi = PsGetCurrentProcessWin32Process(); - pTeb = NtCurrentTeb(); - if (pTeb) + if (Win32Thread->rpdesk && !Win32Thread->pDeskInfo) { - Win32Thread->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo; - Win32Thread->pClientInfo->pClientThreadInfo = NULL; + Win32Thread->pDeskInfo = Win32Thread->rpdesk->pDeskInfo; } Win32Thread->MessageQueue = MsqCreateMessageQueue(Thread); Win32Thread->KeyboardLayout = W32kGetDefaultKeyLayout(); + pTeb = NtCurrentTeb(); + if (pTeb) + { /* Attempt to startup client support which should have been initialized in IntSetThreadDesktop. */ + PCLIENTINFO pci = (PCLIENTINFO)pTeb->Win32ClientInfo; + Win32Thread->pClientInfo = pci; + pci->pClientThreadInfo = NULL; + pci->ppi = Win32Thread->ppi; + pci->fsHooks = Win32Thread->fsHooks; + if (Win32Thread->KeyboardLayout) pci->hKL = Win32Thread->KeyboardLayout->hkl; + pci->dwTIFlags = Win32Thread->TIF_flags; + /* CI may not have been initialized. */ + if (!pci->pDeskInfo && Win32Thread->pDeskInfo) + { + if (!pci->ulClientDelta) pci->ulClientDelta = DesktopHeapGetUserDelta(); + + pci->pDeskInfo = (PVOID)((ULONG_PTR)Win32Thread->pDeskInfo - pci->ulClientDelta); + } + } + else + { + DPRINT1("No TEB for this Thread!\n"); + } Win32Thread->pEThread = Thread; } else diff --git a/reactos/subsystems/win32/win32k/ntuser/callback.c b/reactos/subsystems/win32/win32k/ntuser/callback.c index 2b4f2409a8b..b683edd27b7 100644 --- a/reactos/subsystems/win32/win32k/ntuser/callback.c +++ b/reactos/subsystems/win32/win32k/ntuser/callback.c @@ -335,6 +335,7 @@ co_IntCallHookProc(INT HookId, PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL; PTHREADINFO pti; PWND pWnd; + PMSG pMsg = NULL; BOOL Hit = FALSE; ASSERT(Proc); @@ -346,8 +347,8 @@ co_IntCallHookProc(INT HookId, return 0; } - ArgumentLength = sizeof(HOOKPROC_CALLBACK_ARGUMENTS) - sizeof(WCHAR) - + ModuleName->Length; + ArgumentLength = sizeof(HOOKPROC_CALLBACK_ARGUMENTS); + switch(HookId) { case WH_CBT: @@ -360,6 +361,7 @@ co_IntCallHookProc(INT HookId, DPRINT1("WH_CBT HCBT_CREATEWND wParam bad hWnd!\n"); goto Fault_Exit; } + DPRINT1("HCBT_CREATEWND AnsiCreator %s, AnsiHook %s\n", pWnd->state & WNDS_ANSICREATOR ? "True" : "False", Ansi ? "True" : "False"); // Due to KsStudio.exe, just pass the callers original pointers // except class which point to kernel space if not an atom. // Found by, Olaf Siejka @@ -432,24 +434,20 @@ co_IntCallHookProc(INT HookId, Common->lParam = lParam; Common->Proc = Proc; Common->Ansi = Ansi; - Common->ModuleNameLength = ModuleName->Length; - if (ModuleName->Buffer) - RtlCopyMemory(Common->ModuleName, ModuleName->Buffer, ModuleName->Length); - Extra = (PCHAR) Common->ModuleName + Common->ModuleNameLength; + Extra = (PCHAR) Common + sizeof(HOOKPROC_CALLBACK_ARGUMENTS); switch(HookId) { case WH_CBT: switch(Code) - { + { // Need to remember this is not the first time through! Call Next Hook? case HCBT_CREATEWND: - Common->lParam = (LPARAM) (Extra - (PCHAR) Common); CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS) Extra; RtlCopyMemory( &CbtCreatewndExtra->Cs, CbtCreateWnd->lpcs, sizeof(CREATESTRUCTW) ); CbtCreatewndExtra->WndInsertAfter = CbtCreateWnd->hwndInsertAfter; - CbtCreatewndExtra->Cs.lpszClass = CbtCreateWnd->lpcs->lpszClass; // if Atom + CbtCreatewndExtra->Cs.lpszClass = CbtCreateWnd->lpcs->lpszClass; CbtCreatewndExtra->Cs.lpszName = CbtCreateWnd->lpcs->lpszName; - Extra = (PCHAR) (CbtCreatewndExtra + 1); + Common->lParam = (LPARAM) (Extra - (PCHAR) Common); break; case HCBT_CLICKSKIPPED: RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT)); @@ -488,7 +486,8 @@ co_IntCallHookProc(INT HookId, case WH_MSGFILTER: case WH_SYSMSGFILTER: case WH_GETMESSAGE: - RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSG)); + pMsg = (PMSG)lParam; + RtlCopyMemory(Extra, (PVOID) pMsg, sizeof(MSG)); Common->lParam = (LPARAM) (Extra - (PCHAR) Common); break; case WH_FOREGROUNDIDLE: @@ -548,9 +547,9 @@ co_IntCallHookProc(INT HookId, break; // "The GetMsgProc hook procedure can examine or modify the message." case WH_GETMESSAGE: - if (lParam) + if (pMsg) { - RtlCopyMemory((PVOID) lParam, Extra, sizeof(MSG)); + RtlCopyMemory((PVOID) pMsg, Extra, sizeof(MSG)); } break; } diff --git a/reactos/subsystems/win32/win32k/ntuser/desktop.c b/reactos/subsystems/win32/win32k/ntuser/desktop.c index 673fd452ae0..91b5a53224a 100644 --- a/reactos/subsystems/win32/win32k/ntuser/desktop.c +++ b/reactos/subsystems/win32/win32k/ntuser/desktop.c @@ -880,14 +880,24 @@ NtUserCreateDesktop( PUNICODE_STRING lpszDesktopName = NULL; UNICODE_STRING ClassName, MenuName; LARGE_STRING WindowName; + BOOL NoHooks = FALSE; PWND pWnd = NULL; CREATESTRUCTW Cs; INT i; + PTHREADINFO ptiCurrent; DECLARE_RETURN(HDESK); DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName); UserEnterExclusive(); + ptiCurrent = PsGetCurrentThreadWin32Thread(); + if (ptiCurrent) + { + /* Turn off hooks when calling any CreateWindowEx from inside win32k. */ + NoHooks = (ptiCurrent->TIF_flags & TIF_DISABLEHOOKS); + ptiCurrent->TIF_flags |= TIF_DISABLEHOOKS; + } + _SEH2_TRY { ProbeForRead( poa, @@ -1102,6 +1112,7 @@ NtUserCreateDesktop( RETURN( Desktop); CLEANUP: + if (!NoHooks && ptiCurrent) ptiCurrent->TIF_flags &= ~TIF_DISABLEHOOKS; DPRINT("Leave NtUserCreateDesktop, ret=%i\n",_ret_); UserLeave(); END_CLEANUP; diff --git a/reactos/subsystems/win32/win32k/ntuser/hook.c b/reactos/subsystems/win32/win32k/ntuser/hook.c index 810a7dfd759..4baee93a476 100644 --- a/reactos/subsystems/win32/win32k/ntuser/hook.c +++ b/reactos/subsystems/win32/win32k/ntuser/hook.c @@ -21,6 +21,7 @@ typedef struct _HOOKPACK { PHOOK pHk; LPARAM lParam; + PVOID pHookStructs; } HOOKPACK, *PHOOKPACK; /* PRIVATE FUNCTIONS *********************************************************/ @@ -36,6 +37,7 @@ IntCallLowLevelHook( PHOOK Hook, NTSTATUS Status; PTHREADINFO pti; PHOOKPACK pHP; + INT Size; ULONG_PTR uResult = 0; if (Hook->Thread) @@ -48,6 +50,56 @@ IntCallLowLevelHook( PHOOK Hook, pHP->pHk = Hook; pHP->lParam = lParam; + pHP->pHookStructs = NULL; + Size = 0; + +// Once the rest is enabled again, This prevents stack corruption from the caller. + switch(Hook->HookId) + { + case WH_CBT: + switch(Code) + { + case HCBT_CREATEWND: + Size = sizeof(CBT_CREATEWNDW); + break; + case HCBT_MOVESIZE: + Size = sizeof(RECTL); + break; + case HCBT_ACTIVATE: + Size = sizeof(CBTACTIVATESTRUCT); + break; + case HCBT_CLICKSKIPPED: + Size = sizeof(MOUSEHOOKSTRUCT); + break; + } + break; + case WH_KEYBOARD_LL: + Size = sizeof(KBDLLHOOKSTRUCT); + break; + case WH_MOUSE_LL: + Size = sizeof(MSLLHOOKSTRUCT); + break; + case WH_MOUSE: + Size = sizeof(MOUSEHOOKSTRUCT); + break; + case WH_CALLWNDPROC: + Size = sizeof(CWPSTRUCT); + break; + case WH_CALLWNDPROCRET: + Size = sizeof(CWPRETSTRUCT); + break; + case WH_MSGFILTER: + case WH_SYSMSGFILTER: + case WH_GETMESSAGE: + Size = sizeof(MSG); + break; + } + + if (Size) + { + pHP->pHookStructs = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_HOOK); + if (pHP->pHookStructs) RtlCopyMemory(pHP->pHookStructs, (PVOID)lParam, Size); + } /* FIXME should get timeout from * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */ @@ -63,11 +115,70 @@ IntCallLowLevelHook( PHOOK Hook, if (!NT_SUCCESS(Status)) { DPRINT1("Error Hook Call SendMsg. %d Status: 0x%x\n", Hook->HookId, Status); + if (pHP->pHookStructs) ExFreePoolWithTag(pHP->pHookStructs, TAG_HOOK); ExFreePoolWithTag(pHP, TAG_HOOK); } return NT_SUCCESS(Status) ? uResult : 0; } + +// +// Dispatch MsgQueue Hook Call processor! +// +LRESULT +FASTCALL +co_CallHook( INT HookId, + INT Code, + WPARAM wParam, + LPARAM lParam) +{ + LRESULT Result; + PHOOK phk; + PHOOKPACK pHP = (PHOOKPACK)lParam; + + phk = pHP->pHk; + lParam = pHP->lParam; + + switch(HookId) + { + case WH_CBT: + switch(Code) + { + case HCBT_CREATEWND: + case HCBT_MOVESIZE: + case HCBT_ACTIVATE: + case HCBT_CLICKSKIPPED: + lParam = (LPARAM)pHP->pHookStructs; + break; + } + break; + case WH_KEYBOARD_LL: + case WH_MOUSE_LL: + case WH_MOUSE: + case WH_CALLWNDPROC: + case WH_CALLWNDPROCRET: + case WH_MSGFILTER: + case WH_SYSMSGFILTER: + case WH_GETMESSAGE: + lParam = (LPARAM)pHP->pHookStructs; + break; + } + + /* The odds are high for this to be a Global call. */ + Result = co_IntCallHookProc( HookId, + Code, + wParam, + lParam, + phk->Proc, + phk->Ansi, + &phk->ModuleName); + + /* The odds so high, no one is waiting for the results. */ + if (pHP->pHookStructs) ExFreePoolWithTag(pHP->pHookStructs, TAG_HOOK); + ExFreePoolWithTag(pHP, TAG_HOOK); + return Result; +} + static LRESULT FASTCALL @@ -93,34 +204,6 @@ co_HOOK_CallHookNext( PHOOK Hook, &Hook->ModuleName); } -// -// Dispatch MsgQueue Hook Call processor! -// -LRESULT -FASTCALL -co_CallHook( INT HookId, - INT Code, - WPARAM wParam, - LPARAM lParam) -{ - LRESULT Result; - PHOOK phk; - PHOOKPACK pHP = (PHOOKPACK)lParam; - - phk = pHP->pHk; - /* The odds are high for this to be a Global call. */ - Result = co_IntCallHookProc( HookId, - Code, - wParam, - pHP->lParam, - phk->Proc, - phk->Ansi, - &phk->ModuleName); - - ExFreePoolWithTag(pHP, TAG_HOOK); - return Result; -} - LRESULT FASTCALL IntCallDebugHook( PHOOK Hook, @@ -704,6 +787,20 @@ IntGetFirstHook(PLIST_ENTRY Table) return Elem == Table ? NULL : CONTAINING_RECORD(Elem, HOOK, Chain); } +static +PHOOK +FASTCALL +IntGetNextGlobalHook(PHOOK Hook, PDESKTOP pdo) +{ + int HookId = Hook->HookId; + PLIST_ENTRY Elem; + + Elem = Hook->Chain.Flink; + if (Elem != &pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) + return CONTAINING_RECORD(Elem, HOOK, Chain); + return NULL; +} + /* find the next hook in the chain */ PHOOK FASTCALL @@ -724,10 +821,7 @@ IntGetNextHook(PHOOK Hook) else { pti = PsGetCurrentThreadWin32Thread(); - - Elem = Hook->Chain.Flink; - if (Elem != &pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) - return CONTAINING_RECORD(Elem, HOOK, Chain); + return IntGetNextGlobalHook(Hook, pti->rpdesk); } return NULL; } @@ -756,6 +850,7 @@ IntRemoveHook(PHOOK Hook) { INT HookId; PTHREADINFO pti; + PDESKTOP pdo; HookId = Hook->HookId; @@ -783,13 +878,13 @@ IntRemoveHook(PHOOK Hook) { IntFreeHook( Hook); - pti = PsGetCurrentThreadWin32Thread(); + pdo = IntGetActiveDesktop(); - if ( pti->rpdesk && - pti->rpdesk->pDeskInfo && - IsListEmpty(&pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) ) + if ( pdo && + pdo->pDeskInfo && + IsListEmpty(&pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) ) { - pti->rpdesk->pDeskInfo->fsHooks &= ~HOOKID_TO_FLAG(HookId); + pdo->pDeskInfo->fsHooks &= ~HOOKID_TO_FLAG(HookId); return TRUE; } } @@ -808,13 +903,13 @@ HOOK_DestroyThreadHooks(PETHREAD Thread) pti = Thread->Tcb.Win32Thread; pdo = IntGetActiveDesktop(); -DPRINT1("DestroyThreadHooks 1\n"); + if (!pti || !pdo) { DPRINT1("Kill Thread Hooks pti 0x%x pdo 0x%x\n",pti,pdo); return; } - ObReferenceObject(pti->pEThread); + ObReferenceObject(Thread); // Local Thread cleanup. if (pti->fsHooks) @@ -838,7 +933,6 @@ DPRINT1("DestroyThreadHooks 1\n"); } pti->fsHooks = 0; } -DPRINT1("DestroyThreadHooks 2\n"); // Global search based on Thread and cleanup. if (pdo->pDeskInfo->fsHooks) { @@ -854,7 +948,7 @@ DPRINT1("DestroyThreadHooks 2\n"); { if (!HookObj) break; if (HookObj->head.pti == pti) - { DPRINT1("Global Hook Removed\n"); + { if (IntRemoveHook(HookObj)) break; } pElem = HookObj->Chain.Flink; @@ -863,8 +957,7 @@ DPRINT1("DestroyThreadHooks 2\n"); while (pElem != pGLE); } } - ObDereferenceObject(pti->pEThread); -DPRINT1("DestroyThreadHooks 3\n"); + ObDereferenceObject(Thread); return; } @@ -882,6 +975,7 @@ co_HOOK_CallHooks( INT HookId, PTHREADINFO pti; PCLIENTINFO ClientInfo; PLIST_ENTRY pLLE, pGLE; + PDESKTOP pdo; BOOL Local = FALSE, Global = FALSE; LRESULT Result = 0; @@ -889,9 +983,20 @@ co_HOOK_CallHooks( INT HookId, pti = PsGetCurrentThreadWin32Thread(); if (!pti || !pti->rpdesk || !pti->rpdesk->pDeskInfo) - goto Exit; // Must have a desktop running for hooks. + { + pdo = IntGetActiveDesktop(); + /* If KeyboardThread|MouseThread|(RawInputThread or RIT) aka system threads, + pti->fsHooks most likely, is zero. So process KbT & MsT to "send" the message. + */ + if ( !pti || !pdo || (!(HookId == WH_KEYBOARD_LL) && !(HookId == WH_MOUSE_LL)) ) + goto Exit; + } + else + { + pdo = pti->rpdesk; + } - if ( pti->TIF_flags & TIF_INCLEANUP) + if ( pti->TIF_flags & (TIF_INCLEANUP|TIF_DISABLEHOOKS)) goto Exit; if ( ISITHOOKED(HookId) ) @@ -900,7 +1005,7 @@ co_HOOK_CallHooks( INT HookId, Local = TRUE; } - if ( pti->rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(HookId) ) + if ( pdo->pDeskInfo->fsHooks & HOOKID_TO_FLAG(HookId) ) { DPRINT("Global Hooker %d\n", HookId); Global = TRUE; @@ -908,8 +1013,6 @@ co_HOOK_CallHooks( INT HookId, if ( !Local && !Global ) goto Exit; // No work! - pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; - pGLE = &pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]; Hook = NULL; /* SetWindowHookEx sorts out the Thread issue by placing the Hook to @@ -917,6 +1020,7 @@ co_HOOK_CallHooks( INT HookId, */ if ( Local ) { + pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; Hook = IntGetFirstHook(pLLE); if (!Hook) { @@ -970,6 +1074,7 @@ co_HOOK_CallHooks( INT HookId, { PTHREADINFO ptiHook; + pGLE = &pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]; Hook = IntGetFirstHook(pGLE); if (!Hook) { @@ -988,10 +1093,11 @@ co_HOOK_CallHooks( INT HookId, /* "Global hook monitors messages for all threads in the same desktop * as the calling thread." */ - if ( ptiHook->TIF_flags & TIF_INCLEANUP || - ptiHook->rpdesk != pti->rpdesk) + if ( ptiHook->TIF_flags & (TIF_INCLEANUP|TIF_DISABLEHOOKS) || + ptiHook->rpdesk != pdo) { - Hook = IntGetNextHook(Hook); + DPRINT("Next Hook 0x%x, 0x%x\n",ptiHook->rpdesk,pdo); + Hook = IntGetNextGlobalHook(Hook, pdo); if (!Hook) break; continue; } @@ -999,8 +1105,14 @@ co_HOOK_CallHooks( INT HookId, ObReferenceObject(ptiHook->pEThread); if (ptiHook != pti ) { - DPRINT("\nGlobal Hook posting to another Thread! %d\n",HookId ); - Result = IntCallLowLevelHook(Hook, Code, wParam, lParam); + /* This fixed the ros regtest. Wine does this too. Need more time + to investigate this. MSDN "Hooks Overview" can't be wrong? + */ + if (HookId == WH_KEYBOARD_LL || HookId == WH_MOUSE_LL) + { + DPRINT("\nGlobal Hook posting to another Thread! %d\n",HookId ); + Result = IntCallLowLevelHook(Hook, Code, wParam, lParam); + } } else { /* Make the direct call. */ @@ -1014,7 +1126,7 @@ co_HOOK_CallHooks( INT HookId, &Hook->ModuleName); } ObDereferenceObject(ptiHook->pEThread); - Hook = IntGetNextHook(Hook); + Hook = IntGetNextGlobalHook(Hook, pdo); } while ( Hook ); DPRINT("Ret: Global HookId %d Result 0x%x\n", HookId,Result); @@ -1248,7 +1360,7 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, } } else /* system-global hook */ - { + { pti = ptiCurrent; // gptiCurrent; if ( !Mod && (HookId == WH_GETMESSAGE || @@ -1294,6 +1406,8 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, Hook->Proc = HookProc; Hook->Ansi = Ansi; + DPRINT1("Set Hook Desk 0x%x DeskInfo 0x%x Handle Desk 0x%x\n",pti->rpdesk, pti->pDeskInfo,Hook->head.rpdesk); + if (ThreadId) /* thread-local hook */ { InsertHeadList(&pti->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain); @@ -1343,10 +1457,10 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, } else { - InsertHeadList(&pti->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain); + InsertHeadList(&pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain); Hook->ptiHooked = NULL; //gptiCurrent->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId); - pti->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId); + pti->rpdesk->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId); } RtlInitUnicodeString(&Hook->ModuleName, NULL); @@ -1393,7 +1507,7 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, else Hook->offPfn = 0; - DPRINT1("Installing: HookId %d Global %s\n", HookId, !ThreadId ? "TRUE" : "FALSE"); + DPRINT("Installing: HookId %d Global %s\n", HookId, !ThreadId ? "TRUE" : "FALSE"); RETURN( Handle); CLEANUP: diff --git a/reactos/subsystems/win32/win32k/ntuser/input.c b/reactos/subsystems/win32/win32k/ntuser/input.c index 8919d57d6ad..4014e4edee9 100644 --- a/reactos/subsystems/win32/win32k/ntuser/input.c +++ b/reactos/subsystems/win32/win32k/ntuser/input.c @@ -22,6 +22,8 @@ extern NTSTATUS Win32kInitWin32Thread(PETHREAD Thread); /* GLOBALS *******************************************************************/ PTHREADINFO ptiRawInput; +PTHREADINFO ptiKeyboard; +PTHREADINFO ptiMouse; PKTIMER MasterTimer = NULL; PATTACHINFO gpai = NULL; @@ -234,6 +236,18 @@ MouseThreadMain(PVOID StartContext) FILE_SYNCHRONOUS_IO_ALERT); } while (!NT_SUCCESS(Status)); + /* Need to setup basic win32k for this thread to process WH_MOUSE_LL messages. */ + Status = Win32kInitWin32Thread(PsGetCurrentThread()); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Win32K: Failed making mouse thread a win32 thread.\n"); + return; //(Status); + } + + ptiMouse = PsGetCurrentThreadWin32Thread(); + ptiMouse->TIF_flags |= TIF_SYSTEMTHREAD; + DPRINT1("\nMouse Thread 0x%x \n", ptiMouse); + KeSetPriorityThread(&PsGetCurrentThread()->Tcb, LOW_REALTIME_PRIORITY + 3); @@ -530,6 +544,10 @@ KeyboardThreadMain(PVOID StartContext) return; //(Status); } + ptiKeyboard = PsGetCurrentThreadWin32Thread(); + ptiKeyboard->TIF_flags |= TIF_SYSTEMTHREAD; + DPRINT1("\nKeyboard Thread 0x%x \n", ptiKeyboard); + KeSetPriorityThread(&PsGetCurrentThread()->Tcb, LOW_REALTIME_PRIORITY + 3); @@ -890,8 +908,8 @@ RawInputThreadMain(PVOID StartContext) } ptiRawInput = PsGetCurrentThreadWin32Thread(); - DPRINT("\nRaw Input Thread 0x%x \n", ptiRawInput); - + ptiRawInput->TIF_flags |= TIF_SYSTEMTHREAD; + DPRINT1("\nRaw Input Thread 0x%x \n", ptiRawInput); KeSetPriorityThread(&PsGetCurrentThread()->Tcb, LOW_REALTIME_PRIORITY + 3); diff --git a/reactos/subsystems/win32/win32k/ntuser/window.c b/reactos/subsystems/win32/win32k/ntuser/window.c index e81ab4baef9..4233818e00d 100644 --- a/reactos/subsystems/win32/win32k/ntuser/window.c +++ b/reactos/subsystems/win32/win32k/ntuser/window.c @@ -1910,9 +1910,9 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, LRESULT Result; USER_REFERENCE_ENTRY ParentRef, Ref; PTHREADINFO pti; - ANSI_STRING asClassName; DWORD dwShowMode = SW_SHOW; CREATESTRUCTW *pCsw; + PVOID pszClass = NULL, pszName = NULL; DECLARE_RETURN(PWND); /* Get the current window station and reference it */ @@ -1927,7 +1927,6 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, pCsw = NULL; pCbtCreate = NULL; - RtlInitAnsiString(&asClassName, NULL); /* Get the class and reference it*/ Class = IntGetAndReferenceClass(ClassName, Cs->hInstance); @@ -2008,17 +2007,58 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, pCsw->dwExStyle = Cs->dwExStyle; dwStyle = Cs->style; // Save it anyway. pCsw->style = Window->style; /* HCBT_CREATEWND needs the real window style */ + pCsw->lpszName = Cs->lpszName; + pCsw->lpszClass = Cs->lpszClass; - pCsw->lpszName = (LPCWSTR) WindowName->Buffer; - pCsw->lpszClass = (LPCWSTR) ClassName->Buffer; - - if (Window->state & WNDS_ANSICREATOR) + // Based on the assumption this is from "unicode source" user32, ReactOS, answer is yes. + if (!IS_ATOM(ClassName->Buffer)) { - if (!IS_ATOM(ClassName->Buffer)) + if (Window->state & WNDS_ANSICREATOR) { - RtlUnicodeStringToAnsiString(&asClassName, ClassName, TRUE); - pCsw->lpszClass = (LPCWSTR) asClassName.Buffer; + ANSI_STRING AnsiString; + AnsiString.MaximumLength = RtlUnicodeStringToAnsiSize(ClassName)+sizeof(CHAR); + pszClass = UserHeapAlloc(AnsiString.MaximumLength); + RtlZeroMemory(pszClass, AnsiString.MaximumLength); + AnsiString.Buffer = (PCHAR)pszClass; + RtlUnicodeStringToAnsiString(&AnsiString, ClassName, FALSE); } + else + { + UNICODE_STRING UnicodeString; + UnicodeString.MaximumLength = ClassName->Length + sizeof(UNICODE_NULL); + pszClass = UserHeapAlloc(UnicodeString.MaximumLength); + RtlZeroMemory(pszClass, UnicodeString.MaximumLength); + UnicodeString.Buffer = (PWSTR)pszClass; + RtlCopyUnicodeString(&UnicodeString, ClassName); + } + if (pszClass) pCsw->lpszClass = UserHeapAddressToUser(pszClass); + } + if (WindowName->Length) + { + UNICODE_STRING Name; + Name.Buffer = WindowName->Buffer; + Name.Length = WindowName->Length; + Name.MaximumLength = WindowName->MaximumLength; + + if (Window->state & WNDS_ANSICREATOR) + { + ANSI_STRING AnsiString; + AnsiString.MaximumLength = RtlUnicodeStringToAnsiSize(&Name)+sizeof(CHAR); + pszName = UserHeapAlloc(AnsiString.MaximumLength); + RtlZeroMemory(pszName, AnsiString.MaximumLength); + AnsiString.Buffer = (PCHAR)pszName; + RtlUnicodeStringToAnsiString(&AnsiString, &Name, FALSE); + } + else + { + UNICODE_STRING UnicodeString; + UnicodeString.MaximumLength = Name.Length + sizeof(UNICODE_NULL); + pszName = UserHeapAlloc(UnicodeString.MaximumLength); + RtlZeroMemory(pszName, UnicodeString.MaximumLength); + UnicodeString.Buffer = (PWSTR)pszName; + RtlCopyUnicodeString(&UnicodeString, &Name); + } + if (pszName) pCsw->lpszName = UserHeapAddressToUser(pszName); } pCbtCreate->lpcs = pCsw; @@ -2037,7 +2077,10 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, Cs->y = pCsw->y; hwndInsertAfter = pCbtCreate->hwndInsertAfter; - Cs->style = dwStyle; /* NCCREATE and WM_NCCALCSIZE need the original values*/ + /* NCCREATE and WM_NCCALCSIZE need the original values */ + Cs->style = dwStyle; + Cs->lpszName = (LPCWSTR) WindowName; + Cs->lpszClass = (LPCWSTR) ClassName; /* Send the WM_GETMINMAXINFO message*/ Size.cx = Cs->cx; @@ -2187,7 +2230,8 @@ CLEANUP: if (pCsw) ExFreePoolWithTag(pCsw, TAG_HOOK); if (pCbtCreate) ExFreePoolWithTag(pCbtCreate, TAG_HOOK); - RtlFreeAnsiString(&asClassName); + if (pszName) UserHeapFree(pszName); + if (pszClass) UserHeapFree(pszClass); if (Window) { @@ -2337,10 +2381,11 @@ NtUserCreateWindowEx( Cs.cy = nHeight; Cs.x = x; Cs.y = y; -// Cs.lpszName = (LPCWSTR) WindowName->Buffer; -// Cs.lpszClass = (LPCWSTR) ClassName->Buffer; - Cs.lpszName = (LPCWSTR) plstrWindowName; - Cs.lpszClass = (LPCWSTR) &ustrClassName; + Cs.lpszName = (LPCWSTR) plstrWindowName->Buffer; + if (IS_ATOM(plstrClassName)) + Cs.lpszClass = (LPCWSTR) plstrClassName; + else + Cs.lpszClass = (LPCWSTR) plstrClassName->Buffer; Cs.dwExStyle = dwExStyle; UserEnterExclusive();