Author: gadamopoulos Date: Tue Jul 12 08:43:43 2011 New Revision: 52650
URL: http://svn.reactos.org/svn/reactos?rev=52650&view=rev Log: [win32k] - Implement NtUserRegisterUserApiHook and NtUserUnregisterUserApiHook
Modified: branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/include/hook.h branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/include/msgqueue.h branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/include/win32.h branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/ntuser/hook.c branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/ntuser/msgqueue.c branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/ntuser/ntstubs.c branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/ntuser/simplecall.c
Modified: branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/include/hook.h URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/ThemesSupport/subsyste... ============================================================================== --- branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/include/hook.h [iso-8859-1] (original) +++ branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/include/hook.h [iso-8859-1] Tue Jul 12 08:43:43 2011 @@ -4,6 +4,13 @@ #define HOOKID_TO_INDEX(HookId) (HookId - WH_MINHOOK) #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 { @@ -43,4 +50,10 @@ 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 */
Modified: branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/include/msgqueue.h URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/ThemesSupport/subsyste... ============================================================================== --- branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/include/msgqueue.h [iso-8859-1] (original) +++ branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/include/msgqueue.h [iso-8859-1] Tue Jul 12 08:43:43 2011 @@ -7,6 +7,7 @@ #define MSQ_NORMAL 0 #define MSQ_ISHOOK 1 #define MSQ_ISEVENT 2 +#define MSQ_INJECTMODULE 3
#define QSIDCOUNTS 6
Modified: branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/include/win32.h URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/ThemesSupport/subsyste... ============================================================================== --- branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/include/win32.h [iso-8859-1] (original) +++ branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/include/win32.h [iso-8859-1] Tue Jul 12 08:43:43 2011 @@ -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;
Modified: branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/ntuser/hook.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/ThemesSupport/subsyste... ============================================================================== --- branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/ntuser/hook.c [iso-8859-1] (original) +++ branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/ntuser/hook.c [iso-8859-1] Tue Jul 12 08:43:43 2011 @@ -24,7 +24,219 @@ 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 @@ -1527,4 +1739,64 @@ 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 */
Modified: branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/ntuser/msgqueue.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/ThemesSupport/subsyste... ============================================================================== --- branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/ntuser/msgqueue.c [iso-8859-1] (original) +++ branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/ntuser/msgqueue.c [iso-8859-1] Tue Jul 12 08:43:43 2011 @@ -811,6 +811,12 @@ 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 */
Modified: branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/ntuser/ntstubs.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/ThemesSupport/subsyste... ============================================================================== --- branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/ntuser/ntstubs.c [iso-8859-1] (original) +++ branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/ntuser/ntstubs.c [iso-8859-1] Tue Jul 12 08:43:43 2011 @@ -891,20 +891,6 @@
BOOL APIENTRY -NtUserRegisterUserApiHook( - PUNICODE_STRING m_dllname1, - PUNICODE_STRING m_funname1, - DWORD dwUnknown3, - DWORD dwUnknown4) -{ - UserEnterExclusive(); - UNIMPLEMENTED; - UserLeave(); - return 0; -} - -BOOL -APIENTRY NtUserRegisterRawInputDevices( IN PCRAWINPUTDEVICE pRawInputDevices, IN UINT uiNumDevices, @@ -1038,14 +1024,6 @@
BOOL APIENTRY -NtUserUnregisterUserApiHook(VOID) -{ - UNIMPLEMENTED; - return 0; -} - -BOOL -APIENTRY NtUserGetLayeredWindowAttributes( HWND hwnd, COLORREF *pcrKey,
Modified: branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/ntuser/simplecall.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/ThemesSupport/subsyste... ============================================================================== --- branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/ntuser/simplecall.c [iso-8859-1] (original) +++ branches/GSoC_2011/ThemesSupport/subsystems/win32/win32k/ntuser/simplecall.c [iso-8859-1] Tue Jul 12 08:43:43 2011 @@ -121,6 +121,9 @@
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);