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 HOOKID_TO_FLAG(HookId) (1 << ((HookId) + 1))
|
||||||
#define ISITHOOKED(HookId) (((PTHREADINFO)PsGetCurrentThreadWin32Thread())->fsHooks & HOOKID_TO_FLAG(HookId))
|
#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
|
typedef struct tagEVENTHOOK
|
||||||
{
|
{
|
||||||
THROBJHEAD head;
|
THROBJHEAD head;
|
||||||
|
@ -43,4 +50,10 @@ PHOOK FASTCALL IntGetNextHook(PHOOK Hook);
|
||||||
LRESULT FASTCALL UserCallNextHookEx( PHOOK pHook, int Code, WPARAM wParam, LPARAM lParam, BOOL Ansi);
|
LRESULT FASTCALL UserCallNextHookEx( PHOOK pHook, int Code, WPARAM wParam, LPARAM lParam, BOOL Ansi);
|
||||||
BOOL FASTCALL IntUnhookWindowsHook(int,HOOKPROC);
|
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 */
|
/* EOF */
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#define MSQ_NORMAL 0
|
#define MSQ_NORMAL 0
|
||||||
#define MSQ_ISHOOK 1
|
#define MSQ_ISHOOK 1
|
||||||
#define MSQ_ISEVENT 2
|
#define MSQ_ISEVENT 2
|
||||||
|
#define MSQ_INJECTMODULE 3
|
||||||
|
|
||||||
#define QSIDCOUNTS 6
|
#define QSIDCOUNTS 6
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#define W32PF_NOWINDOWGHOSTING (0x01000000)
|
#define W32PF_NOWINDOWGHOSTING (0x01000000)
|
||||||
#define W32PF_MANUALGUICHECK (0x02000000)
|
#define W32PF_MANUALGUICHECK (0x02000000)
|
||||||
#define W32PF_CREATEDWINORDC (0x04000000)
|
#define W32PF_CREATEDWINORDC (0x04000000)
|
||||||
|
#define W32PF_APIHOOKLOADED (0x08000000)
|
||||||
|
|
||||||
extern BOOL ClientPfnInit;
|
extern BOOL ClientPfnInit;
|
||||||
extern HINSTANCE hModClient;
|
extern HINSTANCE hModClient;
|
||||||
|
|
|
@ -24,8 +24,220 @@ typedef struct _HOOKPACK
|
||||||
PVOID pHookStructs;
|
PVOID pHookStructs;
|
||||||
} HOOKPACK, *PHOOKPACK;
|
} HOOKPACK, *PHOOKPACK;
|
||||||
|
|
||||||
|
UNICODE_STRING strUahModule;
|
||||||
|
UNICODE_STRING strUahInitFunc;
|
||||||
|
PPROCESSINFO ppiUahServer;
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS *********************************************************/
|
/* 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
|
static
|
||||||
LRESULT
|
LRESULT
|
||||||
FASTCALL
|
FASTCALL
|
||||||
|
@ -1527,4 +1739,64 @@ CLEANUP:
|
||||||
END_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 */
|
/* EOF */
|
||||||
|
|
|
@ -811,6 +811,12 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
|
||||||
Message->Msg.wParam,
|
Message->Msg.wParam,
|
||||||
Message->Msg.lParam);
|
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)
|
else if ((Message->CompletionCallback)
|
||||||
&& (Message->CallBackSenderQueue == MessageQueue))
|
&& (Message->CallBackSenderQueue == MessageQueue))
|
||||||
{ /* Call the callback routine */
|
{ /* Call the callback routine */
|
||||||
|
|
|
@ -889,20 +889,6 @@ NtUserRealWaitMessageEx(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
|
||||||
APIENTRY
|
|
||||||
NtUserRegisterUserApiHook(
|
|
||||||
PUNICODE_STRING m_dllname1,
|
|
||||||
PUNICODE_STRING m_funname1,
|
|
||||||
DWORD dwUnknown3,
|
|
||||||
DWORD dwUnknown4)
|
|
||||||
{
|
|
||||||
UserEnterExclusive();
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
UserLeave();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
APIENTRY
|
APIENTRY
|
||||||
NtUserRegisterRawInputDevices(
|
NtUserRegisterRawInputDevices(
|
||||||
|
@ -1036,14 +1022,6 @@ NtUserPaintMenuBar(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
|
||||||
APIENTRY
|
|
||||||
NtUserUnregisterUserApiHook(VOID)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
APIENTRY
|
APIENTRY
|
||||||
NtUserGetLayeredWindowAttributes(
|
NtUserGetLayeredWindowAttributes(
|
||||||
|
|
|
@ -122,6 +122,9 @@ NtUserCallNoParam(DWORD Routine)
|
||||||
case NOPARAM_ROUTINE_RELEASECAPTURE:
|
case NOPARAM_ROUTINE_RELEASECAPTURE:
|
||||||
RETURN( (DWORD_PTR)IntReleaseCapture());
|
RETURN( (DWORD_PTR)IntReleaseCapture());
|
||||||
|
|
||||||
|
case NOPARAM_ROUTINE_LOADUSERAPIHOOK:
|
||||||
|
RETURN(UserLoadApiHook());
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DPRINT1("Calling invalid routine number 0x%x in NtUserCallNoParam\n", Routine);
|
DPRINT1("Calling invalid routine number 0x%x in NtUserCallNoParam\n", Routine);
|
||||||
EngSetLastError(ERROR_INVALID_PARAMETER);
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
|
Loading…
Reference in a new issue