ReactOS  0.4.12-dev-934-g9a4676f
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 pti;
1041  PDESKTOP pdo;
1042  PHOOK Hook = Object;
1043 
1044  HookId = Hook->HookId;
1045 
1046  if (Hook->ptiHooked) // Local
1047  {
1048  pti = Hook->ptiHooked;
1049 
1050  IntFreeHook( Hook);
1051 
1052  if ( IsListEmpty(&pti->aphkStart[HOOKID_TO_INDEX(HookId)]) )
1053  {
1054  pti->fsHooks &= ~HOOKID_TO_FLAG(HookId);
1055  _SEH2_TRY
1056  {
1057  pti->pClientInfo->fsHooks = pti->fsHooks;
1058  }
1060  {
1061  /* Do nothing */
1062  (void)0;
1063  }
1064  _SEH2_END;
1065  }
1066  }
1067  else // Global
1068  {
1069  IntFreeHook( Hook);
1070 
1071  pdo = IntGetActiveDesktop();
1072 
1073  if ( pdo &&
1074  pdo->pDeskInfo &&
1075  IsListEmpty(&pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) )
1076  {
1077  pdo->pDeskInfo->fsHooks &= ~HOOKID_TO_FLAG(HookId);
1078  }
1079  }
1080 
1081  return TRUE;
1082 }
1083 
1084 /*
1085  Win32k Kernel Space Hook Caller.
1086  */
1087 LRESULT
1088 APIENTRY
1090  INT Code,
1091  WPARAM wParam,
1092  LPARAM lParam)
1093 {
1094  PHOOK Hook, SaveHook;
1095  PTHREADINFO pti;
1097  PLIST_ENTRY pLastHead;
1098  PDESKTOP pdo;
1099  BOOL Local = FALSE, Global = FALSE;
1100  LRESULT Result = 0;
1102 
1103  ASSERT(WH_MINHOOK <= HookId && HookId <= WH_MAXHOOK);
1104 
1106  if (!pti || !pti->rpdesk || !pti->rpdesk->pDeskInfo)
1107  {
1108  pdo = IntGetActiveDesktop();
1109  /* If KeyboardThread|MouseThread|(RawInputThread or RIT) aka system threads,
1110  pti->fsHooks most likely, is zero. So process KbT & MsT to "send" the message.
1111  */
1112  if ( !pti || !pdo || (!(HookId == WH_KEYBOARD_LL) && !(HookId == WH_MOUSE_LL)) )
1113  {
1114  TRACE("No PDO %d\n", HookId);
1115  goto Exit;
1116  }
1117  }
1118  else
1119  {
1120  pdo = pti->rpdesk;
1121  }
1122 
1124  {
1125  TRACE("Hook Thread dead %d\n", HookId);
1126  goto Exit;
1127  }
1128 
1129  if ( ISITHOOKED(HookId) )
1130  {
1131  TRACE("Local Hooker %d\n", HookId);
1132  Local = TRUE;
1133  }
1134 
1135  if ( pdo->pDeskInfo->fsHooks & HOOKID_TO_FLAG(HookId) )
1136  {
1137  TRACE("Global Hooker %d\n", HookId);
1138  Global = TRUE;
1139  }
1140 
1141  if ( !Local && !Global ) goto Exit; // No work!
1142 
1143  Hook = NULL;
1144 
1145  /* SetWindowHookEx sorts out the Thread issue by placing the Hook to
1146  the correct Thread if not NULL.
1147  */
1148  if ( Local )
1149  {
1150  pLastHead = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
1151  if (IsListEmpty(pLastHead))
1152  {
1153  ERR("No Local Hook Found!\n");
1154  goto Exit;
1155  }
1156 
1157  Hook = CONTAINING_RECORD(pLastHead->Flink, HOOK, Chain);
1158  ObReferenceObject(pti->pEThread);
1160  UserRefObjectCo(Hook, &Ref);
1161 
1162  ClientInfo = pti->pClientInfo;
1163  SaveHook = pti->sphkCurrent;
1164  /* Note: Setting pti->sphkCurrent will also lock the next hook to this
1165  * hook ID. So, the CallNextHookEx will only call to that hook ID
1166  * chain anyway. For Thread Hooks....
1167  */
1168 
1169  /* Load it for the next call. */
1170  pti->sphkCurrent = Hook;
1171  Hook->phkNext = IntGetNextHook(Hook);
1172  if (ClientInfo)
1173  {
1174  _SEH2_TRY
1175  {
1176  ClientInfo->phkCurrent = Hook;
1177  }
1179  {
1180  ClientInfo = NULL; // Don't bother next run.
1181  }
1182  _SEH2_END;
1183  }
1184  Result = co_IntCallHookProc( HookId,
1185  Code,
1186  wParam,
1187  lParam,
1188  Hook->Proc,
1189  Hook->ihmod,
1190  Hook->offPfn,
1191  Hook->Ansi,
1192  &Hook->ModuleName);
1193  if (ClientInfo)
1194  {
1195  _SEH2_TRY
1196  {
1197  ClientInfo->phkCurrent = SaveHook;
1198  }
1200  {
1201  /* Do nothing */
1202  (void)0;
1203  }
1204  _SEH2_END;
1205  }
1206  pti->sphkCurrent = SaveHook;
1207  Hook->phkNext = NULL;
1208  UserDerefObjectCo(Hook);
1210  ObDereferenceObject(pti->pEThread);
1211  }
1212 
1213  if ( Global )
1214  {
1215  PTHREADINFO ptiHook;
1216  HHOOK *pHookHandles;
1217  unsigned i;
1218 
1219  /* Keep hooks in array because hooks can be destroyed in user world */
1220  pHookHandles = IntGetGlobalHookHandles(pdo, HookId);
1221  if(!pHookHandles)
1222  goto Exit;
1223 
1224  /* Performance goes down the drain. If more hooks are associated to this
1225  * hook ID, this will have to post to each of the thread message queues
1226  * or make a direct call.
1227  */
1228  for(i = 0; pHookHandles[i]; ++i)
1229  {
1230  Hook = (PHOOK)UserGetObject(gHandleTable, pHookHandles[i], TYPE_HOOK);
1231  if(!Hook)
1232  {
1233  ERR("Invalid hook!\n");
1234  continue;
1235  }
1236 
1237  /* Hook->Thread is null, we hax around this with Hook->head.pti. */
1238  ptiHook = Hook->head.pti;
1239 
1240  if ( (pti->TIF_flags & TIF_DISABLEHOOKS) || (ptiHook->TIF_flags & TIF_INCLEANUP))
1241  {
1242  TRACE("Next Hook %p, %p\n", ptiHook->rpdesk, pdo);
1243  continue;
1244  }
1245  UserRefObjectCo(Hook, &Ref);
1246 
1247  if (ptiHook != pti )
1248  {
1249  // Block | TimeOut
1250  if ( HookId == WH_JOURNALPLAYBACK || // 1 | 0
1251  HookId == WH_JOURNALRECORD || // 1 | 0
1252  HookId == WH_KEYBOARD || // 1 | 200
1253  HookId == WH_MOUSE || // 1 | 200
1254  HookId == WH_KEYBOARD_LL || // 0 | 300
1255  HookId == WH_MOUSE_LL ) // 0 | 300
1256  {
1257  TRACE("\nGlobal Hook posting to another Thread! %d\n",HookId );
1259  }
1260  else if (ptiHook->ppi == pti->ppi)
1261  {
1262  TRACE("\nGlobal Hook calling to another Thread! %d\n",HookId );
1263  ObReferenceObject(ptiHook->pEThread);
1264  IntReferenceThreadInfo(ptiHook);
1265  Result = co_IntCallHookProc( HookId,
1266  Code,
1267  wParam,
1268  lParam,
1269  Hook->Proc,
1270  Hook->ihmod,
1271  Hook->offPfn,
1272  Hook->Ansi,
1273  &Hook->ModuleName);
1274  IntDereferenceThreadInfo(ptiHook);
1275  ObDereferenceObject(ptiHook->pEThread);
1276  }
1277  }
1278  else
1279  { /* Make the direct call. */
1280  TRACE("Global going Local Hook calling to Thread! %d\n",HookId );
1281  ObReferenceObject(pti->pEThread);
1283  Result = co_IntCallHookProc( HookId,
1284  Code,
1285  wParam,
1286  lParam,
1287  Hook->Proc,
1288  Hook->ihmod,
1289  Hook->offPfn,
1290  Hook->Ansi,
1291  &Hook->ModuleName);
1293  ObDereferenceObject(pti->pEThread);
1294  }
1295  UserDerefObjectCo(Hook);
1296  }
1297  ExFreePoolWithTag(pHookHandles, TAG_HOOK);
1298  TRACE("Ret: Global HookId %d Result 0x%x\n", HookId,Result);
1299  }
1300 Exit:
1301  return Result;
1302 }
1303 
1304 BOOL
1305 FASTCALL
1306 IntUnhookWindowsHook(int HookId, HOOKPROC pfnFilterProc)
1307 {
1308  PHOOK Hook;
1309  PLIST_ENTRY pLastHead, pElement;
1311 
1312  if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId )
1313  {
1315  return FALSE;
1316  }
1317 
1318  if (pti->fsHooks)
1319  {
1320  pLastHead = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
1321 
1322  pElement = pLastHead->Flink;
1323  while (pElement != pLastHead)
1324  {
1325  Hook = CONTAINING_RECORD(pElement, HOOK, Chain);
1326 
1327  /* Get the next element now, we might free the hook in what follows */
1328  pElement = Hook->Chain.Flink;
1329 
1330  if (Hook->Proc == pfnFilterProc)
1331  {
1332  if (Hook->head.pti == pti)
1333  {
1334  IntRemoveHook(Hook);
1335  return TRUE;
1336  }
1337  else
1338  {
1340  return FALSE;
1341  }
1342  }
1343  }
1344  }
1345  return FALSE;
1346 }
1347 
1348 /*
1349  * Support for compatibility only? Global hooks are processed in kernel space.
1350  * This is very thread specific! Never seeing applications with more than one
1351  * hook per thread installed. Most of the applications are Global hookers and
1352  * associated with just one hook Id. Maybe it's for diagnostic testing or a
1353  * throw back to 3.11?
1354  */
1355 LRESULT
1356 APIENTRY
1358  WPARAM wParam,
1359  LPARAM lParam,
1360  BOOL Ansi)
1361 {
1362  PTHREADINFO pti;
1363  PHOOK HookObj, NextObj;
1365  LRESULT lResult = 0;
1367 
1368  TRACE("Enter NtUserCallNextHookEx\n");
1370 
1371  pti = GetW32ThreadInfo();
1372 
1373  HookObj = pti->sphkCurrent;
1374 
1375  if (!HookObj) RETURN( 0);
1376 
1377  NextObj = HookObj->phkNext;
1378 
1379  pti->sphkCurrent = NextObj;
1380  ClientInfo = pti->pClientInfo;
1381  _SEH2_TRY
1382  {
1383  ClientInfo->phkCurrent = NextObj;
1384  }
1386  {
1387  ClientInfo = NULL;
1388  }
1389  _SEH2_END;
1390 
1391  /* Now in List run down. */
1392  if (ClientInfo && NextObj)
1393  {
1394  NextObj->phkNext = IntGetNextHook(NextObj);
1395  lResult = co_UserCallNextHookEx( NextObj, Code, wParam, lParam, NextObj->Ansi);
1396  }
1397  RETURN( lResult);
1398 
1399 CLEANUP:
1400  TRACE("Leave NtUserCallNextHookEx, ret=%i\n",_ret_);
1401  UserLeave();
1402  END_CLEANUP;
1403 }
1404 
1405 HHOOK
1406 APIENTRY
1408  HOOKPROC lpfn,
1409  BOOL Ansi)
1410 {
1411  DWORD ThreadId;
1412  UNICODE_STRING USModuleName;
1413 
1414  RtlInitUnicodeString(&USModuleName, NULL);
1416 
1417  return NtUserSetWindowsHookEx( NULL,
1418  &USModuleName,
1419  ThreadId,
1420  idHook,
1421  lpfn,
1422  Ansi);
1423 }
1424 
1425 HHOOK
1426 APIENTRY
1428  PUNICODE_STRING UnsafeModuleName,
1429  DWORD ThreadId,
1430  int HookId,
1431  HOOKPROC HookProc,
1432  BOOL Ansi)
1433 {
1434  PWINSTATION_OBJECT WinStaObj;
1435  PHOOK Hook = NULL;
1437  NTSTATUS Status;
1438  HHOOK Handle;
1439  PTHREADINFO pti, ptiHook = NULL;
1440  DECLARE_RETURN(HHOOK);
1441 
1442  TRACE("Enter NtUserSetWindowsHookEx\n");
1444 
1446 
1447  if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId )
1448  {
1450  RETURN( NULL);
1451  }
1452 
1453  if (!HookProc)
1454  {
1456  RETURN( NULL);
1457  }
1458 
1459  if (ThreadId) /* thread-local hook */
1460  {
1461  if ( HookId == WH_JOURNALRECORD ||
1462  HookId == WH_JOURNALPLAYBACK ||
1463  HookId == WH_KEYBOARD_LL ||
1464  HookId == WH_MOUSE_LL ||
1465  HookId == WH_SYSMSGFILTER)
1466  {
1467  TRACE("Local hook installing Global HookId: %d\n",HookId);
1468  /* these can only be global */
1470  RETURN( NULL);
1471  }
1472 
1473  if ( !(ptiHook = IntTID2PTI( UlongToHandle(ThreadId) )))
1474  {
1475  ERR("Invalid thread id 0x%x\n", ThreadId);
1477  RETURN( NULL);
1478  }
1479 
1480  if ( ptiHook->rpdesk != pti->rpdesk) // gptiCurrent->rpdesk)
1481  {
1482  ERR("Local hook wrong desktop HookId: %d\n",HookId);
1484  RETURN( NULL);
1485  }
1486 
1487  if (ptiHook->ppi != pti->ppi)
1488  {
1489  if ( !Mod &&
1490  (HookId == WH_GETMESSAGE ||
1491  HookId == WH_CALLWNDPROC ||
1492  HookId == WH_CBT ||
1493  HookId == WH_HARDWARE ||
1494  HookId == WH_DEBUG ||
1495  HookId == WH_SHELL ||
1496  HookId == WH_FOREGROUNDIDLE ||
1497  HookId == WH_CALLWNDPROCRET) )
1498  {
1499  ERR("Local hook needs hMod HookId: %d\n",HookId);
1501  RETURN( NULL);
1502  }
1503 
1504  if ( (ptiHook->TIF_flags & (TIF_CSRSSTHREAD|TIF_SYSTEMTHREAD)) &&
1505  (HookId == WH_GETMESSAGE ||
1506  HookId == WH_CALLWNDPROC ||
1507  HookId == WH_CBT ||
1508  HookId == WH_HARDWARE ||
1509  HookId == WH_DEBUG ||
1510  HookId == WH_SHELL ||
1511  HookId == WH_FOREGROUNDIDLE ||
1512  HookId == WH_CALLWNDPROCRET) )
1513  {
1515  RETURN( NULL);
1516  }
1517  }
1518  }
1519  else /* System-global hook */
1520  {
1521  ptiHook = pti; // gptiCurrent;
1522  if ( !Mod &&
1523  (HookId == WH_GETMESSAGE ||
1524  HookId == WH_CALLWNDPROC ||
1525  HookId == WH_CBT ||
1526  HookId == WH_SYSMSGFILTER ||
1527  HookId == WH_HARDWARE ||
1528  HookId == WH_DEBUG ||
1529  HookId == WH_SHELL ||
1530  HookId == WH_FOREGROUNDIDLE ||
1531  HookId == WH_CALLWNDPROCRET) )
1532  {
1533  ERR("Global hook needs hMod HookId: %d\n",HookId);
1535  RETURN( NULL);
1536  }
1537  }
1538 
1540  UserMode,
1541  0,
1542  &WinStaObj,
1543  0);
1544 
1545  if (!NT_SUCCESS(Status))
1546  {
1548  RETURN( NULL);
1549  }
1550  ObDereferenceObject(WinStaObj);
1551 
1552  Hook = UserCreateObject(gHandleTable, NULL, ptiHook, (PHANDLE)&Handle, TYPE_HOOK, sizeof(HOOK));
1553 
1554  if (!Hook)
1555  {
1556  RETURN( NULL);
1557  }
1558 
1559  Hook->ihmod = (INT_PTR)Mod; // Module Index from atom table, Do this for now.
1560  Hook->HookId = HookId;
1561  Hook->rpdesk = ptiHook->rpdesk;
1562  Hook->phkNext = NULL; /* Dont use as a chain! Use link lists for chaining. */
1563  Hook->Proc = HookProc;
1564  Hook->Ansi = Ansi;
1565 
1566  TRACE("Set Hook Desk %p DeskInfo %p Handle Desk %p\n", pti->rpdesk, pti->pDeskInfo, Hook->head.rpdesk);
1567 
1568  if (ThreadId) /* Thread-local hook */
1569  {
1570  InsertHeadList(&ptiHook->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain);
1571  ptiHook->sphkCurrent = NULL;
1572  Hook->ptiHooked = ptiHook;
1573  ptiHook->fsHooks |= HOOKID_TO_FLAG(HookId);
1574 
1575  if (ptiHook->pClientInfo)
1576  {
1577  if ( ptiHook->ppi == pti->ppi) /* gptiCurrent->ppi) */
1578  {
1579  _SEH2_TRY
1580  {
1581  ptiHook->pClientInfo->fsHooks = ptiHook->fsHooks;
1582  ptiHook->pClientInfo->phkCurrent = NULL;
1583  }
1585  {
1586  ERR("Problem writing to Local ClientInfo!\n");
1587  }
1588  _SEH2_END;
1589  }
1590  else
1591  {
1592  KeAttachProcess(&ptiHook->ppi->peProcess->Pcb);
1593  _SEH2_TRY
1594  {
1595  ptiHook->pClientInfo->fsHooks = ptiHook->fsHooks;
1596  ptiHook->pClientInfo->phkCurrent = NULL;
1597  }
1599  {
1600  ERR("Problem writing to Remote ClientInfo!\n");
1601  }
1602  _SEH2_END;
1603  KeDetachProcess();
1604  }
1605  }
1606  }
1607  else
1608  {
1609  InsertHeadList(&ptiHook->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain);
1610  Hook->ptiHooked = NULL;
1611  //gptiCurrent->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId);
1612  ptiHook->rpdesk->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId);
1613  ptiHook->sphkCurrent = NULL;
1614  ptiHook->pClientInfo->phkCurrent = NULL;
1615  }
1616 
1618 
1619  if (Mod)
1620  {
1622  UnsafeModuleName,
1623  sizeof(UNICODE_STRING));
1624  if (!NT_SUCCESS(Status))
1625  {
1626  IntRemoveHook(Hook);
1628  RETURN( NULL);
1629  }
1630 
1632  ModuleName.MaximumLength,
1633  TAG_HOOK);
1634  if (NULL == Hook->ModuleName.Buffer)
1635  {
1636  IntRemoveHook(Hook);
1638  RETURN( NULL);
1639  }
1640 
1641  Hook->ModuleName.MaximumLength = ModuleName.MaximumLength;
1643  ModuleName.Buffer,
1644  ModuleName.MaximumLength);
1645  if (!NT_SUCCESS(Status))
1646  {
1648  Hook->ModuleName.Buffer = NULL;
1649  IntRemoveHook(Hook);
1651  RETURN( NULL);
1652  }
1653 
1657  FIXME("NtUserSetWindowsHookEx Setting process hMod instance addressing.\n");
1658  /* Make proc relative to the module base */
1659  Hook->offPfn = (ULONG_PTR)((char *)HookProc - (char *)Mod);
1660  }
1661  else
1662  Hook->offPfn = 0;
1663 
1664  TRACE("Installing: HookId %d Global %s\n", HookId, !ThreadId ? "TRUE" : "FALSE");
1665  RETURN( Handle);
1666 
1667 CLEANUP:
1668  if (Hook)
1669  UserDereferenceObject(Hook);
1670  TRACE("Leave NtUserSetWindowsHookEx, ret=%p\n", _ret_);
1671  UserLeave();
1672  END_CLEANUP;
1673 }
1674 
1675 BOOL
1676 APIENTRY
1678 {
1679  PHOOK HookObj;
1681 
1682  TRACE("Enter NtUserUnhookWindowsHookEx\n");
1684 
1685  if (!(HookObj = IntGetHookObject(Hook)))
1686  {
1687  ERR("Invalid handle passed to NtUserUnhookWindowsHookEx\n");
1688  /* SetLastNtError(Status); */
1689  RETURN( FALSE);
1690  }
1691 
1692  ASSERT(Hook == UserHMGetHandle(HookObj));
1693 
1694  IntRemoveHook(HookObj);
1695 
1696  UserDereferenceObject(HookObj);
1697 
1698  RETURN( TRUE);
1699 
1700 CLEANUP:
1701  TRACE("Leave NtUserUnhookWindowsHookEx, ret=%i\n",_ret_);
1702  UserLeave();
1703  END_CLEANUP;
1704 }
1705 
1706 BOOL
1707 APIENTRY
1709  PUNICODE_STRING m_dllname1,
1710  PUNICODE_STRING m_funname1,
1711  DWORD dwUnknown3,
1712  DWORD dwUnknown4)
1713 {
1714  BOOL ret;
1715  UNICODE_STRING strDllNameSafe;
1716  UNICODE_STRING strFuncNameSafe;
1717  NTSTATUS Status;
1718 
1719  /* Probe and capture parameters */
1720  Status = ProbeAndCaptureUnicodeString(&strDllNameSafe, UserMode, m_dllname1);
1721  if(!NT_SUCCESS(Status))
1722  {
1724  return FALSE;
1725  }
1726 
1727  Status = ProbeAndCaptureUnicodeString(&strFuncNameSafe, UserMode, m_funname1);
1728  if(!NT_SUCCESS(Status))
1729  {
1730  ReleaseCapturedUnicodeString(&strDllNameSafe, UserMode);
1732  return FALSE;
1733  }
1734 
1736 
1737  /* Call internal function */
1738  ret = UserRegisterUserApiHook(&strDllNameSafe, &strFuncNameSafe);
1739 
1740  UserLeave();
1741 
1742  /* Cleanup only in case of failure */
1743  if(ret == FALSE)
1744  {
1745  ReleaseCapturedUnicodeString(&strDllNameSafe, UserMode);
1746  ReleaseCapturedUnicodeString(&strFuncNameSafe, UserMode);
1747  }
1748 
1749  return ret;
1750 }
1751 
1752 BOOL
1753 APIENTRY
1755 {
1756  BOOL ret;
1757 
1760  UserLeave();
1761 
1762  return ret;
1763 }
1764 
1765 /* 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)
#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:1754
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:2928
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
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:5593
#define MmCopyFromCaller
Definition: polytest.cpp:29
#define W32PF_APIHOOKLOADED
Definition: win32.h:34
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:610
struct @1567 Msg[]
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:1252
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:1357
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:1708
LRESULT(CALLBACK * HOOKPROC)(int, WPARAM, LPARAM)
Definition: winuser.h:2852
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:783
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:1018
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
#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:1407
#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:1677
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:1427
#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:475
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:1089
#define MSG
Definition: Mailslot.c:11
VOID NTAPI KeDetachProcess(VOID)
Definition: procobj.c:618
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:2917
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 KeAttachProcess(IN PKPROCESS Process)
Definition: procobj.c:579
PVOID pHookStructs
Definition: hook.c:20
unsigned int UINT
Definition: ndis.h:50
PVOID NTAPI PsGetCurrentProcessWin32Process(VOID)
Definition: process.c:1183
#define ERROR_HOOK_TYPE_NOT_ALLOWED
Definition: winerror.h:939
BOOL FASTCALL IntUnhookWindowsHook(int HookId, HOOKPROC pfnFilterProc)
Definition: hook.c:1306
#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:2918
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:1061
#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 RETURN(rrr)
Definition: decompress.c:40
#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