- Rewrite HOOKs, Implement CallNextHookEx and fix prototype for NtUserCallNextHookEx. Move hook structure to ntuser.h for user verifying.

- Tested with FF, Seamonkey, Abiword, and the rest of our applications.

svn path=/trunk/; revision=34653
This commit is contained in:
James Tabor 2008-07-22 04:54:53 +00:00
parent c688052ea5
commit 4f11e10d3d
8 changed files with 480 additions and 47 deletions

View file

@ -193,9 +193,66 @@ CallNextHookEx(
WPARAM wParam,
LPARAM lParam)
{
return NtUserCallNextHookEx(Hook, Code, wParam, lParam);
PW32CLIENTINFO ClientInfo;
PHOOK pHook;
DWORD Flags, Save;
LRESULT lResult = 0;
GetConnected();
ClientInfo = GetWin32ClientInfo();
pHook = ValidateHandle(Hook, VALIDATE_TYPE_HOOK);
if (!pHook) return 0;
ClientInfo->phkCurrent = (PHOOK)pHook->Self; // Pass this over to the kernel.
if (pHook->HookId == WH_CALLWNDPROC || pHook->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 (pHook->HookId == WH_CALLWNDPROC)
{
PCWPSTRUCT pCWP = (PCWPSTRUCT)lParam;
lResult = NtUserMessageCall( pCWP->hwnd,
pCWP->message,
pCWP->wParam,
pCWP->lParam,
0,
FNID_CALLWNDPROC,
pHook->Ansi);
}
else
{
PCWPRETSTRUCT pCWPR = (PCWPRETSTRUCT)lParam;
ClientInfo->dwHookData = pCWPR->lResult;
lResult = NtUserMessageCall( pCWPR->hwnd,
pCWPR->message,
pCWPR->wParam,
pCWPR->lParam,
0,
FNID_CALLWNDPROCRET,
pHook->Ansi);
}
ClientInfo->CI_flags ^= ((ClientInfo->CI_flags ^ Flags) & CI_CURTHPRHOOK);
ClientInfo->dwHookData = Save;
}
else
lResult = NtUserCallNextHookEx(Code, wParam, lParam, pHook->Ansi);
return lResult;
}
/*
* @unimplemented
*/
@ -366,6 +423,7 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
LPARAM lParam;
PKBDLLHOOKSTRUCT KeyboardLlData;
PMSLLHOOKSTRUCT MouseLlData;
PMSG Msg;
Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Arguments;
@ -446,6 +504,13 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
MouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) MouseLlData);
break;
case WH_MSGFILTER:
case WH_SYSMSGFILTER:
case WH_GETMESSAGE:
Msg = (PMSG)((PCHAR) Common + Common->lParam);
FIXME("UHOOK Memory: %x: %x\n",Common, Msg);
Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) Msg);
break;
default:
return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
}

View file

