mirror of
https://github.com/reactos/reactos.git
synced 2025-04-05 21:21:33 +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
6 changed files with 263 additions and 17 deletions
|
@ -33,6 +33,8 @@ typedef struct tagEVENTHOOK
|
|||
PETHREAD Thread; /* Thread owning the event */
|
||||
UINT eventMin;
|
||||
UINT eventMax;
|
||||
DWORD idProcess;
|
||||
DWORD idThread;
|
||||
WINEVENTPROC Proc; /* Event function */
|
||||
BOOLEAN Ansi; /* Is it an Ansi event? */
|
||||
ULONG Flags; /* Some internal flags */
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
#include "hook.h"
|
||||
|
||||
#define MSQ_HUNG 5000
|
||||
#define MSQ_NORMAL 0
|
||||
#define MSQ_ISHOOK 1
|
||||
#define MSQ_ISEVENT 2
|
||||
|
||||
typedef struct _USER_MESSAGE
|
||||
{
|
||||
|
@ -25,7 +28,7 @@ typedef struct _USER_SENT_MESSAGE
|
|||
ULONG_PTR CompletionCallbackContext;
|
||||
/* entry in the dispatching list of the sender's message queue */
|
||||
LIST_ENTRY DispatchingListEntry;
|
||||
BOOL HookMessage;
|
||||
INT HookMessage;
|
||||
} USER_SENT_MESSAGE, *PUSER_SENT_MESSAGE;
|
||||
|
||||
typedef struct _USER_SENT_MESSAGE_NOTIFY
|
||||
|
@ -121,7 +124,7 @@ MsqIsHung(PUSER_MESSAGE_QUEUE MessageQueue);
|
|||
NTSTATUS FASTCALL
|
||||
co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
|
||||
HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
|
||||
UINT uTimeout, BOOL Block, BOOL HookMessage,
|
||||
UINT uTimeout, BOOL Block, INT HookMessage,
|
||||
ULONG_PTR *uResult);
|
||||
PUSER_MESSAGE FASTCALL
|
||||
MsqCreateMessage(LPMSG Msg, BOOLEAN FreeLParam);
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
#define NDEBUG
|
||||
#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 *********************************************************/
|
||||
|
||||
|
@ -43,6 +44,88 @@ GetMaskFromEvent(DWORD Event)
|
|||
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
|
||||
DWORD
|
||||
|
@ -52,6 +135,48 @@ TimeStamp(VOID)
|
|||
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 *****************************************************************/
|
||||
|
||||
LRESULT
|
||||
|
@ -62,18 +187,26 @@ co_EVENT_CallEvents( DWORD event,
|
|||
LONG idChild)
|
||||
{
|
||||
|
||||
PEVENTHOOK peh = UserHeapAlloc(sizeof(EVENTHOOK));
|
||||
PEVENTHOOK pEH = UserHeapAlloc(sizeof(EVENTHOOK));
|
||||
|
||||
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,
|
||||
hwnd,
|
||||
idObject,
|
||||
idChild,
|
||||
(DWORD)(NtCurrentTeb()->Cid).UniqueThread,
|
||||
TimeStamp(),
|
||||
peh->Proc);
|
||||
pEH->Proc);
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
@ -86,7 +219,9 @@ NtUserNotifyWinEvent(
|
|||
LONG idObject,
|
||||
LONG idChild)
|
||||
{
|
||||
UserEnterExclusive();
|
||||
UNIMPLEMENTED
|
||||
UserLeave();
|
||||
}
|
||||
|
||||
HWINEVENTHOOK
|
||||
|
@ -101,12 +236,98 @@ NtUserSetWinEventHook(
|
|||
DWORD idThread,
|
||||
UINT dwflags)
|
||||
{
|
||||
gpsi->SrvEventActivity |= GetMaskFromEvent(eventMin);
|
||||
gpsi->SrvEventActivity &= ~GetMaskFromEvent(eventMin);
|
||||
PEVENTHOOK pEH;
|
||||
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(
|
||||
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 */
|
||||
|
|
|
@ -281,7 +281,7 @@ IntCallLowLevelHook(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam)
|
|||
lParam,
|
||||
5000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
MSQ_ISHOOK,
|
||||
&uResult);
|
||||
|
||||
return NT_SUCCESS(Status) ? uResult : 0;
|
||||
|
|
|
@ -1555,7 +1555,7 @@ co_IntSendMessageTimeoutSingle(HWND hWnd,
|
|||
lParam,
|
||||
uTimeout,
|
||||
(uFlags & SMTO_BLOCK),
|
||||
FALSE,
|
||||
MSQ_NORMAL,
|
||||
uResult);
|
||||
}
|
||||
while ((STATUS_TIMEOUT == Status) &&
|
||||
|
|
|
@ -929,13 +929,20 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
|
|||
InsertTailList(&MessageQueue->LocalDispatchingMessagesHead,
|
||||
&Message->ListEntry);
|
||||
|
||||
if (Message->HookMessage)
|
||||
if (Message->HookMessage == MSQ_ISHOOK)
|
||||
{
|
||||
Result = co_HOOK_CallHooks(Message->Msg.message,
|
||||
(INT)(INT_PTR)Message->Msg.hwnd,
|
||||
Message->Msg.wParam,
|
||||
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
|
||||
{
|
||||
/* Call the window procedure. */
|
||||
|
@ -1090,7 +1097,7 @@ MsqSendNotifyMessage(PUSER_MESSAGE_QUEUE MessageQueue,
|
|||
NTSTATUS FASTCALL
|
||||
co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
|
||||
HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
|
||||
UINT uTimeout, BOOL Block, BOOL HookMessage,
|
||||
UINT uTimeout, BOOL Block, INT HookMessage,
|
||||
ULONG_PTR *uResult)
|
||||
{
|
||||
PUSER_SENT_MESSAGE Message;
|
||||
|
|
Loading…
Reference in a new issue