ReactOS 0.4.16-dev-92-g0c2cdca
hook.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Window hooks
5 * PROGRAMER: Casper S. Hornstrup <chorns@users.sourceforge.net>
6 * James Tabor <james.tabor@reactos.org>
7 * Rafal Harabien <rafalh@reactos.org>
8 * NOTE: Most of this code was adapted from Wine,
9 * Copyright (C) 2002 Alexandre Julliard
10 */
11
12#include <win32k.h>
14
15typedef struct _HOOKPACK
16{
21
25
26/* PRIVATE FUNCTIONS *********************************************************/
27
28/* Calls ClientLoadLibrary in user32 in order to load or unload a module */
29BOOL
30IntLoadHookModule(int iHookID, HHOOK hHook, BOOL Unload)
31{
32 PPROCESSINFO ppi;
33 BOOL bResult;
34
36
37 TRACE("IntLoadHookModule. Client PID: %p\n", PsGetProcessId(ppi->peProcess));
38
39 /* Check if this is the api hook */
40 if(iHookID == WH_APIHOOK)
41 {
42 if(!Unload && !(ppi->W32PF_flags & W32PF_APIHOOKLOADED))
43 {
44 /* A callback in user mode can trigger UserLoadApiHook to be called and
45 as a result IntLoadHookModule will be called recursively.
46 To solve this we set the flag that means that the application has
47 loaded the api hook before the callback and in case of error we remove it */
48 ppi->W32PF_flags |= W32PF_APIHOOKLOADED;
49
50 /* Call ClientLoadLibrary in user32 */
52 TRACE("co_IntClientLoadLibrary returned %d\n", bResult );
53 if (!bResult)
54 {
55 /* Remove the flag we set before */
56 ppi->W32PF_flags &= ~W32PF_APIHOOKLOADED;
57 }
58 return bResult;
59 }
60 else if(Unload && (ppi->W32PF_flags & W32PF_APIHOOKLOADED))
61 {
62 /* Call ClientLoadLibrary in user32 */
64 if (bResult)
65 {
66 ppi->W32PF_flags &= ~W32PF_APIHOOKLOADED;
67 }
68 return bResult;
69 }
70
71 return TRUE;
72 }
73
74 STUB;
75
76 return FALSE;
77}
78
79/*
80IntHookModuleUnloaded:
81Sends a internal message to all threads of the requested desktop
82and notifies them that a global hook was destroyed
83and an injected module must be unloaded.
84As a result, IntLoadHookModule will be called for all the threads that
85will receive the special purpose internal message.
86*/
87BOOL
88IntHookModuleUnloaded(PDESKTOP pdesk, int iHookID, HHOOK hHook)
89{
90 PTHREADINFO ptiCurrent;
91 PLIST_ENTRY ListEntry;
92 PPROCESSINFO ppiCsr;
93
94 TRACE("IntHookModuleUnloaded: iHookID=%d\n", iHookID);
95
97
98 ListEntry = pdesk->PtiList.Flink;
99 while(ListEntry != &pdesk->PtiList)
100 {
101 ptiCurrent = CONTAINING_RECORD(ListEntry, THREADINFO, PtiLink);
102
103 /* FIXME: Do some more security checks here */
104
105 /* FIXME: HACK: The first check is a reactos specific hack for system threads */
106 if(!PsIsSystemProcess(ptiCurrent->ppi->peProcess) &&
107 ptiCurrent->ppi != ppiCsr)
108 {
109 if(ptiCurrent->ppi->W32PF_flags & W32PF_APIHOOKLOADED)
110 {
111 TRACE("IntHookModuleUnloaded: sending message to PID %p, ppi=%p\n", PsGetProcessId(ptiCurrent->ppi->peProcess), ptiCurrent->ppi);
112 co_MsqSendMessageAsync( ptiCurrent,
113 0,
114 iHookID,
115 TRUE,
116 (LPARAM)hHook,
117 NULL,
118 0,
119 FALSE,
121 }
122 }
123 ListEntry = ListEntry->Flink;
124 }
125
126 return TRUE;
127}
128
129BOOL
132{
134}
135
136BOOL
139 PUNICODE_STRING pstrDllName,
140 PUNICODE_STRING pstrFuncName)
141{
142 PTHREADINFO pti, ptiCurrent;
143 HWND *List;
144 PWND DesktopWindow, pwndCurrent;
145 ULONG i;
146 PPROCESSINFO ppiCsr;
147
150
151 /* Fail if the api hook is already registered */
153 {
154 return FALSE;
155 }
156
157 TRACE("UserRegisterUserApiHook. Server PID: %p\n", PsGetProcessId(pti->ppi->peProcess));
158
159 /* Register the api hook */
161
162 strUahModule = *pstrDllName;
163 strUahInitFunc = *pstrFuncName;
164 ppiUahServer = pti->ppi;
165
166 /* Broadcast an internal message to every top level window */
169
170 if (List != NULL)
171 {
172 for (i = 0; List[i]; i++)
173 {
174 pwndCurrent = UserGetWindowObject(List[i]);
175 if(pwndCurrent == NULL)
176 {
177 continue;
178 }
179 ptiCurrent = pwndCurrent->head.pti;
180
181 /* FIXME: The first check is a reactos specific hack for system threads */
182 if(PsIsSystemProcess(ptiCurrent->ppi->peProcess) ||
183 ptiCurrent->ppi == ppiCsr)
184 {
185 continue;
186 }
187
188 co_MsqSendMessageAsync( ptiCurrent,
189 0,
191 FALSE, /* Load the module */
192 0,
193 NULL,
194 0,
195 FALSE,
197 }
199 }
200
201 return TRUE;
202}
203
204BOOL
207{
208 PTHREADINFO pti;
209
211
212 /* Fail if the api hook is not registered */
214 {
215 return FALSE;
216 }
217
218 /* Only the process that registered the api hook can uregister it */
220 {
221 return FALSE;
222 }
223
224 TRACE("UserUnregisterUserApiHook. Server PID: %p\n", PsGetProcessId(pti->ppi->peProcess));
225
226 /* Unregister the api hook */
227 gpsi->dwSRVIFlags &= ~SRVINFO_APIHOOK;
231
232 /* Notify all applications that the api hook module must be unloaded */
233 return IntHookModuleUnloaded(pti->rpdesk, WH_APIHOOK, 0);
234}
235
236static
240 INT Code,
243{
245 PTHREADINFO pti;
246 PHOOKPACK pHP;
247 INT Size = 0;
248 UINT uTimeout = 300;
249 BOOL Block = FALSE;
250 ULONG_PTR uResult = 0;
251
252 if (Hook->ptiHooked)
253 pti = Hook->ptiHooked;
254 else
255 pti = Hook->head.pti;
256
258 if (!pHP) return 0;
259
260 pHP->pHk = Hook;
261 pHP->lParam = lParam;
262 pHP->pHookStructs = NULL;
263
264// This prevents stack corruption from the caller.
265 switch(Hook->HookId)
266 {
268 case WH_JOURNALRECORD:
269 uTimeout = 0;
270 Size = sizeof(EVENTMSG);
271 break;
272 case WH_KEYBOARD_LL:
273 Size = sizeof(KBDLLHOOKSTRUCT);
274 break;
275 case WH_MOUSE_LL:
276 Size = sizeof(MSLLHOOKSTRUCT);
277 break;
278 case WH_MOUSE:
279 uTimeout = 200;
280 Block = TRUE;
281 Size = sizeof(MOUSEHOOKSTRUCT);
282 break;
283 case WH_KEYBOARD:
284 uTimeout = 200;
285 Block = TRUE;
286 break;
287 }
288
289 if (Size)
290 {
293 }
294
295 /* FIXME: Should get timeout from
296 * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
298 IntToPtr(Code), // hWnd
299 Hook->HookId, // Msg
300 wParam,
301 (LPARAM)pHP,
302 uTimeout,
303 Block,
305 &uResult);
306 if (!NT_SUCCESS(Status))
307 {
308 ERR("Error Hook Call SendMsg. %d Status: 0x%x\n", Hook->HookId, Status);
311 }
312 return NT_SUCCESS(Status) ? uResult : 0;
313}
314
315
316//
317// Dispatch MsgQueue Hook Call processor!
318//
322 INT Code,
325{
326 LRESULT Result = 0;
327 PHOOK phk;
329
330 phk = pHP->pHk;
331 lParam = pHP->lParam;
332
333 switch(HookId)
334 {
336 case WH_JOURNALRECORD:
337 case WH_KEYBOARD_LL:
338 case WH_MOUSE_LL:
339 case WH_MOUSE:
340 lParam = (LPARAM)pHP->pHookStructs;
341 case WH_KEYBOARD:
342 break;
343 }
344
346 {
347 /* The odds are high for this to be a Global call. */
348 Result = co_IntCallHookProc( HookId,
349 Code,
350 wParam,
351 lParam,
352 phk->Proc,
353 phk->ihmod,
354 phk->offPfn,
355 phk->Ansi,
356 &phk->ModuleName);
357 }
358 /* The odds so high, no one is waiting for the results. */
361 return Result;
362}
363
364static
368 INT Code,
371{
372 TRACE("Calling Next HOOK %d\n", Hook->HookId);
373
374 return co_IntCallHookProc( Hook->HookId,
375 Code,
376 wParam,
377 lParam,
378 Hook->Proc,
379 Hook->ihmod,
380 Hook->offPfn,
381 Hook->Ansi,
382 &Hook->ModuleName);
383}
384
385static
389 int Code,
392 BOOL Ansi)
393{
394 LRESULT lResult = 0;
395 ULONG Size;
396 DEBUGHOOKINFO Debug;
397 PVOID HooklParam = NULL;
398 BOOL BadChk = FALSE;
399
400 if (lParam)
401 {
403 {
405 sizeof(DEBUGHOOKINFO),
406 1);
407
408 RtlCopyMemory(&Debug,
409 (PVOID)lParam,
410 sizeof(DEBUGHOOKINFO));
411 }
413 {
414 BadChk = TRUE;
415 }
416 _SEH2_END;
417
418 if (BadChk)
419 {
420 ERR("HOOK WH_DEBUG read from lParam ERROR!\n");
421 return lResult;
422 }
423 }
424 else
425 return lResult; /* Need lParam! */
426
427 switch (wParam)
428 {
429 case WH_CBT:
430 {
431 switch (Debug.code)
432 {
434 Size = sizeof(MOUSEHOOKSTRUCTEX);
435 break;
436
437 case HCBT_MOVESIZE:
438 Size = sizeof(RECT);
439 break;
440
441 case HCBT_ACTIVATE:
442 Size = sizeof(CBTACTIVATESTRUCT);
443 break;
444
445 case HCBT_CREATEWND: /* Handle ANSI? */
446 Size = sizeof(CBT_CREATEWND);
447 /* What shall we do? Size += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS); same as CREATESTRUCTEX */
448 break;
449
450 default:
451 Size = sizeof(LPARAM);
452 }
453 }
454 break;
455
456 case WH_MOUSE_LL:
457 Size = sizeof(MSLLHOOKSTRUCT);
458 break;
459
460 case WH_KEYBOARD_LL:
461 Size = sizeof(KBDLLHOOKSTRUCT);
462 break;
463
464 case WH_MSGFILTER:
465 case WH_SYSMSGFILTER:
466 case WH_GETMESSAGE:
467 Size = sizeof(MSG);
468 break;
469
471 case WH_JOURNALRECORD:
472 Size = sizeof(EVENTMSG);
473 break;
474
476 case WH_KEYBOARD:
477 case WH_SHELL:
478 default:
479 Size = sizeof(LPARAM);
480 }
481
482 if (Size > sizeof(LPARAM))
484
485 if (HooklParam)
486 {
488 {
490 Size,
491 1);
492
493 RtlCopyMemory(HooklParam,
494 (PVOID)Debug.lParam,
495 Size);
496 }
498 {
499 BadChk = TRUE;
500 }
501 _SEH2_END;
502
503 if (BadChk)
504 {
505 ERR("HOOK WH_DEBUG read from Debug.lParam ERROR!\n");
506 ExFreePoolWithTag(HooklParam, TAG_HOOK);
507 return lResult;
508 }
509 }
510
511 if (HooklParam) Debug.lParam = (LPARAM)HooklParam;
512 lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Debug);
513 if (HooklParam) ExFreePoolWithTag(HooklParam, TAG_HOOK);
514
515 return lResult;
516}
517
518static
522 int Code,
525 BOOL Ansi)
526{
527 LRESULT lResult = 0;
528 BOOL BadChk = FALSE;
529
530 /* Handle this one first. */
531 if ((Hook->HookId == WH_MOUSE) ||
532 (Hook->HookId == WH_CBT && Code == HCBT_CLICKSKIPPED))
533 {
534 MOUSEHOOKSTRUCTEX Mouse;
535 if (lParam)
536 {
538 {
540 sizeof(MOUSEHOOKSTRUCTEX),
541 1);
542
544 (PVOID)lParam,
545 sizeof(MOUSEHOOKSTRUCTEX));
546 }
548 {
549 BadChk = TRUE;
550 }
551 _SEH2_END;
552
553 if (BadChk)
554 {
555 ERR("HOOK WH_MOUSE read from lParam ERROR!\n");
556 }
557 }
558
559 if (!BadChk)
560 {
561 lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Mouse);
562 }
563
564 return lResult;
565 }
566
567 switch(Hook->HookId)
568 {
569 case WH_MOUSE_LL:
570 {
572
573 if (lParam)
574 {
576 {
578 sizeof(MSLLHOOKSTRUCT),
579 1);
580
582 (PVOID)lParam,
583 sizeof(MSLLHOOKSTRUCT));
584 }
586 {
587 BadChk = TRUE;
588 }
589 _SEH2_END;
590
591 if (BadChk)
592 {
593 ERR("HOOK WH_MOUSE_LL read from lParam ERROR!\n");
594 }
595 }
596
597 if (!BadChk)
598 {
599 lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Mouse);
600 }
601 break;
602 }
603
604 case WH_KEYBOARD_LL:
605 {
607
608 if (lParam)
609 {
611 {
613 sizeof(KBDLLHOOKSTRUCT),
614 1);
615
617 (PVOID)lParam,
618 sizeof(KBDLLHOOKSTRUCT));
619 }
621 {
622 BadChk = TRUE;
623 }
624 _SEH2_END;
625
626 if (BadChk)
627 {
628 ERR("HOOK WH_KEYBORD_LL read from lParam ERROR!\n");
629 }
630 }
631
632 if (!BadChk)
633 {
634 lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Keyboard);
635 }
636 break;
637 }
638
639 case WH_MSGFILTER:
640 case WH_SYSMSGFILTER:
641 case WH_GETMESSAGE:
642 {
643 MSG Msg;
644
645 if (lParam)
646 {
648 {
650 sizeof(MSG),
651 1);
652
654 (PVOID)lParam,
655 sizeof(MSG));
656 }
658 {
659 BadChk = TRUE;
660 }
661 _SEH2_END;
662
663 if (BadChk)
664 {
665 ERR("HOOK WH_XMESSAGEX read from lParam ERROR!\n");
666 }
667 }
668
669 if (!BadChk)
670 {
671 lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Msg);
672
673 if (lParam && (Hook->HookId == WH_GETMESSAGE))
674 {
676 {
678 sizeof(MSG),
679 1);
680
682 &Msg,
683 sizeof(MSG));
684 }
686 {
687 BadChk = TRUE;
688 }
689 _SEH2_END;
690
691 if (BadChk)
692 {
693 ERR("HOOK WH_GETMESSAGE write to lParam ERROR!\n");
694 }
695 }
696 }
697 break;
698 }
699
700 case WH_CBT:
701 TRACE("HOOK WH_CBT!\n");
702 switch (Code)
703 {
704 case HCBT_CREATEWND:
705 {
707
708 TRACE("HOOK HCBT_CREATEWND\n");
710 {
711 if (Ansi)
712 {
713 ProbeForRead( pcbtcww,
714 sizeof(CBT_CREATEWNDA),
715 1);
716 ProbeForWrite(pcbtcww->lpcs,
717 sizeof(CREATESTRUCTA),
718 1);
719 ProbeForRead( pcbtcww->lpcs->lpszName,
720 sizeof(CHAR),
721 1);
722
723 if (!IS_ATOM(pcbtcww->lpcs->lpszClass))
724 {
725 _Analysis_assume_(pcbtcww->lpcs->lpszClass != NULL);
726 ProbeForRead(pcbtcww->lpcs->lpszClass,
727 sizeof(CHAR),
728 1);
729 }
730 }
731 else
732 {
733 ProbeForRead( pcbtcww,
734 sizeof(CBT_CREATEWNDW),
735 1);
736 ProbeForWrite(pcbtcww->lpcs,
737 sizeof(CREATESTRUCTW),
738 1);
739 ProbeForRead( pcbtcww->lpcs->lpszName,
740 sizeof(WCHAR),
741 1);
742
743 if (!IS_ATOM(pcbtcww->lpcs->lpszClass))
744 {
745 _Analysis_assume_(pcbtcww->lpcs->lpszClass != NULL);
746 ProbeForRead(pcbtcww->lpcs->lpszClass,
747 sizeof(WCHAR),
748 1);
749 }
750 }
751 }
753 {
754 BadChk = TRUE;
755 }
756 _SEH2_END;
757
758 if (BadChk)
759 {
760 ERR("HOOK HCBT_CREATEWND write ERROR!\n");
761 }
762 /* The next call handles the structures. */
763 if (!BadChk && Hook->Proc)
764 {
765 lResult = co_HOOK_CallHookNext(Hook, Code, wParam, lParam);
766 }
767 break;
768 }
769
770 case HCBT_MOVESIZE:
771 {
772 RECTL rt;
773
774 TRACE("HOOK HCBT_MOVESIZE\n");
775
776 if (lParam)
777 {
779 {
781 sizeof(RECT),
782 1);
783
784 RtlCopyMemory(&rt,
785 (PVOID)lParam,
786 sizeof(RECT));
787 }
789 {
790 BadChk = TRUE;
791 }
792 _SEH2_END;
793
794 if (BadChk)
795 {
796 ERR("HOOK HCBT_MOVESIZE read from lParam ERROR!\n");
797 }
798 }
799
800 if (!BadChk)
801 {
802 lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&rt);
803 }
804 break;
805 }
806
807 case HCBT_ACTIVATE:
808 {
810
811 TRACE("HOOK HCBT_ACTIVATE\n");
812 if (lParam)
813 {
815 {
817 sizeof(CBTACTIVATESTRUCT),
818 1);
819
820 RtlCopyMemory(&CbAs,
821 (PVOID)lParam,
822 sizeof(CBTACTIVATESTRUCT));
823 }
825 {
826 BadChk = TRUE;
827 }
828 _SEH2_END;
829
830 if (BadChk)
831 {
832 ERR("HOOK HCBT_ACTIVATE read from lParam ERROR!\n");
833 }
834 }
835
836 if (!BadChk)
837 {
838 lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&CbAs);
839 }
840 break;
841 }
842
843 /* The rest just use default. */
844 default:
845 TRACE("HOOK HCBT_ %d\n",Code);
846 lResult = co_HOOK_CallHookNext(Hook, Code, wParam, lParam);
847 break;
848 }
849 break;
850/*
851 Note WH_JOURNALPLAYBACK,
852 "To have the system wait before processing the message, the return value
853 must be the amount of time, in clock ticks, that the system should wait."
854 */
856 case WH_JOURNALRECORD:
857 {
858 EVENTMSG EventMsg;
859
860 if (lParam)
861 {
863 {
865 sizeof(EVENTMSG),
866 1);
867
868 RtlCopyMemory(&EventMsg,
869 (PVOID)lParam,
870 sizeof(EVENTMSG));
871 }
873 {
874 BadChk = TRUE;
875 }
876 _SEH2_END;
877
878 if (BadChk)
879 {
880 ERR("HOOK WH_JOURNAL read from lParam ERROR!\n");
881 }
882 }
883
884 if (!BadChk)
885 {
886 lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)(lParam ? &EventMsg : NULL));
887
888 if (lParam)
889 {
891 {
893 sizeof(EVENTMSG),
894 1);
895
897 &EventMsg,
898 sizeof(EVENTMSG));
899 }
901 {
902 BadChk = TRUE;
903 }
904 _SEH2_END;
905
906 if (BadChk)
907 {
908 ERR("HOOK WH_JOURNAL write to lParam ERROR!\n");
909 }
910 }
911 }
912 break;
913 }
914
915 case WH_DEBUG:
916 lResult = co_IntCallDebugHook(Hook, Code, wParam, lParam, Ansi);
917 break;
918
919 /*
920 * Default the rest like, WH_FOREGROUNDIDLE, WH_KEYBOARD and WH_SHELL.
921 */
923 case WH_KEYBOARD:
924 case WH_SHELL:
925 lResult = co_HOOK_CallHookNext(Hook, Code, wParam, lParam);
926 break;
927
928 default:
929 ERR("Unsupported HOOK Id -> %d\n",Hook->HookId);
930 break;
931 }
932 return lResult;
933}
934
935PHOOK
938{
939 PHOOK Hook;
940
941 if (!hHook)
942 {
944 return NULL;
945 }
946
947 Hook = (PHOOK)UserGetObject(gHandleTable, hHook, TYPE_HOOK);
948 if (!Hook)
949 {
951 return NULL;
952 }
953
955
956 return Hook;
957}
958
959static
960HHOOK*
963{
964 PLIST_ENTRY pLastHead, pElem;
965 unsigned i = 0;
966 unsigned cHooks = 0;
967 HHOOK *pList;
968 PHOOK pHook;
969
970 pLastHead = &pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)];
971 for (pElem = pLastHead->Flink; pElem != pLastHead; pElem = pElem->Flink)
972 ++cHooks;
973
974 pList = ExAllocatePoolWithTag(PagedPool, (cHooks + 1) * sizeof(HHOOK), TAG_HOOK);
975 if (!pList)
976 {
978 return NULL;
979 }
980
981 for (pElem = pLastHead->Flink; pElem != pLastHead; pElem = pElem->Flink)
982 {
983 pHook = CONTAINING_RECORD(pElem, HOOK, Chain);
984 NT_ASSERT(i < cHooks);
985 pList[i++] = UserHMGetHandle(pHook);
986 }
987 pList[i] = NULL;
988
989 return pList;
990}
991
992/* Find the next hook in the chain */
993PHOOK
996{
997 int HookId = Hook->HookId;
998 PLIST_ENTRY pLastHead, pElem;
999 PTHREADINFO pti;
1000
1001 if (Hook->ptiHooked)
1002 {
1003 pti = Hook->ptiHooked;
1004 pLastHead = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
1005 }
1006 else
1007 {
1009 pLastHead = &pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)];
1010 }
1011
1012 pElem = Hook->Chain.Flink;
1013 if (pElem != pLastHead)
1014 return CONTAINING_RECORD(pElem, HOOK, Chain);
1015 return NULL;
1016}
1017
1018/* Free a hook, removing it from its chain */
1019static
1020VOID
1023{
1024 RemoveEntryList(&Hook->Chain);
1025 if (Hook->ModuleName.Buffer)
1026 {
1028 Hook->ModuleName.Buffer = NULL;
1029 }
1030 /* Close handle */
1032}
1033
1034/* Remove a hook, freeing it from the chain */
1035BOOLEAN
1037{
1038 INT HookId;
1039 PTHREADINFO ptiHook, pti;
1040 PDESKTOP pdo;
1041 PHOOK Hook = Object;
1042
1044
1045 HookId = Hook->HookId;
1047
1048 if (Hook->ptiHooked) // Local
1049 {
1050 ptiHook = Hook->ptiHooked;
1051
1052 IntFreeHook(Hook);
1053
1054 if (IsListEmpty(&ptiHook->aphkStart[HOOKID_TO_INDEX(HookId)]))
1055 {
1056 BOOL bOtherProcess;
1058
1059 ptiHook->fsHooks &= ~HOOKID_TO_FLAG(HookId);
1060 bOtherProcess = (ptiHook->ppi != pti->ppi);
1061
1062 if (bOtherProcess)
1063 KeStackAttachProcess(&ptiHook->ppi->peProcess->Pcb, &ApcState);
1064
1065 _SEH2_TRY
1066 {
1067 ptiHook->pClientInfo->fsHooks = ptiHook->fsHooks;
1068 }
1070 {
1071 /* Do nothing */
1072 (void)0;
1073 }
1074 _SEH2_END;
1075
1076 if (bOtherProcess)
1078 }
1079 }
1080 else // Global
1081 {
1082 IntFreeHook(Hook);
1083
1084 pdo = IntGetActiveDesktop();
1085
1086 if (pdo &&
1087 pdo->pDeskInfo &&
1089 {
1090 pdo->pDeskInfo->fsHooks &= ~HOOKID_TO_FLAG(HookId);
1091 }
1092 }
1093
1094 return TRUE;
1095}
1096
1097/*
1098 Win32k Kernel Space Hook Caller.
1099 */
1100LRESULT
1103 INT Code,
1104 WPARAM wParam,
1105 LPARAM lParam)
1106{
1107 PHOOK Hook, SaveHook;
1108 PTHREADINFO pti;
1110 PLIST_ENTRY pLastHead;
1111 PDESKTOP pdo;
1112 BOOL Local = FALSE, Global = FALSE;
1113 LRESULT Result = 0;
1115
1116 ASSERT(WH_MINHOOK <= HookId && HookId <= WH_MAXHOOK);
1117
1119 if (!pti || !pti->rpdesk || !pti->rpdesk->pDeskInfo)
1120 {
1121 pdo = IntGetActiveDesktop();
1122 /* If KeyboardThread|MouseThread|(RawInputThread or RIT) aka system threads,
1123 pti->fsHooks most likely, is zero. So process KbT & MsT to "send" the message.
1124 */
1125 if ( !pti || !pdo || (!(HookId == WH_KEYBOARD_LL) && !(HookId == WH_MOUSE_LL)) )
1126 {
1127 TRACE("No PDO %d\n", HookId);
1128 goto Exit;
1129 }
1130 }
1131 else
1132 {
1133 pdo = pti->rpdesk;
1134 }
1135
1137 {
1138 TRACE("Hook Thread dead %d\n", HookId);
1139 goto Exit;
1140 }
1141
1142 if ( ISITHOOKED(HookId) )
1143 {
1144 TRACE("Local Hooker %d\n", HookId);
1145 Local = TRUE;
1146 }
1147
1148 if ( pdo->pDeskInfo->fsHooks & HOOKID_TO_FLAG(HookId) )
1149 {
1150 TRACE("Global Hooker %d\n", HookId);
1151 Global = TRUE;
1152 }
1153
1154 if ( !Local && !Global ) goto Exit; // No work!
1155
1156 Hook = NULL;
1157
1158 /* SetWindowHookEx sorts out the Thread issue by placing the Hook to
1159 the correct Thread if not NULL.
1160 */
1161 if ( Local )
1162 {
1163 pLastHead = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
1164 if (IsListEmpty(pLastHead))
1165 {
1166 ERR("No Local Hook Found!\n");
1167 goto Exit;
1168 }
1169
1170 Hook = CONTAINING_RECORD(pLastHead->Flink, HOOK, Chain);
1171 ObReferenceObject(pti->pEThread);
1173 UserRefObjectCo(Hook, &Ref);
1174
1175 ClientInfo = pti->pClientInfo;
1176 SaveHook = pti->sphkCurrent;
1177 /* Note: Setting pti->sphkCurrent will also lock the next hook to this
1178 * hook ID. So, the CallNextHookEx will only call to that hook ID
1179 * chain anyway. For Thread Hooks....
1180 */
1181
1182 /* Load it for the next call. */
1183 pti->sphkCurrent = Hook;
1184 Hook->phkNext = IntGetNextHook(Hook);
1185 if (ClientInfo)
1186 {
1187 _SEH2_TRY
1188 {
1189 ClientInfo->phkCurrent = Hook;
1190 }
1192 {
1193 ClientInfo = NULL; // Don't bother next run.
1194 }
1195 _SEH2_END;
1196 }
1197 Result = co_IntCallHookProc( HookId,
1198 Code,
1199 wParam,
1200 lParam,
1201 Hook->Proc,
1202 Hook->ihmod,
1203 Hook->offPfn,
1204 Hook->Ansi,
1205 &Hook->ModuleName);
1206 if (ClientInfo)
1207 {
1208 _SEH2_TRY
1209 {
1210 ClientInfo->phkCurrent = SaveHook;
1211 }
1213 {
1214 /* Do nothing */
1215 (void)0;
1216 }
1217 _SEH2_END;
1218 }
1219 pti->sphkCurrent = SaveHook;
1220 Hook->phkNext = NULL;
1221 UserDerefObjectCo(Hook);
1223 ObDereferenceObject(pti->pEThread);
1224 }
1225
1226 if ( Global )
1227 {
1228 PTHREADINFO ptiHook;
1229 HHOOK *pHookHandles;
1230 unsigned i;
1231
1232 /* Keep hooks in array because hooks can be destroyed in user world */
1233 pHookHandles = IntGetGlobalHookHandles(pdo, HookId);
1234 if(!pHookHandles)
1235 goto Exit;
1236
1237 /* Performance goes down the drain. If more hooks are associated to this
1238 * hook ID, this will have to post to each of the thread message queues
1239 * or make a direct call.
1240 */
1241 for(i = 0; pHookHandles[i]; ++i)
1242 {
1243 Hook = (PHOOK)UserGetObject(gHandleTable, pHookHandles[i], TYPE_HOOK);
1244 if(!Hook)
1245 {
1246 ERR("Invalid hook!\n");
1247 continue;
1248 }
1249
1250 /* Hook->Thread is null, we hax around this with Hook->head.pti. */
1251 ptiHook = Hook->head.pti;
1252
1253 if ( (pti->TIF_flags & TIF_DISABLEHOOKS) || (ptiHook->TIF_flags & TIF_INCLEANUP))
1254 {
1255 TRACE("Next Hook %p, %p\n", ptiHook->rpdesk, pdo);
1256 continue;
1257 }
1258 UserRefObjectCo(Hook, &Ref);
1259
1260 if (ptiHook != pti )
1261 {
1262 // Block | TimeOut
1263 if ( HookId == WH_JOURNALPLAYBACK || // 1 | 0
1264 HookId == WH_JOURNALRECORD || // 1 | 0
1265 HookId == WH_KEYBOARD || // 1 | 200
1266 HookId == WH_MOUSE || // 1 | 200
1267 HookId == WH_KEYBOARD_LL || // 0 | 300
1268 HookId == WH_MOUSE_LL ) // 0 | 300
1269 {
1270 TRACE("\nGlobal Hook posting to another Thread! %d\n",HookId );
1272 }
1273 else if (ptiHook->ppi == pti->ppi)
1274 {
1275 TRACE("\nGlobal Hook calling to another Thread! %d\n",HookId );
1276 ObReferenceObject(ptiHook->pEThread);
1277 IntReferenceThreadInfo(ptiHook);
1278 Result = co_IntCallHookProc( HookId,
1279 Code,
1280 wParam,
1281 lParam,
1282 Hook->Proc,
1283 Hook->ihmod,
1284 Hook->offPfn,
1285 Hook->Ansi,
1286 &Hook->ModuleName);
1287 IntDereferenceThreadInfo(ptiHook);
1288 ObDereferenceObject(ptiHook->pEThread);
1289 }
1290 }
1291 else
1292 { /* Make the direct call. */
1293 TRACE("Global going Local Hook calling to Thread! %d\n",HookId );
1294 ObReferenceObject(pti->pEThread);
1296 Result = co_IntCallHookProc( HookId,
1297 Code,
1298 wParam,
1299 lParam,
1300 Hook->Proc,
1301 Hook->ihmod,
1302 Hook->offPfn,
1303 Hook->Ansi,
1304 &Hook->ModuleName);
1306 ObDereferenceObject(pti->pEThread);
1307 }
1308 UserDerefObjectCo(Hook);
1309 }
1310 ExFreePoolWithTag(pHookHandles, TAG_HOOK);
1311 TRACE("Ret: Global HookId %d Result 0x%x\n", HookId,Result);
1312 }
1313Exit:
1314 return Result;
1315}
1316
1317BOOL
1319IntUnhookWindowsHook(int HookId, HOOKPROC pfnFilterProc)
1320{
1321 PHOOK Hook;
1322 PLIST_ENTRY pLastHead, pElement;
1324
1325 if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId )
1326 {
1328 return FALSE;
1329 }
1330
1331 if (pti->fsHooks)
1332 {
1333 pLastHead = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
1334
1335 pElement = pLastHead->Flink;
1336 while (pElement != pLastHead)
1337 {
1338 Hook = CONTAINING_RECORD(pElement, HOOK, Chain);
1339
1340 /* Get the next element now, we might free the hook in what follows */
1341 pElement = Hook->Chain.Flink;
1342
1343 if (Hook->Proc == pfnFilterProc)
1344 {
1345 if (Hook->head.pti == pti)
1346 {
1347 IntRemoveHook(Hook);
1348 return TRUE;
1349 }
1350 else
1351 {
1353 return FALSE;
1354 }
1355 }
1356 }
1357 }
1358 return FALSE;
1359}
1360
1361/*
1362 * Support for compatibility only? Global hooks are processed in kernel space.
1363 * This is very thread specific! Never seeing applications with more than one
1364 * hook per thread installed. Most of the applications are Global hookers and
1365 * associated with just one hook Id. Maybe it's for diagnostic testing or a
1366 * throw back to 3.11?
1367 */
1368LRESULT
1371 WPARAM wParam,
1372 LPARAM lParam,
1373 BOOL Ansi)
1374{
1375 PTHREADINFO pti;
1376 PHOOK HookObj, NextObj;
1378 LRESULT lResult = 0;
1379
1380 TRACE("Enter NtUserCallNextHookEx\n");
1382
1383 pti = GetW32ThreadInfo();
1384
1385 HookObj = pti->sphkCurrent;
1386
1387 if (!HookObj)
1388 goto Exit; // Return 0
1389
1390 NextObj = HookObj->phkNext;
1391
1392 pti->sphkCurrent = NextObj;
1393 ClientInfo = pti->pClientInfo;
1394 _SEH2_TRY
1395 {
1396 ClientInfo->phkCurrent = NextObj;
1397 }
1399 {
1400 ClientInfo = NULL;
1401 }
1402 _SEH2_END;
1403
1404 /* Now in List run down. */
1405 if (ClientInfo && NextObj)
1406 {
1407 NextObj->phkNext = IntGetNextHook(NextObj);
1408 lResult = co_UserCallNextHookEx( NextObj, Code, wParam, lParam, NextObj->Ansi);
1409 }
1410
1411Exit:
1412 TRACE("Leave NtUserCallNextHookEx, ret=%i\n", lResult);
1413 UserLeave();
1414 return lResult;
1415}
1416
1417HHOOK
1420 HOOKPROC lpfn,
1421 BOOL Ansi)
1422{
1423 DWORD ThreadId;
1424 UNICODE_STRING USModuleName;
1425
1426 RtlInitUnicodeString(&USModuleName, NULL);
1428
1430 &USModuleName,
1431 ThreadId,
1432 idHook,
1433 lpfn,
1434 Ansi);
1435}
1436
1437HHOOK
1440 PUNICODE_STRING UnsafeModuleName,
1441 DWORD ThreadId,
1442 int HookId,
1443 HOOKPROC HookProc,
1444 BOOL Ansi)
1445{
1446 PWINSTATION_OBJECT WinStaObj;
1447 PHOOK Hook = NULL;
1450 HHOOK Handle;
1451 PTHREADINFO pti, ptiHook = NULL;
1452 HHOOK Ret = NULL;
1453
1454 TRACE("Enter NtUserSetWindowsHookEx\n");
1456
1458
1459 if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId )
1460 {
1462 goto Cleanup; // Return NULL
1463 }
1464
1465 if (!HookProc)
1466 {
1468 goto Cleanup; // Return NULL
1469 }
1470
1471 if (ThreadId) /* thread-local hook */
1472 {
1473 if ( HookId == WH_JOURNALRECORD ||
1474 HookId == WH_JOURNALPLAYBACK ||
1475 HookId == WH_KEYBOARD_LL ||
1476 HookId == WH_MOUSE_LL ||
1477 HookId == WH_SYSMSGFILTER)
1478 {
1479 TRACE("Local hook installing Global HookId: %d\n",HookId);
1480 /* these can only be global */
1482 goto Cleanup; // Return NULL
1483 }
1484
1485 if ( !(ptiHook = IntTID2PTI( UlongToHandle(ThreadId) )))
1486 {
1487 ERR("Invalid thread id 0x%x\n", ThreadId);
1489 goto Cleanup; // Return NULL
1490 }
1491
1492 if ( ptiHook->rpdesk != pti->rpdesk) // gptiCurrent->rpdesk)
1493 {
1494 ERR("Local hook wrong desktop HookId: %d\n",HookId);
1496 goto Cleanup; // Return NULL
1497 }
1498
1499 if (ptiHook->ppi != pti->ppi)
1500 {
1501 if ( !Mod &&
1502 (HookId == WH_GETMESSAGE ||
1503 HookId == WH_CALLWNDPROC ||
1504 HookId == WH_CBT ||
1505 HookId == WH_HARDWARE ||
1506 HookId == WH_DEBUG ||
1507 HookId == WH_SHELL ||
1508 HookId == WH_FOREGROUNDIDLE ||
1509 HookId == WH_CALLWNDPROCRET) )
1510 {
1511 ERR("Local hook needs hMod HookId: %d\n",HookId);
1513 goto Cleanup; // Return NULL
1514 }
1515
1516 if ( (ptiHook->TIF_flags & (TIF_CSRSSTHREAD|TIF_SYSTEMTHREAD)) &&
1517 (HookId == WH_GETMESSAGE ||
1518 HookId == WH_CALLWNDPROC ||
1519 HookId == WH_CBT ||
1520 HookId == WH_HARDWARE ||
1521 HookId == WH_DEBUG ||
1522 HookId == WH_SHELL ||
1523 HookId == WH_FOREGROUNDIDLE ||
1524 HookId == WH_CALLWNDPROCRET) )
1525 {
1527 goto Cleanup; // Return NULL
1528 }
1529 }
1530 }
1531 else /* System-global hook */
1532 {
1533 ptiHook = pti; // gptiCurrent;
1534 if ( !Mod &&
1535 (HookId == WH_GETMESSAGE ||
1536 HookId == WH_CALLWNDPROC ||
1537 HookId == WH_CBT ||
1538 HookId == WH_SYSMSGFILTER ||
1539 HookId == WH_HARDWARE ||
1540 HookId == WH_DEBUG ||
1541 HookId == WH_SHELL ||
1542 HookId == WH_FOREGROUNDIDLE ||
1543 HookId == WH_CALLWNDPROCRET) )
1544 {
1545 ERR("Global hook needs hMod HookId: %d\n",HookId);
1547 goto Cleanup; // Return NULL
1548 }
1549 }
1550
1552 UserMode,
1553 0,
1554 &WinStaObj,
1555 0);
1556
1557 if (!NT_SUCCESS(Status))
1558 {
1560 goto Cleanup; // Return NULL
1561 }
1562 ObDereferenceObject(WinStaObj);
1563
1564 Hook = UserCreateObject(gHandleTable, NULL, ptiHook, (PHANDLE)&Handle, TYPE_HOOK, sizeof(HOOK));
1565
1566 if (!Hook)
1567 {
1568 goto Cleanup; // Return NULL
1569 }
1570
1571 Hook->ihmod = (INT_PTR)Mod; // Module Index from atom table, Do this for now.
1572 Hook->HookId = HookId;
1573 Hook->rpdesk = ptiHook->rpdesk;
1574 Hook->phkNext = NULL; /* Dont use as a chain! Use link lists for chaining. */
1575 Hook->Proc = HookProc;
1576 Hook->Ansi = Ansi;
1577
1578 TRACE("Set Hook Desk %p DeskInfo %p Handle Desk %p\n", pti->rpdesk, pti->pDeskInfo, Hook->head.rpdesk);
1579
1580 if (ThreadId) /* Thread-local hook */
1581 {
1582 InsertHeadList(&ptiHook->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain);
1583 ptiHook->sphkCurrent = NULL;
1584 Hook->ptiHooked = ptiHook;
1585 ptiHook->fsHooks |= HOOKID_TO_FLAG(HookId);
1586
1587 if (ptiHook->pClientInfo)
1588 {
1589 if ( ptiHook->ppi == pti->ppi) /* gptiCurrent->ppi) */
1590 {
1591 _SEH2_TRY
1592 {
1593 ptiHook->pClientInfo->fsHooks = ptiHook->fsHooks;
1594 ptiHook->pClientInfo->phkCurrent = NULL;
1595 }
1597 {
1598 ERR("Problem writing to Local ClientInfo!\n");
1599 }
1600 _SEH2_END;
1601 }
1602 else
1603 {
1605
1606 KeStackAttachProcess(&ptiHook->ppi->peProcess->Pcb, &ApcState);
1607 _SEH2_TRY
1608 {
1609 ptiHook->pClientInfo->fsHooks = ptiHook->fsHooks;
1610 ptiHook->pClientInfo->phkCurrent = NULL;
1611 }
1613 {
1614 ERR("Problem writing to Remote ClientInfo!\n");
1615 }
1616 _SEH2_END;
1618 }
1619 }
1620 }
1621 else
1622 {
1623 InsertHeadList(&ptiHook->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain);
1624 Hook->ptiHooked = NULL;
1625 //gptiCurrent->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId);
1626 ptiHook->rpdesk->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId);
1627 ptiHook->sphkCurrent = NULL;
1628 ptiHook->pClientInfo->phkCurrent = NULL;
1629 }
1630
1632
1633 if (Mod)
1634 {
1636 UnsafeModuleName,
1637 sizeof(UNICODE_STRING));
1638 if (!NT_SUCCESS(Status))
1639 {
1640 IntRemoveHook(Hook);
1642 goto Cleanup; // Return NULL
1643 }
1644
1646 ModuleName.MaximumLength,
1647 TAG_HOOK);
1648 if (NULL == Hook->ModuleName.Buffer)
1649 {
1650 IntRemoveHook(Hook);
1652 goto Cleanup; // Return NULL
1653 }
1654
1655 Hook->ModuleName.MaximumLength = ModuleName.MaximumLength;
1657 ModuleName.Buffer,
1658 ModuleName.MaximumLength);
1659 if (!NT_SUCCESS(Status))
1660 {
1662 Hook->ModuleName.Buffer = NULL;
1663 IntRemoveHook(Hook);
1665 goto Cleanup; // Return NULL
1666 }
1667
1671 FIXME("NtUserSetWindowsHookEx Setting process hMod instance addressing.\n");
1672 /* Make proc relative to the module base */
1673 Hook->offPfn = (ULONG_PTR)((char *)HookProc - (char *)Mod);
1674 }
1675 else
1676 Hook->offPfn = 0;
1677
1678 TRACE("Installing: HookId %d Global %s\n", HookId, !ThreadId ? "TRUE" : "FALSE");
1679 Ret = Handle;
1680
1681Cleanup:
1682 if (Hook)
1684 TRACE("Leave NtUserSetWindowsHookEx, ret=%p\n", Ret);
1685 UserLeave();
1686 return Ret;
1687}
1688
1689BOOL
1692{
1693 PHOOK HookObj;
1694 BOOL Ret = FALSE;
1695
1696 TRACE("Enter NtUserUnhookWindowsHookEx\n");
1698
1699 if (!(HookObj = IntGetHookObject(Hook)))
1700 {
1701 ERR("Invalid handle passed to NtUserUnhookWindowsHookEx\n");
1702 /* SetLastNtError(Status); */
1703 goto Exit; // Return FALSE
1704 }
1705
1706 ASSERT(Hook == UserHMGetHandle(HookObj));
1707
1708 IntRemoveHook(HookObj);
1709
1710 UserDereferenceObject(HookObj);
1711
1712 Ret = TRUE;
1713
1714Exit:
1715 TRACE("Leave NtUserUnhookWindowsHookEx, ret=%i\n", Ret);
1716 UserLeave();
1717 return Ret;
1718}
1719
1720BOOL
1723 PUNICODE_STRING m_dllname1,
1724 PUNICODE_STRING m_funname1,
1725 DWORD dwUnknown3,
1726 DWORD dwUnknown4)
1727{
1728 BOOL ret;
1729 UNICODE_STRING strDllNameSafe;
1730 UNICODE_STRING strFuncNameSafe;
1732
1733 /* Probe and capture parameters */
1734 Status = ProbeAndCaptureUnicodeString(&strDllNameSafe, UserMode, m_dllname1);
1735 if(!NT_SUCCESS(Status))
1736 {
1738 return FALSE;
1739 }
1740
1741 Status = ProbeAndCaptureUnicodeString(&strFuncNameSafe, UserMode, m_funname1);
1742 if(!NT_SUCCESS(Status))
1743 {
1744 ReleaseCapturedUnicodeString(&strDllNameSafe, UserMode);
1746 return FALSE;
1747 }
1748
1750
1751 /* Call internal function */
1752 ret = UserRegisterUserApiHook(&strDllNameSafe, &strFuncNameSafe);
1753
1754 UserLeave();
1755
1756 /* Cleanup only in case of failure */
1757 if(ret == FALSE)
1758 {
1759 ReleaseCapturedUnicodeString(&strDllNameSafe, UserMode);
1760 ReleaseCapturedUnicodeString(&strFuncNameSafe, UserMode);
1761 }
1762
1763 return ret;
1764}
1765
1766BOOL
1769{
1770 BOOL ret;
1771
1774 UserLeave();
1775
1776 return ret;
1777}
1778
1779/* EOF */
#define MSG
Definition: Mailslot.c:11
unsigned char BOOLEAN
ACPI_BUFFER *RetBuffer ACPI_BUFFER *RetBuffer char ACPI_WALK_RESOURCE_CALLBACK void *Context ACPI_BUFFER *RetBuffer UINT16 ACPI_RESOURCE **ResourcePtr ACPI_GENERIC_ADDRESS *Reg UINT32 *ReturnValue UINT8 UINT8 *Slp_TypB ACPI_PHYSICAL_ADDRESS PhysicalAddress64 UINT32 UINT32 *TimeElapsed UINT32 ACPI_STATUS const char UINT32 ACPI_STATUS const char UINT32 const char const char * ModuleName
Definition: acpixf.h:1280
LONG NTSTATUS
Definition: precomp.h:26
#define FIXME(fmt,...)
Definition: precomp.h:53
#define ERR(fmt,...)
Definition: precomp.h:57
#define UlongToHandle(ul)
Definition: basetsd.h:97
#define PtrToUint(p)
Definition: basetsd.h:85
#define IntToPtr(i)
Definition: basetsd.h:89
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
#define IS_ATOM(x)
Definition: class.h:3
struct @1636 Msg[]
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
PEPROCESS gpepCSRSS
Definition: csr.c:15
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define APIENTRY
Definition: api.h:79
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
PSERVERINFO gpsi
Definition: imm.c:18
static const WCHAR Cleanup[]
Definition: register.c:80
#define ULONG_PTR
Definition: config.h:101
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define NonPagedPool
Definition: env_spec_w32.h:307
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
static VOID NTAPI Unload(PDRIVER_OBJECT DriverObject)
Definition: floppy.c:377
FxChildList * pList
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define HOOKID_TO_INDEX(HookId)
Definition: hook.h:4
#define ISITHOOKED(HookId)
Definition: hook.h:6
#define WH_APIHOOK
Definition: hook.h:12
#define HOOKID_TO_FLAG(HookId)
Definition: hook.h:5
@ Keyboard
Definition: i8042prt.h:115
@ Mouse
Definition: i8042prt.h:116
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define TIF_CSRSSTHREAD
Definition: ntuser.h:266
#define TIF_INCLEANUP
Definition: ntuser.h:263
#define UserHMGetHandle(obj)
Definition: ntuser.h:230
struct tagHOOK * PHOOK
struct _THREADINFO * GetW32ThreadInfo(VOID)
Definition: misc.c:807
@ TYPE_HOOK
Definition: ntuser.h:45
#define SRVINFO_APIHOOK
Definition: ntuser.h:950
#define TIF_SYSTEMTHREAD
Definition: ntuser.h:265
#define TIF_DISABLEHOOKS
Definition: ntuser.h:291
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
CLIENT_DATA ClientInfo
#define NtCurrentTeb
#define STUB
Definition: kernel32.h:27
UNICODE_STRING Global
Definition: symlink.c:46
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define _Analysis_assume_(expr)
Definition: ms_sal.h:2901
NTSTATUS FASTCALL co_MsqSendMessage(PTHREADINFO ptirec, HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam, UINT uTimeout, BOOL Block, INT HookMessage, ULONG_PTR *uResult)
Definition: msgqueue.c:1056
BOOL FASTCALL co_MsqSendMessageAsync(PTHREADINFO ptiReceiver, HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, SENDASYNCPROC CompletionCallback, ULONG_PTR CompletionCallbackContext, BOOL HasPackedLParam, INT HookMessage)
Definition: msgqueue.c:1014
#define MSQ_ISHOOK
Definition: msgqueue.h:5
#define MSQ_INJECTMODULE
Definition: msgqueue.h:6
unsigned int UINT
Definition: ndis.h:50
#define UserMode
Definition: asm.h:35
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define FASTCALL
Definition: nt_native.h:50
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1765
BOOLEAN NTAPI PsIsSystemProcess(IN PEPROCESS Process)
Definition: process.c:1223
PVOID NTAPI PsGetProcessWin32Process(PEPROCESS Process)
Definition: process.c:1193
PVOID NTAPI PsGetCurrentProcessWin32Process(VOID)
Definition: process.c:1183
HANDLE NTAPI PsGetProcessId(PEPROCESS Process)
Definition: process.c:1063
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
static HHOOK *FASTCALL IntGetGlobalHookHandles(PDESKTOP pdo, int HookId)
Definition: hook.c:962
LRESULT APIENTRY co_CallHook(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
Definition: hook.c:321
struct _HOOKPACK HOOKPACK
UNICODE_STRING strUahModule
Definition: hook.c:22
static LRESULT APIENTRY co_HOOK_CallHookNext(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam)
Definition: hook.c:367
static LRESULT FASTCALL co_IntCallLowLevelHook(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam)
Definition: hook.c:239
BOOL FASTCALL UserUnregisterUserApiHook(VOID)
Definition: hook.c:206
UNICODE_STRING strUahInitFunc
Definition: hook.c:23
BOOL APIENTRY NtUserUnregisterUserApiHook(VOID)
Definition: hook.c:1768
BOOL APIENTRY NtUserRegisterUserApiHook(PUNICODE_STRING m_dllname1, PUNICODE_STRING m_funname1, DWORD dwUnknown3, DWORD dwUnknown4)
Definition: hook.c:1722
LRESULT APIENTRY NtUserCallNextHookEx(int Code, WPARAM wParam, LPARAM lParam, BOOL Ansi)
Definition: hook.c:1370
PHOOK FASTCALL IntGetNextHook(PHOOK Hook)
Definition: hook.c:995
struct _HOOKPACK * PHOOKPACK
BOOL IntHookModuleUnloaded(PDESKTOP pdesk, int iHookID, HHOOK hHook)
Definition: hook.c:88
LRESULT APIENTRY co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
Definition: hook.c:1102
BOOL APIENTRY NtUserUnhookWindowsHookEx(HHOOK Hook)
Definition: hook.c:1691
BOOL FASTCALL UserLoadApiHook(VOID)
Definition: hook.c:131
HHOOK APIENTRY NtUserSetWindowsHookEx(HINSTANCE Mod, PUNICODE_STRING UnsafeModuleName, DWORD ThreadId, int HookId, HOOKPROC HookProc, BOOL Ansi)
Definition: hook.c:1439
static LRESULT FASTCALL co_IntCallDebugHook(PHOOK Hook, int Code, WPARAM wParam, LPARAM lParam, BOOL Ansi)
Definition: hook.c:388
HHOOK APIENTRY NtUserSetWindowsHookAW(int idHook, HOOKPROC lpfn, BOOL Ansi)
Definition: hook.c:1419
static VOID FASTCALL IntFreeHook(PHOOK Hook)
Definition: hook.c:1022
static LRESULT APIENTRY co_UserCallNextHookEx(PHOOK Hook, int Code, WPARAM wParam, LPARAM lParam, BOOL Ansi)
Definition: hook.c:521
PHOOK FASTCALL IntGetHookObject(HHOOK hHook)
Definition: hook.c:937
PPROCESSINFO ppiUahServer
Definition: hook.c:24
BOOLEAN IntRemoveHook(PVOID Object)
Definition: hook.c:1036
BOOL IntLoadHookModule(int iHookID, HHOOK hHook, BOOL Unload)
Definition: hook.c:30
BOOL FASTCALL IntUnhookWindowsHook(int HookId, HOOKPROC pfnFilterProc)
Definition: hook.c:1319
BOOL FASTCALL UserRegisterUserApiHook(PUNICODE_STRING pstrDllName, PUNICODE_STRING pstrFuncName)
Definition: hook.c:138
NTSTATUS FASTCALL IntValidateWindowStationHandle(HWINSTA WindowStation, KPROCESSOR_MODE AccessMode, ACCESS_MASK DesiredAccess, PWINSTATION_OBJECT *Object, POBJECT_HANDLE_INFORMATION pObjectHandleInfo)
Definition: winsta.c:232
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:258
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:249
BOOL FASTCALL UserIsEnteredExclusive(VOID)
Definition: ntuser.c:231
static __inline VOID UserDerefObjectCo(PVOID obj)
Definition: object.h:40
static __inline VOID UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry)
Definition: object.h:27
#define MmCopyFromCaller
Definition: polytest.cpp:29
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
static __inline NTSTATUS ProbeAndCaptureUnicodeString(OUT PUNICODE_STRING Dest, IN KPROCESSOR_MODE CurrentMode, IN const UNICODE_STRING *UnsafeSrc)
Definition: probe.h:142
static __inline VOID ReleaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString, IN KPROCESSOR_MODE CurrentMode)
Definition: probe.h:239
static void Exit(void)
Definition: sock.c:1330
#define TRACE(s)
Definition: solgame.cpp:4
Implementation of the Explorer desktop window.
Definition: desktop.h:52
HANDLE UniqueThread
Definition: compat.h:826
DWORD fsHooks
Definition: ntuser.h:138
LIST_ENTRY aphkStart[NB_HOOKS]
Definition: ntuser.h:139
LIST_ENTRY PtiList
Definition: desktop.h:25
PDESKTOPINFO pDeskInfo
Definition: desktop.h:8
Definition: hook.c:16
PVOID pHookStructs
Definition: hook.c:19
PHOOK pHk
Definition: hook.c:17
LPARAM lParam
Definition: hook.c:18
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
struct _DESKTOP * rpdesk
Definition: ntuser.h:194
PPROCESSINFO ppi
Definition: win32.h:88
struct _DESKTOPINFO * pDeskInfo
Definition: win32.h:93
struct tagHOOK * sphkCurrent
Definition: win32.h:118
ULONG fsHooks
Definition: win32.h:117
struct _CLIENTINFO * pClientInfo
Definition: win32.h:94
LIST_ENTRY aphkStart[NB_HOOKS]
FIXME!
Definition: win32.h:143
FLONG TIF_flags
Definition: win32.h:95
struct _DESKTOP * rpdesk
Definition: win32.h:92
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: object.h:4
Definition: ntuser.h:694
THRDESKHEAD head
Definition: ntuser.h:695
ACPI_SIZE Length
Definition: actypes.h:1053
LPCREATESTRUCTW lpcs
Definition: winuser.h:2978
LPCWSTR lpszClass
Definition: winuser.h:2968
LPCWSTR lpszName
Definition: winuser.h:2967
INT_PTR ihmod
Definition: ntuser.h:245
struct tagHOOK * phkNext
Definition: ntuser.h:241
THRDESKHEAD head
Definition: ntuser.h:240
HOOKPROC Proc
Definition: ntuser.h:250
LIST_ENTRY Chain
Definition: ntuser.h:249
ULONG_PTR offPfn
Definition: ntuser.h:243
int HookId
Definition: ntuser.h:242
struct _THREADINFO * ptiHooked
Definition: ntuser.h:246
struct _DESKTOP * rpdesk
Definition: ntuser.h:247
BOOLEAN Ansi
Definition: ntuser.h:251
UNICODE_STRING ModuleName
Definition: ntuser.h:252
DWORD dwSRVIFlags
Definition: ntuser.h:1051
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
int32_t INT_PTR
Definition: typedefs.h:64
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:124
int ret
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_In_ UCHAR _In_ UCHAR _In_ ULONG Code
Definition: wdfdevice.h:1701
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
#define IntDereferenceThreadInfo(pti)
Definition: win32.h:171
#define IntReferenceThreadInfo(pti)
Definition: win32.h:166
#define W32PF_APIHOOKLOADED
Definition: win32.h:35
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:31
#define RECT
Definition: precomp.h:26
BOOL NTAPI co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName, PUNICODE_STRING pstrInitFunc, BOOL Unload, BOOL ApiHook)
Definition: callback.c:136
LRESULT APIENTRY co_IntCallHookProc(INT HookId, INT Code, WPARAM wParam, LPARAM lParam, HOOKPROC Proc, INT Mod, ULONG_PTR offPfn, BOOLEAN Ansi, PUNICODE_STRING ModuleName)
Definition: callback.c:508
PDESKTOP FASTCALL IntGetActiveDesktop(VOID)
Definition: desktop.c:1279
HWND FASTCALL IntGetDesktopWindow(VOID)
Definition: desktop.c:1391
PTHREADINFO FASTCALL IntTID2PTI(HANDLE id)
Definition: misc.c:42
PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type)
Definition: object.c:495
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:644
BOOL FASTCALL UserDeleteObject(HANDLE h, HANDLE_TYPE type)
Definition: object.c:717
PUSER_HANDLE_TABLE gHandleTable
Definition: object.c:13
BOOL FASTCALL UserObjectInDestroy(HANDLE h)
Definition: object.c:703
PVOID FASTCALL UserCreateObject(PUSER_HANDLE_TABLE ht, PDESKTOP pDesktop, PTHREADINFO pti, HANDLE *h, HANDLE_TYPE type, ULONG size)
Definition: object.c:568
VOID FASTCALL UserReferenceObject(PVOID obj)
Definition: object.c:731
#define USERTAG_WINDOWLIST
Definition: tags.h:298
#define TAG_HOOK
Definition: tags.h:5
HWND *FASTCALL IntWinListChildren(PWND Window)
Definition: window.c:276
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:22
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
#define ERROR_HOOK_TYPE_NOT_ALLOWED
Definition: winerror.h:939
#define ERROR_INVALID_FILTER_PROC
Definition: winerror.h:908
#define ERROR_HOOK_NEEDS_HMOD
Definition: winerror.h:909
#define ERROR_INVALID_HOOK_FILTER
Definition: winerror.h:907
#define ERROR_INVALID_HOOK_HANDLE
Definition: winerror.h:885
#define ERROR_GLOBAL_ONLY_HOOK
Definition: winerror.h:910
#define WH_KEYBOARD
Definition: winuser.h:32
LRESULT(CALLBACK * HOOKPROC)(int, WPARAM, LPARAM)
Definition: winuser.h:2902
#define WH_CALLWNDPROCRET
Definition: winuser.h:42
struct tagEVENTMSG EVENTMSG
struct tagMOUSEHOOKSTRUCT MOUSEHOOKSTRUCT
#define HCBT_ACTIVATE
Definition: winuser.h:60
#define WH_MSGFILTER
Definition: winuser.h:29
#define WH_MINHOOK
Definition: winuser.h:46
#define WH_MAXHOOK
Definition: winuser.h:47
struct tagCBTACTIVATESTRUCT CBTACTIVATESTRUCT
#define WH_SHELL
Definition: winuser.h:40
CBT_CREATEWNDA CBT_CREATEWND
Definition: winuser.h:5739
#define WH_CBT
Definition: winuser.h:35
#define WH_JOURNALPLAYBACK
Definition: winuser.h:31
#define HCBT_CREATEWND
Definition: winuser.h:58
#define WH_MOUSE_LL
Definition: winuser.h:44
#define WH_DEBUG
Definition: winuser.h:39
#define WH_MOUSE
Definition: winuser.h:37
#define WH_HARDWARE
Definition: winuser.h:38
#define HCBT_CLICKSKIPPED
Definition: winuser.h:61
#define HCBT_MOVESIZE
Definition: winuser.h:55
#define WH_KEYBOARD_LL
Definition: winuser.h:43
#define WH_GETMESSAGE
Definition: winuser.h:33
#define WH_SYSMSGFILTER
Definition: winuser.h:36
struct tagMSLLHOOKSTRUCT MSLLHOOKSTRUCT
struct tagKBDLLHOOKSTRUCT KBDLLHOOKSTRUCT
#define WH_FOREGROUNDIDLE
Definition: winuser.h:41
struct tagCBT_CREATEWNDW * LPCBT_CREATEWNDW
#define WH_JOURNALRECORD
Definition: winuser.h:30
#define WH_CALLWNDPROC
Definition: winuser.h:34
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1151
KAPC_STATE
Definition: ketypes.h:1409
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define NT_ASSERT
Definition: rtlfuncs.h:3324
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175