[Win32k|User32]

- This hook commit fixes the ros regression testing startup, but consider this a hax fix until more research in Global hooks has completed. More pointed Global hook tests are needed. Misc changes, removed unused storage pointers and reordering. For DosBOX, the mouse low level is now working and the keyboard low level should not be so intermittent as before, now sending messages from system desktop not from thread desktop, see bug 5670 for more details.

svn path=/trunk/; revision=49472
This commit is contained in:
James Tabor 2010-11-04 23:45:34 +00:00
parent 1dec9f52a4
commit 200c27535e
8 changed files with 341 additions and 148 deletions

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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;

View file

@ -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:

View file

@ -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);

View file

@ -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();