reactos/win32ss/user/user32/windows/hook.c

838 lines
22 KiB
C

/*
* ReactOS kernel
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
*
* PROJECT: ReactOS user32.dll
* FILE: win32ss/user/user32/windows/hook.c
* PURPOSE: Hooks
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* UPDATE HISTORY:
* 09-05-2001 CSH Created
*/
#include <user32.h>
WINE_DEFAULT_DEBUG_CHANNEL(user32);
typedef struct _NOTIFYEVENT
{
DWORD event;
LONG idObject;
LONG idChild;
DWORD flags;
} NOTIFYEVENT, *PNOTIFYEVENT;
/* PRIVATE FUNCTIONS *********************************************************/
static
DWORD
FASTCALL
GetMaskFromEvent(DWORD Event)
{
DWORD Ret = 0;
if ( Event > EVENT_OBJECT_STATECHANGE )
{
if ( Event == EVENT_OBJECT_LOCATIONCHANGE ) return SRV_EVENT_LOCATIONCHANGE;
if ( Event == EVENT_OBJECT_NAMECHANGE ) return SRV_EVENT_NAMECHANGE;
if ( Event == EVENT_OBJECT_VALUECHANGE ) return SRV_EVENT_VALUECHANGE;
return SRV_EVENT_CREATE;
}
if ( Event == EVENT_OBJECT_STATECHANGE ) return SRV_EVENT_STATECHANGE;
Ret = SRV_EVENT_RUNNING;
if ( Event < EVENT_SYSTEM_MENUSTART ) return SRV_EVENT_CREATE;
if ( Event <= EVENT_SYSTEM_MENUPOPUPEND )
{
Ret = SRV_EVENT_MENU;
}
else
{
if ( Event <= EVENT_CONSOLE_CARET-1 ) return SRV_EVENT_CREATE;
if ( Event <= EVENT_CONSOLE_END_APPLICATION ) return SRV_EVENT_END_APPLICATION;
if ( Event != EVENT_OBJECT_FOCUS ) return SRV_EVENT_CREATE;
}
return Ret;
}
static
HHOOK
FASTCALL
IntSetWindowsHook(
int idHook,
HOOKPROC lpfn,
HINSTANCE hMod,
DWORD dwThreadId,
BOOL bAnsi)
{
WCHAR ModuleName[MAX_PATH];
UNICODE_STRING USModuleName;
if (NULL != hMod)
{
if (0 == GetModuleFileNameW(hMod, ModuleName, MAX_PATH))
{
return NULL;
}
RtlInitUnicodeString(&USModuleName, ModuleName);
}
else
{
RtlInitUnicodeString(&USModuleName, NULL);
}
return NtUserSetWindowsHookEx(hMod, &USModuleName, dwThreadId, idHook, lpfn, bAnsi);
}
/*
Since ReactOS uses User32 as the main message source this was needed.
Base on the funny rules from the wine tests it left it with this option.
8^(
*/
VOID
FASTCALL
IntNotifyWinEvent(
DWORD event,
HWND hwnd,
LONG idObject,
LONG idChild,
DWORD flags
)
{
NOTIFYEVENT ne;
ne.event = event;
ne.idObject = idObject;
ne.idChild = idChild;
ne.flags = flags;
if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(event))
NtUserxNotifyWinEvent(hwnd, &ne);
}
/* FUNCTIONS *****************************************************************/
#if 0
BOOL
WINAPI
CallMsgFilter(
LPMSG lpMsg,
int nCode)
{
UNIMPLEMENTED;
return FALSE;
}
#endif
/*
* @implemented
*/
BOOL
WINAPI
CallMsgFilterA(
LPMSG lpMsg,
int nCode)
{
MSG Msg;
if ( NtCurrentTeb()->Win32ThreadInfo &&
(ISITHOOKED(WH_MSGFILTER) || ISITHOOKED(WH_SYSMSGFILTER)) )
{
if ( lpMsg->message & ~WM_MAXIMUM )
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
RtlCopyMemory(&Msg, lpMsg, sizeof(MSG));
return NtUserCallMsgFilter( &Msg, nCode);
}
return FALSE;
}
/*
* @implemented
*/
BOOL
WINAPI
CallMsgFilterW(
LPMSG lpMsg,
int nCode)
{
MSG Msg;
if ( NtCurrentTeb()->Win32ThreadInfo &&
(ISITHOOKED(WH_MSGFILTER) || ISITHOOKED(WH_SYSMSGFILTER)) )
{
if ( lpMsg->message & ~WM_MAXIMUM )
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
RtlCopyMemory(&Msg, lpMsg, sizeof(MSG));
return NtUserCallMsgFilter( &Msg, nCode);
}
return FALSE;
}
/*
* @implemented
*/
LRESULT
WINAPI
CallNextHookEx(
HHOOK Hook, // Windows NT/XP/2003: Ignored.
int Code,
WPARAM wParam,
LPARAM lParam)
{
PCLIENTINFO ClientInfo;
DWORD Flags, Save;
PHOOK pHook, phkNext;
LRESULT lResult = 0;
ClientInfo = GetWin32ClientInfo();
if (!ClientInfo->phkCurrent) return 0;
pHook = DesktopPtrToUser(ClientInfo->phkCurrent);
if (!pHook->phkNext) return 0; // Nothing to do....
phkNext = DesktopPtrToUser(pHook->phkNext);
if ( phkNext->HookId == WH_CALLWNDPROC ||
phkNext->HookId == WH_CALLWNDPROCRET)
{
Save = ClientInfo->dwHookData;
Flags = ClientInfo->CI_flags & CI_CURTHPRHOOK;
// wParam: If the message was sent by the current thread/process, it is
// nonzero; otherwise, it is zero.
if (wParam) ClientInfo->CI_flags |= CI_CURTHPRHOOK;
else ClientInfo->CI_flags &= ~CI_CURTHPRHOOK;
if (phkNext->HookId == WH_CALLWNDPROC)
{
PCWPSTRUCT pCWP = (PCWPSTRUCT)lParam;
NtUserMessageCall( pCWP->hwnd,
pCWP->message,
pCWP->wParam,
pCWP->lParam,
(ULONG_PTR)&lResult,
FNID_CALLWNDPROC,
phkNext->Ansi);
}
else
{
PCWPRETSTRUCT pCWPR = (PCWPRETSTRUCT)lParam;
ClientInfo->dwHookData = pCWPR->lResult;
NtUserMessageCall( pCWPR->hwnd,
pCWPR->message,
pCWPR->wParam,
pCWPR->lParam,
(ULONG_PTR)&lResult,
FNID_CALLWNDPROCRET,
phkNext->Ansi);
}
ClientInfo->CI_flags ^= ((ClientInfo->CI_flags ^ Flags) & CI_CURTHPRHOOK);
ClientInfo->dwHookData = Save;
}
else
lResult = NtUserCallNextHookEx(Code, wParam, lParam, pHook->Ansi);
return lResult;
}
/*
* @implemented
*/
HHOOK
WINAPI
SetWindowsHookW(int idHook, HOOKPROC lpfn)
{
DWORD ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread);
return IntSetWindowsHook(idHook, lpfn, NULL, ThreadId, FALSE);
// return NtUserSetWindowsHookAW(idHook, lpfn, FALSE);
}
/*
* @implemented
*/
HHOOK
WINAPI
SetWindowsHookA(int idHook, HOOKPROC lpfn)
{
DWORD ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread);
return IntSetWindowsHook(idHook, lpfn, NULL, ThreadId, TRUE);
// return NtUserSetWindowsHookAW(idHook, lpfn, TRUE);
}
/*
* @unimplemented
*/
BOOL
WINAPI
DeregisterShellHookWindow(HWND hWnd)
{
return NtUserxDeregisterShellHookWindow(hWnd);
}
/*
* @unimplemented
*/
BOOL
WINAPI
RegisterShellHookWindow(HWND hWnd)
{
return NtUserxRegisterShellHookWindow(hWnd);
}
/*
* @implemented
*/
BOOL
WINAPI
UnhookWindowsHook ( int nCode, HOOKPROC pfnFilterProc )
{
return NtUserxUnhookWindowsHook(nCode, pfnFilterProc);
}
/*
* @implemented
*/
VOID
WINAPI
NotifyWinEvent(
DWORD event,
HWND hwnd,
LONG idObject,
LONG idChild
)
{
// "Servers call NotifyWinEvent to announce the event to the system after the
// event has occurred; they must never notify the system of an event before
// the event has occurred." msdn on NotifyWinEvent.
if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(event)) // Check to see.
NtUserNotifyWinEvent(event, hwnd, idObject, idChild);
}
/*
* @implemented
*/
HWINEVENTHOOK
WINAPI
SetWinEventHook(
UINT eventMin,
UINT eventMax,
HMODULE hmodWinEventProc,
WINEVENTPROC pfnWinEventProc,
DWORD idProcess,
DWORD idThread,
UINT dwFlags
)
{
WCHAR ModuleName[MAX_PATH];
UNICODE_STRING USModuleName;
PUNICODE_STRING pusmodName;
RtlInitUnicodeString(&USModuleName, NULL);
if ((hmodWinEventProc != NULL) && (dwFlags & WINEVENT_INCONTEXT))
{
if (0 == GetModuleFileNameW(hmodWinEventProc, ModuleName, MAX_PATH))
{
return NULL;
}
RtlInitUnicodeString(&USModuleName, ModuleName);
pusmodName = &USModuleName;
}
else
{
pusmodName = NULL;
}
return NtUserSetWinEventHook(eventMin,
eventMax,
hmodWinEventProc,
pusmodName,
pfnWinEventProc,
idProcess,
idThread,
dwFlags);
}
/*
* @implemented
*/
BOOL
WINAPI
IsWinEventHookInstalled(
DWORD event)
{
if ((PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo)
{
return (gpsi->dwInstalledEventHooks & GetMaskFromEvent(event)) != 0;
}
return FALSE;
}
/*
* @implemented
*/
HHOOK
WINAPI
SetWindowsHookExA(
int idHook,
HOOKPROC lpfn,
HINSTANCE hMod,
DWORD dwThreadId)
{
return IntSetWindowsHook(idHook, lpfn, hMod, dwThreadId, TRUE);
}
/*
* @implemented
*/
HHOOK
WINAPI
SetWindowsHookExW(
int idHook,
HOOKPROC lpfn,
HINSTANCE hMod,
DWORD dwThreadId)
{
return IntSetWindowsHook(idHook, lpfn, hMod, dwThreadId, FALSE);
}
static
BOOL
ClientLoadLibrary(
PUNICODE_STRING pstrLibName,
PUNICODE_STRING pstrInitFunc,
BOOL bUnload,
BOOL bApiHook)
{
HINSTANCE hLibrary;
PVOID pInitFunction;
NTSTATUS Status;
ANSI_STRING InitFuncName;
BOOL bResult = FALSE;
TRACE("ClientLoadLibrary: pid: %d, strLibraryName: %S, "
"strInitFuncName: %S, bUnload: %d, bApiHook:%d\n",
GetCurrentProcessId(),
pstrLibName->Buffer,
pstrInitFunc->Buffer,
bUnload,
bApiHook);
/* Check if we have to load the module */
if (bUnload == FALSE)
{
ASSERT(pstrLibName->Buffer != NULL);
/* Load it */
hLibrary = LoadLibrary(pstrLibName->Buffer);
if (hLibrary == 0)
{
return FALSE;
}
if (!bApiHook)
{
/* There is nothing more to do for a global hook*/
return TRUE;
}
/* Initialize the user api hook */
ASSERT(pstrInitFunc->Buffer);
Status = RtlUnicodeStringToAnsiString(&InitFuncName,
pstrInitFunc,
TRUE);
if (!NT_SUCCESS(Status))
{
FreeLibrary(hLibrary);
return FALSE;
}
/* Get the address of the initialization routine */
pInitFunction = GetProcAddress(hLibrary, InitFuncName.Buffer);
if (pInitFunction)
{
/* Call the initialization routine */
bResult = InitUserApiHook(hLibrary, (USERAPIHOOKPROC)pInitFunction);
}
RtlFreeAnsiString(&InitFuncName);
/* In case of error unload the library */
if (bResult == FALSE)
{
FreeLibrary(hLibrary);
}
}
else
{
/* Cleanup user api hook before unloading */
if (bApiHook)
{
hLibrary = ghmodUserApiHook;
bResult = ClearUserApiHook(ghmodUserApiHook);
/* Check if we can we unload it now */
if (!bResult)
{
/* Return success because we are going to free
the library in EndUserApiHook*/
return TRUE;
}
}
else
{
/* Get the library handle from the name */
hLibrary = GetModuleHandle(pstrLibName->Buffer);
if (hLibrary == NULL)
{
return FALSE;
}
}
bResult = FreeLibrary(hLibrary);
}
return bResult;
}
NTSTATUS WINAPI
User32CallClientLoadLibraryFromKernel(PVOID Arguments, ULONG ArgumentLength)
{
BOOL bResult;
PCLIENT_LOAD_LIBRARY_ARGUMENTS Argument;
/* Retireve the callback parameters */
Argument = (PCLIENT_LOAD_LIBRARY_ARGUMENTS)Arguments;
if(Argument->strLibraryName.Buffer != NULL)
{
Argument->strLibraryName.Buffer = (PWCHAR)((ULONG_PTR)Argument->strLibraryName.Buffer + (ULONG_PTR)Argument);
}
if(Argument->strInitFuncName.Buffer != NULL)
{
Argument->strInitFuncName.Buffer = (PWCHAR)((ULONG_PTR)Argument->strInitFuncName.Buffer + (ULONG_PTR)Argument);
}
/* Call the implementation of the callback */
bResult = ClientLoadLibrary(&Argument->strLibraryName,
&Argument->strInitFuncName,
Argument->Unload,
Argument->ApiHook);
return ZwCallbackReturn(&bResult, sizeof(HINSTANCE), STATUS_SUCCESS);
}
NTSTATUS WINAPI
User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
{
PHOOKPROC_CALLBACK_ARGUMENTS Common;
CREATESTRUCTW Csw;
CBT_CREATEWNDW CbtCreatewndw;
PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL;
KBDLLHOOKSTRUCT KeyboardLlData, *pKeyboardLlData;
MSLLHOOKSTRUCT MouseLlData, *pMouseLlData;
MSG *pcMsg, *pMsg;
PMOUSEHOOKSTRUCT pMHook;
CWPSTRUCT *pCWP;
CWPRETSTRUCT *pCWPR;
PRECTL prl;
LPCBTACTIVATESTRUCT pcbtas;
HOOKPROC Proc;
WPARAM wParam = 0;
LPARAM lParam = 0;
LRESULT Result = 0;
BOOL Hit = FALSE, Loaded = FALSE;
HMODULE mod = NULL;
NTSTATUS Status = STATUS_SUCCESS;
Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Arguments;
Proc = Common->Proc;
// HookProc Justin Case module is from another process.
if (Common->offPfn && Common->Mod)
{
if (!(mod = GetModuleHandleW((LPCWSTR)Common->ModuleName)))
{
TRACE("Reloading Hook Module.\n");
if (!(mod = LoadLibraryExW((LPCWSTR)Common->ModuleName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)))
{
ERR("Failed to load Hook Module.\n");
}
else
{
Loaded = TRUE; // Free it only when loaded.
}
}
if (mod)
{
TRACE("Loading Hook Module. %S\n",Common->ModuleName);
Proc = (HOOKPROC)((char *)mod + Common->offPfn);
}
}
switch(Common->HookId)
{
case WH_CBT:
{
//ERR("WH_CBT: Code %d\n", Common->Code);
switch(Common->Code)
{
case HCBT_CREATEWND:
CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS)
((PCHAR) Common + Common->lParam);
RtlCopyMemory(&Csw, &CbtCreatewndExtra->Cs, sizeof(CREATESTRUCTW));
CbtCreatewndw.lpcs = &Csw;
CbtCreatewndw.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
wParam = Common->wParam;
lParam = (LPARAM) &CbtCreatewndw;
//ERR("HCBT_CREATEWND: hWnd 0x%x Name 0x%x Class 0x%x\n", Common->wParam, Csw.lpszName, Csw.lpszClass);
break;
case HCBT_CLICKSKIPPED:
pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
lParam = (LPARAM) pMHook;
wParam = Common->wParam;
break;
case HCBT_MOVESIZE:
prl = (PRECTL)((PCHAR) Common + Common->lParam);
lParam = (LPARAM) prl;
wParam = Common->wParam;
break;
case HCBT_ACTIVATE:
//ERR("HCBT_ACTIVATE: hwnd %p\n",Common->wParam);
pcbtas = (LPCBTACTIVATESTRUCT)((PCHAR) Common + Common->lParam);
lParam = (LPARAM) pcbtas;
wParam = Common->wParam;
break;
case HCBT_KEYSKIPPED: /* The rest SEH support */
case HCBT_MINMAX:
case HCBT_SETFOCUS:
case HCBT_SYSCOMMAND:
case HCBT_DESTROYWND:
case HCBT_QS:
wParam = Common->wParam;
lParam = Common->lParam;
break;
default:
if (Loaded) FreeLibrary(mod);
ERR("HCBT_ not supported = %d\n", Common->Code);
return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
}
if (Proc)
{
_SEH2_TRY
{
Result = Proc(Common->Code, wParam, lParam);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Hit = TRUE;
}
_SEH2_END;
}
else
{
ERR("Null Proc! Common = 0x%x, Proc = 0x%x\n",Common,Proc);
}
switch(Common->Code)
{
case HCBT_CREATEWND:
CbtCreatewndExtra->WndInsertAfter = CbtCreatewndw.hwndInsertAfter;
CbtCreatewndExtra->Cs.x = CbtCreatewndw.lpcs->x;
CbtCreatewndExtra->Cs.y = CbtCreatewndw.lpcs->y;
CbtCreatewndExtra->Cs.cx = CbtCreatewndw.lpcs->cx;
CbtCreatewndExtra->Cs.cy = CbtCreatewndw.lpcs->cy;
break;
}
break;
}
case WH_KEYBOARD_LL:
//ERR("WH_KEYBOARD_LL: Code %d, wParam %d\n",Common->Code,Common->wParam);
pKeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
RtlCopyMemory(&KeyboardLlData, pKeyboardLlData, sizeof(KBDLLHOOKSTRUCT));
Result = Proc(Common->Code, Common->wParam, (LPARAM) &KeyboardLlData);
break;
case WH_MOUSE_LL:
//ERR("WH_MOUSE_LL: Code %d, wParam %d\n",Common->Code,Common->wParam);
pMouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
RtlCopyMemory(&MouseLlData, pMouseLlData, sizeof(MSLLHOOKSTRUCT));
Result = Proc(Common->Code, Common->wParam, (LPARAM) &MouseLlData);
break;
case WH_MOUSE: /* SEH support */
pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
_SEH2_TRY
{
Result = Proc(Common->Code, Common->wParam, (LPARAM) pMHook);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Hit = TRUE;
}
_SEH2_END;
break;
case WH_CALLWNDPROC:
// ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common->Code,Common->wParam);
pCWP = HeapAlloc(GetProcessHeap(), 0, ArgumentLength - sizeof(HOOKPROC_CALLBACK_ARGUMENTS));
RtlCopyMemory(pCWP, (PCHAR) Common + Common->lParam, sizeof(CWPSTRUCT));
/* If more memory is reserved, then lParam is a pointer.
* Size of the buffer is stocked in the lParam member, and its content
* is at the end of the argument buffer */
if(ArgumentLength > (sizeof(CWPSTRUCT) + sizeof(HOOKPROC_CALLBACK_ARGUMENTS)))
{
RtlCopyMemory((PCHAR)pCWP + sizeof(CWPSTRUCT),
(PCHAR)Common + Common->lParam + sizeof(CWPSTRUCT),
pCWP->lParam);
pCWP->lParam = (LPARAM)((PCHAR)pCWP + sizeof(CWPSTRUCT));
}
Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWP);
HeapFree(GetProcessHeap(), 0, pCWP);
break;
case WH_CALLWNDPROCRET:
/* Almost the same as WH_CALLWNDPROC */
pCWPR = HeapAlloc(GetProcessHeap(), 0, ArgumentLength - sizeof(HOOKPROC_CALLBACK_ARGUMENTS));
RtlCopyMemory(pCWPR, (PCHAR) Common + Common->lParam, sizeof(CWPRETSTRUCT));
if(ArgumentLength > (sizeof(CWPRETSTRUCT) + sizeof(HOOKPROC_CALLBACK_ARGUMENTS)))
{
RtlCopyMemory((PCHAR)pCWPR + sizeof(CWPRETSTRUCT),
(PCHAR)Common + Common->lParam + sizeof(CWPRETSTRUCT),
pCWPR->lParam);
pCWPR->lParam = (LPARAM)((PCHAR)pCWPR + sizeof(CWPRETSTRUCT));
}
Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWPR);
HeapFree(GetProcessHeap(), 0, pCWPR);
break;
case WH_MSGFILTER: /* All SEH support */
case WH_SYSMSGFILTER:
case WH_GETMESSAGE:
pMsg = (PMSG)((PCHAR) Common + Common->lParam);
pcMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MSG));
RtlCopyMemory(pcMsg, pMsg, sizeof(MSG));
// ERR("pMsg %d pcMsg %d\n",pMsg->message, pcMsg->message);
_SEH2_TRY
{
Result = Proc(Common->Code, Common->wParam, (LPARAM) pcMsg);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Hit = TRUE;
}
_SEH2_END;
if (!Hit && Common->HookId == WH_GETMESSAGE)
RtlCopyMemory(pMsg, pcMsg, sizeof(MSG));
HeapFree( GetProcessHeap(), 0, pcMsg );
break;
case WH_KEYBOARD:
case WH_SHELL:
Result = Proc(Common->Code, Common->wParam, Common->lParam);
break;
case WH_FOREGROUNDIDLE: /* <-- SEH support */
_SEH2_TRY
{
Result = Proc(Common->Code, Common->wParam, Common->lParam);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Hit = TRUE;
}
_SEH2_END;
break;
default:
if (Loaded) FreeLibrary(mod);
ERR("WH_ not supported = %d\n", Common->HookId);
return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
}
if (Hit)
{
ERR("Hook Exception! Id: %d, Code %d, Proc 0x%x\n",Common->HookId,Common->Code,Proc);
Status = STATUS_UNSUCCESSFUL;
}
if (Loaded) FreeLibrary(mod);
Common->Result = Result;
return ZwCallbackReturn(Arguments, ArgumentLength, Status);
}
NTSTATUS WINAPI
User32CallEventProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
{
PEVENTPROC_CALLBACK_ARGUMENTS Common;
WINEVENTPROC Proc;
WCHAR module[MAX_PATH];
DWORD len;
HMODULE mod = NULL;
BOOL Loaded = FALSE;
Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Arguments;
Proc = Common->Proc;
if (Common->offPfn && Common->Mod)
{ // Validate the module again.
if (!(len = GetModuleFileNameW((HINSTANCE)Common->Mod, module, MAX_PATH)) || len >= MAX_PATH)
{
ERR("Error check for module!\n");
Common->Mod = 0;
}
if (Common->Mod && !(mod = GetModuleHandleW(module)))
{
TRACE("Reloading Event Module.\n");
if (!(mod = LoadLibraryExW(module, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)))
{
ERR("Failed to load Event Module.\n");
}
else
{
Loaded = TRUE; // Free it only when loaded.
}
}
if (mod)
{
TRACE("Loading Event Module. %S\n",module);
Proc = (WINEVENTPROC)((char *)mod + Common->offPfn);
}
}
Proc(Common->hook,
Common->event,
Common->hwnd,
Common->idObject,
Common->idChild,
Common->dwEventThread,
Common->dwmsEventTime);
if (Loaded) FreeLibrary(mod);
return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS);
}