mirror of
https://github.com/reactos/reactos.git
synced 2024-09-28 21:44:31 +00:00
- Preliminary implementation of SetWinEventHook and UnhookWinEvent.
- Only wine cross test uses this and testing is not stable. - Patches are welcome but all code is subject to change. - All Hook code should be ready by Aug 4th. svn path=/trunk/; revision=34988
This commit is contained in:
parent
30d2593564
commit
3e6656c48c
|
@ -33,6 +33,8 @@ typedef struct tagEVENTHOOK
|
||||||
PETHREAD Thread; /* Thread owning the event */
|
PETHREAD Thread; /* Thread owning the event */
|
||||||
UINT eventMin;
|
UINT eventMin;
|
||||||
UINT eventMax;
|
UINT eventMax;
|
||||||
|
DWORD idProcess;
|
||||||
|
DWORD idThread;
|
||||||
WINEVENTPROC Proc; /* Event function */
|
WINEVENTPROC Proc; /* Event function */
|
||||||
BOOLEAN Ansi; /* Is it an Ansi event? */
|
BOOLEAN Ansi; /* Is it an Ansi event? */
|
||||||
ULONG Flags; /* Some internal flags */
|
ULONG Flags; /* Some internal flags */
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
#include "hook.h"
|
#include "hook.h"
|
||||||
|
|
||||||
#define MSQ_HUNG 5000
|
#define MSQ_HUNG 5000
|
||||||
|
#define MSQ_NORMAL 0
|
||||||
|
#define MSQ_ISHOOK 1
|
||||||
|
#define MSQ_ISEVENT 2
|
||||||
|
|
||||||
typedef struct _USER_MESSAGE
|
typedef struct _USER_MESSAGE
|
||||||
{
|
{
|
||||||
|
@ -25,7 +28,7 @@ typedef struct _USER_SENT_MESSAGE
|
||||||
ULONG_PTR CompletionCallbackContext;
|
ULONG_PTR CompletionCallbackContext;
|
||||||
/* entry in the dispatching list of the sender's message queue */
|
/* entry in the dispatching list of the sender's message queue */
|
||||||
LIST_ENTRY DispatchingListEntry;
|
LIST_ENTRY DispatchingListEntry;
|
||||||
BOOL HookMessage;
|
INT HookMessage;
|
||||||
} USER_SENT_MESSAGE, *PUSER_SENT_MESSAGE;
|
} USER_SENT_MESSAGE, *PUSER_SENT_MESSAGE;
|
||||||
|
|
||||||
typedef struct _USER_SENT_MESSAGE_NOTIFY
|
typedef struct _USER_SENT_MESSAGE_NOTIFY
|
||||||
|
@ -121,7 +124,7 @@ MsqIsHung(PUSER_MESSAGE_QUEUE MessageQueue);
|
||||||
NTSTATUS FASTCALL
|
NTSTATUS FASTCALL
|
||||||
co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
|
co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
|
||||||
HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
|
HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
|
||||||
UINT uTimeout, BOOL Block, BOOL HookMessage,
|
UINT uTimeout, BOOL Block, INT HookMessage,
|
||||||
ULONG_PTR *uResult);
|
ULONG_PTR *uResult);
|
||||||
PUSER_MESSAGE FASTCALL
|
PUSER_MESSAGE FASTCALL
|
||||||
MsqCreateMessage(LPMSG Msg, BOOLEAN FreeLParam);
|
MsqCreateMessage(LPMSG Msg, BOOLEAN FreeLParam);
|
||||||
|
|
|
@ -4,8 +4,9 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
//static PEVENTTABLE GlobalEvents;
|
static PEVENTTABLE GlobalEvents = NULL;
|
||||||
|
static ULONG EventSys[EVENT_SYSTEM_MINIMIZEEND+1] = {0};
|
||||||
|
static ULONG EventObj[( EVENT_OBJECT_ACCELERATORCHANGE - EVENT_OBJECT_CREATE) +1] = {0};
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS *********************************************************/
|
/* PRIVATE FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
|
@ -43,6 +44,88 @@ GetMaskFromEvent(DWORD Event)
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
FASTCALL
|
||||||
|
IntEventUpCount(ULONG eventMin, ULONG eventMax)
|
||||||
|
{
|
||||||
|
INT i, Min, Max;
|
||||||
|
|
||||||
|
if ( eventMin >= EVENT_SYSTEM_SOUND && eventMax <= EVENT_SYSTEM_MINIMIZEEND)
|
||||||
|
{
|
||||||
|
for (i = eventMin; i < eventMax; i++)
|
||||||
|
{
|
||||||
|
gpsi->SrvEventActivity |= GetMaskFromEvent(i);
|
||||||
|
EventSys[i]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( eventMin >= EVENT_OBJECT_CREATE && eventMax <= EVENT_OBJECT_ACCELERATORCHANGE)
|
||||||
|
{
|
||||||
|
for (i = eventMin; i < eventMax; i++)
|
||||||
|
{
|
||||||
|
gpsi->SrvEventActivity |= GetMaskFromEvent(i);
|
||||||
|
EventObj[i - EVENT_OBJECT_CREATE]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( eventMin >= EVENT_SYSTEM_SOUND && eventMax <= EVENT_OBJECT_ACCELERATORCHANGE)
|
||||||
|
{
|
||||||
|
Max = EVENT_SYSTEM_MINIMIZEEND;
|
||||||
|
for (i = eventMin; i < Max; i++)
|
||||||
|
{
|
||||||
|
gpsi->SrvEventActivity |= GetMaskFromEvent(i);
|
||||||
|
EventSys[i]++;
|
||||||
|
}
|
||||||
|
Min = EVENT_OBJECT_CREATE;
|
||||||
|
for (i = Min; i < eventMax; i++)
|
||||||
|
{
|
||||||
|
gpsi->SrvEventActivity |= GetMaskFromEvent(i);
|
||||||
|
EventObj[i - EVENT_OBJECT_CREATE]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
FASTCALL
|
||||||
|
IntEventDownCount(ULONG eventMin, ULONG eventMax)
|
||||||
|
{
|
||||||
|
INT i, Min, Max;
|
||||||
|
|
||||||
|
if ( eventMin >= EVENT_SYSTEM_SOUND && eventMax <= EVENT_SYSTEM_MINIMIZEEND)
|
||||||
|
{
|
||||||
|
for (i = eventMin; i < eventMax; i++)
|
||||||
|
{
|
||||||
|
EventSys[i]--;
|
||||||
|
if (!EventSys[i]) gpsi->SrvEventActivity &= ~GetMaskFromEvent(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( eventMin >= EVENT_OBJECT_CREATE && eventMax <= EVENT_OBJECT_ACCELERATORCHANGE)
|
||||||
|
{
|
||||||
|
for (i = eventMin; i < eventMax; i++)
|
||||||
|
{
|
||||||
|
EventObj[i - EVENT_OBJECT_CREATE]--;
|
||||||
|
if (!EventObj[i - EVENT_OBJECT_CREATE])
|
||||||
|
gpsi->SrvEventActivity &= ~GetMaskFromEvent(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( eventMin >= EVENT_SYSTEM_SOUND && eventMax <= EVENT_OBJECT_ACCELERATORCHANGE)
|
||||||
|
{
|
||||||
|
Max = EVENT_SYSTEM_MINIMIZEEND;
|
||||||
|
for (i = eventMin; i < Max; i++)
|
||||||
|
{
|
||||||
|
EventSys[i]--;
|
||||||
|
if (!EventSys[i]) gpsi->SrvEventActivity &= ~GetMaskFromEvent(i);
|
||||||
|
}
|
||||||
|
Min = EVENT_OBJECT_CREATE;
|
||||||
|
for (i = Min; i < eventMax; i++)
|
||||||
|
{
|
||||||
|
EventObj[i - EVENT_OBJECT_CREATE]--;
|
||||||
|
if (!EventObj[i - EVENT_OBJECT_CREATE])
|
||||||
|
gpsi->SrvEventActivity &= ~GetMaskFromEvent(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
DWORD
|
DWORD
|
||||||
|
@ -52,6 +135,48 @@ TimeStamp(VOID)
|
||||||
return (DWORD)((ULONGLONG)SharedUserData->TickCountLowDeprecated * SharedUserData->TickCountMultiplier / 16777216);
|
return (DWORD)((ULONGLONG)SharedUserData->TickCountLowDeprecated * SharedUserData->TickCountMultiplier / 16777216);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
LRESULT
|
||||||
|
FASTCALL
|
||||||
|
IntCallLowLevelEvent( PEVENTHOOK pEH,
|
||||||
|
DWORD event,
|
||||||
|
HWND hwnd,
|
||||||
|
LONG idObject,
|
||||||
|
LONG idChild)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG_PTR uResult;
|
||||||
|
|
||||||
|
/* FIXME should get timeout from
|
||||||
|
* HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
|
||||||
|
Status = co_MsqSendMessage(((PW32THREAD)pEH->Thread->Tcb.Win32Thread)->MessageQueue,
|
||||||
|
hwnd,
|
||||||
|
event,
|
||||||
|
idObject,
|
||||||
|
idChild,
|
||||||
|
5000,
|
||||||
|
TRUE,
|
||||||
|
MSQ_ISEVENT,
|
||||||
|
&uResult);
|
||||||
|
|
||||||
|
return NT_SUCCESS(Status) ? uResult : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
BOOL
|
||||||
|
FASTCALL
|
||||||
|
IntRemoveEvent(PEVENTHOOK pEH)
|
||||||
|
{
|
||||||
|
if (pEH)
|
||||||
|
{
|
||||||
|
RemoveEntryList(&pEH->Chain);
|
||||||
|
GlobalEvents->Counts--;
|
||||||
|
UserDeleteObject(pEH->Self, otEvent);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
LRESULT
|
LRESULT
|
||||||
|
@ -62,18 +187,26 @@ co_EVENT_CallEvents( DWORD event,
|
||||||
LONG idChild)
|
LONG idChild)
|
||||||
{
|
{
|
||||||
|
|
||||||
PEVENTHOOK peh = UserHeapAlloc(sizeof(EVENTHOOK));
|
PEVENTHOOK pEH = UserHeapAlloc(sizeof(EVENTHOOK));
|
||||||
|
|
||||||
if ((gpsi->SrvEventActivity & GetMaskFromEvent(event))) return 0; // No events to run.
|
if ((gpsi->SrvEventActivity & GetMaskFromEvent(event))) return 0; // No events to run.
|
||||||
|
|
||||||
LRESULT Result = co_IntCallEventProc(peh->Self,
|
|
||||||
|
if ((pEH->Thread != PsGetCurrentThread()) && (pEH->Thread != NULL))
|
||||||
|
{
|
||||||
|
// Post it in message queue.
|
||||||
|
return IntCallLowLevelEvent(pEH, event, hwnd, idObject, idChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LRESULT Result = co_IntCallEventProc(pEH->Self,
|
||||||
event,
|
event,
|
||||||
hwnd,
|
hwnd,
|
||||||
idObject,
|
idObject,
|
||||||
idChild,
|
idChild,
|
||||||
(DWORD)(NtCurrentTeb()->Cid).UniqueThread,
|
(DWORD)(NtCurrentTeb()->Cid).UniqueThread,
|
||||||
TimeStamp(),
|
TimeStamp(),
|
||||||
peh->Proc);
|
pEH->Proc);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +219,9 @@ NtUserNotifyWinEvent(
|
||||||
LONG idObject,
|
LONG idObject,
|
||||||
LONG idChild)
|
LONG idChild)
|
||||||
{
|
{
|
||||||
|
UserEnterExclusive();
|
||||||
UNIMPLEMENTED
|
UNIMPLEMENTED
|
||||||
|
UserLeave();
|
||||||
}
|
}
|
||||||
|
|
||||||
HWINEVENTHOOK
|
HWINEVENTHOOK
|
||||||
|
@ -101,12 +236,98 @@ NtUserSetWinEventHook(
|
||||||
DWORD idThread,
|
DWORD idThread,
|
||||||
UINT dwflags)
|
UINT dwflags)
|
||||||
{
|
{
|
||||||
gpsi->SrvEventActivity |= GetMaskFromEvent(eventMin);
|
PEVENTHOOK pEH;
|
||||||
gpsi->SrvEventActivity &= ~GetMaskFromEvent(eventMin);
|
HWINEVENTHOOK Ret = NULL;
|
||||||
|
UNICODE_STRING ModuleName;
|
||||||
|
NTSTATUS Status;
|
||||||
|
HANDLE Handle;
|
||||||
|
|
||||||
UNIMPLEMENTED
|
UserEnterExclusive();
|
||||||
|
|
||||||
return 0;
|
DPRINT1("WARNING! Use at your own risk! Function is UNIMPLEMENTED!\n");
|
||||||
|
|
||||||
|
if ( !GlobalEvents )
|
||||||
|
{
|
||||||
|
GlobalEvents = ExAllocatePoolWithTag(PagedPool, sizeof(EVENTTABLE), TAG_HOOK);
|
||||||
|
GlobalEvents->Counts = 0;
|
||||||
|
InitializeListHead(&GlobalEvents->Events);
|
||||||
|
}
|
||||||
|
|
||||||
|
pEH = UserCreateObject(gHandleTable, &Handle, otEvent, sizeof(EVENTHOOK));
|
||||||
|
if (pEH)
|
||||||
|
{
|
||||||
|
InsertTailList(&GlobalEvents->Events, &pEH->Chain);
|
||||||
|
GlobalEvents->Counts++;
|
||||||
|
|
||||||
|
pEH->Self = Handle;
|
||||||
|
pEH->Thread = PsGetCurrentThread();
|
||||||
|
pEH->eventMin = eventMin;
|
||||||
|
pEH->eventMax = eventMax;
|
||||||
|
pEH->idProcess = idProcess;
|
||||||
|
pEH->idThread = idThread;
|
||||||
|
pEH->Ansi = FALSE;
|
||||||
|
pEH->Flags = dwflags;
|
||||||
|
|
||||||
|
if ((dwflags & WINEVENT_INCONTEXT) && !hmodWinEventProc)
|
||||||
|
{
|
||||||
|
SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD);
|
||||||
|
goto SetEventExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventMin > eventMax)
|
||||||
|
{
|
||||||
|
SetLastWin32Error(ERROR_INVALID_HOOK_FILTER);
|
||||||
|
goto SetEventExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL != hmodWinEventProc)
|
||||||
|
{
|
||||||
|
Status = MmCopyFromCaller(&ModuleName, puString, sizeof(UNICODE_STRING));
|
||||||
|
if (! NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
UserDereferenceObject(pEH);
|
||||||
|
IntRemoveEvent(pEH);
|
||||||
|
SetLastNtError(Status);
|
||||||
|
goto SetEventExit;
|
||||||
|
}
|
||||||
|
pEH->ModuleName.Buffer = ExAllocatePoolWithTag(PagedPool,
|
||||||
|
ModuleName.MaximumLength,
|
||||||
|
TAG_HOOK);
|
||||||
|
if (NULL == pEH->ModuleName.Buffer)
|
||||||
|
{
|
||||||
|
UserDereferenceObject(pEH);
|
||||||
|
IntRemoveEvent(pEH);
|
||||||
|
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
goto SetEventExit;
|
||||||
|
}
|
||||||
|
pEH->ModuleName.MaximumLength = ModuleName.MaximumLength;
|
||||||
|
Status = MmCopyFromCaller(pEH->ModuleName.Buffer,
|
||||||
|
ModuleName.Buffer,
|
||||||
|
ModuleName.MaximumLength);
|
||||||
|
if (! NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ExFreePool(pEH->ModuleName.Buffer);
|
||||||
|
UserDereferenceObject(pEH);
|
||||||
|
IntRemoveEvent(pEH);
|
||||||
|
SetLastNtError(Status);
|
||||||
|
goto SetEventExit;
|
||||||
|
}
|
||||||
|
pEH->ModuleName.Length = ModuleName.Length;
|
||||||
|
pEH->Proc = (void *)((char *)lpfnWinEventProc - (char *)hmodWinEventProc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pEH->Proc = lpfnWinEventProc;
|
||||||
|
|
||||||
|
Ret = Handle;
|
||||||
|
/*
|
||||||
|
Now we are good, set the Events and counts.
|
||||||
|
*/
|
||||||
|
IntEventUpCount(eventMin, eventMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetEventExit:
|
||||||
|
UserLeave();
|
||||||
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -115,9 +336,22 @@ STDCALL
|
||||||
NtUserUnhookWinEvent(
|
NtUserUnhookWinEvent(
|
||||||
HWINEVENTHOOK hWinEventHook)
|
HWINEVENTHOOK hWinEventHook)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
PEVENTHOOK pEH;
|
||||||
|
BOOL Ret = FALSE;
|
||||||
|
|
||||||
return FALSE;
|
UserEnterExclusive();
|
||||||
|
|
||||||
|
DPRINT1("WARNING! Use at your own risk! Function is UNIMPLEMENTED!\n");
|
||||||
|
|
||||||
|
pEH = (PEVENTHOOK)UserGetObject(gHandleTable, hWinEventHook, otEvent);
|
||||||
|
if (pEH)
|
||||||
|
{
|
||||||
|
IntEventDownCount(pEH->eventMin, pEH->eventMax);
|
||||||
|
Ret = IntRemoveEvent(pEH);
|
||||||
|
}
|
||||||
|
|
||||||
|
UserLeave();
|
||||||
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -281,7 +281,7 @@ IntCallLowLevelHook(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam)
|
||||||
lParam,
|
lParam,
|
||||||
5000,
|
5000,
|
||||||
TRUE,
|
TRUE,
|
||||||
TRUE,
|
MSQ_ISHOOK,
|
||||||
&uResult);
|
&uResult);
|
||||||
|
|
||||||
return NT_SUCCESS(Status) ? uResult : 0;
|
return NT_SUCCESS(Status) ? uResult : 0;
|
||||||
|
|
|
@ -1555,7 +1555,7 @@ co_IntSendMessageTimeoutSingle(HWND hWnd,
|
||||||
lParam,
|
lParam,
|
||||||
uTimeout,
|
uTimeout,
|
||||||
(uFlags & SMTO_BLOCK),
|
(uFlags & SMTO_BLOCK),
|
||||||
FALSE,
|
MSQ_NORMAL,
|
||||||
uResult);
|
uResult);
|
||||||
}
|
}
|
||||||
while ((STATUS_TIMEOUT == Status) &&
|
while ((STATUS_TIMEOUT == Status) &&
|
||||||
|
|
|
@ -929,13 +929,20 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
|
||||||
InsertTailList(&MessageQueue->LocalDispatchingMessagesHead,
|
InsertTailList(&MessageQueue->LocalDispatchingMessagesHead,
|
||||||
&Message->ListEntry);
|
&Message->ListEntry);
|
||||||
|
|
||||||
if (Message->HookMessage)
|
if (Message->HookMessage == MSQ_ISHOOK)
|
||||||
{
|
{
|
||||||
Result = co_HOOK_CallHooks(Message->Msg.message,
|
Result = co_HOOK_CallHooks(Message->Msg.message,
|
||||||
(INT)(INT_PTR)Message->Msg.hwnd,
|
(INT)(INT_PTR)Message->Msg.hwnd,
|
||||||
Message->Msg.wParam,
|
Message->Msg.wParam,
|
||||||
Message->Msg.lParam);
|
Message->Msg.lParam);
|
||||||
}
|
}
|
||||||
|
else if (Message->HookMessage == MSQ_ISEVENT)
|
||||||
|
{
|
||||||
|
Result = co_EVENT_CallEvents( Message->Msg.message,
|
||||||
|
Message->Msg.hwnd,
|
||||||
|
(LONG) Message->Msg.wParam,
|
||||||
|
(LONG) Message->Msg.lParam);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Call the window procedure. */
|
/* Call the window procedure. */
|
||||||
|
@ -1090,7 +1097,7 @@ MsqSendNotifyMessage(PUSER_MESSAGE_QUEUE MessageQueue,
|
||||||
NTSTATUS FASTCALL
|
NTSTATUS FASTCALL
|
||||||
co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
|
co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
|
||||||
HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
|
HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
|
||||||
UINT uTimeout, BOOL Block, BOOL HookMessage,
|
UINT uTimeout, BOOL Block, INT HookMessage,
|
||||||
ULONG_PTR *uResult)
|
ULONG_PTR *uResult)
|
||||||
{
|
{
|
||||||
PUSER_SENT_MESSAGE Message;
|
PUSER_SENT_MESSAGE Message;
|
||||||
|
|
Loading…
Reference in a new issue