mirror of
https://github.com/reactos/reactos.git
synced 2024-08-20 02:13:29 +00:00
[win32k]
- Implement NtUserRegisterUserApiHook and NtUserUnregisterUserApiHook svn path=/branches/GSoC_2011/ThemesSupport/; revision=52650
This commit is contained in:
parent
723267ac2a
commit
7950b8eb63
|
@ -5,6 +5,13 @@
|
|||
#define HOOKID_TO_FLAG(HookId) (1 << ((HookId) + 1))
|
||||
#define ISITHOOKED(HookId) (((PTHREADINFO)PsGetCurrentThreadWin32Thread())->fsHooks & HOOKID_TO_FLAG(HookId))
|
||||
|
||||
/* NOTE: the following definition is not a real hook but
|
||||
a pseudo-id that will be used only for
|
||||
injecting user api hook module to all processes.
|
||||
It is used internally in win32k */
|
||||
#define WH_APIHOOK WH_MAX + 1
|
||||
|
||||
|
||||
typedef struct tagEVENTHOOK
|
||||
{
|
||||
THROBJHEAD head;
|
||||
|
@ -43,4 +50,10 @@ PHOOK FASTCALL IntGetNextHook(PHOOK Hook);
|
|||
LRESULT FASTCALL UserCallNextHookEx( PHOOK pHook, int Code, WPARAM wParam, LPARAM lParam, BOOL Ansi);
|
||||
BOOL FASTCALL IntUnhookWindowsHook(int,HOOKPROC);
|
||||
|
||||
BOOL FASTCALL UserLoadApiHook();
|
||||
BOOL IntLoadHookModule(int iHookID, HHOOK hHook, BOOL Unload);
|
||||
BOOL FASTCALL UserUnregisterUserApiHook(BOOL Block);
|
||||
|
||||
extern PPROCESSINFO ppiUahServer;
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define MSQ_NORMAL 0
|
||||
#define MSQ_ISHOOK 1
|
||||
#define MSQ_ISEVENT 2
|
||||
#define MSQ_INJECTMODULE 3
|
||||
|
||||
#define QSIDCOUNTS 6
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#define W32PF_NOWINDOWGHOSTING (0x01000000)
|
||||
#define W32PF_MANUALGUICHECK (0x02000000)
|
||||
#define W32PF_CREATEDWINORDC (0x04000000)
|
||||
#define W32PF_APIHOOKLOADED (0x08000000)
|
||||
|
||||
extern BOOL ClientPfnInit;
|
||||
extern HINSTANCE hModClient;
|
||||
|
|
|
@ -24,8 +24,220 @@ typedef struct _HOOKPACK
|
|||
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 */
|
||||
BOOL
|
||||
IntLoadHookModule(int iHookID, HHOOK hHook, BOOL Unload)
|
||||
{
|
||||
PPROCESSINFO ppi;
|
||||
HMODULE hmod;
|
||||
|
||||
ppi = PsGetCurrentProcessWin32Process();
|
||||
|
||||
DPRINT("IntLoadHookModule. Client PID: %d\n", PsGetProcessId(ppi->peProcess));
|
||||
|
||||
/* Check if this is the api hook */
|
||||
if(iHookID == WH_APIHOOK)
|
||||
{
|
||||
if(!Unload && !(ppi->W32PF_flags & W32PF_APIHOOKLOADED))
|
||||
{
|
||||
/* Call ClientLoadLibrary in user32 */
|
||||
hmod = co_IntClientLoadLibrary(&strUahModule, &strUahInitFunc, Unload, TRUE);
|
||||
if(hmod != 0)
|
||||
{
|
||||
ppi->W32PF_flags |= W32PF_APIHOOKLOADED;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
else if(Unload && (ppi->W32PF_flags & W32PF_APIHOOKLOADED))
|
||||
{
|
||||
/* Call ClientLoadLibrary in user32 */
|
||||
hmod = co_IntClientLoadLibrary(NULL, NULL, Unload, TRUE);
|
||||
if(hmod != 0)
|
||||
{
|
||||
ppi->W32PF_flags &= ~W32PF_APIHOOKLOADED;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
IntHookModuleUnloaded:
|
||||
Sends a internal message to all threads of the requested desktop
|
||||
and notifies them that a global hook was destroyed
|
||||
and an injected module must be unloaded.
|
||||
As a result, IntLoadHookModule will be called for all the threads that
|
||||
will receive the special purpose internal message.
|
||||
*/
|
||||
BOOL
|
||||
IntHookModuleUnloaded(PDESKTOP pdesk, int iHookID, HHOOK hHook, BOOL Block)
|
||||
{
|
||||
PTHREADINFO ptiCurrent;
|
||||
PLIST_ENTRY ListEntry;
|
||||
ULONG_PTR Result;
|
||||
PPROCESSINFO ppiCsr;
|
||||
|
||||
DPRINT("IntHookModuleUnloaded: iHookID=%d\n", iHookID);
|
||||
|
||||
ppiCsr = PsGetProcessWin32Process(CsrProcess);
|
||||
|
||||
ListEntry = pdesk->PtiList.Flink;
|
||||
while(ListEntry != &pdesk->PtiList)
|
||||
{
|
||||
ptiCurrent = CONTAINING_RECORD(ListEntry, THREADINFO, PtiLink);
|
||||
|
||||
/* FIXME: do some more security checks here */
|
||||
|
||||
/* FIXME: 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)
|
||||
{
|
||||
DPRINT("IntHookModuleUnloaded: sending message to PID %d, ppi=0x%x\n", PsGetProcessId(ptiCurrent->ppi->peProcess), ptiCurrent->ppi);
|
||||
co_MsqSendMessage( ptiCurrent->MessageQueue,
|
||||
0,
|
||||
iHookID,
|
||||
TRUE,
|
||||
(LPARAM)hHook,
|
||||
0,
|
||||
Block,
|
||||
MSQ_INJECTMODULE,
|
||||
&Result);
|
||||
}
|
||||
}
|
||||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
UserLoadApiHook()
|
||||
{
|
||||
return IntLoadHookModule(WH_APIHOOK, 0, FALSE);
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
UserRegisterUserApiHook(
|
||||
PUNICODE_STRING pstrDllName,
|
||||
PUNICODE_STRING pstrFuncName)
|
||||
{
|
||||
PTHREADINFO pti, ptiCurrent;
|
||||
HWND *List;
|
||||
PWND DesktopWindow, pwndCurrent;
|
||||
ULONG i;
|
||||
ULONG_PTR Result;
|
||||
PPROCESSINFO ppiCsr;
|
||||
|
||||
pti = PsGetCurrentThreadWin32Thread();
|
||||
ppiCsr = PsGetProcessWin32Process(CsrProcess);
|
||||
|
||||
/* Fail if the api hook is already registered */
|
||||
if(gpsi->dwSRVIFlags & SRVINFO_APIHOOK)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DPRINT("UserRegisterUserApiHook. Server PID: %d\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_MsqSendMessage( ptiCurrent->MessageQueue,
|
||||
0,
|
||||
WH_APIHOOK,
|
||||
FALSE, /* load the module */
|
||||
0,
|
||||
0,
|
||||
TRUE,
|
||||
MSQ_INJECTMODULE,
|
||||
&Result);
|
||||
if(Result == FALSE)
|
||||
{
|
||||
DPRINT1("Failed to inject module to process %d\n", PsGetProcessId(ptiCurrent->ppi->peProcess));
|
||||
}
|
||||
}
|
||||
ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
UserUnregisterUserApiHook(BOOL Block)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
DPRINT1("UserUnregisterUserApiHook. Server PID: %d\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, TRUE);
|
||||
}
|
||||
|
||||
static
|
||||
LRESULT
|
||||
FASTCALL
|
||||
|
@ -1527,4 +1739,64 @@ CLEANUP:
|
|||
END_CLEANUP;
|
||||
}
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtUserRegisterUserApiHook(
|
||||
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;
|
||||
}
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtUserUnregisterUserApiHook(VOID)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
UserEnterExclusive();
|
||||
ret = UserUnregisterUserApiHook(TRUE);
|
||||
UserLeave();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -811,6 +811,12 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
|
|||
Message->Msg.wParam,
|
||||
Message->Msg.lParam);
|
||||
}
|
||||
else if(Message->HookMessage == MSQ_INJECTMODULE)
|
||||
{
|
||||
Result = IntLoadHookModule(Message->Msg.message,
|
||||
(HHOOK)Message->Msg.lParam,
|
||||
Message->Msg.wParam);
|
||||
}
|
||||
else if ((Message->CompletionCallback)
|
||||
&& (Message->CallBackSenderQueue == MessageQueue))
|
||||
{ /* Call the callback routine */
|
||||
|
|
|
@ -889,20 +889,6 @@ NtUserRealWaitMessageEx(
|
|||
return 0;
|
||||
}
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtUserRegisterUserApiHook(
|
||||
PUNICODE_STRING m_dllname1,
|
||||
PUNICODE_STRING m_funname1,
|
||||
DWORD dwUnknown3,
|
||||
DWORD dwUnknown4)
|
||||
{
|
||||
UserEnterExclusive();
|
||||
UNIMPLEMENTED;
|
||||
UserLeave();
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtUserRegisterRawInputDevices(
|
||||
|
@ -1036,14 +1022,6 @@ NtUserPaintMenuBar(
|
|||
return 0;
|
||||
}
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtUserUnregisterUserApiHook(VOID)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtUserGetLayeredWindowAttributes(
|
||||
|
|
|
@ -122,6 +122,9 @@ NtUserCallNoParam(DWORD Routine)
|
|||
case NOPARAM_ROUTINE_RELEASECAPTURE:
|
||||
RETURN( (DWORD_PTR)IntReleaseCapture());
|
||||
|
||||
case NOPARAM_ROUTINE_LOADUSERAPIHOOK:
|
||||
RETURN(UserLoadApiHook());
|
||||
|
||||
default:
|
||||
DPRINT1("Calling invalid routine number 0x%x in NtUserCallNoParam\n", Routine);
|
||||
EngSetLastError(ERROR_INVALID_PARAMETER);
|
||||
|
|
Loading…
Reference in a new issue