mirror of
https://github.com/reactos/reactos.git
synced 2024-09-28 21:44:31 +00:00
[Win32ss]
- Fix wine msg:test_winevents. - Fix global hooks while sending to same process different thread. Yes, interesting. - Fix event hooks, use posting (faster) instead of sending. This fixed a problem while sending to the same thread. svn path=/trunk/; revision=66310
This commit is contained in:
parent
2ff860c8f1
commit
0a97b2b39d
|
@ -79,6 +79,8 @@ typedef struct _EVENTPROC_CALLBACK_ARGUMENTS
|
|||
DWORD dwEventThread;
|
||||
DWORD dwmsEventTime;
|
||||
WINEVENTPROC Proc;
|
||||
INT Mod;
|
||||
ULONG_PTR offPfn;
|
||||
} EVENTPROC_CALLBACK_ARGUMENTS, *PEVENTPROC_CALLBACK_ARGUMENTS;
|
||||
|
||||
typedef struct _LOADMENU_CALLBACK_ARGUMENTS
|
||||
|
|
|
@ -805,7 +805,9 @@ co_IntCallEventProc(HWINEVENTHOOK hook,
|
|||
LONG idChild,
|
||||
DWORD dwEventThread,
|
||||
DWORD dwmsEventTime,
|
||||
WINEVENTPROC Proc)
|
||||
WINEVENTPROC Proc,
|
||||
INT Mod,
|
||||
ULONG_PTR offPfn)
|
||||
{
|
||||
LRESULT Result = 0;
|
||||
NTSTATUS Status;
|
||||
|
@ -830,6 +832,8 @@ co_IntCallEventProc(HWINEVENTHOOK hook,
|
|||
Common->dwEventThread = dwEventThread;
|
||||
Common->dwmsEventTime = dwmsEventTime;
|
||||
Common->Proc = Proc;
|
||||
Common->Mod = Mod;
|
||||
Common->offPfn = offPfn;
|
||||
|
||||
ResultPointer = NULL;
|
||||
ResultLength = sizeof(LRESULT);
|
||||
|
|
|
@ -42,7 +42,9 @@ co_IntCallEventProc(HWINEVENTHOOK hook,
|
|||
LONG idChild,
|
||||
DWORD dwEventThread,
|
||||
DWORD dwmsEventTime,
|
||||
WINEVENTPROC Proc);
|
||||
WINEVENTPROC Proc,
|
||||
INT Mod,
|
||||
ULONG_PTR offPfn);
|
||||
|
||||
VOID FASTCALL
|
||||
IntCleanupThreadCallbacks(PTHREADINFO W32Thread);
|
||||
|
|
|
@ -14,6 +14,7 @@ typedef struct _EVENTPACK
|
|||
PEVENTHOOK pEH;
|
||||
LONG idObject;
|
||||
LONG idChild;
|
||||
LONG idThread;
|
||||
} EVENTPACK, *PEVENTPACK;
|
||||
|
||||
static PEVENTTABLE GlobalEvents = NULL;
|
||||
|
@ -98,11 +99,11 @@ IntCallLowLevelEvent( PEVENTHOOK pEH,
|
|||
DWORD event,
|
||||
HWND hwnd,
|
||||
LONG idObject,
|
||||
LONG idChild)
|
||||
LONG idChild,
|
||||
LONG idThread)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PEVENTPACK pEP;
|
||||
ULONG_PTR uResult = 0;
|
||||
MSG Msg;
|
||||
|
||||
pEP = ExAllocatePoolWithTag(NonPagedPool, sizeof(EVENTPACK), TAG_HOOK);
|
||||
if (!pEP) return 0;
|
||||
|
@ -110,23 +111,16 @@ IntCallLowLevelEvent( PEVENTHOOK pEH,
|
|||
pEP->pEH = pEH;
|
||||
pEP->idObject = idObject;
|
||||
pEP->idChild = idChild;
|
||||
pEP->idThread = idThread;
|
||||
|
||||
/* FIXME: Should get timeout from
|
||||
* HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
|
||||
Status = co_MsqSendMessage( pEH->head.pti,
|
||||
hwnd,
|
||||
event,
|
||||
0,
|
||||
(LPARAM)pEP,
|
||||
300,
|
||||
TRUE,
|
||||
MSQ_ISEVENT,
|
||||
&uResult);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExFreePoolWithTag(pEP, TAG_HOOK);
|
||||
}
|
||||
return NT_SUCCESS(Status) ? uResult : 0;
|
||||
Msg.message = event;
|
||||
Msg.hwnd = hwnd;
|
||||
Msg.wParam = 0;
|
||||
Msg.lParam = POSTEVENT_NWE;
|
||||
Msg.time = 0;
|
||||
|
||||
MsqPostMessage(pEH->head.pti, &Msg, FALSE, QS_EVENT, POSTEVENT_NWE, (LONG_PTR)pEP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
|
@ -155,7 +149,7 @@ IntRemoveEvent(PVOID Object)
|
|||
LRESULT
|
||||
APIENTRY
|
||||
co_EVENT_CallEvents( DWORD event,
|
||||
HWND hwnd,
|
||||
HWND hwnd,
|
||||
UINT_PTR idObject,
|
||||
LONG_PTR idChild)
|
||||
{
|
||||
|
@ -164,15 +158,17 @@ co_EVENT_CallEvents( DWORD event,
|
|||
PEVENTPACK pEP = (PEVENTPACK)idChild;
|
||||
|
||||
pEH = pEP->pEH;
|
||||
|
||||
TRACE("Dispatch Event 0x%x, idObject %d hwnd %p\n", event, idObject, hwnd);
|
||||
Result = co_IntCallEventProc( UserHMGetHandle(pEH),
|
||||
event,
|
||||
hwnd,
|
||||
pEP->idObject,
|
||||
pEP->idChild,
|
||||
PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
|
||||
pEP->idThread,
|
||||
(DWORD)EngGetTickCount(),
|
||||
pEH->Proc);
|
||||
pEH->Proc,
|
||||
pEH->ihmod,
|
||||
pEH->offPfn);
|
||||
|
||||
ExFreePoolWithTag(pEP, TAG_HOOK);
|
||||
return Result;
|
||||
|
@ -211,29 +207,19 @@ IntNotifyWinEvent(
|
|||
if (!pEH) break;
|
||||
UserReferenceObject(pEH);
|
||||
// Must be inside the event window.
|
||||
if ( (pEH->eventMin <= Event) && (pEH->eventMax >= Event))
|
||||
if ( Event >= pEH->eventMin && Event <= pEH->eventMax )
|
||||
{
|
||||
// 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.
|
||||
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)
|
||||
if (pEH->Flags & WINEVENT_INCONTEXT)
|
||||
{
|
||||
ERR("Global Event 0x%x, idObject %d\n", Event, idObject);
|
||||
IntCallLowLevelEvent( pEH,
|
||||
Event,
|
||||
pWnd ? UserHMGetHandle(pWnd) : NULL,
|
||||
idObject,
|
||||
idChild);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("Local Event 0x%x, idObject %d\n", Event, idObject);
|
||||
TRACE("In Event 0x%x, idObject %d hwnd %p\n", Event, idObject, pWnd ? UserHMGetHandle(pWnd) : NULL);
|
||||
co_IntCallEventProc( UserHMGetHandle(pEH),
|
||||
Event,
|
||||
pWnd ? UserHMGetHandle(pWnd) : NULL,
|
||||
|
@ -241,7 +227,19 @@ IntNotifyWinEvent(
|
|||
idChild,
|
||||
PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
|
||||
(DWORD)EngGetTickCount(),
|
||||
pEH->Proc);
|
||||
pEH->Proc,
|
||||
pEH->ihmod,
|
||||
pEH->offPfn);
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("Out Event 0x%x, idObject %d hwnd %p\n", Event, idObject, pWnd ? UserHMGetHandle(pWnd) : NULL);
|
||||
IntCallLowLevelEvent( pEH,
|
||||
Event,
|
||||
pWnd ? UserHMGetHandle(pWnd) : NULL,
|
||||
idObject,
|
||||
idChild,
|
||||
PtrToUint(NtCurrentTeb()->ClientId.UniqueThread));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -329,10 +327,25 @@ NtUserSetWinEventHook(
|
|||
goto SetEventExit;
|
||||
}
|
||||
|
||||
if ((dwflags & WINEVENT_INCONTEXT) && !hmodWinEventProc)
|
||||
if (dwflags & WINEVENT_INCONTEXT)
|
||||
{
|
||||
EngSetLastError(ERROR_HOOK_NEEDS_HMOD);
|
||||
goto SetEventExit;
|
||||
if (!hmodWinEventProc)
|
||||
{
|
||||
ERR("Hook needs a module\n");
|
||||
EngSetLastError(ERROR_HOOK_NEEDS_HMOD);
|
||||
goto SetEventExit;
|
||||
}
|
||||
if (puString == NULL)
|
||||
{
|
||||
ERR("Dll not found\n");
|
||||
EngSetLastError(ERROR_DLL_NOT_FOUND);
|
||||
goto SetEventExit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("Out of Context\n");
|
||||
hmodWinEventProc = 0;
|
||||
}
|
||||
|
||||
if (idThread)
|
||||
|
@ -371,14 +384,18 @@ NtUserSetWinEventHook(
|
|||
If WINEVENT_OUTOFCONTEXT just use proc..
|
||||
Do this instead....
|
||||
*/
|
||||
if (NULL != hmodWinEventProc)
|
||||
if (hmodWinEventProc != NULL)
|
||||
{
|
||||
pEH->offPfn = (ULONG_PTR)((char *)lpfnWinEventProc - (char *)hmodWinEventProc);
|
||||
pEH->ihmod = (INT)hmodWinEventProc;
|
||||
pEH->Proc = lpfnWinEventProc;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEH->Proc = lpfnWinEventProc;
|
||||
pEH->offPfn = 0;
|
||||
pEH->ihmod = (INT)hmodWinEventProc;
|
||||
}
|
||||
|
||||
UserDereferenceObject(pEH);
|
||||
|
||||
|
|
|
@ -1251,6 +1251,23 @@ co_HOOK_CallHooks( INT HookId,
|
|||
TRACE("\nGlobal Hook posting to another Thread! %d\n",HookId );
|
||||
Result = co_IntCallLowLevelHook(Hook, Code, wParam, lParam);
|
||||
}
|
||||
else if (ptiHook->ppi == pti->ppi)
|
||||
{
|
||||
TRACE("\nGlobal Hook calling to another Thread! %d\n",HookId );
|
||||
ObReferenceObject(ptiHook->pEThread);
|
||||
IntReferenceThreadInfo(ptiHook);
|
||||
Result = co_IntCallHookProc( HookId,
|
||||
Code,
|
||||
wParam,
|
||||
lParam,
|
||||
Hook->Proc,
|
||||
Hook->ihmod,
|
||||
Hook->offPfn,
|
||||
Hook->Ansi,
|
||||
&Hook->ModuleName);
|
||||
IntDereferenceThreadInfo(ptiHook);
|
||||
ObDereferenceObject(ptiHook->pEThread);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* Make the direct call. */
|
||||
|
|
|
@ -652,6 +652,20 @@ static LRESULT handle_internal_message( PWND pWnd, UINT msg, WPARAM wparam, LPAR
|
|||
return 0;
|
||||
}
|
||||
|
||||
static LRESULT handle_internal_events( PTHREADINFO pti, PWND pWnd, LONG_PTR ExtraInfo, PMSG pMsg)
|
||||
{
|
||||
LRESULT Result = 0;
|
||||
|
||||
switch(pMsg->lParam)
|
||||
{
|
||||
case POSTEVENT_NWE:
|
||||
{
|
||||
co_EVENT_CallEvents( pMsg->message, pMsg->hwnd, pMsg->wParam, ExtraInfo);
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
LRESULT FASTCALL
|
||||
IntDispatchMessage(PMSG pMsg)
|
||||
{
|
||||
|
@ -845,7 +859,7 @@ co_IntPeekMessage( PMSG Msg,
|
|||
ExtraInfo,
|
||||
Msg ))
|
||||
{
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Only check for quit messages if not posted messages pending. */
|
||||
|
@ -880,6 +894,24 @@ co_IntPeekMessage( PMSG Msg,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Now check for System Event messages. */
|
||||
{
|
||||
LONG_PTR eExtraInfo;
|
||||
MSG eMsg;
|
||||
if (MsqPeekMessage( pti,
|
||||
TRUE,
|
||||
Window,
|
||||
0,
|
||||
0,
|
||||
QS_EVENT,
|
||||
&eExtraInfo,
|
||||
&eMsg ))
|
||||
{
|
||||
handle_internal_events( pti, Window, eExtraInfo, &eMsg);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for sent messages again. */
|
||||
while ( co_MsqDispatchOneSentMessage(pti) )
|
||||
{
|
||||
|
|
|
@ -800,13 +800,6 @@ co_MsqDispatchOneSentMessage(PTHREADINFO pti)
|
|||
Message->Msg.wParam,
|
||||
Message->Msg.lParam);
|
||||
}
|
||||
else if (Message->HookMessage == MSQ_ISEVENT)
|
||||
{ // Direct Event Call processor
|
||||
Result = co_EVENT_CallEvents( Message->Msg.message,
|
||||
Message->Msg.hwnd,
|
||||
Message->Msg.wParam,
|
||||
Message->Msg.lParam);
|
||||
}
|
||||
else if(Message->HookMessage == MSQ_INJECTMODULE)
|
||||
{
|
||||
Result = IntLoadHookModule(Message->Msg.message,
|
||||
|
@ -2076,6 +2069,13 @@ MsqCleanupThreadMsgs(PTHREADINFO pti)
|
|||
{
|
||||
CurrentEntry = RemoveHeadList(&pti->PostedMessagesListHead);
|
||||
CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry);
|
||||
if (CurrentMessage->dwQEvent)
|
||||
{
|
||||
if (CurrentMessage->dwQEvent == POSTEVENT_NWE)
|
||||
{
|
||||
ExFreePoolWithTag( (PVOID)CurrentMessage->ExtraInfo, TAG_HOOK);
|
||||
}
|
||||
}
|
||||
MsqDestroyMessage(CurrentMessage);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
#define MSQ_HUNG 5000
|
||||
#define MSQ_NORMAL 0
|
||||
#define MSQ_ISHOOK 1
|
||||
#define MSQ_ISEVENT 2
|
||||
#define MSQ_INJECTMODULE 3
|
||||
#define MSQ_INJECTMODULE 2
|
||||
|
||||
typedef struct _USER_MESSAGE
|
||||
{
|
||||
|
@ -116,6 +115,8 @@ enum internal_event_message
|
|||
WM_ASYNC_DESTROYWINDOW
|
||||
};
|
||||
|
||||
#define POSTEVENT_NWE 14
|
||||
|
||||
BOOL FASTCALL MsqIsHung(PTHREADINFO pti);
|
||||
VOID CALLBACK HungAppSysTimerProc(HWND,UINT,UINT_PTR,DWORD);
|
||||
NTSTATUS FASTCALL co_MsqSendMessage(PTHREADINFO ptirec,
|
||||
|
|
|
@ -357,6 +357,9 @@ SetWinEventHook(
|
|||
{
|
||||
WCHAR ModuleName[MAX_PATH];
|
||||
UNICODE_STRING USModuleName;
|
||||
PUNICODE_STRING pusmodName;
|
||||
|
||||
RtlInitUnicodeString(&USModuleName, NULL);
|
||||
|
||||
if ((hmodWinEventProc != NULL) && (dwFlags & WINEVENT_INCONTEXT))
|
||||
{
|
||||
|
@ -365,16 +368,17 @@ SetWinEventHook(
|
|||
return NULL;
|
||||
}
|
||||
RtlInitUnicodeString(&USModuleName, ModuleName);
|
||||
pusmodName = &USModuleName;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlInitUnicodeString(&USModuleName, NULL);
|
||||
pusmodName = NULL;
|
||||
}
|
||||
|
||||
return NtUserSetWinEventHook(eventMin,
|
||||
eventMax,
|
||||
hmodWinEventProc,
|
||||
&USModuleName,
|
||||
pusmodName,
|
||||
pfnWinEventProc,
|
||||
idProcess,
|
||||
idThread,
|
||||
|
@ -779,16 +783,53 @@ NTSTATUS WINAPI
|
|||
User32CallEventProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
|
||||
{
|
||||
PEVENTPROC_CALLBACK_ARGUMENTS Common;
|
||||
WINEVENTPROC Proc;
|
||||
WCHAR module[MAX_PATH];
|
||||
DWORD len;
|
||||
HMODULE mod = NULL;
|
||||
BOOL Loaded = FALSE;
|
||||
|
||||
Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Arguments;
|
||||
|
||||
Common->Proc(Common->hook,
|
||||
Common->event,
|
||||
Common->hwnd,
|
||||
Common->idObject,
|
||||
Common->idChild,
|
||||
Common->dwEventThread,
|
||||
Common->dwmsEventTime);
|
||||
Proc = Common->Proc;
|
||||
|
||||
if (Common->offPfn && Common->Mod)
|
||||
{ // Validate the module again.
|
||||
if (!(len = GetModuleFileNameW((HINSTANCE)Common->Mod, module, MAX_PATH)) || len >= MAX_PATH)
|
||||
{
|
||||
ERR("Error check for module!\n");
|
||||
Common->Mod = 0;
|
||||
}
|
||||
|
||||
if (Common->Mod && !(mod = GetModuleHandleW(module)))
|
||||
{
|
||||
TRACE("Reloading Event Module.\n");
|
||||
if (!(mod = LoadLibraryExW(module, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)))
|
||||
{
|
||||
ERR("Failed to load Event Module.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Loaded = TRUE; // Free it only when loaded.
|
||||
}
|
||||
}
|
||||
|
||||
if (mod)
|
||||
{
|
||||
TRACE("Loading Event Module. %S\n",module);
|
||||
Proc = (WINEVENTPROC)((char *)mod + Common->offPfn);
|
||||
}
|
||||
}
|
||||
|
||||
Proc(Common->hook,
|
||||
Common->event,
|
||||
Common->hwnd,
|
||||
Common->idObject,
|
||||
Common->idChild,
|
||||
Common->dwEventThread,
|
||||
Common->dwmsEventTime);
|
||||
|
||||
if (Loaded) FreeLibrary(mod);
|
||||
|
||||
return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue