mirror of
https://github.com/reactos/reactos.git
synced 2024-11-07 15:10:53 +00:00
568b6d0558
Allocate heap instead of data segment to be used for callbacks on user side. Move and correct initial hook call out setup. Use it in more than one hook call. This fixes issues with strings out of alignment and use of kernel pointers. See CORE-13907 and CORE-16769. KsStudio still needs retested. Small wow update.
850 lines
22 KiB
C
850 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 *pCsw = NULL;
|
|
CBT_CREATEWNDW *pCbtCreatewndw = NULL;
|
|
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);
|
|
|
|
pCbtCreatewndw = (CBT_CREATEWNDW*)HeapAlloc(GetProcessHeap(), 0, sizeof(CBT_CREATEWNDW));
|
|
RtlCopyMemory(pCbtCreatewndw, CbtCreatewndExtra, sizeof(CBT_CREATEWNDW));
|
|
|
|
pCsw = (CREATESTRUCTW*)HeapAlloc(GetProcessHeap(), 0, sizeof(CREATESTRUCTW));
|
|
RtlCopyMemory(pCsw, &CbtCreatewndExtra->Cs, sizeof(CREATESTRUCTW));
|
|
|
|
pCbtCreatewndw->lpcs = pCsw;
|
|
pCbtCreatewndw->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
|
|
wParam = Common->wParam;
|
|
lParam = (LPARAM) pCbtCreatewndw;
|
|
//ERR("HCBT_CREATEWND: hWnd %p Csw %p Name %p Class %p\n", Common->wParam, pCsw, pCsw->lpszName, pCsw->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 = pCbtCreatewndw->hwndInsertAfter;
|
|
CbtCreatewndExtra->Cs.x = pCbtCreatewndw->lpcs->x;
|
|
CbtCreatewndExtra->Cs.y = pCbtCreatewndw->lpcs->y;
|
|
CbtCreatewndExtra->Cs.cx = pCbtCreatewndw->lpcs->cx;
|
|
CbtCreatewndExtra->Cs.cy = pCbtCreatewndw->lpcs->cy;
|
|
HeapFree(GetProcessHeap(), 0, pCsw);
|
|
HeapFree(GetProcessHeap(), 0, pCbtCreatewndw);
|
|
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:
|
|
{
|
|
PCWP_Struct pcwps = (PCWP_Struct)Common;
|
|
CWPSTRUCT *pCWPT = &pcwps->cwps;
|
|
pCWP = HeapAlloc(GetProcessHeap(), 0, Common->lParamSize + sizeof(CWPSTRUCT));
|
|
RtlCopyMemory(pCWP, pCWPT, sizeof(CWPSTRUCT));
|
|
// ERR("WH_CALLWNDPROC: Code %d, wParam %d msg %d\n",Common->Code,Common->wParam,pCWP->message);
|
|
/* 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 ( Common->lParamSize )
|
|
{
|
|
pCWP->lParam = (LPARAM)((PCHAR)pCWP + sizeof(CWPSTRUCT));
|
|
RtlCopyMemory( (PCHAR)pCWP + sizeof(CWPSTRUCT), &pcwps->Extra, Common->lParamSize );
|
|
}
|
|
Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWP);
|
|
HeapFree(GetProcessHeap(), 0, pCWP);
|
|
}
|
|
break;
|
|
case WH_CALLWNDPROCRET:
|
|
/* Almost the same as WH_CALLWNDPROC */
|
|
{
|
|
PCWPR_Struct pcwprs = (PCWPR_Struct)Common;
|
|
CWPRETSTRUCT *pCWPRT = &pcwprs->cwprs;
|
|
pCWPR = HeapAlloc(GetProcessHeap(), 0, Common->lParamSize + sizeof(CWPRETSTRUCT));
|
|
RtlCopyMemory(pCWPR, pCWPRT, sizeof(CWPSTRUCT));
|
|
if ( Common->lParamSize )
|
|
{
|
|
pCWPR->lParam = (LPARAM)((PCHAR)pCWPR + sizeof(CWPRETSTRUCT));
|
|
RtlCopyMemory( (PCHAR)pCWPR + sizeof(CWPRETSTRUCT), &pcwprs->Extra, Common->lParamSize );
|
|
}
|
|
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);
|
|
}
|
|
|
|
|
|
|