static PHOOK
IntAddHook(PETHREAD Thread, int HookId, BOOLEAN Global, PWINSTATION_OBJECT WinStaObj)
{
- PW32THREAD W32Thread;
+ PTHREADINFO W32Thread;
PHOOK Hook;
- PHOOKTABLE Table = Global ? GlobalHooks : MsqGetHooks(((PW32THREAD)Thread->Tcb.Win32Thread)->MessageQueue);
+ PHOOKTABLE Table = Global ? GlobalHooks : MsqGetHooks(((PTHREADINFO)Thread->Tcb.Win32Thread)->MessageQueue);
HANDLE Handle;
if (NULL == Table)
}
else
{
- MsqSetHooks(((PW32THREAD)Thread->Tcb.Win32Thread)->MessageQueue, Table);
+ MsqSetHooks(((PTHREADINFO)Thread->Tcb.Win32Thread)->MessageQueue, Table);
}
}
if (Thread)
{
- W32Thread = ((PW32THREAD)Thread->Tcb.Win32Thread);
+ W32Thread = ((PTHREADINFO)Thread->Tcb.Win32Thread);
ASSERT(W32Thread != NULL);
W32Thread->Hooks |= HOOKID_TO_FLAG(HookId);
if (W32Thread->ThreadInfo != NULL)
return GlobalHooks;
}
- return MsqGetHooks(((PW32THREAD)Hook->Thread->Tcb.Win32Thread)->MessageQueue);
+ return MsqGetHooks(((PTHREADINFO)Hook->Thread->Tcb.Win32Thread)->MessageQueue);
}
/* get the first hook in the chain */
}
/* find the next hook in the chain, skipping the deleted ones */
-static PHOOK FASTCALL
+PHOOK
+FASTCALL
IntGetNextHook(PHOOK Hook)
{
PHOOKTABLE Table = IntGetTable(Hook);
static VOID
IntRemoveHook(PHOOK Hook, PWINSTATION_OBJECT WinStaObj, BOOL TableAlreadyLocked)
{
- PW32THREAD W32Thread;
+ PTHREADINFO W32Thread;
PHOOKTABLE Table = IntGetTable(Hook);
ASSERT(NULL != Table);
return;
}
- W32Thread = ((PW32THREAD)Hook->Thread->Tcb.Win32Thread);
+ W32Thread = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread);
ASSERT(W32Thread != NULL);
W32Thread->Hooks &= ~HOOKID_TO_FLAG(Hook->HookId);
if (W32Thread->ThreadInfo != NULL)
}
static LRESULT FASTCALL
-IntCallLowLevelHook(INT HookId, INT Code, WPARAM wParam, LPARAM lParam, PHOOK Hook)
+IntCallLowLevelHook(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam)
{
NTSTATUS Status;
ULONG_PTR uResult;
/* FIXME should get timeout from
* HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
- Status = co_MsqSendMessage(((PW32THREAD)Hook->Thread->Tcb.Win32Thread)->MessageQueue, (HWND) Code, HookId,
- wParam, lParam, 5000, TRUE, TRUE, &uResult);
+ Status = co_MsqSendMessage(((PTHREADINFO)Hook->Thread->Tcb.Win32Thread)->MessageQueue,
+ (HWND) Code,
+ Hook->HookId,
+ wParam,
+ lParam,
+ 5000,
+ TRUE,
+ MSQ_ISHOOK,
+ &uResult);
return NT_SUCCESS(Status) ? uResult : 0;
}
-LRESULT FASTCALL
+/*
+ Called from inside kernel space.
+ */
+LRESULT
+FASTCALL
co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
{
- PHOOK Hook;
- PW32THREAD Win32Thread;
+ PHOOK Hook, SaveHook;
+ PTHREADINFO pti;
+ PCLIENTINFO ClientInfo;
PHOOKTABLE Table;
LRESULT Result;
PWINSTATION_OBJECT WinStaObj;
ASSERT(WH_MINHOOK <= HookId && HookId <= WH_MAXHOOK);
- Win32Thread = PsGetCurrentThreadWin32Thread();
- if (NULL == Win32Thread)
+ pti = PsGetCurrentThreadWin32Thread();
+ if (!pti)
{
Table = NULL;
}
else
{
- Table = MsqGetHooks(Win32Thread->MessageQueue);
+ Table = MsqGetHooks(pti->MessageQueue);
}
if (NULL == Table || ! (Hook = IntGetFirstValidHook(Table, HookId)))
}
}
- if (Hook->Thread != PsGetCurrentThread()
- && (WH_KEYBOARD_LL == HookId || WH_MOUSE_LL == HookId))
- {
- DPRINT("Calling hook in owning thread\n");
- return IntCallLowLevelHook(HookId, Code, wParam, lParam, Hook);
- }
-
if ((Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL))
{
- DPRINT1("Calling hooks in other threads not implemented yet");
- return 0;
+ // Post it in message queue.
+ return IntCallLowLevelHook(Hook, Code, wParam, lParam);
}
Table->Counts[HOOKID_TO_INDEX(HookId)]++;
GlobalHooks->Counts[HOOKID_TO_INDEX(HookId)]++;
}
- Result = co_IntCallHookProc(HookId, Code, wParam, lParam, Hook->Proc,
- Hook->Ansi, &Hook->ModuleName);
+ ClientInfo = GetWin32ClientInfo();
+ SaveHook = ClientInfo->phkCurrent;
+ ClientInfo->phkCurrent = Hook; // Load the call.
+
+ Result = co_IntCallHookProc( HookId,
+ Code,
+ wParam,
+ lParam,
+ Hook->Proc,
+ Hook->Ansi,
+ &Hook->ModuleName);
+
+ ClientInfo->phkCurrent = SaveHook;
Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
KernelMode,
}
else
{
- IntReleaseHookChain(MsqGetHooks(PsGetCurrentThreadWin32Thread()->MessageQueue), HookId, WinStaObj);
+ IntReleaseHookChain(MsqGetHooks(pti->MessageQueue), HookId, WinStaObj);
IntReleaseHookChain(GlobalHooks, HookId, WinStaObj);
ObDereferenceObject(WinStaObj);
}
}
}
+static LRESULT
+FASTCALL
+co_HOOK_CallHookNext(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam)
+{
+ if ((Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL))
+ {
+ DPRINT1("CALLING HOOK from another Thread. %d\n",Hook->HookId);
+ return IntCallLowLevelHook(Hook, Code, wParam, lParam);
+ }
+ DPRINT("CALLING HOOK %d\n",Hook->HookId);
+ return co_IntCallHookProc(Hook->HookId,
+ Code,
+ wParam,
+ lParam,
+ Hook->Proc,
+ Hook->Ansi,
+ &Hook->ModuleName);
+}
+
+
LRESULT
FASTCALL
IntCallDebugHook(
+ PHOOK Hook,
int Code,
WPARAM wParam,
LPARAM lParam)
if (lParam)
{
- _SEH_TRY
+ _SEH2_TRY
{
ProbeForRead((PVOID)lParam,
sizeof(DEBUGHOOKINFO),
(PVOID)lParam,
sizeof(DEBUGHOOKINFO));
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
BadChk = TRUE;
}
- _SEH_END;
+ _SEH2_END;
if (BadChk)
{
DPRINT1("HOOK WH_DEBUG read from lParam ERROR!\n");
if (HooklParam)
{
- _SEH_TRY
+ _SEH2_TRY
{
ProbeForRead((PVOID)Debug.lParam,
Size,
(PVOID)Debug.lParam,
Size);
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
BadChk = TRUE;
}
- _SEH_END;
+ _SEH2_END;
if (BadChk)
{
DPRINT1("HOOK WH_DEBUG read from Debug.lParam ERROR!\n");
}
if (HooklParam) Debug.lParam = (LPARAM)HooklParam;
- lResult = co_HOOK_CallHooks(WH_DEBUG, Code, wParam, (LPARAM)&Debug);
- if (HooklParam) ExFreePool(HooklParam);
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Debug);
+ if (HooklParam) ExFreePoolWithTag(HooklParam, TAG_HOOK);
return lResult;
}
+/*
+ Called from user space via CallNextHook.
+ */
LRESULT
FASTCALL
UserCallNextHookEx(
- int HookId,
+ PHOOK Hook,
int Code,
WPARAM wParam,
LPARAM lParam,
BOOL BadChk = FALSE;
// Handle this one first.
- if ((HookId == WH_MOUSE) || (HookId == WH_CBT && Code == HCBT_CLICKSKIPPED))
+ if ((Hook->HookId == WH_MOUSE) ||
+ (Hook->HookId == WH_CBT && Code == HCBT_CLICKSKIPPED))
{
MOUSEHOOKSTRUCTEX Mouse;
if (lParam)
{
- _SEH_TRY
+ _SEH2_TRY
{
ProbeForRead((PVOID)lParam,
sizeof(MOUSEHOOKSTRUCTEX),
(PVOID)lParam,
sizeof(MOUSEHOOKSTRUCTEX));
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
BadChk = TRUE;
}
- _SEH_END;
+ _SEH2_END;
if (BadChk)
{
DPRINT1("HOOK WH_MOUSE read from lParam ERROR!\n");
}
if (!BadChk)
{
- lResult = co_HOOK_CallHooks(HookId, Code, wParam, (LPARAM)&Mouse);
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Mouse);
}
return lResult;
}
- switch(HookId)
+ switch(Hook->HookId)
{
case WH_MOUSE_LL:
{
MSLLHOOKSTRUCT Mouse;
if (lParam)
{
- _SEH_TRY
+ _SEH2_TRY
{
ProbeForRead((PVOID)lParam,
sizeof(MSLLHOOKSTRUCT),
(PVOID)lParam,
sizeof(MSLLHOOKSTRUCT));
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
BadChk = TRUE;
}
- _SEH_END;
+ _SEH2_END;
if (BadChk)
{
DPRINT1("HOOK WH_MOUSE_LL read from lParam ERROR!\n");
}
if (!BadChk)
{
- lResult = co_HOOK_CallHooks(HookId, Code, wParam, (LPARAM)&Mouse);
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Mouse);
}
break;
}
KBDLLHOOKSTRUCT Keyboard;
if (lParam)
{
- _SEH_TRY
+ _SEH2_TRY
{
ProbeForRead((PVOID)lParam,
sizeof(KBDLLHOOKSTRUCT),
(PVOID)lParam,
sizeof(KBDLLHOOKSTRUCT));
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
BadChk = TRUE;
}
- _SEH_END;
+ _SEH2_END;
if (BadChk)
{
DPRINT1("HOOK WH_KEYBORD_LL read from lParam ERROR!\n");
}
if (!BadChk)
{
- lResult = co_HOOK_CallHooks(HookId, Code, wParam, (LPARAM)&Keyboard);
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Keyboard);
}
break;
}
MSG Msg;
if (lParam)
{
- _SEH_TRY
+ _SEH2_TRY
{
ProbeForRead((PVOID)lParam,
sizeof(MSG),
(PVOID)lParam,
sizeof(MSG));
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
BadChk = TRUE;
}
- _SEH_END;
+ _SEH2_END;
if (BadChk)
{
DPRINT1("HOOK WH_XMESSAGEX read from lParam ERROR!\n");
}
if (!BadChk)
{
- lResult = co_HOOK_CallHooks(HookId, Code, wParam, (LPARAM)&Msg);
- if (lParam && (HookId == WH_GETMESSAGE))
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Msg);
+ if (lParam && (Hook->HookId == WH_GETMESSAGE))
{
- _SEH_TRY
+ _SEH2_TRY
{
ProbeForWrite((PVOID)lParam,
sizeof(MSG),
&Msg,
sizeof(MSG));
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
BadChk = TRUE;
}
- _SEH_END;
+ _SEH2_END;
if (BadChk)
{
DPRINT1("HOOK WH_GETMESSAGE write to lParam ERROR!\n");
}
case WH_CBT:
+ DPRINT1("HOOK WH_CBT!\n");
switch (Code)
{
case HCBT_CREATEWND: // Use Ansi.
- lResult = co_HOOK_CallHooks(HookId, Code, wParam, lParam);
+ DPRINT1("HOOK HCBT_CREATEWND\n");
+// lResult = co_HOOK_CallHookNext(Hook, Code, wParam, lParam);
break;
case HCBT_MOVESIZE:
{
RECT rt;
-
+ DPRINT1("HOOK HCBT_MOVESIZE\n");
if (lParam)
{
- _SEH_TRY
+ _SEH2_TRY
{
ProbeForRead((PVOID)lParam,
sizeof(RECT),
(PVOID)lParam,
sizeof(RECT));
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
BadChk = TRUE;
}
- _SEH_END;
+ _SEH2_END;
if (BadChk)
{
DPRINT1("HOOK HCBT_MOVESIZE read from lParam ERROR!\n");
}
if (!BadChk)
{
- lResult = co_HOOK_CallHooks(HookId, Code, wParam, (LPARAM)&rt);
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&rt);
}
break;
}
case HCBT_ACTIVATE:
{
CBTACTIVATESTRUCT CbAs;
-
+ DPRINT1("HOOK HCBT_ACTIVATE\n");
if (lParam)
{
- _SEH_TRY
+ _SEH2_TRY
{
ProbeForRead((PVOID)lParam,
sizeof(CBTACTIVATESTRUCT),
(PVOID)lParam,
sizeof(CBTACTIVATESTRUCT));
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
BadChk = TRUE;
}
- _SEH_END;
+ _SEH2_END;
if (BadChk)
{
DPRINT1("HOOK HCBT_ACTIVATE read from lParam ERROR!\n");
}
if (!BadChk)
{
- lResult = co_HOOK_CallHooks(HookId, Code, wParam, (LPARAM)&CbAs);
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&CbAs);
}
break;
}
The rest just use default.
*/
default:
- lResult = co_HOOK_CallHooks(HookId, Code, wParam, lParam);
+ DPRINT1("HOOK HCBT_ %d\n",Code);
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, lParam);
break;
}
break;
EVENTMSG EventMsg;
if (lParam)
{
- _SEH_TRY
+ _SEH2_TRY
{
ProbeForRead((PVOID)lParam,
sizeof(EVENTMSG),
(PVOID)lParam,
sizeof(EVENTMSG));
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
BadChk = TRUE;
}
- _SEH_END;
+ _SEH2_END;
if (BadChk)
{
DPRINT1("HOOK WH_JOURNAL read from lParam ERROR!\n");
}
if (!BadChk)
{
- lResult = co_HOOK_CallHooks(HookId, Code, wParam, (LPARAM)(lParam ? &EventMsg : NULL));
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)(lParam ? &EventMsg : NULL));
if (lParam)
{
- _SEH_TRY
+ _SEH2_TRY
{
ProbeForWrite((PVOID)lParam,
sizeof(EVENTMSG),
&EventMsg,
sizeof(EVENTMSG));
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
BadChk = TRUE;
}
- _SEH_END;
+ _SEH2_END;
if (BadChk)
{
DPRINT1("HOOK WH_JOURNAL write to lParam ERROR!\n");
}
case WH_DEBUG:
- lResult = IntCallDebugHook( Code, wParam, lParam);
+ lResult = IntCallDebugHook(Hook, Code, wParam, lParam);
break;
/*
Default the rest like, WH_FOREGROUNDIDLE, WH_KEYBOARD and WH_SHELL.
case WH_FOREGROUNDIDLE:
case WH_KEYBOARD:
case WH_SHELL:
- lResult = co_HOOK_CallHooks(HookId, Code, wParam, lParam);
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, lParam);
break;
default:
- DPRINT1("Unsupported HOOK Id -> %d\n",HookId);
+ DPRINT1("Unsupported HOOK Id -> %d\n",Hook->HookId);
break;
}
return lResult;
}
LRESULT
-STDCALL
+APIENTRY
NtUserCallNextHookEx(
int Code,
WPARAM wParam,
BOOL Ansi)
{
PHOOK HookObj, NextObj;
- PW32CLIENTINFO ClientInfo;
+ PCLIENTINFO ClientInfo;
PWINSTATION_OBJECT WinStaObj;
NTSTATUS Status;
- LRESULT lResult;
- INT HookId;
DECLARE_RETURN(LRESULT);
DPRINT("Enter NtUserCallNextHookEx\n");
KernelMode,
0,
&WinStaObj);
-
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
ClientInfo = GetWin32ClientInfo();
- HookObj = ClientInfo->phkCurrent; // Use this one set from SetWindowHook.
+ if (!ClientInfo) RETURN( 0);
+
+ HookObj = ClientInfo->phkCurrent;
+
+ if (!HookObj) RETURN( 0);
+
+ UserReferenceObject(HookObj);
- HookId = HookObj->HookId;
Ansi = HookObj->Ansi;
if (NULL != HookObj->Thread && (HookObj->Thread != PsGetCurrentThread()))
}
NextObj = IntGetNextHook(HookObj);
+ ClientInfo->phkCurrent = NextObj; // Preset next hook from list.
+ UserCallNextHookEx( HookObj, Code, wParam, lParam, Ansi);
UserDereferenceObject(HookObj);
- if (NULL != NextObj)
- {
- lResult = UserCallNextHookEx( HookId, Code, wParam, lParam, Ansi);
-
- ClientInfo->phkCurrent = NextObj;
-
- if (lResult == 0) RETURN( 0);
- RETURN( (LRESULT)NextObj);
- }
- ClientInfo->phkCurrent = NextObj;
- RETURN( 0);
+ RETURN( (LRESULT)NextObj);
CLEANUP:
DPRINT("Leave NtUserCallNextHookEx, ret=%i\n",_ret_);
}
HHOOK
-STDCALL
+APIENTRY
NtUserSetWindowsHookAW(
int idHook,
HOOKPROC lpfn,
}
HHOOK
-STDCALL
+APIENTRY
NtUserSetWindowsHookEx(
HINSTANCE Mod,
PUNICODE_STRING UnsafeModuleName,
BOOL Ansi)
{
PWINSTATION_OBJECT WinStaObj;
- PW32CLIENTINFO ClientInfo;
+ PCLIENTINFO ClientInfo;
BOOLEAN Global;
PETHREAD Thread;
PHOOK Hook;
DPRINT("Enter NtUserSetWindowsHookEx\n");
UserEnterExclusive();
- if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId || NULL == HookProc)
+ if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId )
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
RETURN( NULL);
}
+ if (!HookProc)
+ {
+ SetLastWin32Error(ERROR_INVALID_FILTER_PROC);
+ RETURN( NULL);
+ }
+
ClientInfo = GetWin32ClientInfo();
if (ThreadId) /* thread-local hook */
}
else if (NULL == Mod)
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD);
RETURN( NULL);
}
else
Global = TRUE;
}
- /* We only (partially) support local WH_CBT hooks and
- * WH_KEYBOARD_LL, WH_MOUSE_LL and WH_GETMESSAGE hooks for now
- */
- if (Global ||
+ if ( ( Global && (HookId != WH_KEYBOARD_LL || HookId != WH_MOUSE_LL) ) ||
WH_DEBUG == HookId ||
WH_JOURNALPLAYBACK == HookId ||
- WH_JOURNALRECORD == HookId ||
- WH_FOREGROUNDIDLE == HookId ||
- WH_SHELL == HookId)
+ WH_JOURNALRECORD == HookId)
{
#if 0 /* Removed to get winEmbed working again */
UNIMPLEMENTED
ModuleName.MaximumLength);
if (! NT_SUCCESS(Status))
{
- ExFreePool(Hook->ModuleName.Buffer);
+ ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK);
UserDereferenceObject(Hook);
IntRemoveHook(Hook, WinStaObj, FALSE);
if (NULL != Thread)
RETURN( NULL);
}
Hook->ModuleName.Length = ModuleName.Length;
+ /* make proc relative to the module base */
+ Hook->Proc = (void *)((char *)HookProc - (char *)Mod);
}
+ else
+ Hook->Proc = HookProc;
- Hook->Proc = HookProc;
Hook->Ansi = Ansi;
Handle = Hook->Self;
-// Set the client threads next hook based on the hooks type.
- ClientInfo->phkCurrent = IntGetNextHook( Hook);
+// Clear the client threads next hook.
+ ClientInfo->phkCurrent = 0;
UserDereferenceObject(Hook);
+
+ if (NULL != Thread)
+ {
+ ObDereferenceObject(Thread);
+ }
ObDereferenceObject(WinStaObj);
RETURN( Handle);
BOOL
-STDCALL
+APIENTRY
NtUserUnhookWindowsHookEx(
HHOOK Hook)
{