Something went wrong. Try again.
Reactos
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * PURPOSE: Window hooks * PROGRAMER: Casper S. Hornstrup <chorns@users.sourceforge.net> * James Tabor <james.tabor@reactos.org> * Rafal Harabien <rafalh@reactos.org> * NOTE: Most of this code was adapted from Wine, * Copyright (C) 2002 Alexandre Julliard */
#include <win32k.h>DBG_DEFAULT_CHANNEL(UserHook);
typedef struct _HOOKPACK{ PHOOK pHk; LPARAM lParam; PVOID pHookStructs;} HOOKPACK, *PHOOKPACK;
UNICODE_STRING strUahModule;UNICODE_STRING strUahInitFunc;PPROCESSINFO ppiUahServer;
/* PRIVATE FUNCTIONS *********************************************************/
/* Calls ClientLoadLibrary in user32 in order to load or unload a module */BOOLIntLoadHookModule(int iHookID, HHOOK hHook, BOOL Unload){ PPROCESSINFO ppi; BOOL bResult;
ppi = PsGetCurrentProcessWin32Process();
TRACE("IntLoadHookModule. Client PID: %p\n", PsGetProcessId(ppi->peProcess));
/* Check if this is the api hook */ if(iHookID == WH_APIHOOK) { if(!Unload && !(ppi->W32PF_flags & W32PF_APIHOOKLOADED)) { /* A callback in user mode can trigger UserLoadApiHook to be called and as a result IntLoadHookModule will be called recursively. To solve this we set the flag that means that the application has loaded the api hook before the callback and in case of error we remove it */ ppi->W32PF_flags |= W32PF_APIHOOKLOADED;
/* Call ClientLoadLibrary in user32 */ bResult = co_IntClientLoadLibrary(&strUahModule, &strUahInitFunc, Unload, TRUE); TRACE("co_IntClientLoadLibrary returned %d\n", bResult ); if (!bResult) { /* Remove the flag we set before */ ppi->W32PF_flags &= ~W32PF_APIHOOKLOADED; } return bResult; } else if(Unload && (ppi->W32PF_flags & W32PF_APIHOOKLOADED)) { /* Call ClientLoadLibrary in user32 */ bResult = co_IntClientLoadLibrary(NULL, NULL, Unload, TRUE); if (bResult) { ppi->W32PF_flags &= ~W32PF_APIHOOKLOADED; } return bResult; }
return TRUE; }
STUB;
return FALSE;}
/*IntHookModuleUnloaded:Sends a internal message to all threads of the requested desktopand notifies them that a global hook was destroyedand an injected module must be unloaded.As a result, IntLoadHookModule will be called for all the threads thatwill receive the special purpose internal message.*/BOOLIntHookModuleUnloaded(PDESKTOP pdesk, int iHookID, HHOOK hHook){ PTHREADINFO ptiCurrent; PLIST_ENTRY ListEntry; PPROCESSINFO ppiCsr;
TRACE("IntHookModuleUnloaded: iHookID=%d\n", iHookID);
ppiCsr = PsGetProcessWin32Process(gpepCSRSS);
ListEntry = pdesk->PtiList.Flink; while(ListEntry != &pdesk->PtiList) { ptiCurrent = CONTAINING_RECORD(ListEntry, THREADINFO, PtiLink);
/* FIXME: Do some more security checks here */
/* FIXME: HACK: The first check is a reactos specific hack for system threads */ if(!PsIsSystemProcess(ptiCurrent->ppi->peProcess) && ptiCurrent->ppi != ppiCsr) { if(ptiCurrent->ppi->W32PF_flags & W32PF_APIHOOKLOADED) { TRACE("IntHookModuleUnloaded: sending message to PID %p, ppi=%p\n", PsGetProcessId(ptiCurrent->ppi->peProcess), ptiCurrent->ppi); co_MsqSendMessageAsync( ptiCurrent, 0, iHookID, TRUE, (LPARAM)hHook, NULL, 0, FALSE, MSQ_INJECTMODULE); } } ListEntry = ListEntry->Flink; }
return TRUE;}
BOOLFASTCALLUserLoadApiHook(VOID){ return IntLoadHookModule(WH_APIHOOK, 0, FALSE);}
BOOLFASTCALLUserRegisterUserApiHook( PUNICODE_STRING pstrDllName, PUNICODE_STRING pstrFuncName){ PTHREADINFO pti, ptiCurrent; HWND *List; PWND DesktopWindow, pwndCurrent; ULONG i; PPROCESSINFO ppiCsr;
pti = PsGetCurrentThreadWin32Thread(); ppiCsr = PsGetProcessWin32Process(gpepCSRSS);
/* Fail if the api hook is already registered */ if(gpsi->dwSRVIFlags & SRVINFO_APIHOOK) { return FALSE; }
TRACE("UserRegisterUserApiHook. Server PID: %p\n", PsGetProcessId(pti->ppi->peProcess));
/* Register the api hook */ gpsi->dwSRVIFlags |= SRVINFO_APIHOOK;
strUahModule = *pstrDllName; strUahInitFunc = *pstrFuncName; ppiUahServer = pti->ppi;
/* Broadcast an internal message to every top level window */ DesktopWindow = UserGetWindowObject(IntGetDesktopWindow()); List = IntWinListChildren(DesktopWindow);
if (List != NULL) { for (i = 0; List[i]; i++) { pwndCurrent = UserGetWindowObject(List[i]); if(pwndCurrent == NULL) { continue; } ptiCurrent = pwndCurrent->head.pti;
/* FIXME: The first check is a reactos specific hack for system threads */ if(PsIsSystemProcess(ptiCurrent->ppi->peProcess) || ptiCurrent->ppi == ppiCsr) { continue; }
co_MsqSendMessageAsync( ptiCurrent, 0, WH_APIHOOK, FALSE, /* Load the module */ 0, NULL, 0, FALSE, MSQ_INJECTMODULE); } ExFreePoolWithTag(List, USERTAG_WINDOWLIST); }
return TRUE;}
BOOLFASTCALLUserUnregisterUserApiHook(VOID){ PTHREADINFO pti;
pti = PsGetCurrentThreadWin32Thread();
/* Fail if the api hook is not registered */ if(!(gpsi->dwSRVIFlags & SRVINFO_APIHOOK)) { return FALSE; }
/* Only the process that registered the api hook can uregister it */ if(ppiUahServer != PsGetCurrentProcessWin32Process()) { return FALSE; }
TRACE("UserUnregisterUserApiHook. Server PID: %p\n", PsGetProcessId(pti->ppi->peProcess));
/* Unregister the api hook */ gpsi->dwSRVIFlags &= ~SRVINFO_APIHOOK; ppiUahServer = NULL; ReleaseCapturedUnicodeString(&strUahModule, UserMode); ReleaseCapturedUnicodeString(&strUahInitFunc, UserMode);
/* Notify all applications that the api hook module must be unloaded */ return IntHookModuleUnloaded(pti->rpdesk, WH_APIHOOK, 0);}
staticLRESULTFASTCALLco_IntCallLowLevelHook(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam){ NTSTATUS Status; PTHREADINFO pti; PHOOKPACK pHP; INT Size = 0; UINT uTimeout = 300; BOOL Block = FALSE; ULONG_PTR uResult = 0;
if (Hook->ptiHooked) pti = Hook->ptiHooked; else pti = Hook->head.pti;
pHP = ExAllocatePoolWithTag(NonPagedPool, sizeof(HOOKPACK), TAG_HOOK); if (!pHP) return 0;
pHP->pHk = Hook; pHP->lParam = lParam; pHP->pHookStructs = NULL;
// This prevents stack corruption from the caller. switch(Hook->HookId) { case WH_JOURNALPLAYBACK: case WH_JOURNALRECORD: uTimeout = 0; Size = sizeof(EVENTMSG); break; case WH_KEYBOARD_LL: Size = sizeof(KBDLLHOOKSTRUCT); break; case WH_MOUSE_LL: Size = sizeof(MSLLHOOKSTRUCT); break; case WH_MOUSE: uTimeout = 200; Block = TRUE; Size = sizeof(MOUSEHOOKSTRUCT); break; case WH_KEYBOARD: uTimeout = 200; Block = TRUE; break; }
if (Size) { pHP->pHookStructs = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_HOOK); if (pHP->pHookStructs) RtlCopyMemory(pHP->pHookStructs, (PVOID)lParam, Size); }
/* FIXME: Should get timeout from * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */ Status = co_MsqSendMessage( pti, IntToPtr(Code), // hWnd Hook->HookId, // Msg wParam, (LPARAM)pHP, uTimeout, Block, MSQ_ISHOOK, &uResult); if (!NT_SUCCESS(Status)) { ERR("Error Hook Call SendMsg. %d Status: 0x%x\n", Hook->HookId, Status); if (pHP->pHookStructs) ExFreePoolWithTag(pHP->pHookStructs, TAG_HOOK); ExFreePoolWithTag(pHP, TAG_HOOK); } return NT_SUCCESS(Status) ? uResult : 0;}
//// Dispatch MsgQueue Hook Call processor!//LRESULTAPIENTRYco_CallHook( INT HookId, INT Code, WPARAM wParam, LPARAM lParam){ LRESULT Result = 0; PHOOK phk; PHOOKPACK pHP = (PHOOKPACK)lParam;
phk = pHP->pHk; lParam = pHP->lParam;
switch(HookId) { case WH_JOURNALPLAYBACK: case WH_JOURNALRECORD: case WH_KEYBOARD_LL: case WH_MOUSE_LL: case WH_MOUSE: lParam = (LPARAM)pHP->pHookStructs; case WH_KEYBOARD: break; }
if (!UserObjectInDestroy(UserHMGetHandle(phk))) //// Fix CORE-10549. { /* The odds are high for this to be a Global call. */ Result = co_IntCallHookProc( HookId, Code, wParam, lParam, phk->Proc, phk->ihmod, phk->offPfn, phk->Ansi, &phk->ModuleName); } /* The odds so high, no one is waiting for the results. */ if (pHP->pHookStructs) ExFreePoolWithTag(pHP->pHookStructs, TAG_HOOK); ExFreePoolWithTag(pHP, TAG_HOOK); return Result;}
staticLRESULTAPIENTRYco_HOOK_CallHookNext( PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam){ TRACE("Calling Next HOOK %d\n", Hook->HookId);
return co_IntCallHookProc( Hook->HookId, Code, wParam, lParam, Hook->Proc, Hook->ihmod, Hook->offPfn, Hook->Ansi, &Hook->ModuleName);}
staticLRESULTFASTCALLco_IntCallDebugHook(PHOOK Hook, int Code, WPARAM wParam, LPARAM lParam, BOOL Ansi){ LRESULT lResult = 0; ULONG Size; DEBUGHOOKINFO Debug; PVOID HooklParam = NULL; BOOL BadChk = FALSE;
if (lParam) { _SEH2_TRY { ProbeForRead((PVOID)lParam, sizeof(DEBUGHOOKINFO), 1);
RtlCopyMemory(&Debug, (PVOID)lParam, sizeof(DEBUGHOOKINFO)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { BadChk = TRUE; } _SEH2_END;
if (BadChk) { ERR("HOOK WH_DEBUG read from lParam ERROR!\n"); return lResult; } } else return lResult; /* Need lParam! */
switch (wParam) { case WH_CBT: { switch (Debug.code) { case HCBT_CLICKSKIPPED: Size = sizeof(MOUSEHOOKSTRUCTEX); break;
case HCBT_MOVESIZE: Size = sizeof(RECT); break;
case HCBT_ACTIVATE: Size = sizeof(CBTACTIVATESTRUCT); break;
case HCBT_CREATEWND: /* Handle ANSI? */ Size = sizeof(CBT_CREATEWND); /* What shall we do? Size += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS); same as CREATESTRUCTEX */ break;
default: Size = sizeof(LPARAM); } } break;
case WH_MOUSE_LL: Size = sizeof(MSLLHOOKSTRUCT); break;
case WH_KEYBOARD_LL: Size = sizeof(KBDLLHOOKSTRUCT); break;
case WH_MSGFILTER: case WH_SYSMSGFILTER: case WH_GETMESSAGE: Size = sizeof(MSG); break;
case WH_JOURNALPLAYBACK: case WH_JOURNALRECORD: Size = sizeof(EVENTMSG); break;
case WH_FOREGROUNDIDLE: case WH_KEYBOARD: case WH_SHELL: default: Size = sizeof(LPARAM); }
if (Size > sizeof(LPARAM)) HooklParam = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_HOOK);
if (HooklParam) { _SEH2_TRY { ProbeForRead((PVOID)Debug.lParam, Size, 1);
RtlCopyMemory(HooklParam, (PVOID)Debug.lParam, Size); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { BadChk = TRUE; } _SEH2_END;
if (BadChk) { ERR("HOOK WH_DEBUG read from Debug.lParam ERROR!\n"); ExFreePoolWithTag(HooklParam, TAG_HOOK); return lResult; } }
if (HooklParam) Debug.lParam = (LPARAM)HooklParam; lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Debug); if (HooklParam) ExFreePoolWithTag(HooklParam, TAG_HOOK);
return lResult;}
staticLRESULTAPIENTRYco_UserCallNextHookEx(PHOOK Hook, int Code, WPARAM wParam, LPARAM lParam, BOOL Ansi){ LRESULT lResult = 0; BOOL BadChk = FALSE;
/* Handle this one first. */ if ((Hook->HookId == WH_MOUSE) || (Hook->HookId == WH_CBT && Code == HCBT_CLICKSKIPPED)) { MOUSEHOOKSTRUCTEX Mouse; if (lParam) { _SEH2_TRY { ProbeForRead((PVOID)lParam, sizeof(MOUSEHOOKSTRUCTEX), 1);
RtlCopyMemory(&Mouse, (PVOID)lParam, sizeof(MOUSEHOOKSTRUCTEX)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { BadChk = TRUE; } _SEH2_END;
if (BadChk) { ERR("HOOK WH_MOUSE read from lParam ERROR!\n"); } }
if (!BadChk) { lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Mouse); }
return lResult; }
switch(Hook->HookId) { case WH_MOUSE_LL: { MSLLHOOKSTRUCT Mouse;
if (lParam) { _SEH2_TRY { ProbeForRead((PVOID)lParam, sizeof(MSLLHOOKSTRUCT), 1);
RtlCopyMemory(&Mouse, (PVOID)lParam, sizeof(MSLLHOOKSTRUCT)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { BadChk = TRUE; } _SEH2_END;
if (BadChk) { ERR("HOOK WH_MOUSE_LL read from lParam ERROR!\n"); } }
if (!BadChk) { lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Mouse); } break; }
case WH_KEYBOARD_LL: { KBDLLHOOKSTRUCT Keyboard;
if (lParam) { _SEH2_TRY { ProbeForRead((PVOID)lParam, sizeof(KBDLLHOOKSTRUCT), 1);
RtlCopyMemory(&Keyboard, (PVOID)lParam, sizeof(KBDLLHOOKSTRUCT)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { BadChk = TRUE; } _SEH2_END;
if (BadChk) { ERR("HOOK WH_KEYBORD_LL read from lParam ERROR!\n"); } }
if (!BadChk) { lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Keyboard); } break; }
case WH_MSGFILTER: case WH_SYSMSGFILTER: case WH_GETMESSAGE: { MSG Msg;
if (lParam) { _SEH2_TRY { ProbeForRead((PVOID)lParam, sizeof(MSG), 1);
RtlCopyMemory(&Msg, (PVOID)lParam, sizeof(MSG)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { BadChk = TRUE; } _SEH2_END;
if (BadChk) { ERR("HOOK WH_XMESSAGEX read from lParam ERROR!\n"); } }
if (!BadChk) { lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Msg);
if (lParam && (Hook->HookId == WH_GETMESSAGE)) { _SEH2_TRY { ProbeForWrite((PVOID)lParam, sizeof(MSG), 1);
RtlCopyMemory((PVOID)lParam, &Msg, sizeof(MSG)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { BadChk = TRUE; } _SEH2_END;
if (BadChk) { ERR("HOOK WH_GETMESSAGE write to lParam ERROR!\n"); } } } break; }
case WH_CBT: TRACE("HOOK WH_CBT!\n"); switch (Code) { case HCBT_CREATEWND: { LPCBT_CREATEWNDW pcbtcww = (LPCBT_CREATEWNDW)lParam;
TRACE("HOOK HCBT_CREATEWND\n"); _SEH2_TRY { if (Ansi) { ProbeForRead( pcbtcww, sizeof(CBT_CREATEWNDA), 1); ProbeForWrite(pcbtcww->lpcs, sizeof(CREATESTRUCTA), 1); ProbeForRead( pcbtcww->lpcs->lpszName, sizeof(CHAR), 1);
if (!IS_ATOM(pcbtcww->lpcs->lpszClass)) { _Analysis_assume_(pcbtcww->lpcs->lpszClass != NULL); ProbeForRead(pcbtcww->lpcs->lpszClass, sizeof(CHAR), 1); } } else { ProbeForRead( pcbtcww, sizeof(CBT_CREATEWNDW), 1); ProbeForWrite(pcbtcww->lpcs, sizeof(CREATESTRUCTW), 1); ProbeForRead( pcbtcww->lpcs->lpszName, sizeof(WCHAR), 1);
if (!IS_ATOM(pcbtcww->lpcs->lpszClass)) { _Analysis_assume_(pcbtcww->lpcs->lpszClass != NULL); ProbeForRead(pcbtcww->lpcs->lpszClass, sizeof(WCHAR), 1); } } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { BadChk = TRUE; } _SEH2_END;
if (BadChk) { ERR("HOOK HCBT_CREATEWND write ERROR!\n"); } /* The next call handles the structures. */ if (!BadChk && Hook->Proc) { lResult = co_HOOK_CallHookNext(Hook, Code, wParam, lParam); } break; }
case HCBT_MOVESIZE: { RECTL rt;
TRACE("HOOK HCBT_MOVESIZE\n");
if (lParam) { _SEH2_TRY { ProbeForRead((PVOID)lParam, sizeof(RECT), 1);
RtlCopyMemory(&rt, (PVOID)lParam, sizeof(RECT)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { BadChk = TRUE; } _SEH2_END;
if (BadChk) { ERR("HOOK HCBT_MOVESIZE read from lParam ERROR!\n"); } }
if (!BadChk) { lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&rt); } break; }
case HCBT_ACTIVATE: { CBTACTIVATESTRUCT CbAs;
TRACE("HOOK HCBT_ACTIVATE\n"); if (lParam) { _SEH2_TRY { ProbeForRead((PVOID)lParam, sizeof(CBTACTIVATESTRUCT), 1);
RtlCopyMemory(&CbAs, (PVOID)lParam, sizeof(CBTACTIVATESTRUCT)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { BadChk = TRUE; } _SEH2_END;
if (BadChk) { ERR("HOOK HCBT_ACTIVATE read from lParam ERROR!\n"); } }
if (!BadChk) { lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&CbAs); } break; }
/* The rest just use default. */ default: TRACE("HOOK HCBT_ %d\n",Code); lResult = co_HOOK_CallHookNext(Hook, Code, wParam, lParam); break; } break;/* Note WH_JOURNALPLAYBACK, "To have the system wait before processing the message, the return value must be the amount of time, in clock ticks, that the system should wait." */ case WH_JOURNALPLAYBACK: case WH_JOURNALRECORD: { EVENTMSG EventMsg;
if (lParam) { _SEH2_TRY { ProbeForRead((PVOID)lParam, sizeof(EVENTMSG), 1);
RtlCopyMemory(&EventMsg, (PVOID)lParam, sizeof(EVENTMSG)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { BadChk = TRUE; } _SEH2_END;
if (BadChk) { ERR("HOOK WH_JOURNAL read from lParam ERROR!\n"); } }
if (!BadChk) { lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)(lParam ? &EventMsg : NULL));
if (lParam) { _SEH2_TRY { ProbeForWrite((PVOID)lParam, sizeof(EVENTMSG), 1);
RtlCopyMemory((PVOID)lParam, &EventMsg, sizeof(EVENTMSG)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { BadChk = TRUE; } _SEH2_END;
if (BadChk) { ERR("HOOK WH_JOURNAL write to lParam ERROR!\n"); } } } break; }
case WH_DEBUG: lResult = co_IntCallDebugHook(Hook, Code, wParam, lParam, Ansi); break;
/* * Default the rest like, WH_FOREGROUNDIDLE, WH_KEYBOARD and WH_SHELL. */ case WH_FOREGROUNDIDLE: case WH_KEYBOARD: case WH_SHELL: lResult = co_HOOK_CallHookNext(Hook, Code, wParam, lParam); break;
default: ERR("Unsupported HOOK Id -> %d\n",Hook->HookId); break; } return lResult;}
PHOOKFASTCALLIntGetHookObject(HHOOK hHook){ PHOOK Hook;
if (!hHook) { EngSetLastError(ERROR_INVALID_HOOK_HANDLE); return NULL; }
Hook = (PHOOK)UserGetObject(gHandleTable, hHook, TYPE_HOOK); if (!Hook) { EngSetLastError(ERROR_INVALID_HOOK_HANDLE); return NULL; }
UserReferenceObject(Hook);
return Hook;}
staticHHOOK*FASTCALLIntGetGlobalHookHandles(PDESKTOP pdo, int HookId){ PLIST_ENTRY pLastHead, pElem; unsigned i = 0; unsigned cHooks = 0; HHOOK *pList; PHOOK pHook;
pLastHead = &pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]; for (pElem = pLastHead->Flink; pElem != pLastHead; pElem = pElem->Flink) ++cHooks;
pList = ExAllocatePoolWithTag(PagedPool, (cHooks + 1) * sizeof(HHOOK), TAG_HOOK); if (!pList) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; }
for (pElem = pLastHead->Flink; pElem != pLastHead; pElem = pElem->Flink) { pHook = CONTAINING_RECORD(pElem, HOOK, Chain); NT_ASSERT(i < cHooks); pList[i++] = UserHMGetHandle(pHook); } pList[i] = NULL;
return pList;}
/* Find the next hook in the chain */PHOOKFASTCALLIntGetNextHook(PHOOK Hook){ int HookId = Hook->HookId; PLIST_ENTRY pLastHead, pElem; PTHREADINFO pti;
if (Hook->ptiHooked) { pti = Hook->ptiHooked; pLastHead = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; } else { pti = PsGetCurrentThreadWin32Thread(); pLastHead = &pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]; }
pElem = Hook->Chain.Flink; if (pElem != pLastHead) return CONTAINING_RECORD(pElem, HOOK, Chain); return NULL;}
/* Free a hook, removing it from its chain */staticVOIDFASTCALLIntFreeHook(PHOOK Hook){ RemoveEntryList(&Hook->Chain); if (Hook->ModuleName.Buffer) { ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK); Hook->ModuleName.Buffer = NULL; } /* Close handle */ UserDeleteObject(UserHMGetHandle(Hook), TYPE_HOOK);}
/* Remove a hook, freeing it from the chain */BOOLEANIntRemoveHook(PVOID Object){ INT HookId; PTHREADINFO ptiHook, pti; PDESKTOP pdo; PHOOK Hook = Object;
NT_ASSERT(UserIsEnteredExclusive());
HookId = Hook->HookId; pti = PsGetCurrentThreadWin32Thread();
if (Hook->ptiHooked) // Local { ptiHook = Hook->ptiHooked;
IntFreeHook(Hook);
if (IsListEmpty(&ptiHook->aphkStart[HOOKID_TO_INDEX(HookId)])) { BOOL bOtherProcess; KAPC_STATE ApcState;
ptiHook->fsHooks &= ~HOOKID_TO_FLAG(HookId); bOtherProcess = (ptiHook->ppi != pti->ppi);
if (bOtherProcess) KeStackAttachProcess(&ptiHook->ppi->peProcess->Pcb, &ApcState);
_SEH2_TRY { ptiHook->pClientInfo->fsHooks = ptiHook->fsHooks; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Do nothing */ (void)0; } _SEH2_END;
if (bOtherProcess) KeUnstackDetachProcess(&ApcState); } } else // Global { IntFreeHook(Hook);
pdo = IntGetActiveDesktop();
if (pdo && pdo->pDeskInfo && IsListEmpty(&pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)])) { pdo->pDeskInfo->fsHooks &= ~HOOKID_TO_FLAG(HookId); } }
return TRUE;}
/* Win32k Kernel Space Hook Caller. */LRESULTAPIENTRYco_HOOK_CallHooks( INT HookId, INT Code, WPARAM wParam, LPARAM lParam){ PHOOK Hook, SaveHook; PTHREADINFO pti; PCLIENTINFO ClientInfo; PLIST_ENTRY pLastHead; PDESKTOP pdo; BOOL Local = FALSE, Global = FALSE; LRESULT Result = 0; USER_REFERENCE_ENTRY Ref;
ASSERT(WH_MINHOOK <= HookId && HookId <= WH_MAXHOOK);
pti = PsGetCurrentThreadWin32Thread(); if (!pti || !pti->rpdesk || !pti->rpdesk->pDeskInfo) { pdo = IntGetActiveDesktop(); /* If KeyboardThread|MouseThread|(RawInputThread or RIT) aka system threads, pti->fsHooks most likely, is zero. So process KbT & MsT to "send" the message. */ if ( !pti || !pdo || (!(HookId == WH_KEYBOARD_LL) && !(HookId == WH_MOUSE_LL)) ) { TRACE("No PDO %d\n", HookId); goto Exit; } } else { pdo = pti->rpdesk; }
if ( pti->TIF_flags & (TIF_INCLEANUP|TIF_DISABLEHOOKS)) { TRACE("Hook Thread dead %d\n", HookId); goto Exit; }
if ( ISITHOOKED(HookId) ) { TRACE("Local Hooker %d\n", HookId); Local = TRUE; }
if ( pdo->pDeskInfo->fsHooks & HOOKID_TO_FLAG(HookId) ) { TRACE("Global Hooker %d\n", HookId); Global = TRUE; }
if ( !Local && !Global ) goto Exit; // No work!
Hook = NULL;
/* SetWindowHookEx sorts out the Thread issue by placing the Hook to the correct Thread if not NULL. */ if ( Local ) { pLastHead = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; if (IsListEmpty(pLastHead)) { ERR("No Local Hook Found!\n"); goto Exit; }
Hook = CONTAINING_RECORD(pLastHead->Flink, HOOK, Chain); ObReferenceObject(pti->pEThread); IntReferenceThreadInfo(pti); UserRefObjectCo(Hook, &Ref);
ClientInfo = pti->pClientInfo; SaveHook = pti->sphkCurrent; /* Note: Setting pti->sphkCurrent will also lock the next hook to this * hook ID. So, the CallNextHookEx will only call to that hook ID * chain anyway. For Thread Hooks.... */
/* Load it for the next call. */ pti->sphkCurrent = Hook; Hook->phkNext = IntGetNextHook(Hook); if (ClientInfo) { _SEH2_TRY { ClientInfo->phkCurrent = Hook; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ClientInfo = NULL; // Don't bother next run. } _SEH2_END; } Result = co_IntCallHookProc( HookId, Code, wParam, lParam, Hook->Proc, Hook->ihmod, Hook->offPfn, Hook->Ansi, &Hook->ModuleName); if (ClientInfo) { _SEH2_TRY { ClientInfo->phkCurrent = SaveHook; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Do nothing */ (void)0; } _SEH2_END; } pti->sphkCurrent = SaveHook; Hook->phkNext = NULL; UserDerefObjectCo(Hook); IntDereferenceThreadInfo(pti); ObDereferenceObject(pti->pEThread); }
if ( Global ) { PTHREADINFO ptiHook; HHOOK *pHookHandles; unsigned i;
/* Keep hooks in array because hooks can be destroyed in user world */ pHookHandles = IntGetGlobalHookHandles(pdo, HookId); if(!pHookHandles) goto Exit;
/* Performance goes down the drain. If more hooks are associated to this * hook ID, this will have to post to each of the thread message queues * or make a direct call. */ for(i = 0; pHookHandles[i]; ++i) { Hook = (PHOOK)UserGetObject(gHandleTable, pHookHandles[i], TYPE_HOOK); if(!Hook) { ERR("Invalid hook!\n"); continue; }
/* Hook->Thread is null, we hax around this with Hook->head.pti. */ ptiHook = Hook->head.pti;
if ( (pti->TIF_flags & TIF_DISABLEHOOKS) || (ptiHook->TIF_flags & TIF_INCLEANUP)) { TRACE("Next Hook %p, %p\n", ptiHook->rpdesk, pdo); continue; } UserRefObjectCo(Hook, &Ref);
if (ptiHook != pti ) { // Block | TimeOut if ( HookId == WH_JOURNALPLAYBACK || // 1 | 0 HookId == WH_JOURNALRECORD || // 1 | 0 HookId == WH_KEYBOARD || // 1 | 200 HookId == WH_MOUSE || // 1 | 200 HookId == WH_KEYBOARD_LL || // 0 | 300 HookId == WH_MOUSE_LL ) // 0 | 300 { TRACE("\nGlobal Hook posting to another Thread! %d\n",HookId ); Result = co_IntCallLowLevelHook(Hook, Code, wParam, lParam); } else if (ptiHook->ppi == pti->ppi) { TRACE("\nGlobal Hook calling to another Thread! %d\n",HookId ); ObReferenceObject(ptiHook->pEThread); IntReferenceThreadInfo(ptiHook); Result = co_IntCallHookProc( HookId, Code, wParam, lParam, Hook->Proc, Hook->ihmod, Hook->offPfn, Hook->Ansi, &Hook->ModuleName); IntDereferenceThreadInfo(ptiHook); ObDereferenceObject(ptiHook->pEThread); } } else { /* Make the direct call. */ TRACE("Global going Local Hook calling to Thread! %d\n",HookId ); ObReferenceObject(pti->pEThread); IntReferenceThreadInfo(pti); Result = co_IntCallHookProc( HookId, Code, wParam, lParam, Hook->Proc, Hook->ihmod, Hook->offPfn, Hook->Ansi, &Hook->ModuleName); IntDereferenceThreadInfo(pti); ObDereferenceObject(pti->pEThread); } UserDerefObjectCo(Hook); } ExFreePoolWithTag(pHookHandles, TAG_HOOK); TRACE("Ret: Global HookId %d Result 0x%x\n", HookId,Result); }Exit: return Result;}
BOOLFASTCALLIntUnhookWindowsHook(int HookId, HOOKPROC pfnFilterProc){ PHOOK Hook; PLIST_ENTRY pLastHead, pElement; PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId ) { EngSetLastError(ERROR_INVALID_HOOK_FILTER); return FALSE; }
if (pti->fsHooks) { pLastHead = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
pElement = pLastHead->Flink; while (pElement != pLastHead) { Hook = CONTAINING_RECORD(pElement, HOOK, Chain);
/* Get the next element now, we might free the hook in what follows */ pElement = Hook->Chain.Flink;
if (Hook->Proc == pfnFilterProc) { if (Hook->head.pti == pti) { IntRemoveHook(Hook); return TRUE; } else { EngSetLastError(ERROR_ACCESS_DENIED); return FALSE; } } } } return FALSE;}
/* * Support for compatibility only? Global hooks are processed in kernel space. * This is very thread specific! Never seeing applications with more than one * hook per thread installed. Most of the applications are Global hookers and * associated with just one hook Id. Maybe it's for diagnostic testing or a * throw back to 3.11? */LRESULTAPIENTRYNtUserCallNextHookEx( int Code, WPARAM wParam, LPARAM lParam, BOOL Ansi){ PTHREADINFO pti; PHOOK HookObj, NextObj; PCLIENTINFO ClientInfo; LRESULT lResult = 0;
TRACE("Enter NtUserCallNextHookEx\n"); UserEnterExclusive();
pti = GetW32ThreadInfo();
HookObj = pti->sphkCurrent;
if (!HookObj) goto Exit; // Return 0
NextObj = HookObj->phkNext;
pti->sphkCurrent = NextObj; ClientInfo = pti->pClientInfo; _SEH2_TRY { ClientInfo->phkCurrent = NextObj; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ClientInfo = NULL; } _SEH2_END;
/* Now in List run down. */ if (ClientInfo && NextObj) { NextObj->phkNext = IntGetNextHook(NextObj); lResult = co_UserCallNextHookEx( NextObj, Code, wParam, lParam, NextObj->Ansi); }
Exit: TRACE("Leave NtUserCallNextHookEx, ret=%i\n", lResult); UserLeave(); return lResult;}
HHOOKAPIENTRYNtUserSetWindowsHookAW( int idHook, HOOKPROC lpfn, BOOL Ansi){ DWORD ThreadId; UNICODE_STRING USModuleName;
RtlInitUnicodeString(&USModuleName, NULL); ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread);
return NtUserSetWindowsHookEx( NULL, &USModuleName, ThreadId, idHook, lpfn, Ansi);}
HHOOKAPIENTRYNtUserSetWindowsHookEx( HINSTANCE Mod, PUNICODE_STRING UnsafeModuleName, DWORD ThreadId, int HookId, HOOKPROC HookProc, BOOL Ansi){ PWINSTATION_OBJECT WinStaObj; PHOOK Hook = NULL; UNICODE_STRING ModuleName; NTSTATUS Status; HHOOK Handle; PTHREADINFO pti, ptiHook = NULL; HHOOK Ret = NULL;
TRACE("Enter NtUserSetWindowsHookEx\n"); UserEnterExclusive();
pti = PsGetCurrentThreadWin32Thread();
if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId ) { EngSetLastError(ERROR_INVALID_HOOK_FILTER); goto Cleanup; // Return NULL }
if (!HookProc) { EngSetLastError(ERROR_INVALID_FILTER_PROC); goto Cleanup; // Return NULL }
if (ThreadId) /* thread-local hook */ { if ( HookId == WH_JOURNALRECORD || HookId == WH_JOURNALPLAYBACK || HookId == WH_KEYBOARD_LL || HookId == WH_MOUSE_LL || HookId == WH_SYSMSGFILTER) { TRACE("Local hook installing Global HookId: %d\n",HookId); /* these can only be global */ EngSetLastError(ERROR_GLOBAL_ONLY_HOOK); goto Cleanup; // Return NULL }
if ( !(ptiHook = IntTID2PTI( UlongToHandle(ThreadId) ))) { ERR("Invalid thread id 0x%x\n", ThreadId); EngSetLastError(ERROR_INVALID_PARAMETER); goto Cleanup; // Return NULL }
if ( ptiHook->rpdesk != pti->rpdesk) // gptiCurrent->rpdesk) { ERR("Local hook wrong desktop HookId: %d\n",HookId); EngSetLastError(ERROR_ACCESS_DENIED); goto Cleanup; // Return NULL }
if (ptiHook->ppi != pti->ppi) { if ( !Mod && (HookId == WH_GETMESSAGE || HookId == WH_CALLWNDPROC || HookId == WH_CBT || HookId == WH_HARDWARE || HookId == WH_DEBUG || HookId == WH_SHELL || HookId == WH_FOREGROUNDIDLE || HookId == WH_CALLWNDPROCRET) ) { ERR("Local hook needs hMod HookId: %d\n",HookId); EngSetLastError(ERROR_HOOK_NEEDS_HMOD); goto Cleanup; // Return NULL }
if ( (ptiHook->TIF_flags & (TIF_CSRSSTHREAD|TIF_SYSTEMTHREAD)) && (HookId == WH_GETMESSAGE || HookId == WH_CALLWNDPROC || HookId == WH_CBT || HookId == WH_HARDWARE || HookId == WH_DEBUG || HookId == WH_SHELL || HookId == WH_FOREGROUNDIDLE || HookId == WH_CALLWNDPROCRET) ) { EngSetLastError(ERROR_HOOK_TYPE_NOT_ALLOWED); goto Cleanup; // Return NULL } } } else /* System-global hook */ { ptiHook = pti; // gptiCurrent; if ( !Mod && (HookId == WH_GETMESSAGE || HookId == WH_CALLWNDPROC || HookId == WH_CBT || HookId == WH_SYSMSGFILTER || HookId == WH_HARDWARE || HookId == WH_DEBUG || HookId == WH_SHELL || HookId == WH_FOREGROUNDIDLE || HookId == WH_CALLWNDPROCRET) ) { ERR("Global hook needs hMod HookId: %d\n",HookId); EngSetLastError(ERROR_HOOK_NEEDS_HMOD); goto Cleanup; // Return NULL } }
Status = IntValidateWindowStationHandle( PsGetCurrentProcess()->Win32WindowStation, UserMode, 0, &WinStaObj, 0);
if (!NT_SUCCESS(Status)) { SetLastNtError(Status); goto Cleanup; // Return NULL } ObDereferenceObject(WinStaObj);
Hook = UserCreateObject(gHandleTable, NULL, ptiHook, (PHANDLE)&Handle, TYPE_HOOK, sizeof(HOOK));
if (!Hook) { goto Cleanup; // Return NULL }
Hook->ihmod = (INT_PTR)Mod; // Module Index from atom table, Do this for now. Hook->HookId = HookId; Hook->rpdesk = ptiHook->rpdesk; Hook->phkNext = NULL; /* Dont use as a chain! Use link lists for chaining. */ Hook->Proc = HookProc; Hook->Ansi = Ansi;
TRACE("Set Hook Desk %p DeskInfo %p Handle Desk %p\n", pti->rpdesk, pti->pDeskInfo, Hook->head.rpdesk);
if (ThreadId) /* Thread-local hook */ { InsertHeadList(&ptiHook->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain); ptiHook->sphkCurrent = NULL; Hook->ptiHooked = ptiHook; ptiHook->fsHooks |= HOOKID_TO_FLAG(HookId);
if (ptiHook->pClientInfo) { if ( ptiHook->ppi == pti->ppi) /* gptiCurrent->ppi) */ { _SEH2_TRY { ptiHook->pClientInfo->fsHooks = ptiHook->fsHooks; ptiHook->pClientInfo->phkCurrent = NULL; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ERR("Problem writing to Local ClientInfo!\n"); } _SEH2_END; } else { KAPC_STATE ApcState;
KeStackAttachProcess(&ptiHook->ppi->peProcess->Pcb, &ApcState); _SEH2_TRY { ptiHook->pClientInfo->fsHooks = ptiHook->fsHooks; ptiHook->pClientInfo->phkCurrent = NULL; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ERR("Problem writing to Remote ClientInfo!\n"); } _SEH2_END; KeUnstackDetachProcess(&ApcState); } } } else { InsertHeadList(&ptiHook->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain); Hook->ptiHooked = NULL; //gptiCurrent->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId); ptiHook->rpdesk->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId); ptiHook->sphkCurrent = NULL; ptiHook->pClientInfo->phkCurrent = NULL; }
RtlInitUnicodeString(&Hook->ModuleName, NULL);
if (Mod) { Status = MmCopyFromCaller(&ModuleName, UnsafeModuleName, sizeof(UNICODE_STRING)); if (!NT_SUCCESS(Status)) { IntRemoveHook(Hook); SetLastNtError(Status); goto Cleanup; // Return NULL }
Hook->ModuleName.Buffer = ExAllocatePoolWithTag( PagedPool, ModuleName.MaximumLength, TAG_HOOK); if (NULL == Hook->ModuleName.Buffer) { IntRemoveHook(Hook); EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); goto Cleanup; // Return NULL }
Hook->ModuleName.MaximumLength = ModuleName.MaximumLength; Status = MmCopyFromCaller( Hook->ModuleName.Buffer, ModuleName.Buffer, ModuleName.MaximumLength); if (!NT_SUCCESS(Status)) { ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK); Hook->ModuleName.Buffer = NULL; IntRemoveHook(Hook); SetLastNtError(Status); goto Cleanup; // Return NULL }
Hook->ModuleName.Length = ModuleName.Length; //// FIXME: Need to load from user32 to verify hMod before calling hook with hMod set!!!! //// Mod + offPfn == new HookProc Justin Case module is from another process. FIXME("NtUserSetWindowsHookEx Setting process hMod instance addressing.\n"); /* Make proc relative to the module base */ Hook->offPfn = (ULONG_PTR)((char *)HookProc - (char *)Mod); } else Hook->offPfn = 0;
TRACE("Installing: HookId %d Global %s\n", HookId, !ThreadId ? "TRUE" : "FALSE"); Ret = Handle;
Cleanup: if (Hook) UserDereferenceObject(Hook); TRACE("Leave NtUserSetWindowsHookEx, ret=%p\n", Ret); UserLeave(); return Ret;}
BOOLAPIENTRYNtUserUnhookWindowsHookEx(HHOOK Hook){ PHOOK HookObj; BOOL Ret = FALSE;
TRACE("Enter NtUserUnhookWindowsHookEx\n"); UserEnterExclusive();
if (!(HookObj = IntGetHookObject(Hook))) { ERR("Invalid handle passed to NtUserUnhookWindowsHookEx\n"); /* SetLastNtError(Status); */ goto Exit; // Return FALSE }
ASSERT(Hook == UserHMGetHandle(HookObj));
IntRemoveHook(HookObj);
UserDereferenceObject(HookObj);
Ret = TRUE;
Exit: TRACE("Leave NtUserUnhookWindowsHookEx, ret=%i\n", Ret); UserLeave(); return Ret;}
BOOLAPIENTRYNtUserRegisterUserApiHook( PUNICODE_STRING m_dllname1, PUNICODE_STRING m_funname1, DWORD dwUnknown3, DWORD dwUnknown4){ BOOL ret; UNICODE_STRING strDllNameSafe; UNICODE_STRING strFuncNameSafe; NTSTATUS Status;
/* Probe and capture parameters */ Status = ProbeAndCaptureUnicodeString(&strDllNameSafe, UserMode, m_dllname1); if(!NT_SUCCESS(Status)) { EngSetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
Status = ProbeAndCaptureUnicodeString(&strFuncNameSafe, UserMode, m_funname1); if(!NT_SUCCESS(Status)) { ReleaseCapturedUnicodeString(&strDllNameSafe, UserMode); EngSetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
UserEnterExclusive();
/* Call internal function */ ret = UserRegisterUserApiHook(&strDllNameSafe, &strFuncNameSafe);
UserLeave();
/* Cleanup only in case of failure */ if(ret == FALSE) { ReleaseCapturedUnicodeString(&strDllNameSafe, UserMode); ReleaseCapturedUnicodeString(&strFuncNameSafe, UserMode); }
return ret;}
BOOLAPIENTRYNtUserUnregisterUserApiHook(VOID){ BOOL ret;
UserEnterExclusive(); ret = UserUnregisterUserApiHook(); UserLeave();
return ret;}
/* EOF */