@ -317,6 +317,20 @@ typedef struct _W32THREADINFO
} W32THREADINFO, *PW32THREADINFO;
/* Window Client Information structure */
struct _ETHREAD;
typedef struct tagHOOK
{
LIST_ENTRY Chain; /* Hook chain entry */
HHOOK Self; /* user handle for this hook */
struct _ETHREAD* Thread; /* Thread owning the hook */
int HookId; /* Hook table index */
HOOKPROC Proc; /* Hook function */
BOOLEAN Ansi; /* Is it an Ansi hook? */
ULONG Flags; /* Some internal flags */
UNICODE_STRING ModuleName; /* Module name for global hooks */
} HOOK, *PHOOK;
typedef struct _CALLBACKWND
{
@ -324,6 +338,8 @@ typedef struct _CALLBACKWND
PVOID pvWnd;
} CALLBACKWND, *PCALLBACKWND;
#define CI_CURTHPRHOOK 0x00000010
typedef struct _W32CLIENTINFO
{
ULONG CI_flags;
@ -334,7 +350,7 @@ typedef struct _W32CLIENTINFO
DWORD dwTIFlags;
PVOID pDeskInfo;
ULONG_PTR ulClientDelta;
PVOID phkCurrent;
PHOOK phkCurrent;
ULONG fsHooks;
HWND hWND; // Will be replaced with CALLBACKWND.
PVOID pvWND; // " "
@ -848,10 +864,10 @@ NtUserCallMsgFilter(
LRESULT
NTAPI
NtUserCallNextHookEx(
HHOOK Hook,
int Code,
WPARAM wParam,
LPARAM lParam);
LPARAM lParam,
BOOL Ansi);
DWORD
NTAPI

View file

@ -2,7 +2,7 @@
#define _WIN32K_HOOK_H
#define HOOK_THREAD_REFERENCED (0x1)
#if 0
typedef struct tagHOOK
{
LIST_ENTRY Chain; /* Hook chain entry */
@ -14,8 +14,11 @@ typedef struct tagHOOK
ULONG Flags; /* Some internal flags */
UNICODE_STRING ModuleName; /* Module name for global hooks */
} HOOK, *PHOOK;
#endif
#define NB_HOOKS (WH_MAXHOOK-WH_MINHOOK+1)
#define HOOKID_TO_INDEX(HookId) (HookId - WH_MINHOOK)
#define HOOKID_TO_FLAG(HookId) (1 << ((HookId) + 1))
#define ISITHOOKED(HookId) (PsGetCurrentThreadWin32Thread()->Hooks & HOOKID_TO_FLAG(HookId))
typedef struct tagHOOKTABLE
{
@ -46,6 +49,7 @@ LRESULT FASTCALL co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM l
LRESULT FASTCALL co_EVENT_CallEvents(DWORD, HWND, LONG, LONG);
VOID FASTCALL HOOK_DestroyThreadHooks(PETHREAD Thread);
PHOOK FASTCALL IntGetHookObject(HHOOK);
LRESULT FASTCALL UserCallNextHookEx( int HookId, int Code, WPARAM wParam, LPARAM lParam, BOOL Ansi);
#endif /* _WIN32K_HOOK_H */

View file

@ -165,7 +165,7 @@ BOOL FASTCALL
IntShowOwnedPopups( PWINDOW_OBJECT owner, BOOL fShow );
LRESULT FASTCALL
IntDefWindowProc( PWINDOW_OBJECT Window, UINT Msg, WPARAM wParam, LPARAM lParam);
IntDefWindowProc( PWINDOW_OBJECT Window, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL Ansi);
#endif /* _WIN32K_WINDOW_H */

View file

@ -379,6 +379,13 @@ co_IntCallHookProc(INT HookId,
case WH_MOUSE_LL:
ArgumentLength += sizeof(MSLLHOOKSTRUCT);
break;
case WH_MSGFILTER:
case WH_SYSMSGFILTER:
case WH_GETMESSAGE:
ArgumentLength += sizeof(MSG);
break;
// case WH_SHELL:
// break;
default:
DPRINT1("Trying to call unsupported window hook %d\n", HookId);
return 0;
@ -437,6 +444,16 @@ co_IntCallHookProc(INT HookId,
RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSLLHOOKSTRUCT));
Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
break;
case WH_MSGFILTER:
case WH_SYSMSGFILTER:
case WH_GETMESSAGE:
RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSG));
Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
DPRINT1("KHOOK Memory: %x\n",Common);
break;
// case WH_SHELL:
// Extra = lParam;
// break;
}
ResultPointer = NULL;

View file

