/*
- * ReactOS W32 Subsystem
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 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.
- */
-/* $Id$
- *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Window hooks
- * FILE: subsys/win32k/ntuser/hook.c
+ * FILE: subsystem/win32/win32k/ntuser/hook.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISION HISTORY:
* 06-06-2001 CSH Created
#define NDEBUG
#include <debug.h>
-#define HOOKID_TO_INDEX(HookId) (HookId - WH_MINHOOK)
-
static PHOOKTABLE GlobalHooks;
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+
/* create a new hook table */
static PHOOKTABLE
IntAllocHookTable(void)
static PHOOK
IntAddHook(PETHREAD Thread, int HookId, BOOLEAN Global, PWINSTATION_OBJECT WinStaObj)
{
+ PTHREADINFO W32Thread;
PHOOK Hook;
- PHOOKTABLE Table = Global ? GlobalHooks : MsqGetHooks(((PW32THREAD)Thread->Tcb.Win32Thread)->MessageQueue);
+ PHOOKTABLE Table = Global ? GlobalHooks : MsqGetHooks(((PTHREADINFO)Thread->Tcb.Win32Thread)->MessageQueue);
HANDLE Handle;
if (NULL == Table)
}
else
{
- MsqSetHooks(((PW32THREAD)Thread->Tcb.Win32Thread)->MessageQueue, Table);
+ MsqSetHooks(((PTHREADINFO)Thread->Tcb.Win32Thread)->MessageQueue, Table);
}
}
- Hook = ObmCreateObject(gHandleTable, &Handle, otHook, sizeof(HOOK));
+ Hook = UserCreateObject(gHandleTable, &Handle, otHook, sizeof(HOOK));
if (NULL == Hook)
{
return NULL;
Hook->Self = Handle;
Hook->Thread = Thread;
Hook->HookId = HookId;
+
+ if (Thread)
+ {
+ W32Thread = ((PTHREADINFO)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);
InsertHeadList(&Table->Hooks[HOOKID_TO_INDEX(HookId)], &Hook->Chain);
return GlobalHooks;
}
- return MsqGetHooks(((PW32THREAD)Hook->Thread->Tcb.Win32Thread)->MessageQueue);
+ return MsqGetHooks(((PTHREADINFO)Hook->Thread->Tcb.Win32Thread)->MessageQueue);
}
/* get the first hook in the chain */
}
/* find the next hook in the chain, skipping the deleted ones */
-static PHOOK FASTCALL
+PHOOK
+FASTCALL
IntGetNextHook(PHOOK Hook)
{
PHOOKTABLE Table = IntGetTable(Hook);
}
/* Close handle */
- ObmDeleteObject(Hook->Self, otHook);
+ UserDeleteObject(Hook->Self, otHook);
}
/* remove a hook, freeing it if the chain is not in use */
static VOID
IntRemoveHook(PHOOK Hook, PWINSTATION_OBJECT WinStaObj, BOOL TableAlreadyLocked)
{
+ PTHREADINFO W32Thread;
PHOOKTABLE Table = IntGetTable(Hook);
ASSERT(NULL != Table);
return;
}
+ W32Thread = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread);
+ ASSERT(W32Thread != NULL);
+ W32Thread->Hooks &= ~HOOKID_TO_FLAG(Hook->HookId);
+ if (W32Thread->ThreadInfo != NULL)
+ W32Thread->ThreadInfo->Hooks = W32Thread->Hooks;
+
if (0 != Table->Counts[HOOKID_TO_INDEX(Hook->HookId)])
{
Hook->Proc = NULL; /* chain is in use, just mark it and return */
}
static LRESULT FASTCALL
-IntCallLowLevelHook(INT HookId, INT Code, WPARAM wParam, LPARAM lParam, PHOOK Hook)
+IntCallLowLevelHook(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam)
{
NTSTATUS Status;
ULONG_PTR uResult;
/* FIXME should get timeout from
* HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
- Status = co_MsqSendMessage(((PW32THREAD)Hook->Thread->Tcb.Win32Thread)->MessageQueue, (HWND) Code, HookId,
- wParam, lParam, 5000, TRUE, TRUE, &uResult);
+ Status = co_MsqSendMessage(((PTHREADINFO)Hook->Thread->Tcb.Win32Thread)->MessageQueue,
+ (HWND) Code,
+ Hook->HookId,
+ wParam,
+ lParam,
+ 5000,
+ TRUE,
+ MSQ_ISHOOK,
+ &uResult);
return NT_SUCCESS(Status) ? uResult : 0;
}
-LRESULT FASTCALL
+/*
+ Called from inside kernel space.
+ */
+LRESULT
+FASTCALL
co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
{
- PHOOK Hook;
- PW32THREAD Win32Thread;
+ PHOOK Hook, SaveHook;
+ PTHREADINFO pti;
+ PCLIENTINFO ClientInfo;
PHOOKTABLE Table;
LRESULT Result;
PWINSTATION_OBJECT WinStaObj;
ASSERT(WH_MINHOOK <= HookId && HookId <= WH_MAXHOOK);
- Win32Thread = PsGetCurrentThreadWin32Thread();
- if (NULL == Win32Thread)
+ pti = PsGetCurrentThreadWin32Thread();
+ if (!pti)
{
Table = NULL;
}
else
{
- Table = MsqGetHooks(Win32Thread->MessageQueue);
+ Table = MsqGetHooks(pti->MessageQueue);
}
if (NULL == Table || ! (Hook = IntGetFirstValidHook(Table, HookId)))
}
}
- if (Hook->Thread != PsGetCurrentThread()
- && (WH_KEYBOARD_LL == HookId || WH_MOUSE_LL == HookId))
- {
- DPRINT("Calling hook in owning thread\n");
- 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;
+ // Post it in message queue.
+ return IntCallLowLevelHook(Hook, Code, wParam, lParam);
}
Table->Counts[HOOKID_TO_INDEX(HookId)]++;
GlobalHooks->Counts[HOOKID_TO_INDEX(HookId)]++;
}
- Result = co_IntCallHookProc(HookId, Code, wParam, lParam, Hook->Proc,
- Hook->Ansi, &Hook->ModuleName);
+ ClientInfo = GetWin32ClientInfo();
+ SaveHook = ClientInfo->phkCurrent;
+ ClientInfo->phkCurrent = Hook; // Load the call.
+
+ Result = co_IntCallHookProc( HookId,
+ Code,
+ wParam,
+ lParam,
+ Hook->Proc,
+ Hook->Ansi,
+ &Hook->ModuleName);
+
+ ClientInfo->phkCurrent = SaveHook;
Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
KernelMode,
}
else
{
- IntReleaseHookChain(MsqGetHooks(PsGetCurrentThreadWin32Thread()->MessageQueue), HookId, WinStaObj);
+ IntReleaseHookChain(MsqGetHooks(pti->MessageQueue), HookId, WinStaObj);
IntReleaseHookChain(GlobalHooks, HookId, WinStaObj);
ObDereferenceObject(WinStaObj);
}
break;
}
}
+ }
+}
- ObDereferenceObject(WinStaObj);
+static LRESULT
+FASTCALL
+co_HOOK_CallHookNext(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam)
+{
+ if ((Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL))
+ {
+ DPRINT1("CALLING HOOK from another Thread. %d\n",Hook->HookId);
+ return IntCallLowLevelHook(Hook, Code, wParam, lParam);
}
+ DPRINT("CALLING HOOK %d\n",Hook->HookId);
+ return co_IntCallHookProc(Hook->HookId,
+ Code,
+ wParam,
+ lParam,
+ Hook->Proc,
+ Hook->Ansi,
+ &Hook->ModuleName);
}
+
LRESULT
-STDCALL
-NtUserCallNextHookEx(
- HHOOK Hook,
+FASTCALL
+IntCallDebugHook(
+ PHOOK Hook,
int Code,
WPARAM wParam,
LPARAM lParam)
+{
+ LRESULT lResult = 0;
+ ULONG Size;
+ DEBUGHOOKINFO Debug;
+ PVOID HooklParam = NULL;
+ BOOL BadChk = FALSE;
+
+ if (lParam)
+ {
+ _SEH2_TRY
+ {
+ ProbeForRead((PVOID)lParam,
+ sizeof(DEBUGHOOKINFO),
+ 1);
+ RtlCopyMemory( &Debug,
+ (PVOID)lParam,
+ sizeof(DEBUGHOOKINFO));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ if (BadChk)
+ {
+ DPRINT1("HOOK WH_DEBUG read from lParam ERROR!\n");
+ return lResult;
+ }
+ }
+ else
+ return lResult; // Need lParam!
+
+ switch (wParam)
+ {
+ case WH_CBT:
+ {
+ switch (Debug.code)
+ {
+ case HCBT_CLICKSKIPPED:
+ Size = sizeof(MOUSEHOOKSTRUCTEX);
+ break;
+ case HCBT_MOVESIZE:
+ Size = sizeof(RECT);
+ break;
+ case HCBT_ACTIVATE:
+ Size = sizeof(CBTACTIVATESTRUCT);
+ break;
+ case HCBT_CREATEWND: // Handle Ansi?
+ Size = sizeof(CBT_CREATEWND);
+ // What shall we do? Size += sizeof(CREATESTRUCTEX);
+ break;
+ default:
+ Size = sizeof(LPARAM);
+ }
+ }
+ break;
+
+ case WH_MOUSE_LL:
+ Size = sizeof(MSLLHOOKSTRUCT);
+ break;
+
+ case WH_KEYBOARD_LL:
+ Size = sizeof(KBDLLHOOKSTRUCT);
+ break;
+
+ case WH_MSGFILTER:
+ case WH_SYSMSGFILTER:
+ case WH_GETMESSAGE:
+ Size = sizeof(MSG);
+ break;
+
+ case WH_JOURNALPLAYBACK:
+ case WH_JOURNALRECORD:
+ Size = sizeof(EVENTMSG);
+ break;
+
+ case WH_FOREGROUNDIDLE:
+ case WH_KEYBOARD:
+ case WH_SHELL:
+ default:
+ Size = sizeof(LPARAM);
+ }
+
+ if (Size > sizeof(LPARAM))
+ HooklParam = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_HOOK);
+
+ if (HooklParam)
+ {
+ _SEH2_TRY
+ {
+ ProbeForRead((PVOID)Debug.lParam,
+ Size,
+ 1);
+ RtlCopyMemory( HooklParam,
+ (PVOID)Debug.lParam,
+ Size);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ if (BadChk)
+ {
+ DPRINT1("HOOK WH_DEBUG read from Debug.lParam ERROR!\n");
+ ExFreePool(HooklParam);
+ return lResult;
+ }
+ }
+
+ if (HooklParam) Debug.lParam = (LPARAM)HooklParam;
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Debug);
+ if (HooklParam) ExFreePoolWithTag(HooklParam, TAG_HOOK);
+ return lResult;
+}
+
+/*
+ Called from user space via CallNextHook.
+ */
+LRESULT
+FASTCALL
+UserCallNextHookEx(
+ PHOOK Hook,
+ int Code,
+ WPARAM wParam,
+ LPARAM lParam,
+ BOOL Ansi)
+{
+ LRESULT lResult = 0;
+ BOOL BadChk = FALSE;
+
+// Handle this one first.
+ if ((Hook->HookId == WH_MOUSE) ||
+ (Hook->HookId == WH_CBT && Code == HCBT_CLICKSKIPPED))
+ {
+ MOUSEHOOKSTRUCTEX Mouse;
+ if (lParam)
+ {
+ _SEH2_TRY
+ {
+ ProbeForRead((PVOID)lParam,
+ sizeof(MOUSEHOOKSTRUCTEX),
+ 1);
+ RtlCopyMemory( &Mouse,
+ (PVOID)lParam,
+ sizeof(MOUSEHOOKSTRUCTEX));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ if (BadChk)
+ {
+ DPRINT1("HOOK WH_MOUSE read from lParam ERROR!\n");
+ }
+ }
+ if (!BadChk)
+ {
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Mouse);
+ }
+ return lResult;
+ }
+
+ switch(Hook->HookId)
+ {
+ case WH_MOUSE_LL:
+ {
+ MSLLHOOKSTRUCT Mouse;
+ if (lParam)
+ {
+ _SEH2_TRY
+ {
+ ProbeForRead((PVOID)lParam,
+ sizeof(MSLLHOOKSTRUCT),
+ 1);
+ RtlCopyMemory( &Mouse,
+ (PVOID)lParam,
+ sizeof(MSLLHOOKSTRUCT));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ if (BadChk)
+ {
+ DPRINT1("HOOK WH_MOUSE_LL read from lParam ERROR!\n");
+ }
+ }
+ if (!BadChk)
+ {
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Mouse);
+ }
+ break;
+ }
+
+ case WH_KEYBOARD_LL:
+ {
+ KBDLLHOOKSTRUCT Keyboard;
+ if (lParam)
+ {
+ _SEH2_TRY
+ {
+ ProbeForRead((PVOID)lParam,
+ sizeof(KBDLLHOOKSTRUCT),
+ 1);
+ RtlCopyMemory( &Keyboard,
+ (PVOID)lParam,
+ sizeof(KBDLLHOOKSTRUCT));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ if (BadChk)
+ {
+ DPRINT1("HOOK WH_KEYBORD_LL read from lParam ERROR!\n");
+ }
+ }
+ if (!BadChk)
+ {
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Keyboard);
+ }
+ break;
+ }
+
+ case WH_MSGFILTER:
+ case WH_SYSMSGFILTER:
+ case WH_GETMESSAGE:
+ {
+ MSG Msg;
+ if (lParam)
+ {
+ _SEH2_TRY
+ {
+ ProbeForRead((PVOID)lParam,
+ sizeof(MSG),
+ 1);
+ RtlCopyMemory( &Msg,
+ (PVOID)lParam,
+ sizeof(MSG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ if (BadChk)
+ {
+ DPRINT1("HOOK WH_XMESSAGEX read from lParam ERROR!\n");
+ }
+ }
+ if (!BadChk)
+ {
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Msg);
+ if (lParam && (Hook->HookId == WH_GETMESSAGE))
+ {
+ _SEH2_TRY
+ {
+ ProbeForWrite((PVOID)lParam,
+ sizeof(MSG),
+ 1);
+ RtlCopyMemory((PVOID)lParam,
+ &Msg,
+ sizeof(MSG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ if (BadChk)
+ {
+ DPRINT1("HOOK WH_GETMESSAGE write to lParam ERROR!\n");
+ }
+ }
+ }
+ break;
+ }
+
+ case WH_CBT:
+ DPRINT1("HOOK WH_CBT!\n");
+ switch (Code)
+ {
+ case HCBT_CREATEWND: // Use Ansi.
+ DPRINT1("HOOK HCBT_CREATEWND\n");
+// lResult = co_HOOK_CallHookNext(Hook, Code, wParam, lParam);
+ break;
+
+ case HCBT_MOVESIZE:
+ {
+ RECT rt;
+ DPRINT1("HOOK HCBT_MOVESIZE\n");
+ if (lParam)
+ {
+ _SEH2_TRY
+ {
+ ProbeForRead((PVOID)lParam,
+ sizeof(RECT),
+ 1);
+ RtlCopyMemory( &rt,
+ (PVOID)lParam,
+ sizeof(RECT));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ if (BadChk)
+ {
+ DPRINT1("HOOK HCBT_MOVESIZE read from lParam ERROR!\n");
+ }
+ }
+ if (!BadChk)
+ {
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&rt);
+ }
+ break;
+ }
+
+ case HCBT_ACTIVATE:
+ {
+ CBTACTIVATESTRUCT CbAs;
+ DPRINT1("HOOK HCBT_ACTIVATE\n");
+ if (lParam)
+ {
+ _SEH2_TRY
+ {
+ ProbeForRead((PVOID)lParam,
+ sizeof(CBTACTIVATESTRUCT),
+ 1);
+ RtlCopyMemory( &CbAs,
+ (PVOID)lParam,
+ sizeof(CBTACTIVATESTRUCT));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ if (BadChk)
+ {
+ DPRINT1("HOOK HCBT_ACTIVATE read from lParam ERROR!\n");
+ }
+ }
+ if (!BadChk)
+ {
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&CbAs);
+ }
+ break;
+ }
+ /*
+ The rest just use default.
+ */
+ default:
+ DPRINT1("HOOK HCBT_ %d\n",Code);
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, lParam);
+ break;
+ }
+ break;
+
+ case WH_JOURNALPLAYBACK:
+ case WH_JOURNALRECORD:
+ {
+ EVENTMSG EventMsg;
+ if (lParam)
+ {
+ _SEH2_TRY
+ {
+ ProbeForRead((PVOID)lParam,
+ sizeof(EVENTMSG),
+ 1);
+ RtlCopyMemory( &EventMsg,
+ (PVOID)lParam,
+ sizeof(EVENTMSG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ if (BadChk)
+ {
+ DPRINT1("HOOK WH_JOURNAL read from lParam ERROR!\n");
+ }
+ }
+ if (!BadChk)
+ {
+ lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)(lParam ? &EventMsg : NULL));
+ if (lParam)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWrite((PVOID)lParam,
+ sizeof(EVENTMSG),
+ 1);
+ RtlCopyMemory((PVOID)lParam,
+ &EventMsg,
+ sizeof(EVENTMSG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ if (BadChk)
+ {
+ DPRINT1("HOOK WH_JOURNAL write to lParam ERROR!\n");
+ }
+ }
+ }
+ break;
+ }
+
+ case WH_DEBUG:
+ lResult = IntCallDebugHook(Hook, 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_CallHookNext(Hook, Code, wParam, lParam);
+ break;
+
+ default:
+ DPRINT1("Unsupported HOOK Id -> %d\n",Hook->HookId);
+ break;
+ }
+ return lResult;
+}
+
+LRESULT
+APIENTRY
+NtUserCallNextHookEx(
+ int Code,
+ WPARAM wParam,
+ LPARAM lParam,
+ BOOL Ansi)
{
PHOOK HookObj, NextObj;
+ PCLIENTINFO ClientInfo;
PWINSTATION_OBJECT WinStaObj;
NTSTATUS Status;
DECLARE_RETURN(LRESULT);
KernelMode,
0,
&WinStaObj);
-
- if (! NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
- RETURN( FALSE);
+ RETURN( 0);
}
- //Status = ObmReferenceObjectByHandle(gHandleTable, Hook,
- // otHookProc, (PVOID *) &HookObj);
ObDereferenceObject(WinStaObj);
- // if (! NT_SUCCESS(Status))
- // {
- // DPRINT1("Invalid handle passed to NtUserCallNextHookEx\n");
- // SetLastNtError(Status);
- // RETURN( 0);
- // }
+ ClientInfo = GetWin32ClientInfo();
- if (!(HookObj = IntGetHookObject(Hook)))
- {
- RETURN(0);
- }
+ if (!ClientInfo) RETURN( 0);
- ASSERT(Hook == HookObj->Self);
+ HookObj = ClientInfo->phkCurrent;
+
+ if (!HookObj) RETURN( 0);
+
+ UserReferenceObject(HookObj);
+
+ Ansi = HookObj->Ansi;
if (NULL != HookObj->Thread && (HookObj->Thread != PsGetCurrentThread()))
{
DPRINT1("Thread mismatch\n");
- ObmDereferenceObject(HookObj);
+ UserDereferenceObject(HookObj);
SetLastWin32Error(ERROR_INVALID_HANDLE);
RETURN( 0);
}
-
+
NextObj = IntGetNextHook(HookObj);
- ObmDereferenceObject(HookObj);
- if (NULL != NextObj)
- {
- DPRINT1("Calling next hook not implemented\n");
- UNIMPLEMENTED
- SetLastWin32Error(ERROR_NOT_SUPPORTED);
- RETURN( 0);
- }
+ ClientInfo->phkCurrent = NextObj; // Preset next hook from list.
+ UserCallNextHookEx( HookObj, Code, wParam, lParam, Ansi);
+ UserDereferenceObject(HookObj);
- RETURN( 0);
+ RETURN( (LRESULT)NextObj);
CLEANUP:
DPRINT("Leave NtUserCallNextHookEx, ret=%i\n",_ret_);
END_CLEANUP;
}
-DWORD
-STDCALL
+HHOOK
+APIENTRY
NtUserSetWindowsHookAW(
- DWORD Unknown0,
- DWORD Unknown1,
- DWORD Unknown2)
+ int idHook,
+ HOOKPROC lpfn,
+ BOOL Ansi)
{
- UNIMPLEMENTED
-
- return 0;
+ UNICODE_STRING USModuleName;
+ RtlInitUnicodeString(&USModuleName, NULL);
+ return NtUserSetWindowsHookEx(NULL, &USModuleName, 0, idHook, lpfn, Ansi);
}
HHOOK
-STDCALL
+APIENTRY
NtUserSetWindowsHookEx(
HINSTANCE Mod,
PUNICODE_STRING UnsafeModuleName,
BOOL Ansi)
{
PWINSTATION_OBJECT WinStaObj;
+ PCLIENTINFO ClientInfo;
BOOLEAN Global;
PETHREAD Thread;
PHOOK Hook;
DPRINT("Enter NtUserSetWindowsHookEx\n");
UserEnterExclusive();
- if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId || NULL == HookProc)
+ if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId )
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
RETURN( NULL);
}
+ if (!HookProc)
+ {
+ SetLastWin32Error(ERROR_INVALID_FILTER_PROC);
+ RETURN( NULL);
+ }
+
+ ClientInfo = GetWin32ClientInfo();
+
if (ThreadId) /* thread-local hook */
{
if (HookId == WH_JOURNALRECORD ||
}
else if (NULL == Mod)
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD);
RETURN( NULL);
}
else
Global = TRUE;
}
- /* 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)
+ if ( ( Global && (HookId != WH_KEYBOARD_LL || HookId != WH_MOUSE_LL) ) ||
+ WH_DEBUG == HookId ||
+ WH_JOURNALPLAYBACK == HookId ||
+ WH_JOURNALRECORD == HookId)
{
#if 0 /* Removed to get winEmbed working again */
UNIMPLEMENTED
Status = MmCopyFromCaller(&ModuleName, UnsafeModuleName, sizeof(UNICODE_STRING));
if (! NT_SUCCESS(Status))
{
- ObmDereferenceObject(Hook);
+ UserDereferenceObject(Hook);
IntRemoveHook(Hook, WinStaObj, FALSE);
if (NULL != Thread)
{
TAG_HOOK);
if (NULL == Hook->ModuleName.Buffer)
{
- ObmDereferenceObject(Hook);
+ UserDereferenceObject(Hook);
IntRemoveHook(Hook, WinStaObj, FALSE);
if (NULL != Thread)
{
ModuleName.MaximumLength);
if (! NT_SUCCESS(Status))
{
- ExFreePool(Hook->ModuleName.Buffer);
- ObmDereferenceObject(Hook);
+ ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK);
+ UserDereferenceObject(Hook);
IntRemoveHook(Hook, WinStaObj, FALSE);
if (NULL != Thread)
{
RETURN( NULL);
}
Hook->ModuleName.Length = ModuleName.Length;
+ /* make proc relative to the module base */
+ Hook->Proc = (void *)((char *)HookProc - (char *)Mod);
}
+ else
+ Hook->Proc = HookProc;
- Hook->Proc = HookProc;
Hook->Ansi = Ansi;
Handle = Hook->Self;
- ObmDereferenceObject(Hook);
+// Clear the client threads next hook.
+ ClientInfo->phkCurrent = 0;
+
+ UserDereferenceObject(Hook);
+
+ if (NULL != Thread)
+ {
+ ObDereferenceObject(Thread);
+ }
ObDereferenceObject(WinStaObj);
RETURN( Handle);
END_CLEANUP;
}
-DWORD
-STDCALL
-NtUserSetWinEventHook(
- DWORD Unknown0,
- DWORD Unknown1,
- DWORD Unknown2,
- DWORD Unknown3,
- DWORD Unknown4,
- DWORD Unknown5,
- DWORD Unknown6,
- DWORD Unknown7)
-{
- UNIMPLEMENTED
-
- return 0;
-}
BOOL
-STDCALL
+APIENTRY
NtUserUnhookWindowsHookEx(
HHOOK Hook)
{
RETURN( FALSE);
}
- // Status = ObmReferenceObjectByHandle(gHandleTable, Hook,
+ // Status = UserReferenceObjectByHandle(gHandleTable, Hook,
// otHookProc, (PVOID *) &HookObj);
if (!(HookObj = IntGetHookObject(Hook)))
{
IntRemoveHook(HookObj, WinStaObj, FALSE);
- ObmDereferenceObject(HookObj);
+ UserDereferenceObject(HookObj);
ObDereferenceObject(WinStaObj);
RETURN( TRUE);
UserLeave();
END_CLEANUP;
}
-
-DWORD
-STDCALL
-NtUserUnhookWinEvent(
- DWORD Unknown0)
-{
- UNIMPLEMENTED
-
- return 0;
-}
-
+
/* EOF */