2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Window hooks
5 * FILE: subsystems/win32/win32k/ntuser/hook.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * James Tabor (james.tabor@rectos.org)
10 * 06-06-2001 CSH Created
11 * NOTE: Most of this code was adapted from Wine,
12 * Copyright (C) 2002 Alexandre Julliard
20 typedef struct _HOOKPACK
24 } HOOKPACK
, *PHOOKPACK
;
26 /* PRIVATE FUNCTIONS *********************************************************/
31 IntCallLowLevelHook( PHOOK Hook
,
39 ULONG_PTR uResult
= 0;
42 pti
= Hook
->Thread
->Tcb
.Win32Thread
;
46 pHP
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(HOOKPACK
), TAG_HOOK
);
52 /* FIXME should get timeout from
53 * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
54 Status
= co_MsqSendMessage( pti
->MessageQueue
,
55 IntToPtr(Code
), // hWnd
63 if (!NT_SUCCESS(Status
))
65 DPRINT1("Error Hook Call SendMsg. %d Status: 0x%x\n", Hook
->HookId
, Status
);
66 ExFreePoolWithTag(pHP
, TAG_HOOK
);
68 return NT_SUCCESS(Status
) ? uResult
: 0;
74 co_HOOK_CallHookNext( PHOOK Hook
,
79 if ( (Hook
->Thread
!= PsGetCurrentThread()) && (Hook
->Thread
!= NULL
) )
81 DPRINT1("Calling Next HOOK from another Thread. %d\n", Hook
->HookId
);
82 return IntCallLowLevelHook(Hook
, Code
, wParam
, lParam
);
85 DPRINT("Calling Next HOOK %d\n", Hook
->HookId
);
87 return co_IntCallHookProc( Hook
->HookId
,
97 // Dispatch MsgQueue Hook Call processor!
101 co_CallHook( INT HookId
,
108 PHOOKPACK pHP
= (PHOOKPACK
)lParam
;
111 /* The odds are high for this to be a Global call. */
112 Result
= co_IntCallHookProc( HookId
,
120 ExFreePoolWithTag(pHP
, TAG_HOOK
);
126 IntCallDebugHook( PHOOK Hook
,
135 PVOID HooklParam
= NULL
;
142 ProbeForRead((PVOID
)lParam
,
143 sizeof(DEBUGHOOKINFO
),
146 RtlCopyMemory(&Debug
,
148 sizeof(DEBUGHOOKINFO
));
150 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
158 DPRINT1("HOOK WH_DEBUG read from lParam ERROR!\n");
163 return lResult
; /* Need lParam! */
171 case HCBT_CLICKSKIPPED
:
172 Size
= sizeof(MOUSEHOOKSTRUCTEX
);
180 Size
= sizeof(CBTACTIVATESTRUCT
);
183 case HCBT_CREATEWND
: /* Handle Ansi? */
184 Size
= sizeof(CBT_CREATEWND
);
185 /* What shall we do? Size += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS); same as CREATESTRUCTEX */
189 Size
= sizeof(LPARAM
);
195 Size
= sizeof(MSLLHOOKSTRUCT
);
199 Size
= sizeof(KBDLLHOOKSTRUCT
);
203 case WH_SYSMSGFILTER
:
208 case WH_JOURNALPLAYBACK
:
209 case WH_JOURNALRECORD
:
210 Size
= sizeof(EVENTMSG
);
213 case WH_FOREGROUNDIDLE
:
217 Size
= sizeof(LPARAM
);
220 if (Size
> sizeof(LPARAM
))
221 HooklParam
= ExAllocatePoolWithTag(NonPagedPool
, Size
, TAG_HOOK
);
227 ProbeForRead((PVOID
)Debug
.lParam
,
231 RtlCopyMemory(HooklParam
,
235 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
243 DPRINT1("HOOK WH_DEBUG read from Debug.lParam ERROR!\n");
244 ExFreePool(HooklParam
);
249 if (HooklParam
) Debug
.lParam
= (LPARAM
)HooklParam
;
250 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, (LPARAM
)&Debug
);
251 if (HooklParam
) ExFreePoolWithTag(HooklParam
, TAG_HOOK
);
258 UserCallNextHookEx( PHOOK Hook
,
267 /* Handle this one first. */
268 if ((Hook
->HookId
== WH_MOUSE
) ||
269 (Hook
->HookId
== WH_CBT
&& Code
== HCBT_CLICKSKIPPED
))
271 MOUSEHOOKSTRUCTEX Mouse
;
276 ProbeForRead((PVOID
)lParam
,
277 sizeof(MOUSEHOOKSTRUCTEX
),
280 RtlCopyMemory(&Mouse
,
282 sizeof(MOUSEHOOKSTRUCTEX
));
284 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
292 DPRINT1("HOOK WH_MOUSE read from lParam ERROR!\n");
298 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, (LPARAM
)&Mouse
);
308 MSLLHOOKSTRUCT Mouse
;
314 ProbeForRead((PVOID
)lParam
,
315 sizeof(MSLLHOOKSTRUCT
),
318 RtlCopyMemory(&Mouse
,
320 sizeof(MSLLHOOKSTRUCT
));
322 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
330 DPRINT1("HOOK WH_MOUSE_LL read from lParam ERROR!\n");
336 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, (LPARAM
)&Mouse
);
343 KBDLLHOOKSTRUCT Keyboard
;
349 ProbeForRead((PVOID
)lParam
,
350 sizeof(KBDLLHOOKSTRUCT
),
353 RtlCopyMemory(&Keyboard
,
355 sizeof(KBDLLHOOKSTRUCT
));
357 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
365 DPRINT1("HOOK WH_KEYBORD_LL read from lParam ERROR!\n");
371 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, (LPARAM
)&Keyboard
);
377 case WH_SYSMSGFILTER
:
386 ProbeForRead((PVOID
)lParam
,
394 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
402 DPRINT1("HOOK WH_XMESSAGEX read from lParam ERROR!\n");
408 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, (LPARAM
)&Msg
);
410 if (lParam
&& (Hook
->HookId
== WH_GETMESSAGE
))
414 ProbeForWrite((PVOID
)lParam
,
418 RtlCopyMemory((PVOID
)lParam
,
422 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
430 DPRINT1("HOOK WH_GETMESSAGE write to lParam ERROR!\n");
438 DPRINT("HOOK WH_CBT!\n");
443 LPCBT_CREATEWNDW pcbtcww
= (LPCBT_CREATEWNDW
)lParam
;
445 DPRINT("HOOK HCBT_CREATEWND\n");
450 ProbeForRead( pcbtcww
,
451 sizeof(CBT_CREATEWNDA
),
453 ProbeForWrite(pcbtcww
->lpcs
,
454 sizeof(CREATESTRUCTA
),
456 ProbeForRead( pcbtcww
->lpcs
->lpszName
,
460 if (!IS_ATOM(pcbtcww
->lpcs
->lpszClass
))
462 ProbeForRead( pcbtcww
->lpcs
->lpszClass
,
469 ProbeForRead( pcbtcww
,
470 sizeof(CBT_CREATEWNDW
),
472 ProbeForWrite(pcbtcww
->lpcs
,
473 sizeof(CREATESTRUCTW
),
475 ProbeForRead( pcbtcww
->lpcs
->lpszName
,
479 if (!IS_ATOM(pcbtcww
->lpcs
->lpszClass
))
481 ProbeForRead( pcbtcww
->lpcs
->lpszClass
,
487 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
495 DPRINT1("HOOK HCBT_CREATEWND write ERROR!\n");
497 /* The next call handles the structures. */
498 if (!BadChk
&& Hook
->Proc
)
500 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, lParam
);
509 DPRINT("HOOK HCBT_MOVESIZE\n");
515 ProbeForRead((PVOID
)lParam
,
523 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
531 DPRINT1("HOOK HCBT_MOVESIZE read from lParam ERROR!\n");
537 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, (LPARAM
)&rt
);
544 CBTACTIVATESTRUCT CbAs
;
546 DPRINT("HOOK HCBT_ACTIVATE\n");
551 ProbeForRead((PVOID
)lParam
,
552 sizeof(CBTACTIVATESTRUCT
),
557 sizeof(CBTACTIVATESTRUCT
));
559 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
567 DPRINT1("HOOK HCBT_ACTIVATE read from lParam ERROR!\n");
573 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, (LPARAM
)&CbAs
);
578 /* The rest just use default. */
580 DPRINT("HOOK HCBT_ %d\n",Code
);
581 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, lParam
);
586 case WH_JOURNALPLAYBACK
:
587 case WH_JOURNALRECORD
:
595 ProbeForRead((PVOID
)lParam
,
599 RtlCopyMemory(&EventMsg
,
603 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
611 DPRINT1("HOOK WH_JOURNAL read from lParam ERROR!\n");
617 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, (LPARAM
)(lParam
? &EventMsg
: NULL
));
623 ProbeForWrite((PVOID
)lParam
,
627 RtlCopyMemory((PVOID
)lParam
,
631 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
639 DPRINT1("HOOK WH_JOURNAL write to lParam ERROR!\n");
647 lResult
= IntCallDebugHook(Hook
, Code
, wParam
, lParam
, Ansi
);
651 * Default the rest like, WH_FOREGROUNDIDLE, WH_KEYBOARD and WH_SHELL.
653 case WH_FOREGROUNDIDLE
:
656 lResult
= co_HOOK_CallHookNext(Hook
, Code
, wParam
, lParam
);
660 DPRINT1("Unsupported HOOK Id -> %d\n",Hook
->HookId
);
663 if (Hook
->HookId
== WH_JOURNALPLAYBACK
&& lResult
== 0)
670 IntGetHookObject(HHOOK hHook
)
676 SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE
);
680 Hook
= (PHOOK
)UserGetObject(gHandleTable
, hHook
, otHook
);
683 SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE
);
687 UserReferenceObject(Hook
);
692 /* get the first hook in the chain */
696 IntGetFirstHook(PLIST_ENTRY Table
)
698 PLIST_ENTRY Elem
= Table
->Flink
;
700 if (IsListEmpty(Table
)) return NULL
;
702 return Elem
== Table
? NULL
: CONTAINING_RECORD(Elem
, HOOK
, Chain
);
705 /* find the next hook in the chain */
708 IntGetNextHook(PHOOK Hook
)
710 int HookId
= Hook
->HookId
;
716 pti
= ((PTHREADINFO
)Hook
->Thread
->Tcb
.Win32Thread
);
718 Elem
= Hook
->Chain
.Flink
;
719 if (Elem
!= &pti
->aphkStart
[HOOKID_TO_INDEX(HookId
)])
720 return CONTAINING_RECORD(Elem
, HOOK
, Chain
);
724 pti
= PsGetCurrentThreadWin32Thread();
726 Elem
= Hook
->Chain
.Flink
;
727 if (Elem
!= &pti
->pDeskInfo
->aphkStart
[HOOKID_TO_INDEX(HookId
)])
728 return CONTAINING_RECORD(Elem
, HOOK
, Chain
);
733 /* free a hook, removing it from its chain */
737 IntFreeHook(PHOOK Hook
)
739 RemoveEntryList(&Hook
->Chain
);
740 if (Hook
->ModuleName
.Buffer
)
742 ExFreePoolWithTag(Hook
->ModuleName
.Buffer
, TAG_HOOK
);
743 Hook
->ModuleName
.Buffer
= NULL
;
746 UserDeleteObject(UserHMGetHandle(Hook
), otHook
);
749 /* remove a hook, freeing it from the chain */
753 IntRemoveHook(PHOOK Hook
)
758 HookId
= Hook
->HookId
;
760 if (Hook
->Thread
) // Local
762 pti
= ((PTHREADINFO
)Hook
->Thread
->Tcb
.Win32Thread
);
766 if ( IsListEmpty(&pti
->aphkStart
[HOOKID_TO_INDEX(HookId
)]) )
768 pti
->fsHooks
&= ~HOOKID_TO_FLAG(HookId
);
771 GetWin32ClientInfo()->fsHooks
= pti
->fsHooks
;
773 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
784 pti
= PsGetCurrentThreadWin32Thread();
786 if ( pti
->pDeskInfo
&&
787 IsListEmpty(&pti
->pDeskInfo
->aphkStart
[HOOKID_TO_INDEX(HookId
)]) )
789 pti
->pDeskInfo
->fsHooks
&= ~HOOKID_TO_FLAG(HookId
);
798 HOOK_DestroyThreadHooks(PETHREAD Thread
)
805 pti
= Thread
->Tcb
.Win32Thread
;
806 if (!pti
|| !pti
->pDeskInfo
) return;
808 // Local Thread cleanup.
811 for (HookId
= WH_MINHOOK
; HookId
<= WH_MAXHOOK
; HookId
++)
813 PLIST_ENTRY pLLE
= &pti
->aphkStart
[HOOKID_TO_INDEX(HookId
)];
815 if (IsListEmpty(pLLE
)) continue;
818 HookObj
= CONTAINING_RECORD(pElem
, HOOK
, Chain
);
822 if (IntRemoveHook(HookObj
)) break;
823 pElem
= HookObj
->Chain
.Flink
;
824 HookObj
= CONTAINING_RECORD(pElem
, HOOK
, Chain
);
826 while (pElem
!= pLLE
);
830 // Global search based on Thread and cleanup.
831 if (pti
->pDeskInfo
->fsHooks
)
833 for (HookId
= WH_MINHOOK
; HookId
<= WH_MAXHOOK
; HookId
++)
835 PLIST_ENTRY pGLE
= &pti
->pDeskInfo
->aphkStart
[HOOKID_TO_INDEX(HookId
)];
837 if (IsListEmpty(pGLE
)) continue;
840 HookObj
= CONTAINING_RECORD(pElem
, HOOK
, Chain
);
844 if (HookObj
->head
.pti
== pti
)
846 if (IntRemoveHook(HookObj
)) break;
848 pElem
= HookObj
->Chain
.Flink
;
849 HookObj
= CONTAINING_RECORD(pElem
, HOOK
, Chain
);
851 while (pElem
!= pGLE
);
858 Win32k Kernel Space Hook Caller.
862 co_HOOK_CallHooks( INT HookId
,
867 PHOOK Hook
, SaveHook
;
869 PCLIENTINFO ClientInfo
;
870 PLIST_ENTRY pLLE
, pGLE
;
871 BOOL Local
= FALSE
, Global
= FALSE
;
874 ASSERT(WH_MINHOOK
<= HookId
&& HookId
<= WH_MAXHOOK
);
876 pti
= PsGetCurrentThreadWin32Thread();
877 if (!pti
|| !pti
->pDeskInfo
)
878 goto Exit
; // Must have a desktop running for hooks.
880 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
883 if ( ISITHOOKED(HookId
) )
885 DPRINT("Local Hooker %d\n", HookId
);
889 if ( pti
->pDeskInfo
->fsHooks
& HOOKID_TO_FLAG(HookId
) )
891 DPRINT("Global Hooker %d\n", HookId
);
895 if ( !Local
&& !Global
) goto Exit
; // No work!
897 pLLE
= &pti
->aphkStart
[HOOKID_TO_INDEX(HookId
)];
898 pGLE
= &pti
->pDeskInfo
->aphkStart
[HOOKID_TO_INDEX(HookId
)];
901 /* SetWindowHookEx sorts out the Thread issue by placing the Hook to
902 the correct Thread if not NULL.
906 Hook
= IntGetFirstHook(pLLE
);
909 DPRINT1("No Local Hook Found!\n");
912 ObReferenceObject(Hook
->Thread
);
914 ClientInfo
= pti
->pClientInfo
;
915 SaveHook
= pti
->sphkCurrent
;
917 /* Load it for the next call. */
918 pti
->sphkCurrent
= Hook
;
919 Hook
->phkNext
= IntGetNextHook(Hook
);
924 ClientInfo
->phkCurrent
= Hook
;
926 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
928 ClientInfo
= NULL
; // Don't bother next run.
932 Result
= co_IntCallHookProc( HookId
,
943 ClientInfo
->phkCurrent
= SaveHook
;
945 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
950 pti
->sphkCurrent
= SaveHook
;
951 Hook
->phkNext
= NULL
;
952 ObDereferenceObject(Hook
->Thread
);
959 Hook
= IntGetFirstHook(pGLE
);
962 DPRINT1("No Global Hook Found!\n");
965 /* Performance goes down the drain. If more hooks are associated to this
966 * hook ID, this will have to post to each of the thread message queues
967 * or make a direct call.
971 /* Hook->Thread is null, we hax around this with Hook->head.pti. */
972 ptiHook
= Hook
->head
.pti
;
974 /* "Global hook monitors messages for all threads in the same desktop
975 * as the calling thread."
977 if ( ptiHook
->TIF_flags
& TIF_INCLEANUP
||
978 ptiHook
->rpdesk
!= pti
->rpdesk
)
980 Hook
= IntGetNextHook(Hook
);
984 // Lockup the thread while this links through user world.
985 ObReferenceObject(ptiHook
->pEThread
);
988 DPRINT("\nGlobal Hook posting to another Thread! %d\n",HookId
);
989 Result
= IntCallLowLevelHook(Hook
, Code
, wParam
, lParam
);
992 { /* Make the direct call. */
993 Result
= co_IntCallHookProc( HookId
,
1001 ObDereferenceObject(ptiHook
->pEThread
);
1002 Hook
= IntGetNextHook(Hook
);
1005 DPRINT("Ret: Global HookId %d Result 0x%x\n", HookId
,Result
);
1008 if (HookId
== WH_JOURNALPLAYBACK
&& Result
== 0)
1015 IntUnhookWindowsHook(int HookId
, HOOKPROC pfnFilterProc
)
1018 PLIST_ENTRY pLLE
, pLE
;
1019 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1021 if (HookId
< WH_MINHOOK
|| WH_MAXHOOK
< HookId
)
1023 SetLastWin32Error(ERROR_INVALID_HOOK_FILTER
);
1029 pLLE
= &pti
->aphkStart
[HOOKID_TO_INDEX(HookId
)];
1031 if (IsListEmpty(pLLE
)) return FALSE
;
1034 Hook
= CONTAINING_RECORD(pLE
, HOOK
, Chain
);
1038 if (Hook
->Proc
== pfnFilterProc
)
1040 if (Hook
->head
.pti
== pti
)
1042 IntRemoveHook(Hook
);
1043 UserDereferenceObject(Hook
);
1048 SetLastWin32Error(ERROR_ACCESS_DENIED
);
1052 pLE
= Hook
->Chain
.Flink
;
1053 Hook
= CONTAINING_RECORD(pLE
, HOOK
, Chain
);
1055 while (pLE
!= pLLE
);
1061 * Support for compatibility only? Global hooks are processed in kernel space.
1062 * This is very thread specific! Never seeing applications with more than one
1063 * hook per thread installed. Most of the applications are Global hookers and
1064 * associated with just one hook Id. Maybe it's for diagnostic testing or a
1065 * throw back to 3.11?
1069 NtUserCallNextHookEx( int Code
,
1075 PHOOK HookObj
, NextObj
;
1076 PCLIENTINFO ClientInfo
;
1077 LRESULT lResult
= 0;
1078 DECLARE_RETURN(LRESULT
);
1080 DPRINT("Enter NtUserCallNextHookEx\n");
1081 UserEnterExclusive();
1083 pti
= GetW32ThreadInfo();
1085 HookObj
= pti
->sphkCurrent
;
1087 if (!HookObj
) RETURN( 0);
1089 NextObj
= HookObj
->phkNext
;
1091 pti
->sphkCurrent
= NextObj
;
1092 ClientInfo
= pti
->pClientInfo
;
1095 ClientInfo
->phkCurrent
= NextObj
;
1097 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1103 /* Now in List run down. */
1104 if (ClientInfo
&& NextObj
)
1106 NextObj
->phkNext
= IntGetNextHook(NextObj
);
1107 lResult
= UserCallNextHookEx( NextObj
, Code
, wParam
, lParam
, NextObj
->Ansi
);
1112 DPRINT("Leave NtUserCallNextHookEx, ret=%i\n",_ret_
);
1119 NtUserSetWindowsHookAW( int idHook
,
1124 UNICODE_STRING USModuleName
;
1126 RtlInitUnicodeString(&USModuleName
, NULL
);
1127 ThreadId
= PtrToUint(NtCurrentTeb()->ClientId
.UniqueThread
);
1129 return NtUserSetWindowsHookEx( NULL
,
1139 NtUserSetWindowsHookEx( HINSTANCE Mod
,
1140 PUNICODE_STRING UnsafeModuleName
,
1146 PWINSTATION_OBJECT WinStaObj
;
1148 UNICODE_STRING ModuleName
;
1151 PETHREAD Thread
= NULL
;
1152 PTHREADINFO ptiCurrent
, pti
= NULL
;
1154 DECLARE_RETURN(HHOOK
);
1156 DPRINT("Enter NtUserSetWindowsHookEx\n");
1157 UserEnterExclusive();
1159 ptiCurrent
= GetW32ThreadInfo();
1161 if (HookId
< WH_MINHOOK
|| WH_MAXHOOK
< HookId
)
1163 SetLastWin32Error(ERROR_INVALID_HOOK_FILTER
);
1169 SetLastWin32Error(ERROR_INVALID_FILTER_PROC
);
1173 if (ThreadId
) /* thread-local hook */
1175 if ( HookId
== WH_JOURNALRECORD
||
1176 HookId
== WH_JOURNALPLAYBACK
||
1177 HookId
== WH_KEYBOARD_LL
||
1178 HookId
== WH_MOUSE_LL
||
1179 HookId
== WH_SYSMSGFILTER
)
1181 /* these can only be global */
1182 SetLastWin32Error(ERROR_GLOBAL_ONLY_HOOK
);
1186 if (!NT_SUCCESS(PsLookupThreadByThreadId((HANDLE
)(DWORD_PTR
) ThreadId
, &Thread
)))
1188 DPRINT1("Invalid thread id 0x%x\n", ThreadId
);
1189 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1193 pti
= Thread
->Tcb
.Win32Thread
;
1195 ObDereferenceObject(Thread
);
1197 if ( pti
->rpdesk
!= ptiCurrent
->rpdesk
) // gptiCurrent->rpdesk)
1199 SetLastWin32Error(ERROR_ACCESS_DENIED
);
1203 if (Thread
->ThreadsProcess
!= PsGetCurrentProcess())
1206 (HookId
== WH_GETMESSAGE
||
1207 HookId
== WH_CALLWNDPROC
||
1209 HookId
== WH_HARDWARE
||
1210 HookId
== WH_DEBUG
||
1211 HookId
== WH_SHELL
||
1212 HookId
== WH_FOREGROUNDIDLE
||
1213 HookId
== WH_CALLWNDPROCRET
) )
1215 SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD
);
1219 if ( (pti
->TIF_flags
& (TIF_CSRSSTHREAD
|TIF_SYSTEMTHREAD
)) &&
1220 (HookId
== WH_GETMESSAGE
||
1221 HookId
== WH_CALLWNDPROC
||
1223 HookId
== WH_HARDWARE
||
1224 HookId
== WH_DEBUG
||
1225 HookId
== WH_SHELL
||
1226 HookId
== WH_FOREGROUNDIDLE
||
1227 HookId
== WH_CALLWNDPROCRET
) )
1229 SetLastWin32Error(ERROR_HOOK_TYPE_NOT_ALLOWED
);
1234 else /* system-global hook */
1236 pti
= ptiCurrent
; // gptiCurrent;
1238 (HookId
== WH_GETMESSAGE
||
1239 HookId
== WH_CALLWNDPROC
||
1241 HookId
== WH_SYSMSGFILTER
||
1242 HookId
== WH_HARDWARE
||
1243 HookId
== WH_DEBUG
||
1244 HookId
== WH_SHELL
||
1245 HookId
== WH_FOREGROUNDIDLE
||
1246 HookId
== WH_CALLWNDPROCRET
) )
1248 SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD
);
1253 Status
= IntValidateWindowStationHandle( PsGetCurrentProcess()->Win32WindowStation
,
1258 if (!NT_SUCCESS(Status
))
1260 SetLastNtError(Status
);
1263 ObDereferenceObject(WinStaObj
);
1265 Hook
= UserCreateObject(gHandleTable
, NULL
, &Handle
, otHook
, sizeof(HOOK
));
1272 Hook
->ihmod
= (INT
)Mod
; // Module Index from atom table, Do this for now.
1273 Hook
->Thread
= Thread
; /* Set Thread, Null is Global. */
1274 Hook
->HookId
= HookId
;
1275 Hook
->rpdesk
= pti
->rpdesk
;
1276 Hook
->phkNext
= NULL
; /* Dont use as a chain! Use link lists for chaining. */
1277 Hook
->Proc
= HookProc
;
1280 if (ThreadId
) /* thread-local hook */
1282 InsertHeadList(&pti
->aphkStart
[HOOKID_TO_INDEX(HookId
)], &Hook
->Chain
);
1283 pti
->sphkCurrent
= NULL
;
1284 Hook
->ptiHooked
= pti
;
1285 pti
->fsHooks
|= HOOKID_TO_FLAG(HookId
);
1287 if (pti
->pClientInfo
)
1289 if ( pti
->ppi
== ptiCurrent
->ppi
) /* gptiCurrent->ppi) */
1293 pti
->pClientInfo
->fsHooks
= pti
->fsHooks
;
1294 pti
->pClientInfo
->phkCurrent
= 0;
1296 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1303 DPRINT1("Problem writing to Local ClientInfo!\n");
1308 KeAttachProcess(&pti
->ppi
->peProcess
->Pcb
);
1311 pti
->pClientInfo
->fsHooks
= pti
->fsHooks
;
1312 pti
->pClientInfo
->phkCurrent
= 0;
1314 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1322 DPRINT1("Problem writing to Remote ClientInfo!\n");
1329 InsertHeadList(&pti
->pDeskInfo
->aphkStart
[HOOKID_TO_INDEX(HookId
)], &Hook
->Chain
);
1330 Hook
->ptiHooked
= NULL
;
1331 //gptiCurrent->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId);
1332 pti
->pDeskInfo
->fsHooks
|= HOOKID_TO_FLAG(HookId
);
1335 RtlInitUnicodeString(&Hook
->ModuleName
, NULL
);
1339 Status
= MmCopyFromCaller(&ModuleName
,
1341 sizeof(UNICODE_STRING
));
1342 if (!NT_SUCCESS(Status
))
1344 IntRemoveHook(Hook
);
1345 SetLastNtError(Status
);
1349 Hook
->ModuleName
.Buffer
= ExAllocatePoolWithTag( PagedPool
,
1350 ModuleName
.MaximumLength
,
1352 if (NULL
== Hook
->ModuleName
.Buffer
)
1354 IntRemoveHook(Hook
);
1355 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1359 Hook
->ModuleName
.MaximumLength
= ModuleName
.MaximumLength
;
1360 Status
= MmCopyFromCaller( Hook
->ModuleName
.Buffer
,
1362 ModuleName
.MaximumLength
);
1363 if (!NT_SUCCESS(Status
))
1365 ExFreePoolWithTag(Hook
->ModuleName
.Buffer
, TAG_HOOK
);
1366 Hook
->ModuleName
.Buffer
= NULL
;
1367 IntRemoveHook(Hook
);
1368 SetLastNtError(Status
);
1372 Hook
->ModuleName
.Length
= ModuleName
.Length
;
1373 /* make proc relative to the module base */
1374 Hook
->offPfn
= (ULONG_PTR
)((char *)HookProc
- (char *)Mod
);
1382 DPRINT("Leave NtUserSetWindowsHookEx, ret=%i\n",_ret_
);
1389 NtUserUnhookWindowsHookEx(HHOOK Hook
)
1392 DECLARE_RETURN(BOOL
);
1394 DPRINT("Enter NtUserUnhookWindowsHookEx\n");
1395 UserEnterExclusive();
1397 if (!(HookObj
= IntGetHookObject(Hook
)))
1399 DPRINT1("Invalid handle passed to NtUserUnhookWindowsHookEx\n");
1400 /* SetLastNtError(Status); */
1404 ASSERT(Hook
== UserHMGetHandle(HookObj
));
1406 IntRemoveHook(HookObj
);
1408 UserDereferenceObject(HookObj
);
1413 DPRINT("Leave NtUserUnhookWindowsHookEx, ret=%i\n",_ret_
);