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