+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: Window event handlers
+ * FILE: subsystems/win32/win32k/ntuser/event.c
+ * PROGRAMER: James Tabor (james.tabor@rectos.org)
+ */
-#include <w32k.h>
+#include <win32k.h>
#define NDEBUG
#include <debug.h>
(event >= EVENT_CONSOLE_CARET && event <= EVENT_CONSOLE_END_APPLICATION) ||
(event >= EVENT_OBJECT_CREATE && event <= EVENT_OBJECT_ACCELERATORCHANGE))
{
- gpsi->SrvEventActivity |= GetMaskFromEvent(event);
+ gpsi->dwInstalledEventHooks |= GetMaskFromEvent(event);
}
if (event > EVENT_SYSTEM_MINIMIZEEND && event < EVENT_CONSOLE_CARET)
{
event = EVENT_CONSOLE_CARET-1;
- gpsi->SrvEventActivity |= GetMaskFromEvent(event);
+ gpsi->dwInstalledEventHooks |= GetMaskFromEvent(event);
}
if (event > EVENT_CONSOLE_END_APPLICATION && event < EVENT_OBJECT_CREATE )
{
event = EVENT_OBJECT_CREATE-1;
- gpsi->SrvEventActivity |= GetMaskFromEvent(event);
+ gpsi->dwInstalledEventHooks |= GetMaskFromEvent(event);
}
if (event > EVENT_OBJECT_ACCELERATORCHANGE && event < EVENT_MAX)
{
event = EVENT_MAX-1;
- gpsi->SrvEventActivity |= GetMaskFromEvent(event);
+ gpsi->dwInstalledEventHooks |= GetMaskFromEvent(event);
break;
- }
+ }
}
- if (!gpsi->SrvEventActivity)
- gpsi->SrvEventActivity |= SRV_EVENT_RUNNING; // Set something.
- DPRINT("SetSrvEventMask 2 : %x\n", gpsi->SrvEventActivity);
+ if (!gpsi->dwInstalledEventHooks)
+ gpsi->dwInstalledEventHooks |= SRV_EVENT_RUNNING; // Set something.
+ DPRINT("SetSrvEventMask 2 : %x\n", gpsi->dwInstalledEventHooks);
}
static
LONG idChild)
{
NTSTATUS Status;
- ULONG_PTR uResult;
- EVENTPACK EP;
+ PEVENTPACK pEP;
+ ULONG_PTR uResult = 0;
+
+ pEP = ExAllocatePoolWithTag(NonPagedPool, sizeof(EVENTPACK), TAG_HOOK);
+ if (!pEP) return 0;
- EP.pEH = pEH;
- EP.idObject = idObject;
- EP.idChild = idChild;
+ pEP->pEH = pEH;
+ pEP->idObject = idObject;
+ pEP->idChild = idChild;
/* FIXME should get timeout from
* HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
- Status = co_MsqSendMessage(((PTHREADINFO)pEH->Thread->Tcb.Win32Thread)->MessageQueue,
- hwnd,
- event,
- 0,
- (LPARAM)&EP,
- 5000,
- TRUE,
- MSQ_ISEVENT,
- &uResult);
-
+ Status = co_MsqSendMessage( pEH->head.pti->MessageQueue,
+ hwnd,
+ event,
+ 0,
+ (LPARAM)pEP,
+ 300,
+ TRUE,
+ MSQ_ISEVENT,
+ &uResult);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(pEP, TAG_HOOK);
+ }
return NT_SUCCESS(Status) ? uResult : 0;
}
-
static
BOOL
FASTCALL
{
if (pEH)
{
+ DPRINT("IntRemoveEvent pEH 0x%x\n",pEH);
+ KeEnterCriticalRegion();
RemoveEntryList(&pEH->Chain);
GlobalEvents->Counts--;
- if (!GlobalEvents->Counts) gpsi->SrvEventActivity = 0;
- UserDeleteObject(pEH->Self, otEvent);
+ if (!GlobalEvents->Counts) gpsi->dwInstalledEventHooks = 0;
+ UserDeleteObject(UserHMGetHandle(pEH), otEvent);
+ KeLeaveCriticalRegion();
return TRUE;
}
return FALSE;
}
+VOID
+FASTCALL
+EVENT_DestroyThreadEvents(PETHREAD Thread)
+{
+ PTHREADINFO pti;
+ PEVENTHOOK pEH;
+ PLIST_ENTRY pLE;
+
+ pti = Thread->Tcb.Win32Thread;
+ if (!pti) return;
+
+ if (!GlobalEvents || !GlobalEvents->Counts) return;
+
+ pLE = GlobalEvents->Events.Flink;
+ if (IsListEmpty(pLE)) return;
+
+ pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
+ do
+ {
+ if (IsListEmpty(pLE)) break;
+ if (!pEH) break;
+ pLE = pEH->Chain.Flink;
+ if (pEH->head.pti == pti)
+ {
+ IntRemoveEvent(pEH);
+ }
+ pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
+ } while (pLE != &GlobalEvents->Events);
+
+ return;
+}
+
/* FUNCTIONS *****************************************************************/
+//
+// Dispatch MsgQueue Event Call processor!
+//
LRESULT
FASTCALL
co_EVENT_CallEvents( DWORD event,
- HWND hwnd,
- UINT_PTR idObject,
- LONG_PTR idChild)
+ HWND hwnd,
+ UINT_PTR idObject,
+ LONG_PTR idChild)
{
PEVENTHOOK pEH;
LRESULT Result;
pEH = pEP->pEH;
- Result = co_IntCallEventProc( pEH->Self,
- event,
- hwnd,
- pEP->idObject,
- pEP->idChild,
- (DWORD)(NtCurrentTeb()->ClientId).UniqueThread,
- (DWORD)EngGetTickCount(),
+ Result = co_IntCallEventProc( UserHMGetHandle(pEH),
+ event,
+ hwnd,
+ pEP->idObject,
+ pEP->idChild,
+ PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
+ (DWORD)EngGetTickCount(),
pEH->Proc);
+
+ ExFreePoolWithTag(pEP, TAG_HOOK);
return Result;
}
FASTCALL
IntNotifyWinEvent(
DWORD Event,
- PWINDOW_OBJECT Window,
+ PWND pWnd,
LONG idObject,
- LONG idChild)
+ LONG idChild,
+ DWORD flags)
{
PEVENTHOOK pEH;
- LRESULT Result;
+ PLIST_ENTRY pLE;
+ PTHREADINFO pti, ptiCurrent;
- if (!GlobalEvents->Counts) return;
+ DPRINT("IntNotifyWinEvent GlobalEvents = 0x%x pWnd 0x%x\n",GlobalEvents, pWnd);
- pEH = (PEVENTHOOK)GlobalEvents->Events.Flink;
+ if (!GlobalEvents || !GlobalEvents->Counts) return;
+ if (pWnd && pWnd->state & WNDS_DESTROYED) return;
+
+ ptiCurrent = PsGetCurrentThreadWin32Thread();
+
+ if (pWnd && flags & WEF_SETBYWNDPTI)
+ pti = pWnd->head.pti;
+ else
+ pti = ptiCurrent;
+
+ pLE = GlobalEvents->Events.Flink;
+ pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
do
- {
+ {
+ if (!pEH) break;
UserReferenceObject(pEH);
// Must be inside the event window.
if ( (pEH->eventMin <= Event) && (pEH->eventMax >= Event))
{
- if ((pEH->Thread != PsGetCurrentThread()) && (pEH->Thread != NULL))
- { // if all process || all thread || other thread same process
- if (!(pEH->idProcess) || !(pEH->idThread) ||
- (NtCurrentTeb()->ClientId.UniqueProcess == (PVOID)pEH->idProcess))
+// if all process || all thread || other thread same process
+// if ^skip own thread && ((Pid && CPid == Pid && ^skip own process) || all process)
+ if ( (!pEH->idProcess || pEH->idProcess == PtrToUint(pti->pEThread->Cid.UniqueProcess)) &&
+ (!(pEH->Flags & WINEVENT_SKIPOWNPROCESS) || pEH->head.pti->ppi != pti->ppi) &&
+ (!pEH->idThread || pEH->idThread == PtrToUint(pti->pEThread->Cid.UniqueThread)) &&
+ (!(pEH->Flags & WINEVENT_SKIPOWNTHREAD) || pEH->head.pti != pti) &&
+ pEH->head.pti->rpdesk == ptiCurrent->rpdesk ) // Same as hooks.
+ {
+ // Send message to the thread if pEH is not current.
+ if (pEH->head.pti != ptiCurrent)
{
- Result = IntCallLowLevelEvent(pEH, Event, Window->hSelf, idObject, idChild);
+ DPRINT1("Global Event 0x%x, idObject %d\n", Event, idObject);
+ IntCallLowLevelEvent( pEH,
+ Event,
+ UserHMGetHandle(pWnd),
+ idObject,
+ idChild);
}
- }// if ^skip own thread && ((Pid && CPid == Pid && ^skip own process) || all process)
- else if ( !(pEH->Flags & WINEVENT_SKIPOWNTHREAD) &&
- ( ((pEH->idProcess &&
- NtCurrentTeb()->ClientId.UniqueProcess == (PVOID)pEH->idProcess) &&
- !(pEH->Flags & WINEVENT_SKIPOWNPROCESS)) ||
- !pEH->idProcess ) )
- {
- Result = co_IntCallEventProc( pEH->Self,
- Event,
- Window->hSelf,
- idObject,
- idChild,
- PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
- (DWORD)EngGetTickCount(),
- pEH->Proc);
- }
+ else
+ {
+ DPRINT1("Local Event 0x%x, idObject %d\n", Event, idObject);
+ co_IntCallEventProc( UserHMGetHandle(pEH),
+ Event,
+ UserHMGetHandle(pWnd),
+ idObject,
+ idChild,
+ PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
+ (DWORD)EngGetTickCount(),
+ pEH->Proc);
+ }
+ }
}
UserDereferenceObject(pEH);
-
- pEH = (PEVENTHOOK)pEH->Chain.Flink;
- } while (pEH != (PEVENTHOOK)&GlobalEvents->Events.Flink);
+ pLE = pEH->Chain.Flink;
+ pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
+ } while (pLE != &GlobalEvents->Events);
}
VOID
-STDCALL
+APIENTRY
NtUserNotifyWinEvent(
DWORD Event,
HWND hWnd,
LONG idObject,
LONG idChild)
{
- PWINDOW_OBJECT Window = NULL;
+ PWND Window = NULL;
USER_REFERENCE_ENTRY Ref;
UserEnterExclusive();
/* Validate input */
- if (hWnd && (hWnd != INVALID_HANDLE_VALUE) && !(Window = UserGetWindowObject(hWnd)))
+ if (hWnd && (hWnd != INVALID_HANDLE_VALUE))
{
- return;
- }
-
- if (gpsi->SrvEventActivity & GetMaskFromEvent(Event))
+ Window = UserGetWindowObject(hWnd);
+ if (!Window)
+ {
+ UserLeave();
+ return;
+ }
+ }
+
+ if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(Event))
{
- UserRefObjectCo(Window, &Ref);
- IntNotifyWinEvent( Event, Window, idObject, idChild);
- UserDerefObjectCo(Window);
+ if (Window) UserRefObjectCo(Window, &Ref);
+ IntNotifyWinEvent( Event, Window, idObject, idChild, WEF_SETBYWNDPTI);
+ if (Window) UserDerefObjectCo(Window);
}
UserLeave();
}
HWINEVENTHOOK
-STDCALL
+APIENTRY
NtUserSetWinEventHook(
UINT eventMin,
UINT eventMax,
{
PEVENTHOOK pEH;
HWINEVENTHOOK Ret = NULL;
- UNICODE_STRING ModuleName;
NTSTATUS Status;
HANDLE Handle;
PETHREAD Thread = NULL;
+ DPRINT("NtUserSetWinEventHook hmod 0x%x, pfn 0x%x\n",hmodWinEventProc, lpfnWinEventProc);
+
UserEnterExclusive();
if ( !GlobalEvents )
{
GlobalEvents = ExAllocatePoolWithTag(PagedPool, sizeof(EVENTTABLE), TAG_HOOK);
+ if (GlobalEvents == NULL)
+ {
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ goto SetEventExit;
+ }
GlobalEvents->Counts = 0;
InitializeListHead(&GlobalEvents->Events);
}
goto SetEventExit;
}
}
-
- pEH = UserCreateObject(gHandleTable, &Handle, otEvent, sizeof(EVENTHOOK));
+ // Creator, pti is set here.
+ pEH = UserCreateObject(gHandleTable, NULL, &Handle, otEvent, sizeof(EVENTHOOK));
if (pEH)
{
InsertTailList(&GlobalEvents->Events, &pEH->Chain);
GlobalEvents->Counts++;
- pEH->Self = Handle;
- if (Thread)
- pEH->Thread = Thread;
- else
- pEH->Thread = PsGetCurrentThread();
+ UserHMGetHandle(pEH) = Handle;
pEH->eventMin = eventMin;
pEH->eventMax = eventMax;
- pEH->idProcess = idProcess;
- pEH->idThread = idThread;
- pEH->Ansi = FALSE;
+ pEH->idProcess = idProcess; // These are cmp'ed
+ pEH->idThread = idThread; // "
pEH->Flags = dwflags;
-
-
+ /*
+ If WINEVENT_INCONTEXT, set offset from hmod and proc. Save ihmod from
+ the atom index table where the hmod data is saved to be recalled later
+ if fSync set by WINEVENT_INCONTEXT.
+ If WINEVENT_OUTOFCONTEXT just use proc..
+ Do this instead....
+ */
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);
+ pEH->offPfn = (ULONG_PTR)((char *)lpfnWinEventProc - (char *)hmodWinEventProc);
+ pEH->ihmod = (INT)hmodWinEventProc;
+ pEH->Proc = lpfnWinEventProc;
}
else
pEH->Proc = lpfnWinEventProc;
}
BOOL
-STDCALL
+APIENTRY
NtUserUnhookWinEvent(
HWINEVENTHOOK hWinEventHook)
{