@ -4,8 +4,7 @@
* PURPOSE: Misc User funcs
* FILE: subsystem/win32/win32k/ntuser/defwnd.c
* PROGRAMER:
* REVISION HISTORY:
* 2003/05/22 Created
*
*/
#include <w32k.h>
@ -22,7 +21,8 @@ IntDefWindowProc(
PWINDOW_OBJECT Window,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
LPARAM lParam,
BOOL Ansi)
{
PWINDOW Wnd;

View file

@ -15,9 +15,6 @@
#define NDEBUG
#include <debug.h>
#define HOOKID_TO_INDEX(HookId) (HookId - WH_MINHOOK)
#define HOOKID_TO_FLAG(HookId) (1 << ((HookId) + 1))
static PHOOKTABLE GlobalHooks;
@ -107,11 +104,14 @@ IntAddHook(PETHREAD Thread, int HookId, BOOLEAN Global, PWINSTATION_OBJECT WinSt
Hook->Thread = Thread;
Hook->HookId = HookId;
W32Thread = ((PW32THREAD)Thread->Tcb.Win32Thread);
ASSERT(W32Thread != NULL);
W32Thread->Hooks |= HOOKID_TO_FLAG(HookId);
if (W32Thread->ThreadInfo != NULL)
W32Thread->ThreadInfo->Hooks = W32Thread->Hooks;
if (Thread)
{
W32Thread = ((PW32THREAD)Thread->Tcb.Win32Thread);
ASSERT(W32Thread != NULL);
W32Thread->Hooks |= HOOKID_TO_FLAG(HookId);
if (W32Thread->ThreadInfo != NULL)
W32Thread->ThreadInfo->Hooks = W32Thread->Hooks;
}
RtlInitUnicodeString(&Hook->ModuleName, NULL);
@ -318,7 +318,7 @@ co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
return IntCallLowLevelHook(HookId, Code, wParam, lParam, Hook);
}
if (Hook->Thread != PsGetCurrentThread())
if ((Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL))
{
DPRINT1("Calling hooks in other threads not implemented yet");
return 0;
@ -394,22 +394,350 @@ HOOK_DestroyThreadHooks(PETHREAD Thread)
break;
}
}
ObDereferenceObject(WinStaObj);
}
}
LRESULT
FASTCALL
IntCallDebugHook(
int Code,
WPARAM wParam,
LPARAM lParam)
{
UNIMPLEMENTED
return 0;
}
LRESULT
FASTCALL
UserCallNextHookEx(
int HookId,
int Code,
WPARAM wParam,
LPARAM lParam,
BOOL Ansi)
{
LRESULT lResult = 0;
BOOL BadChk = FALSE;
// Handle this one first.
if ((HookId == WH_MOUSE) || (HookId == WH_CBT && Code == HCBT_CLICKSKIPPED))
{
MOUSEHOOKSTRUCTEX Mouse;
if (lParam)
{
_SEH_TRY
{
ProbeForRead((PVOID)lParam,
sizeof(MOUSEHOOKSTRUCTEX),
1);
RtlCopyMemory( &Mouse,
(PVOID)lParam,
sizeof(MOUSEHOOKSTRUCTEX));
}
_SEH_HANDLE
{
BadChk = TRUE;
}
_SEH_END;
if (BadChk)
{
DPRINT1("HOOK WH_MOUSE read from lParam ERROR!\n");
}
}
if (!BadChk)
{
lResult = co_HOOK_CallHooks(HookId, Code, wParam, (LPARAM)&Mouse);
}
return lResult;
}
switch(HookId)
{
case WH_MOUSE_LL:
{
MSLLHOOKSTRUCT Mouse;
if (lParam)
{
_SEH_TRY
{
ProbeForRead((PVOID)lParam,
sizeof(MSLLHOOKSTRUCT),
1);
RtlCopyMemory( &Mouse,
(PVOID)lParam,
sizeof(MSLLHOOKSTRUCT));
}
_SEH_HANDLE
{
BadChk = TRUE;
}
_SEH_END;
if (BadChk)
{
DPRINT1("HOOK WH_MOUSE_LL read from lParam ERROR!\n");
}
}
if (!BadChk)
{
lResult = co_HOOK_CallHooks(HookId, Code, wParam, (LPARAM)&Mouse);
}
break;
}
case WH_KEYBOARD_LL:
{
KBDLLHOOKSTRUCT Keyboard;
if (lParam)
{
_SEH_TRY
{
ProbeForRead((PVOID)lParam,
sizeof(KBDLLHOOKSTRUCT),
1);
RtlCopyMemory( &Keyboard,
(PVOID)lParam,
sizeof(KBDLLHOOKSTRUCT));
}
_SEH_HANDLE
{
BadChk = TRUE;
}
_SEH_END;
if (BadChk)
{
DPRINT1("HOOK WH_KEYBORD_LL read from lParam ERROR!\n");
}
}
if (!BadChk)
{
lResult = co_HOOK_CallHooks(HookId, Code, wParam, (LPARAM)&Keyboard);
}
break;
}
case WH_MSGFILTER:
case WH_SYSMSGFILTER:
case WH_GETMESSAGE:
{
MSG Msg;
if (lParam)
{
_SEH_TRY
{
ProbeForRead((PVOID)lParam,
sizeof(MSG),
1);
RtlCopyMemory( &Msg,
(PVOID)lParam,
sizeof(MSG));
}
_SEH_HANDLE
{
BadChk = TRUE;
}
_SEH_END;
if (BadChk)
{
DPRINT1("HOOK WH_XMESSAGEX read from lParam ERROR!\n");
}
}
if (!BadChk)
{
lResult = co_HOOK_CallHooks(HookId, Code, wParam, (LPARAM)&Msg);
if (lParam && (HookId == WH_GETMESSAGE))
{
_SEH_TRY
{
ProbeForWrite((PVOID)lParam,
sizeof(MSG),
1);
RtlCopyMemory((PVOID)lParam,
&Msg,
sizeof(MSG));
}
_SEH_HANDLE
{
BadChk = TRUE;
}
_SEH_END;
if (BadChk)
{
DPRINT1("HOOK WH_GETMESSAGE write to lParam ERROR!\n");
}
}
}
break;
}
case WH_CBT:
switch (Code)
{
case HCBT_CREATEWND:
lResult = co_HOOK_CallHooks(HookId, Code, wParam, lParam);
break;
case HCBT_MOVESIZE:
{
RECT rt;
if (lParam)
{
_SEH_TRY
{
ProbeForRead((PVOID)lParam,
sizeof(RECT),
1);
RtlCopyMemory( &rt,
(PVOID)lParam,
sizeof(RECT));
}
_SEH_HANDLE
{
BadChk = TRUE;
}
_SEH_END;
if (BadChk)
{
DPRINT1("HOOK HCBT_MOVESIZE read from lParam ERROR!\n");
}
}
if (!BadChk)
{
lResult = co_HOOK_CallHooks(HookId, Code, wParam, (LPARAM)&rt);
}
break;
}
case HCBT_ACTIVATE:
{
CBTACTIVATESTRUCT CbAs;
if (lParam)
{
_SEH_TRY
{
ProbeForRead((PVOID)lParam,
sizeof(CBTACTIVATESTRUCT),
1);
RtlCopyMemory( &CbAs,
(PVOID)lParam,
sizeof(CBTACTIVATESTRUCT));
}
_SEH_HANDLE
{
BadChk = TRUE;
}
_SEH_END;
if (BadChk)
{
DPRINT1("HOOK HCBT_ACTIVATE read from lParam ERROR!\n");
}
}
if (!BadChk)
{
lResult = co_HOOK_CallHooks(HookId, Code, wParam, (LPARAM)&CbAs);
}
break;
}
/*
The rest just use default.
*/
default:
lResult = co_HOOK_CallHooks(HookId, Code, wParam, lParam);
break;
}
break;
case WH_JOURNALPLAYBACK:
case WH_JOURNALRECORD:
{
EVENTMSG EventMsg;
if (lParam)
{
_SEH_TRY
{
ProbeForRead((PVOID)lParam,
sizeof(EVENTMSG),
1);
RtlCopyMemory( &EventMsg,
(PVOID)lParam,
sizeof(EVENTMSG));
}
_SEH_HANDLE
{
BadChk = TRUE;
}
_SEH_END;
if (BadChk)
{
DPRINT1("HOOK WH_JOURNAL read from lParam ERROR!\n");
}
}
if (!BadChk)
{
lResult = co_HOOK_CallHooks(HookId, Code, wParam, (LPARAM)(lParam ? &EventMsg : NULL));
if (lParam)
{
_SEH_TRY
{
ProbeForWrite((PVOID)lParam,
sizeof(EVENTMSG),
1);
RtlCopyMemory((PVOID)lParam,
&EventMsg,
sizeof(EVENTMSG));
}
_SEH_HANDLE
{
BadChk = TRUE;
}
_SEH_END;
if (BadChk)
{
DPRINT1("HOOK WH_JOURNAL write to lParam ERROR!\n");
}
}
}
break;
}
case WH_DEBUG:
lResult = IntCallDebugHook( Code, wParam, lParam);
break;
/*
Default the rest like, WH_FOREGROUNDIDLE, WH_KEYBOARD and WH_SHELL.
*/
case WH_FOREGROUNDIDLE:
case WH_KEYBOARD:
case WH_SHELL:
lResult = co_HOOK_CallHooks(HookId, Code, wParam, lParam);
break;
default:
DPRINT1("Unsupported HOOK Id -> %d\n",HookId);
break;
}
return lResult;
}
LRESULT
STDCALL
NtUserCallNextHookEx(
HHOOK Hook,
int Code,
WPARAM wParam,
LPARAM lParam)
LPARAM lParam,
BOOL Ansi)
{
HHOOK Hook;
PHOOK HookObj, NextObj;
PW32CLIENTINFO ClientInfo;
PWINSTATION_OBJECT WinStaObj;
NTSTATUS Status;
LRESULT lResult;
INT HookId;
DECLARE_RETURN(LRESULT);
DPRINT("Enter NtUserCallNextHookEx\n");
@ -420,22 +748,17 @@ NtUserCallNextHookEx(
0,
&WinStaObj);
if (! NT_SUCCESS(Status))
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN( FALSE);
RETURN( 0);
}
//Status = UserReferenceObjectByHandle(gHandleTable, Hook,
// otHookProc, (PVOID *) &HookObj);
ObDereferenceObject(WinStaObj);
// if (! NT_SUCCESS(Status))
// {
// DPRINT1("Invalid handle passed to NtUserCallNextHookEx\n");
// SetLastNtError(Status);
// RETURN( 0);
// }
ClientInfo = GetWin32ClientInfo();
Hook = (HHOOK)ClientInfo->phkCurrent;
if (!(HookObj = IntGetHookObject(Hook)))
{
@ -444,6 +767,9 @@ NtUserCallNextHookEx(
ASSERT(Hook == HookObj->Self);
HookId = HookObj->HookId;
Ansi = HookObj->Ansi;
if (NULL != HookObj->Thread && (HookObj->Thread != PsGetCurrentThread()))
{
DPRINT1("Thread mismatch\n");
@ -451,15 +777,15 @@ NtUserCallNextHookEx(
SetLastWin32Error(ERROR_INVALID_HANDLE);
RETURN( 0);
}
NextObj = IntGetNextHook(HookObj);
UserDereferenceObject(HookObj);
if (NULL != NextObj)
{
DPRINT1("Calling next hook not implemented\n");
UNIMPLEMENTED
SetLastWin32Error(ERROR_NOT_SUPPORTED);
RETURN( 0);
lResult = UserCallNextHookEx( HookId, Code, wParam, lParam, Ansi);
if (lResult == 0) RETURN( 0);
RETURN( (LRESULT)NextObj);
}
RETURN( 0);
@ -570,7 +896,7 @@ NtUserSetWindowsHookEx(
/* We only (partially) support local WH_CBT hooks and
* WH_KEYBOARD_LL/WH_MOUSE_LL hooks for now */
if ((WH_CBT != HookId || Global)
&& WH_KEYBOARD_LL != HookId && WH_MOUSE_LL != HookId) // && WH_GETMESSAGE != HookId)
&& WH_KEYBOARD_LL != HookId && WH_MOUSE_LL != HookId && WH_GETMESSAGE != HookId)
{
#if 0 /* Removed to get winEmbed working again */
UNIMPLEMENTED

View file

@ -694,7 +694,7 @@ CheckMessages:
{
ThreadQueue->QuitPosted = FALSE;
}
return TRUE;
goto MsgExit;
}
/* Now check for normal messages. */
@ -741,7 +741,7 @@ CheckMessages:
if (IntGetPaintMessage(hWnd, MsgFilterMin, MsgFilterMax, PsGetCurrentThreadWin32Thread(), &Msg->Msg, RemoveMessages))
{
Msg->FreeLParam = FALSE;
return TRUE;
goto MsgExit;
}
/* Check for WM_(SYS)TIMER messages */
@ -802,7 +802,7 @@ MessageFound:
// UserDereferenceObject(MsgWindow);
// }
return TRUE;
goto MsgExit;
}
if((Msg->Msg.hwnd && Msg->Msg.message >= WM_MOUSEFIRST && Msg->Msg.message <= WM_MOUSELAST) &&
@ -813,7 +813,14 @@ MessageFound:
/* eat the message, search again */
goto CheckMessages;
}
MsgExit:
// The WH_GETMESSAGE hook enables an application to monitor messages about to
// be returned by the GetMessage or PeekMessage function.
if(ISITHOOKED(WH_GETMESSAGE))
{
DPRINT1("Peek WH_GETMESSAGE -> %x\n",&Msg);
co_HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, RemoveMsg & PM_REMOVE, (LPARAM)&Msg);
}
return TRUE;
}
@ -856,12 +863,10 @@ NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
}
Present = co_IntPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, RemoveMsg);
// The WH_GETMESSAGE hook enables an application to monitor messages about to
// be returned by the GetMessage or PeekMessage function.
co_HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, RemoveMsg & PM_REMOVE, (LPARAM)&Msg);
if (Present)
{
Info.Msg = Msg.Msg;
/* See if this message type is present in the table */
MsgMemoryEntry = FindMsgMemory(Info.Msg.message);
@ -1862,7 +1867,7 @@ NtUserMessageCall(
switch(dwType)
{
case FNID_DEFWINDOWPROC:
lResult = IntDefWindowProc(Window, Msg, wParam, lParam);
lResult = IntDefWindowProc(Window, Msg, wParam, lParam, Ansi);
break;
}
UserDerefObjectCo(Window);