2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Window hooks
5 * FILE: subsystem/win32/win32k/ntuser/hook.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * 06-06-2001 CSH Created
9 * NOTE: Most of this code was adapted from Wine,
10 * Copyright (C) 2002 Alexandre Julliard
18 static PHOOKTABLE GlobalHooks
;
21 /* PRIVATE FUNCTIONS *********************************************************/
24 /* create a new hook table */
26 IntAllocHookTable(void)
31 Table
= ExAllocatePoolWithTag(PagedPool
, sizeof(HOOKTABLE
), TAG_HOOK
);
34 for (i
= 0; i
< NB_HOOKS
; i
++)
36 InitializeListHead(&Table
->Hooks
[i
]);
45 PHOOK FASTCALL
IntGetHookObject(HHOOK hHook
)
51 SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE
);
55 Hook
= (PHOOK
)UserGetObject(gHandleTable
, hHook
, otHook
);
58 SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE
);
62 ASSERT(USER_BODY_TO_HEADER(Hook
)->RefCount
>= 0);
64 USER_BODY_TO_HEADER(Hook
)->RefCount
++;
71 /* create a new hook and add it to the specified table */
73 IntAddHook(PETHREAD Thread
, int HookId
, BOOLEAN Global
, PWINSTATION_OBJECT WinStaObj
)
75 PTHREADINFO W32Thread
;
77 PHOOKTABLE Table
= Global
? GlobalHooks
: MsqGetHooks(((PTHREADINFO
)Thread
->Tcb
.Win32Thread
)->MessageQueue
);
82 Table
= IntAllocHookTable();
93 MsqSetHooks(((PTHREADINFO
)Thread
->Tcb
.Win32Thread
)->MessageQueue
, Table
);
97 Hook
= UserCreateObject(gHandleTable
, &Handle
, otHook
, sizeof(HOOK
));
104 Hook
->Thread
= Thread
;
105 Hook
->HookId
= HookId
;
109 W32Thread
= ((PTHREADINFO
)Thread
->Tcb
.Win32Thread
);
110 ASSERT(W32Thread
!= NULL
);
111 W32Thread
->Hooks
|= HOOKID_TO_FLAG(HookId
);
112 if (W32Thread
->ThreadInfo
!= NULL
)
113 W32Thread
->ThreadInfo
->Hooks
= W32Thread
->Hooks
;
116 RtlInitUnicodeString(&Hook
->ModuleName
, NULL
);
118 InsertHeadList(&Table
->Hooks
[HOOKID_TO_INDEX(HookId
)], &Hook
->Chain
);
123 /* get the hook table that a given hook belongs to */
124 static PHOOKTABLE FASTCALL
125 IntGetTable(PHOOK Hook
)
127 if (NULL
== Hook
->Thread
|| WH_KEYBOARD_LL
== Hook
->HookId
||
128 WH_MOUSE_LL
== Hook
->HookId
)
133 return MsqGetHooks(((PTHREADINFO
)Hook
->Thread
->Tcb
.Win32Thread
)->MessageQueue
);
136 /* get the first hook in the chain */
137 static PHOOK FASTCALL
138 IntGetFirstHook(PHOOKTABLE Table
, int HookId
)
140 PLIST_ENTRY Elem
= Table
->Hooks
[HOOKID_TO_INDEX(HookId
)].Flink
;
141 return Elem
== &Table
->Hooks
[HOOKID_TO_INDEX(HookId
)]
142 ? NULL
: CONTAINING_RECORD(Elem
, HOOK
, Chain
);
145 /* find the first non-deleted hook in the chain */
146 static PHOOK FASTCALL
147 IntGetFirstValidHook(PHOOKTABLE Table
, int HookId
)
152 Hook
= IntGetFirstHook(Table
, HookId
);
153 while (NULL
!= Hook
&& NULL
== Hook
->Proc
)
155 Elem
= Hook
->Chain
.Flink
;
156 Hook
= (Elem
== &Table
->Hooks
[HOOKID_TO_INDEX(HookId
)]
157 ? NULL
: CONTAINING_RECORD(Elem
, HOOK
, Chain
));
163 /* find the next hook in the chain, skipping the deleted ones */
166 IntGetNextHook(PHOOK Hook
)
168 PHOOKTABLE Table
= IntGetTable(Hook
);
169 int HookId
= Hook
->HookId
;
172 Elem
= Hook
->Chain
.Flink
;
173 while (Elem
!= &Table
->Hooks
[HOOKID_TO_INDEX(HookId
)])
175 Hook
= CONTAINING_RECORD(Elem
, HOOK
, Chain
);
176 if (NULL
!= Hook
->Proc
)
182 if (NULL
!= GlobalHooks
&& Table
!= GlobalHooks
) /* now search through the global table */
184 return IntGetFirstValidHook(GlobalHooks
, HookId
);
190 /* free a hook, removing it from its chain */
192 IntFreeHook(PHOOKTABLE Table
, PHOOK Hook
, PWINSTATION_OBJECT WinStaObj
)
194 RemoveEntryList(&Hook
->Chain
);
195 RtlFreeUnicodeString(&Hook
->ModuleName
);
197 /* Dereference thread if required */
198 if (Hook
->Flags
& HOOK_THREAD_REFERENCED
)
200 ObDereferenceObject(Hook
->Thread
);
204 UserDeleteObject(Hook
->Self
, otHook
);
207 /* remove a hook, freeing it if the chain is not in use */
209 IntRemoveHook(PHOOK Hook
, PWINSTATION_OBJECT WinStaObj
, BOOL TableAlreadyLocked
)
211 PTHREADINFO W32Thread
;
212 PHOOKTABLE Table
= IntGetTable(Hook
);
214 ASSERT(NULL
!= Table
);
220 W32Thread
= ((PTHREADINFO
)Hook
->Thread
->Tcb
.Win32Thread
);
221 ASSERT(W32Thread
!= NULL
);
222 W32Thread
->Hooks
&= ~HOOKID_TO_FLAG(Hook
->HookId
);
223 if (W32Thread
->ThreadInfo
!= NULL
)
224 W32Thread
->ThreadInfo
->Hooks
= W32Thread
->Hooks
;
226 if (0 != Table
->Counts
[HOOKID_TO_INDEX(Hook
->HookId
)])
228 Hook
->Proc
= NULL
; /* chain is in use, just mark it and return */
232 IntFreeHook(Table
, Hook
, WinStaObj
);
236 /* release a hook chain, removing deleted hooks if the use count drops to 0 */
238 IntReleaseHookChain(PHOOKTABLE Table
, int HookId
, PWINSTATION_OBJECT WinStaObj
)
248 /* use count shouldn't already be 0 */
249 ASSERT(0 != Table
->Counts
[HOOKID_TO_INDEX(HookId
)]);
250 if (0 == Table
->Counts
[HOOKID_TO_INDEX(HookId
)])
254 if (0 == --Table
->Counts
[HOOKID_TO_INDEX(HookId
)])
256 Elem
= Table
->Hooks
[HOOKID_TO_INDEX(HookId
)].Flink
;
257 while (Elem
!= &Table
->Hooks
[HOOKID_TO_INDEX(HookId
)])
259 HookObj
= CONTAINING_RECORD(Elem
, HOOK
, Chain
);
261 if (NULL
== HookObj
->Proc
)
263 IntFreeHook(Table
, HookObj
, WinStaObj
);
269 static LRESULT FASTCALL
270 IntCallLowLevelHook(PHOOK Hook
, INT Code
, WPARAM wParam
, LPARAM lParam
)
275 /* FIXME should get timeout from
276 * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
277 Status
= co_MsqSendMessage(((PTHREADINFO
)Hook
->Thread
->Tcb
.Win32Thread
)->MessageQueue
,
278 (HWND
)(UINT_PTR
)Code
,
287 return NT_SUCCESS(Status
) ? uResult
: 0;
291 Called from inside kernel space.
295 co_HOOK_CallHooks(INT HookId
, INT Code
, WPARAM wParam
, LPARAM lParam
)
297 PHOOK Hook
, SaveHook
;
299 PCLIENTINFO ClientInfo
;
302 PWINSTATION_OBJECT WinStaObj
;
305 ASSERT(WH_MINHOOK
<= HookId
&& HookId
<= WH_MAXHOOK
);
307 pti
= PsGetCurrentThreadWin32Thread();
314 Table
= MsqGetHooks(pti
->MessageQueue
);
317 if (NULL
== Table
|| ! (Hook
= IntGetFirstValidHook(Table
, HookId
)))
319 /* try global table */
321 if (NULL
== Table
|| ! (Hook
= IntGetFirstValidHook(Table
, HookId
)))
323 return 0; /* no hook set */
327 if ((Hook
->Thread
!= PsGetCurrentThread()) && (Hook
->Thread
!= NULL
))
329 // Post it in message queue.
330 return IntCallLowLevelHook(Hook
, Code
, wParam
, lParam
);
333 Table
->Counts
[HOOKID_TO_INDEX(HookId
)]++;
334 if (Table
!= GlobalHooks
&& GlobalHooks
!= NULL
)
336 GlobalHooks
->Counts
[HOOKID_TO_INDEX(HookId
)]++;
339 ClientInfo
= GetWin32ClientInfo();
340 SaveHook
= ClientInfo
->phkCurrent
;
341 ClientInfo
->phkCurrent
= Hook
; // Load the call.
343 Result
= co_IntCallHookProc( HookId
,
351 ClientInfo
->phkCurrent
= SaveHook
;
353 Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
358 if (! NT_SUCCESS(Status
))
360 DPRINT1("Invalid window station????\n");
364 IntReleaseHookChain(MsqGetHooks(pti
->MessageQueue
), HookId
, WinStaObj
);
365 IntReleaseHookChain(GlobalHooks
, HookId
, WinStaObj
);
366 ObDereferenceObject(WinStaObj
);
373 HOOK_DestroyThreadHooks(PETHREAD Thread
)
378 PWINSTATION_OBJECT WinStaObj
;
381 if (NULL
!= GlobalHooks
)
383 Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
388 if (! NT_SUCCESS(Status
))
390 DPRINT1("Invalid window station????\n");
394 for (HookId
= WH_MINHOOK
; HookId
<= WH_MAXHOOK
; HookId
++)
396 /* only low-level keyboard/mouse global hooks can be owned by a thread */
401 Elem
= GlobalHooks
->Hooks
[HOOKID_TO_INDEX(HookId
)].Flink
;
402 while (Elem
!= &GlobalHooks
->Hooks
[HOOKID_TO_INDEX(HookId
)])
404 HookObj
= CONTAINING_RECORD(Elem
, HOOK
, Chain
);
406 if (HookObj
->Thread
== Thread
)
408 IntRemoveHook(HookObj
, WinStaObj
, TRUE
);
419 co_HOOK_CallHookNext(PHOOK Hook
, INT Code
, WPARAM wParam
, LPARAM lParam
)
421 if ((Hook
->Thread
!= PsGetCurrentThread()) && (Hook
->Thread
!= NULL
))
423 DPRINT1("CALLING HOOK from another Thread. %d\n",Hook
->HookId
);
424 return IntCallLowLevelHook(Hook
, Code
, wParam
, lParam
);
426 DPRINT("CALLING HOOK %d\n",Hook
->HookId
);
427 return co_IntCallHookProc(Hook
->HookId
,
448 PVOID HooklParam
= NULL
;
455 ProbeForRead((PVOID
)lParam
,
456 sizeof(DEBUGHOOKINFO
),
458 RtlCopyMemory( &Debug
,
460 sizeof(DEBUGHOOKINFO
));
469 DPRINT1("HOOK WH_DEBUG read from lParam ERROR!\n");
474 return lResult
; // Need lParam!
482 case HCBT_CLICKSKIPPED
:
483 Size
= sizeof(MOUSEHOOKSTRUCTEX
);
489 Size
= sizeof(CBTACTIVATESTRUCT
);
491 case HCBT_CREATEWND
: // Handle Ansi?
492 Size
= sizeof(CBT_CREATEWND
);
493 // What shall we do? Size += sizeof(CREATESTRUCTEX);
496 Size
= sizeof(LPARAM
);
502 Size
= sizeof(MSLLHOOKSTRUCT
);
506 Size
= sizeof(KBDLLHOOKSTRUCT
);
510 case WH_SYSMSGFILTER
:
515 case WH_JOURNALPLAYBACK
:
516 case WH_JOURNALRECORD
:
517 Size
= sizeof(EVENTMSG
);
520 case WH_FOREGROUNDIDLE
:
524 Size
= sizeof(LPARAM
);
527 if (Size
> sizeof(LPARAM
))
528 HooklParam
= ExAllocatePoolWithTag(NonPagedPool
, Size
, TAG_HOOK
);
534 ProbeForRead((PVOID
)Debug
.lParam
,
537 RtlCopyMemory( HooklParam
,
548 DPRINT1("HOOK WH_DEBUG read from Debug.lParam ERROR!\n");
549 ExFreePool(HooklParam
);
554 if (HooklParam
) Debug
.lParam
= (LPARAM
)HooklParam
;
555 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, (LPARAM
)&Debug
);
556 if (HooklParam
) ExFreePool(HooklParam
);
561 Called from user space via CallNextHook.
575 // Handle this one first.
576 if ((Hook
->HookId
== WH_MOUSE
) ||
577 (Hook
->HookId
== WH_CBT
&& Code
== HCBT_CLICKSKIPPED
))
579 MOUSEHOOKSTRUCTEX Mouse
;
584 ProbeForRead((PVOID
)lParam
,
585 sizeof(MOUSEHOOKSTRUCTEX
),
587 RtlCopyMemory( &Mouse
,
589 sizeof(MOUSEHOOKSTRUCTEX
));
598 DPRINT1("HOOK WH_MOUSE read from lParam ERROR!\n");
603 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, (LPARAM
)&Mouse
);
612 MSLLHOOKSTRUCT Mouse
;
617 ProbeForRead((PVOID
)lParam
,
618 sizeof(MSLLHOOKSTRUCT
),
620 RtlCopyMemory( &Mouse
,
622 sizeof(MSLLHOOKSTRUCT
));
631 DPRINT1("HOOK WH_MOUSE_LL read from lParam ERROR!\n");
636 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, (LPARAM
)&Mouse
);
643 KBDLLHOOKSTRUCT Keyboard
;
648 ProbeForRead((PVOID
)lParam
,
649 sizeof(KBDLLHOOKSTRUCT
),
651 RtlCopyMemory( &Keyboard
,
653 sizeof(KBDLLHOOKSTRUCT
));
662 DPRINT1("HOOK WH_KEYBORD_LL read from lParam ERROR!\n");
667 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, (LPARAM
)&Keyboard
);
673 case WH_SYSMSGFILTER
:
681 ProbeForRead((PVOID
)lParam
,
695 DPRINT1("HOOK WH_XMESSAGEX read from lParam ERROR!\n");
700 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, (LPARAM
)&Msg
);
701 if (lParam
&& (Hook
->HookId
== WH_GETMESSAGE
))
705 ProbeForWrite((PVOID
)lParam
,
708 RtlCopyMemory((PVOID
)lParam
,
719 DPRINT1("HOOK WH_GETMESSAGE write to lParam ERROR!\n");
727 DPRINT1("HOOK WH_CBT!\n");
730 case HCBT_CREATEWND
: // Use Ansi.
731 DPRINT1("HOOK HCBT_CREATEWND\n");
732 // lResult = co_HOOK_CallHookNext(Hook, Code, wParam, lParam);
738 DPRINT1("HOOK HCBT_MOVESIZE\n");
743 ProbeForRead((PVOID
)lParam
,
757 DPRINT1("HOOK HCBT_MOVESIZE read from lParam ERROR!\n");
762 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, (LPARAM
)&rt
);
769 CBTACTIVATESTRUCT CbAs
;
770 DPRINT1("HOOK HCBT_ACTIVATE\n");
775 ProbeForRead((PVOID
)lParam
,
776 sizeof(CBTACTIVATESTRUCT
),
778 RtlCopyMemory( &CbAs
,
780 sizeof(CBTACTIVATESTRUCT
));
789 DPRINT1("HOOK HCBT_ACTIVATE read from lParam ERROR!\n");
794 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, (LPARAM
)&CbAs
);
799 The rest just use default.
802 DPRINT1("HOOK HCBT_ %d\n",Code
);
803 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, lParam
);
808 case WH_JOURNALPLAYBACK
:
809 case WH_JOURNALRECORD
:
816 ProbeForRead((PVOID
)lParam
,
819 RtlCopyMemory( &EventMsg
,
830 DPRINT1("HOOK WH_JOURNAL read from lParam ERROR!\n");
835 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, (LPARAM
)(lParam
? &EventMsg
: NULL
));
840 ProbeForWrite((PVOID
)lParam
,
843 RtlCopyMemory((PVOID
)lParam
,
854 DPRINT1("HOOK WH_JOURNAL write to lParam ERROR!\n");
862 lResult
= IntCallDebugHook(Hook
, Code
, wParam
, lParam
);
865 Default the rest like, WH_FOREGROUNDIDLE, WH_KEYBOARD and WH_SHELL.
867 case WH_FOREGROUNDIDLE
:
870 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, lParam
);
874 DPRINT1("Unsupported HOOK Id -> %d\n",Hook
->HookId
);
882 NtUserCallNextHookEx(
888 PHOOK HookObj
, NextObj
;
889 PCLIENTINFO ClientInfo
;
890 PWINSTATION_OBJECT WinStaObj
;
892 DECLARE_RETURN(LRESULT
);
894 DPRINT("Enter NtUserCallNextHookEx\n");
895 UserEnterExclusive();
897 Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
901 if (!NT_SUCCESS(Status
))
903 SetLastNtError(Status
);
907 ObDereferenceObject(WinStaObj
);
909 ClientInfo
= GetWin32ClientInfo();
911 if (!ClientInfo
) RETURN( 0);
913 HookObj
= ClientInfo
->phkCurrent
;
915 if (!HookObj
) RETURN( 0);
917 UserReferenceObject(HookObj
);
919 Ansi
= HookObj
->Ansi
;
921 if (NULL
!= HookObj
->Thread
&& (HookObj
->Thread
!= PsGetCurrentThread()))
923 DPRINT1("Thread mismatch\n");
924 UserDereferenceObject(HookObj
);
925 SetLastWin32Error(ERROR_INVALID_HANDLE
);
929 NextObj
= IntGetNextHook(HookObj
);
930 ClientInfo
->phkCurrent
= NextObj
; // Preset next hook from list.
931 UserCallNextHookEx( HookObj
, Code
, wParam
, lParam
, Ansi
);
932 UserDereferenceObject(HookObj
);
934 RETURN( (LRESULT
)NextObj
);
937 DPRINT("Leave NtUserCallNextHookEx, ret=%i\n",_ret_
);
944 NtUserSetWindowsHookAW(
949 UNICODE_STRING USModuleName
;
950 RtlInitUnicodeString(&USModuleName
, NULL
);
951 return NtUserSetWindowsHookEx(NULL
, &USModuleName
, 0, idHook
, lpfn
, Ansi
);
956 NtUserSetWindowsHookEx(
958 PUNICODE_STRING UnsafeModuleName
,
964 PWINSTATION_OBJECT WinStaObj
;
965 PCLIENTINFO ClientInfo
;
969 UNICODE_STRING ModuleName
;
972 DECLARE_RETURN(HHOOK
);
974 DPRINT("Enter NtUserSetWindowsHookEx\n");
975 UserEnterExclusive();
977 if (HookId
< WH_MINHOOK
|| WH_MAXHOOK
< HookId
)
979 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
985 SetLastWin32Error(ERROR_INVALID_FILTER_PROC
);
989 ClientInfo
= GetWin32ClientInfo();
991 if (ThreadId
) /* thread-local hook */
993 if (HookId
== WH_JOURNALRECORD
||
994 HookId
== WH_JOURNALPLAYBACK
||
995 HookId
== WH_KEYBOARD_LL
||
996 HookId
== WH_MOUSE_LL
||
997 HookId
== WH_SYSMSGFILTER
)
999 /* these can only be global */
1000 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1005 if (! NT_SUCCESS(PsLookupThreadByThreadId((HANDLE
)(DWORD_PTR
)ThreadId
, &Thread
)))
1007 DPRINT1("Invalid thread id 0x%x\n", ThreadId
);
1008 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1011 if (Thread
->ThreadsProcess
!= PsGetCurrentProcess())
1013 ObDereferenceObject(Thread
);
1014 DPRINT1("Can't specify thread belonging to another process\n");
1015 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1019 else /* system-global hook */
1021 if (HookId
== WH_KEYBOARD_LL
|| HookId
== WH_MOUSE_LL
)
1024 Thread
= PsGetCurrentThread();
1025 Status
= ObReferenceObjectByPointer(Thread
,
1030 if (! NT_SUCCESS(Status
))
1032 SetLastNtError(Status
);
1033 RETURN( (HANDLE
) NULL
);
1036 else if (NULL
== Mod
)
1038 SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD
);
1048 if ( ( Global
&& (HookId
!= WH_KEYBOARD_LL
|| HookId
!= WH_MOUSE_LL
) ) ||
1049 WH_DEBUG
== HookId
||
1050 WH_JOURNALPLAYBACK
== HookId
||
1051 WH_JOURNALRECORD
== HookId
)
1053 #if 0 /* Removed to get winEmbed working again */
1056 DPRINT1("Not implemented: HookId %d Global %s\n", HookId
, Global
? "TRUE" : "FALSE");
1061 ObDereferenceObject(Thread
);
1063 SetLastWin32Error(ERROR_NOT_SUPPORTED
);
1067 Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
1072 if (! NT_SUCCESS(Status
))
1076 ObDereferenceObject(Thread
);
1078 SetLastNtError(Status
);
1079 RETURN( (HANDLE
) NULL
);
1082 Hook
= IntAddHook(Thread
, HookId
, Global
, WinStaObj
);
1087 ObDereferenceObject(Thread
);
1089 ObDereferenceObject(WinStaObj
);
1095 Hook
->Flags
|= HOOK_THREAD_REFERENCED
;
1100 Status
= MmCopyFromCaller(&ModuleName
, UnsafeModuleName
, sizeof(UNICODE_STRING
));
1101 if (! NT_SUCCESS(Status
))
1103 UserDereferenceObject(Hook
);
1104 IntRemoveHook(Hook
, WinStaObj
, FALSE
);
1107 ObDereferenceObject(Thread
);
1109 ObDereferenceObject(WinStaObj
);
1110 SetLastNtError(Status
);
1113 Hook
->ModuleName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
1114 ModuleName
.MaximumLength
,
1116 if (NULL
== Hook
->ModuleName
.Buffer
)
1118 UserDereferenceObject(Hook
);
1119 IntRemoveHook(Hook
, WinStaObj
, FALSE
);
1122 ObDereferenceObject(Thread
);
1124 ObDereferenceObject(WinStaObj
);
1125 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1128 Hook
->ModuleName
.MaximumLength
= ModuleName
.MaximumLength
;
1129 Status
= MmCopyFromCaller(Hook
->ModuleName
.Buffer
,
1131 ModuleName
.MaximumLength
);
1132 if (! NT_SUCCESS(Status
))
1134 ExFreePool(Hook
->ModuleName
.Buffer
);
1135 UserDereferenceObject(Hook
);
1136 IntRemoveHook(Hook
, WinStaObj
, FALSE
);
1139 ObDereferenceObject(Thread
);
1141 ObDereferenceObject(WinStaObj
);
1142 SetLastNtError(Status
);
1145 Hook
->ModuleName
.Length
= ModuleName
.Length
;
1146 /* make proc relative to the module base */
1147 Hook
->Proc
= (void *)((char *)HookProc
- (char *)Mod
);
1150 Hook
->Proc
= HookProc
;
1153 Handle
= Hook
->Self
;
1155 // Clear the client threads next hook.
1156 ClientInfo
->phkCurrent
= 0;
1158 UserDereferenceObject(Hook
);
1159 ObDereferenceObject(WinStaObj
);
1164 DPRINT("Leave NtUserSetWindowsHookEx, ret=%i\n",_ret_
);
1172 NtUserUnhookWindowsHookEx(
1175 PWINSTATION_OBJECT WinStaObj
;
1178 DECLARE_RETURN(BOOL
);
1180 DPRINT("Enter NtUserUnhookWindowsHookEx\n");
1181 UserEnterExclusive();
1183 Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
1188 if (! NT_SUCCESS(Status
))
1190 SetLastNtError(Status
);
1194 // Status = UserReferenceObjectByHandle(gHandleTable, Hook,
1195 // otHookProc, (PVOID *) &HookObj);
1196 if (!(HookObj
= IntGetHookObject(Hook
)))
1198 DPRINT1("Invalid handle passed to NtUserUnhookWindowsHookEx\n");
1199 ObDereferenceObject(WinStaObj
);
1200 // SetLastNtError(Status);
1203 ASSERT(Hook
== HookObj
->Self
);
1205 IntRemoveHook(HookObj
, WinStaObj
, FALSE
);
1207 UserDereferenceObject(HookObj
);
1208 ObDereferenceObject(WinStaObj
);
1213 DPRINT("Leave NtUserUnhookWindowsHookEx, ret=%i\n",_ret_
);