* 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: Messages
PUNICODE_STRING ClassName;
UINT Size = 0;
- _SEH_TRY
+ _SEH2_TRY
{
if (MMS_SIZE_WPARAM == MsgMemoryEntry->Size)
{
Size = sizeof(COPYDATASTRUCT) + ((PCOPYDATASTRUCT)lParam)->cbData;
break;
+ case WM_COPYGLOBALDATA:
+ Size = wParam;
+ break;
+
default:
assert(FALSE);
Size = 0;
{
Size = MsgMemoryEntry->Size;
}
- }
- _SEH_HANDLE
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- DPRINT1("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH_GetExceptionCode());
+ DPRINT1("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
Size = 0;
- }
- _SEH_END;
+ }
+ _SEH2_END;
return Size;
}
return STATUS_INVALID_PARAMETER;
}
-BOOL
-STDCALL
-NtUserCallMsgFilter(
- LPMSG msg,
- INT code)
+static
+VOID
+FASTCALL
+IntCallWndProc
+( PWINDOW_OBJECT Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
- DECLARE_RETURN(BOOL);
-
- DPRINT("Enter NtUserCallMsgFilter\n");
- UserEnterExclusive();
+ BOOL SameThread = FALSE;
- if (co_HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)msg))
- RETURN( TRUE);
- RETURN( co_HOOK_CallHooks( WH_MSGFILTER, code, 0, (LPARAM)msg));
+ if (Window->ti == ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->ThreadInfo)
+ SameThread = TRUE;
-CLEANUP:
- DPRINT("Leave NtUserCallMsgFilter. ret=%i\n", _ret_);
- UserLeave();
- END_CLEANUP;
+ if ((!SameThread && (Window->ti->fsHooks & HOOKID_TO_FLAG(WH_CALLWNDPROC))) ||
+ (SameThread && ISITHOOKED(WH_CALLWNDPROC)) )
+ {
+ CWPSTRUCT CWP;
+ CWP.hwnd = hWnd;
+ CWP.message = Msg;
+ CWP.wParam = wParam;
+ CWP.lParam = lParam;
+ co_HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, SameThread, (LPARAM)&CWP );
+ }
}
-
-LRESULT STDCALL
-NtUserDispatchMessage(PNTUSERDISPATCHMESSAGEINFO UnsafeMsgInfo)
+static
+VOID
+FASTCALL
+IntCallWndProcRet
+( PWINDOW_OBJECT Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *uResult)
{
- NTSTATUS Status;
- NTUSERDISPATCHMESSAGEINFO MsgInfo;
- LRESULT Result = TRUE;
- DECLARE_RETURN(LRESULT);
+ BOOL SameThread = FALSE;
- DPRINT("Enter NtUserDispatchMessage\n");
- UserEnterExclusive();
+ if (Window->ti == ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->ThreadInfo)
+ SameThread = TRUE;
- Status = MmCopyFromCaller(&MsgInfo, UnsafeMsgInfo, sizeof(NTUSERDISPATCHMESSAGEINFO));
- if (! NT_SUCCESS(Status))
+ if ((!SameThread && (Window->ti->fsHooks & HOOKID_TO_FLAG(WH_CALLWNDPROCRET))) ||
+ (SameThread && ISITHOOKED(WH_CALLWNDPROCRET)) )
{
- SetLastNtError(Status);
- RETURN( 0);
+ CWPRETSTRUCT CWPR;
+ CWPR.hwnd = hWnd;
+ CWPR.message = Msg;
+ CWPR.wParam = wParam;
+ CWPR.lParam = lParam;
+ CWPR.lResult = *uResult;
+ co_HOOK_CallHooks( WH_CALLWNDPROCRET, HC_ACTION, SameThread, (LPARAM)&CWPR );
}
+}
- /* Process timer messages. */
- if (WM_TIMER == MsgInfo.Msg.message && 0 != MsgInfo.Msg.lParam)
- {
- LARGE_INTEGER LargeTickCount;
- /* FIXME: Call hooks. */
+LRESULT
+FASTCALL
+IntDispatchMessage(PMSG pMsg)
+{
+ LARGE_INTEGER TickCount;
+ LONG Time;
+ LRESULT retval;
+ PWINDOW_OBJECT Window = NULL;
+
+ if (pMsg->hwnd)
+ {
+ Window = UserGetWindowObject(pMsg->hwnd);
+ if (!Window || !Window->Wnd) return 0;
+ }
+
+ if (((pMsg->message == WM_SYSTIMER) ||
+ (pMsg->message == WM_TIMER)) &&
+ (pMsg->lParam) )
+ {
+ if (pMsg->message == WM_TIMER)
+ {
+ if (ValidateTimerCallback(PsGetCurrentThreadWin32Thread(),Window,pMsg->wParam,pMsg->lParam))
+ {
+ KeQueryTickCount(&TickCount);
+ Time = MsqCalculateMessageTime(&TickCount);
+ return co_IntCallWindowProc((WNDPROC)pMsg->lParam,
+ TRUE,
+ pMsg->hwnd,
+ WM_TIMER,
+ pMsg->wParam,
+ (LPARAM)Time,
+ sizeof(LPARAM));
+ }
+ return 0;
+ }
+ else
+ {
+ PTIMER pTimer = FindSystemTimer(pMsg);
+ if (pTimer && pTimer->pfn)
+ {
+ KeQueryTickCount(&TickCount);
+ Time = MsqCalculateMessageTime(&TickCount);
+ pTimer->pfn(pMsg->hwnd, WM_SYSTIMER, (UINT)pMsg->wParam, Time);
+ }
+ return 0;
+ }
+ }
+ // Need a window!
+ if (!Window) return 0;
+
+ retval = co_IntPostOrSendMessage(pMsg->hwnd, pMsg->message, pMsg->wParam, pMsg->lParam);
+
+ if (pMsg->message == WM_PAINT)
+ {
+ /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
+ HRGN hrgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
+ co_UserGetUpdateRgn( Window, hrgn, TRUE );
+ GreDeleteObject( hrgn );
+ }
+ return retval;
+}
- /* FIXME: Check for continuing validity of timer. */
- MsgInfo.HandledByKernel = FALSE;
- KeQueryTickCount(&LargeTickCount);
- MsgInfo.Proc = (WNDPROC) MsgInfo.Msg.lParam;
- MsgInfo.Msg.lParam = (LPARAM)LargeTickCount.u.LowPart;
- }
- else if (NULL == MsgInfo.Msg.hwnd)
- {
- MsgInfo.HandledByKernel = TRUE;
- Result = 0;
- }
- else
+BOOL
+APIENTRY
+NtUserCallMsgFilter(
+ LPMSG lpmsg,
+ INT code)
+{
+ BOOL BadChk = FALSE, Ret = TRUE;
+ MSG Msg;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserCallMsgFilter\n");
+ UserEnterExclusive();
+ if (lpmsg)
{
- PWINDOW_OBJECT Window;
-
- /* Get the window object. */
- Window = UserGetWindowObject(MsgInfo.Msg.hwnd);
- if (NULL == Window)
+ _SEH2_TRY
{
- MsgInfo.HandledByKernel = TRUE;
- Result = 0;
+ ProbeForRead((PVOID)lpmsg,
+ sizeof(MSG),
+ 1);
+ RtlCopyMemory( &Msg,
+ (PVOID)lpmsg,
+ sizeof(MSG));
}
- else
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- if (Window->OwnerThread != PsGetCurrentThread())
- {
- DPRINT1("Window doesn't belong to the calling thread!\n");
- MsgInfo.HandledByKernel = TRUE;
- Result = 0;
- }
- else
- {
- /* FIXME: Call hook procedures. */
-
- MsgInfo.HandledByKernel = FALSE;
- Result = 0;
-
- MsgInfo.Ansi = !Window->Unicode;
- if (Window->IsSystem)
- MsgInfo.Proc = (Window->Unicode ? Window->WndProc : Window->WndProcExtra);
- else
- MsgInfo.Proc = Window->WndProc;
- }
+ BadChk = TRUE;
}
+ _SEH2_END;
}
- Status = MmCopyToCaller(UnsafeMsgInfo, &MsgInfo, sizeof(NTUSERDISPATCHMESSAGEINFO));
- if (! NT_SUCCESS(Status))
+ else
+ RETURN( FALSE);
+
+ if (BadChk) RETURN( FALSE);
+
+ if (!co_HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)&Msg))
{
- SetLastNtError(Status);
- RETURN( 0);
+ Ret = co_HOOK_CallHooks( WH_MSGFILTER, code, 0, (LPARAM)&Msg);
}
- RETURN( Result);
+ _SEH2_TRY
+ {
+ ProbeForWrite((PVOID)lpmsg,
+ sizeof(MSG),
+ 1);
+ RtlCopyMemory((PVOID)lpmsg,
+ &Msg,
+ sizeof(MSG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ if (BadChk) RETURN( FALSE);
+ RETURN( Ret)
CLEANUP:
- DPRINT("Leave NtUserDispatchMessage. ret=%i\n", _ret_);
+ DPRINT("Leave NtUserCallMsgFilter. ret=%i\n", _ret_);
UserLeave();
END_CLEANUP;
}
+LRESULT APIENTRY
+NtUserDispatchMessage(PMSG UnsafeMsgInfo)
+{
+ LRESULT Res = 0;
+ BOOL Hit = FALSE;
+ MSG SafeMsg;
+
+ UserEnterExclusive();
+ _SEH2_TRY
+ {
+ ProbeForRead(UnsafeMsgInfo, sizeof(MSG), 1);
+ RtlCopyMemory(&SafeMsg, UnsafeMsgInfo, sizeof(MSG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ Hit = TRUE;
+ }
+ _SEH2_END;
+
+ if (!Hit) Res = IntDispatchMessage(&SafeMsg);
+
+ UserLeave();
+ return Res;
+}
+
-BOOL STDCALL
+BOOL APIENTRY
NtUserTranslateMessage(LPMSG lpMsg,
HKL dwhkl)
{
}
Parent = IntGetParent(MsgWindow);//fixme: deref retval?
- /* fixme: abort if no parent ? */
+
+ /* If no parent window, pass MsgWindows HWND as wParam. Fixes bug #3111 */
Result = co_IntSendMessage(MsgWindow->hSelf,
WM_MOUSEACTIVATE,
- (WPARAM) (Parent ? Parent->hSelf : NULL),
+ (WPARAM) (Parent ? Parent->hSelf : MsgWindow->hSelf),
(LPARAM)MAKELONG(*HitTest, Msg->message)
);
if((DesktopWindow = UserGetWindowObject(hDesktop)))
{
PWINDOW_OBJECT Wnd;
-
+
UserRefObjectCo(DesktopWindow, &DesktopRef);
-
+
co_WinPosWindowFromPoint(DesktopWindow, Window->MessageQueue, &Msg->pt, &Wnd);
if(Wnd)
{
}
/* eat the message */
- UserDerefObject(Wnd);
+ UserDereferenceObject(Wnd);
UserDerefObjectCo(DesktopWindow);
UserDerefObjectCo(Window);
return TRUE;
}
- UserDerefObject(Wnd);
+ UserDereferenceObject(Wnd);
}
UserDerefObjectCo(DesktopWindow);
{
/* generate double click messages, if necessary */
if ((((*HitTest) != HTCLIENT) ||
- (Window->Class->Style & CS_DBLCLKS)) &&
+ (Window->Wnd->pcls->style & CS_DBLCLKS)) &&
MsqIsDblClk(Msg, Remove))
{
Msg->message += WM_LBUTTONDBLCLK - WM_LBUTTONDOWN;
{
/* NOTE: Msg->pt should remain in screen coordinates. -- FiN */
Msg->lParam = MAKELONG(
- Msg->pt.x - (WORD)Window->ClientRect.left,
- Msg->pt.y - (WORD)Window->ClientRect.top);
+ Msg->pt.x - (WORD)Window->Wnd->rcClient.left,
+ Msg->pt.y - (WORD)Window->Wnd->rcClient.top);
}
}
*/
BOOL FASTCALL
co_IntPeekMessage(PUSER_MESSAGE Msg,
- HWND hWnd,
+ PWINDOW_OBJECT Window,
UINT MsgFilterMin,
UINT MsgFilterMax,
UINT RemoveMsg)
{
+ PTHREADINFO pti;
LARGE_INTEGER LargeTickCount;
PUSER_MESSAGE_QUEUE ThreadQueue;
PUSER_MESSAGE Message;
BOOL Present, RemoveMessages;
USER_REFERENCE_ENTRY Ref;
USHORT HitTest;
+ MOUSEHOOKSTRUCT MHook;
/* The queues and order in which they are checked are documented in the MSDN
article on GetMessage() */
- ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
+ pti = PsGetCurrentThreadWin32Thread();
+ ThreadQueue = pti->MessageQueue;
/* Inspect RemoveMsg flags */
/* FIXME: The only flag we process is PM_REMOVE - processing of others must still be implemented */
{
ThreadQueue->QuitPosted = FALSE;
}
- return TRUE;
+ goto MsgExit;
}
/* Now check for normal messages. */
Present = co_MsqFindMessage(ThreadQueue,
FALSE,
RemoveMessages,
- hWnd,
+ Window,
MsgFilterMin,
MsgFilterMax,
&Message);
Present = co_MsqFindMessage(ThreadQueue,
TRUE,
RemoveMessages,
- hWnd,
+ Window,
MsgFilterMin,
MsgFilterMax,
&Message);
;
/* Check for paint messages. */
- if (IntGetPaintMessage(hWnd, MsgFilterMin, MsgFilterMax, PsGetWin32Thread(), &Msg->Msg, RemoveMessages))
+ if (IntGetPaintMessage(Window, MsgFilterMin, MsgFilterMax, pti, &Msg->Msg, RemoveMessages))
{
Msg->FreeLParam = FALSE;
- return TRUE;
+ goto MsgExit;
}
+ if (ThreadQueue->WakeMask & QS_TIMER)
+ if (PostTimerMessages(Window)) // If there are timers ready,
+ goto CheckMessages; // go back and process them.
+
+ // LOL! Polling Timer Queue? How much time is spent doing this?
/* Check for WM_(SYS)TIMER messages */
- Present = MsqGetTimerMessage(ThreadQueue, hWnd, MsgFilterMin, MsgFilterMax,
+ Present = MsqGetTimerMessage(ThreadQueue, Window, MsgFilterMin, MsgFilterMax,
&Msg->Msg, RemoveMessages);
if (Present)
{
goto CheckMessages;
}
}
-
+
UserDerefObjectCo(MsgWindow);
}
else
// if(MsgWindow)
// {
-// UserDerefObject(MsgWindow);
+// UserDereferenceObject(MsgWindow);
// }
- return TRUE;
+ goto MsgExit;
}
if((Msg->Msg.hwnd && Msg->Msg.message >= WM_MOUSEFIRST && Msg->Msg.message <= WM_MOUSELAST) &&
/* eat the message, search again */
goto CheckMessages;
}
-
+MsgExit:
+ if ( ISITHOOKED(WH_MOUSE) &&
+ Msg->Msg.message >= WM_MOUSEFIRST &&
+ Msg->Msg.message <= WM_MOUSELAST )
+ {
+ MHook.pt = Msg->Msg.pt;
+ MHook.hwnd = Msg->Msg.hwnd;
+ MHook.wHitTestCode = HitTest;
+ MHook.dwExtraInfo = 0;
+ if (co_HOOK_CallHooks( WH_MOUSE,
+ RemoveMsg ? HC_ACTION : HC_NOREMOVE,
+ Msg->Msg.message,
+ (LPARAM)&MHook ))
+ {
+ if (ISITHOOKED(WH_CBT))
+ {
+ MHook.pt = Msg->Msg.pt;
+ MHook.hwnd = Msg->Msg.hwnd;
+ MHook.wHitTestCode = HitTest;
+ MHook.dwExtraInfo = 0;
+ co_HOOK_CallHooks( WH_CBT, HCBT_CLICKSKIPPED,
+ Msg->Msg.message, (LPARAM)&MHook);
+ }
+ return FALSE;
+ }
+ }
+ if ( ISITHOOKED(WH_KEYBOARD) &&
+ (Msg->Msg.message == WM_KEYDOWN || Msg->Msg.message == WM_KEYUP) )
+ {
+ if (co_HOOK_CallHooks( WH_KEYBOARD,
+ RemoveMsg ? HC_ACTION : HC_NOREMOVE,
+ LOWORD(Msg->Msg.wParam),
+ Msg->Msg.lParam))
+ {
+ if (ISITHOOKED(WH_CBT))
+ {
+ /* skip this message */
+ co_HOOK_CallHooks( WH_CBT, HCBT_KEYSKIPPED,
+ LOWORD(Msg->Msg.wParam), Msg->Msg.lParam );
+ }
+ return FALSE;
+ }
+ }
+ // The WH_GETMESSAGE hook enables an application to monitor messages about to
+ // be returned by the GetMessage or PeekMessage function.
+ if (ISITHOOKED(WH_GETMESSAGE))
+ {
+ //DPRINT1("Peek WH_GETMESSAGE -> %x\n",&Msg);
+ co_HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, RemoveMsg & PM_REMOVE, (LPARAM)&Msg->Msg);
+ }
return TRUE;
}
return Present;
}
-BOOL STDCALL
+BOOL APIENTRY
NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
HWND hWnd,
UINT MsgFilterMin,
PWINDOW_OBJECT Window;
PMSGMEMORY MsgMemoryEntry;
PVOID UserMem;
- UINT Size;
+ SIZE_T Size;
USER_MESSAGE Msg;
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserPeekMessage\n");
UserEnterExclusive();
+ if (hWnd == (HWND)-1 || hWnd == (HWND)0x0000FFFF || hWnd == (HWND)0xFFFFFFFF)
+ hWnd = (HWND)1;
+
/* Validate input */
- if (hWnd && hWnd != INVALID_HANDLE_VALUE)
+ if (hWnd && hWnd != (HWND)1)
{
if (!(Window = UserGetWindowObject(hWnd)))
{
RETURN(-1);
}
}
+ else
+ {
+ Window = (PWINDOW_OBJECT)hWnd;
+ }
if (MsgFilterMax < MsgFilterMin)
{
MsgFilterMax = 0;
}
- Present = co_IntPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, RemoveMsg);
+ Present = co_IntPeekMessage(&Msg, Window, MsgFilterMin, MsgFilterMax, RemoveMsg);
if (Present)
{
+
Info.Msg = Msg.Msg;
/* See if this message type is present in the table */
MsgMemoryEntry = FindMsgMemory(Info.Msg.message);
Info.LParamSize = Size;
UserMem = NULL;
Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem, 0,
- &Info.LParamSize, MEM_COMMIT, PAGE_READWRITE);
+ &Size, MEM_COMMIT, PAGE_READWRITE);
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN( (BOOL) -1);
}
/* Transfer lParam data to user-mode mem */
- Status = MmCopyToCaller(UserMem, (PVOID) Info.Msg.lParam, Size);
+ Status = MmCopyToCaller(UserMem, (PVOID) Info.Msg.lParam, Info.LParamSize);
if (! NT_SUCCESS(Status))
{
ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *) &UserMem,
- &Info.LParamSize, MEM_DECOMMIT);
+ &Size, MEM_RELEASE);
SetLastNtError(Status);
RETURN( (BOOL) -1);
}
}
static BOOL FASTCALL
-co_IntWaitMessage(HWND Wnd,
+co_IntWaitMessage(PWINDOW_OBJECT Window,
UINT MsgFilterMin,
UINT MsgFilterMax)
{
+ PTHREADINFO pti;
PUSER_MESSAGE_QUEUE ThreadQueue;
NTSTATUS Status;
USER_MESSAGE Msg;
- ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
+ pti = PsGetCurrentThreadWin32Thread();
+ ThreadQueue = pti->MessageQueue;
do
{
- if (co_IntPeekMessage(&Msg, Wnd, MsgFilterMin, MsgFilterMax, PM_NOREMOVE))
+ if (co_IntPeekMessage(&Msg, Window, MsgFilterMin, MsgFilterMax, PM_NOREMOVE))
{
return TRUE;
}
/* Nothing found. Wait for new messages. */
- Status = co_MsqWaitForNewMessages(ThreadQueue, Wnd, MsgFilterMin, MsgFilterMax);
+ Status = co_MsqWaitForNewMessages(ThreadQueue, Window, MsgFilterMin, MsgFilterMax);
}
while ((STATUS_WAIT_0 <= Status && Status <= STATUS_WAIT_63) || STATUS_TIMEOUT == Status);
return FALSE;
}
-BOOL STDCALL
+BOOL APIENTRY
NtUserGetMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
HWND hWnd,
UINT MsgFilterMin,
BOOL GotMessage;
NTUSERGETMESSAGEINFO Info;
NTSTATUS Status;
+ /* FIXME: if initialization is removed, gcc complains that this may be used before initialization. Please review */
PWINDOW_OBJECT Window = NULL;
PMSGMEMORY MsgMemoryEntry;
PVOID UserMem;
- UINT Size;
+ SIZE_T Size;
USER_MESSAGE Msg;
DECLARE_RETURN(BOOL);
// USER_REFERENCE_ENTRY Ref;
{
RETURN(-1);
}
-
+
// if (Window) UserRefObjectCo(Window, &Ref);
-
+
if (MsgFilterMax < MsgFilterMin)
{
MsgFilterMin = 0;
do
{
- GotMessage = co_IntPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, PM_REMOVE);
+ GotMessage = co_IntPeekMessage(&Msg, Window, MsgFilterMin, MsgFilterMax, PM_REMOVE);
if (GotMessage)
{
Info.Msg = Msg.Msg;
Info.LParamSize = Size;
UserMem = NULL;
Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem, 0,
- &Info.LParamSize, MEM_COMMIT, PAGE_READWRITE);
+ &Size, MEM_COMMIT, PAGE_READWRITE);
if (! NT_SUCCESS(Status))
{
RETURN( (BOOL) -1);
}
/* Transfer lParam data to user-mode mem */
- Status = MmCopyToCaller(UserMem, (PVOID) Info.Msg.lParam, Size);
+ Status = MmCopyToCaller(UserMem, (PVOID) Info.Msg.lParam, Info.LParamSize);
if (! NT_SUCCESS(Status))
{
ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *) &UserMem,
- &Info.LParamSize, MEM_DECOMMIT);
+ &Size, MEM_DECOMMIT);
SetLastNtError(Status);
RETURN( (BOOL) -1);
}
RETURN( (BOOL) -1);
}
}
- else if (! co_IntWaitMessage(hWnd, MsgFilterMin, MsgFilterMax))
+ else if (! co_IntWaitMessage(Window, MsgFilterMin, MsgFilterMax))
{
RETURN( (BOOL) -1);
}
END_CLEANUP;
}
-DWORD
-STDCALL
-NtUserMessageCall(
- DWORD Unknown0,
- DWORD Unknown1,
- DWORD Unknown2,
- DWORD Unknown3,
- DWORD Unknown4,
- DWORD Unknown5,
- DWORD Unknown6)
-{
- UNIMPLEMENTED
-
- return 0;
-}
static NTSTATUS FASTCALL
CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg, PMSGMEMORY MsgMemoryEntry)
if (! NT_SUCCESS(Status))
{
DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
- ExFreePool(KernelMem);
+ ExFreePoolWithTag(KernelMem, TAG_MSG);
return Status;
}
}
return STATUS_SUCCESS;
}
+BOOL FASTCALL
+UserPostThreadMessage( DWORD idThread,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ MSG Message;
+ PETHREAD peThread;
+ PTHREADINFO pThread;
+ LARGE_INTEGER LargeTickCount;
+ NTSTATUS Status;
+
+ DPRINT1("UserPostThreadMessage wParam 0x%x lParam 0x%x\n", wParam,lParam);
+
+ if (FindMsgMemory(Msg) != 0)
+ {
+ SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
+ return FALSE;
+ }
+
+ Status = PsLookupThreadByThreadId((HANDLE)idThread,&peThread);
+
+ if( Status == STATUS_SUCCESS )
+ {
+ pThread = (PTHREADINFO)peThread->Tcb.Win32Thread;
+ if( !pThread || !pThread->MessageQueue )
+ {
+ ObDereferenceObject( peThread );
+ return FALSE;
+ }
+
+ Message.hwnd = NULL;
+ Message.message = Msg;
+ Message.wParam = wParam;
+ Message.lParam = lParam;
+ IntGetCursorLocation(pThread->Desktop->WindowStation, &Message.pt);
+ KeQueryTickCount(&LargeTickCount);
+ pThread->timeLast = Message.time = MsqCalculateMessageTime(&LargeTickCount);
+ MsqPostMessage(pThread->MessageQueue, &Message, FALSE, QS_POSTMESSAGE);
+ ObDereferenceObject( peThread );
+ return TRUE;
+ }
+ else
+ {
+ SetLastNtError( Status );
+ }
+ return FALSE;
+}
+
BOOL FASTCALL
UserPostMessage(HWND Wnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
- MSG UserModeMsg, KernelModeMsg;
+ PTHREADINFO pti;
+ MSG Message;
LARGE_INTEGER LargeTickCount;
- NTSTATUS Status;
- PMSGMEMORY MsgMemoryEntry;
- if (WM_QUIT == Msg)
+ if (FindMsgMemory(Msg) != 0)
{
- MsqPostQuitMessage(PsGetWin32Thread()->MessageQueue, wParam);
+ SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
+ return FALSE;
}
- else if (Wnd == HWND_BROADCAST)
+
+ if (!Wnd)
+ return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
+ Msg,
+ wParam,
+ lParam);
+
+ pti = PsGetCurrentThreadWin32Thread();
+ if (Wnd == HWND_BROADCAST)
{
HWND *List;
PWINDOW_OBJECT DesktopWindow;
DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
List = IntWinListChildren(DesktopWindow);
-
+
if (List != NULL)
{
for (i = 0; List[i]; i++)
else
{
PWINDOW_OBJECT Window;
-
+
Window = UserGetWindowObject(Wnd);
if (NULL == Window)
{
return FALSE;
}
- UserModeMsg.hwnd = Wnd;
- UserModeMsg.message = Msg;
- UserModeMsg.wParam = wParam;
- UserModeMsg.lParam = lParam;
- MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
- Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
- if (! NT_SUCCESS(Status))
+ if (WM_QUIT == Msg)
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return FALSE;
+ MsqPostQuitMessage(Window->MessageQueue, wParam);
+ }
+ else
+ {
+ Message.hwnd = Wnd;
+ Message.message = Msg;
+ Message.wParam = wParam;
+ Message.lParam = lParam;
+ IntGetCursorLocation(pti->Desktop->WindowStation, &Message.pt);
+ KeQueryTickCount(&LargeTickCount);
+ pti->timeLast = Message.time = MsqCalculateMessageTime(&LargeTickCount);
+ MsqPostMessage(Window->MessageQueue, &Message, FALSE, QS_POSTMESSAGE);
}
- IntGetCursorLocation(PsGetWin32Thread()->Desktop->WindowStation,
- &KernelModeMsg.pt);
- KeQueryTickCount(&LargeTickCount);
- KernelModeMsg.time = LargeTickCount.u.LowPart;
- MsqPostMessage(Window->MessageQueue, &KernelModeMsg,
- NULL != MsgMemoryEntry && 0 != KernelModeMsg.lParam,
- QS_POSTMESSAGE);
}
-
return TRUE;
}
-BOOL STDCALL
+BOOL APIENTRY
NtUserPostMessage(HWND hWnd,
UINT Msg,
WPARAM wParam,
DPRINT("Enter NtUserPostMessage\n");
UserEnterExclusive();
- RETURN(UserPostMessage(hWnd, Msg, wParam, lParam));
+ RETURN( UserPostMessage(hWnd, Msg, wParam, lParam));
CLEANUP:
DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_);
-BOOL STDCALL
+BOOL APIENTRY
NtUserPostThreadMessage(DWORD idThread,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
- MSG UserModeMsg, KernelModeMsg;
- PETHREAD peThread;
- PW32THREAD pThread;
- NTSTATUS Status;
- PMSGMEMORY MsgMemoryEntry;
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserPostThreadMessage\n");
UserEnterExclusive();
- Status = PsLookupThreadByThreadId((HANDLE)idThread,&peThread);
-
- if( Status == STATUS_SUCCESS )
- {
- pThread = (PW32THREAD)peThread->Tcb.Win32Thread;
- if( !pThread || !pThread->MessageQueue )
- {
- ObDereferenceObject( peThread );
- RETURN( FALSE);
- }
-
- UserModeMsg.hwnd = NULL;
- UserModeMsg.message = Msg;
- UserModeMsg.wParam = wParam;
- UserModeMsg.lParam = lParam;
- MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
- Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
- if (! NT_SUCCESS(Status))
- {
- ObDereferenceObject( peThread );
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- RETURN( FALSE);
- }
- MsqPostMessage(pThread->MessageQueue, &KernelModeMsg,
- NULL != MsgMemoryEntry && 0 != KernelModeMsg.lParam,
- QS_POSTMESSAGE);
- ObDereferenceObject( peThread );
- RETURN( TRUE);
- }
- else
- {
- SetLastNtError( Status );
- RETURN( FALSE);
- }
+ RETURN( UserPostThreadMessage( idThread,
+ Msg,
+ wParam,
+ lParam));
CLEANUP:
DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_);
END_CLEANUP;
}
-DWORD STDCALL
+DWORD APIENTRY
NtUserQuerySendMessage(DWORD Unknown0)
{
UNIMPLEMENTED;
return 0;
}
-static
+static
LRESULT FASTCALL
co_IntSendMessageTimeoutSingle(HWND hWnd,
UINT Msg,
PMSGMEMORY MsgMemoryEntry;
INT lParamBufferSize;
LPARAM lParamPacked;
- PW32THREAD Win32Thread;
+ PTHREADINFO Win32Thread;
DECLARE_RETURN(LRESULT);
USER_REFERENCE_ENTRY Ref;
- /* FIXME: Call hooks. */
if (!(Window = UserGetWindowObject(hWnd)))
{
RETURN( FALSE);
}
-
+
UserRefObjectCo(Window, &Ref);
- Win32Thread = PsGetWin32Thread();
+ Win32Thread = PsGetCurrentThreadWin32Thread();
+
+ IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
if (NULL != Win32Thread &&
- Window->MessageQueue == Win32Thread->MessageQueue)
+ Window->MessageQueue == Win32Thread->MessageQueue)
{
if (Win32Thread->IsExiting)
{
if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam)))
{
- DPRINT1("Failed to pack message parameters\n");
+ DPRINT1("Failed to pack message parameters\n");
RETURN( FALSE);
}
- Result = (ULONG_PTR)co_IntCallWindowProc(Window->WndProc, !Window->Unicode, hWnd, Msg, wParam,
+ Result = (ULONG_PTR)co_IntCallWindowProc(Window->Wnd->lpfnWndProc, !Window->Wnd->Unicode, hWnd, Msg, wParam,
lParamPacked,lParamBufferSize);
if(uResult)
*uResult = Result;
}
+ IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
+
if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam)))
{
DPRINT1("Failed to unpack message parameters\n");
- RETURN( TRUE);
+ RETURN( TRUE);
}
- RETURN( TRUE);
+ RETURN( TRUE);
}
- if(uFlags & SMTO_ABORTIFHUNG && MsqIsHung(Window->MessageQueue))
+ if (uFlags & SMTO_ABORTIFHUNG && MsqIsHung(Window->MessageQueue))
{
/* FIXME - Set a LastError? */
- RETURN( FALSE);
+ RETURN( FALSE);
}
- if(Window->Status & WINDOWSTATUS_DESTROYING)
+ if (Window->Status & WINDOWSTATUS_DESTROYING)
{
/* FIXME - last error? */
DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd);
- RETURN( FALSE);
+ RETURN( FALSE);
}
- Status = co_MsqSendMessage(Window->MessageQueue, hWnd, Msg, wParam, lParam,
- uTimeout, (uFlags & SMTO_BLOCK), FALSE, uResult);
+ do
+ {
+ Status = co_MsqSendMessage( Window->MessageQueue,
+ hWnd,
+ Msg,
+ wParam,
+ lParam,
+ uTimeout,
+ (uFlags & SMTO_BLOCK),
+ MSQ_NORMAL,
+ uResult);
+ }
+ while ((STATUS_TIMEOUT == Status) &&
+ (uFlags & SMTO_NOTIMEOUTIFNOTHUNG) &&
+ !MsqIsHung(Window->MessageQueue));
+ IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
if (STATUS_TIMEOUT == Status)
{
- /* MSDN says GetLastError() should return 0 after timeout */
- SetLastWin32Error(0);
- RETURN( FALSE);
+/*
+ MSDN says:
+ Microsoft Windows 2000: If GetLastError returns zero, then the function
+ timed out.
+ XP+ : If the function fails or times out, the return value is zero.
+ To get extended error information, call GetLastError. If GetLastError
+ returns ERROR_TIMEOUT, then the function timed out.
+ */
+ SetLastWin32Error(ERROR_TIMEOUT);
+ RETURN( FALSE);
}
else if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
- RETURN( FALSE);
+ RETURN( FALSE);
}
RETURN( TRUE);
-
+
CLEANUP:
if (Window) UserDerefObjectCo(Window);
END_CLEANUP;
LPARAM lParam)
{
ULONG_PTR Result;
+ PTHREADINFO pti;
PWINDOW_OBJECT Window;
if(hWnd == HWND_BROADCAST)
return 0;
}
- if(Window->MessageQueue != PsGetWin32Thread()->MessageQueue)
+ pti = PsGetCurrentThreadWin32Thread();
+ if(Window->MessageQueue != pti->MessageQueue && FindMsgMemory(Msg) ==0)
{
Result = UserPostMessage(hWnd, Msg, wParam, lParam);
}
else
{
- if(!co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result))
- {
+ if(!co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result)) {
Result = 0;
}
}
PDOSENDMESSAGE dsm,
PNTUSERSENDMESSAGEINFO UnsafeInfo)
{
+ PTHREADINFO pti;
LRESULT Result = TRUE;
NTSTATUS Status;
- PWINDOW_OBJECT Window;
+ PWINDOW_OBJECT Window = NULL;
NTUSERSENDMESSAGEINFO Info;
MSG UserModeMsg;
MSG KernelModeMsg;
MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
return 0;
}
+ if (!Window->Wnd)
+ return 0;
}
/* FIXME: Check for an exiting window. */
/* See if the current thread can handle the message */
- if (HWND_BROADCAST != hWnd && NULL != PsGetWin32Thread() &&
- Window->MessageQueue == PsGetWin32Thread()->MessageQueue)
+ pti = PsGetCurrentThreadWin32Thread();
+ if (HWND_BROADCAST != hWnd && NULL != pti &&
+ Window->MessageQueue == pti->MessageQueue)
{
/* Gather the information usermode needs to call the window proc directly */
Info.HandledByKernel = FALSE;
sizeof(BOOL));
if (! NT_SUCCESS(Status))
{
- Info.Ansi = ! Window->Unicode;
+ Info.Ansi = ! Window->Wnd->Unicode;
}
- Info.Ansi = !Window->Unicode;
- if (Window->IsSystem)
- Info.Proc = (Window->Unicode ? Window->WndProc : Window->WndProcExtra);
+ IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
+
+ if (Window->Wnd->IsSystem)
+ {
+ Info.Proc = (!Info.Ansi ? Window->Wnd->lpfnWndProc : Window->Wnd->WndProcExtra);
+ }
else
- Info.Proc = Window->WndProc;
+ {
+ Info.Ansi = !Window->Wnd->Unicode;
+ Info.Proc = Window->Wnd->lpfnWndProc;
+ }
+
+ IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, &Result);
+
}
else
{
/* Must be handled by other thread */
// if (HWND_BROADCAST != hWnd)
// {
-// UserDerefObject(Window);
+// UserDereferenceObject(Window);
// }
Info.HandledByKernel = TRUE;
UserModeMsg.hwnd = hWnd;
return (LRESULT)Result;
}
-LRESULT STDCALL
+LRESULT APIENTRY
NtUserSendMessageTimeout(HWND hWnd,
UINT Msg,
WPARAM wParam,
END_CLEANUP;
}
-LRESULT STDCALL
+LRESULT APIENTRY
NtUserSendMessage(HWND Wnd,
UINT Msg,
WPARAM wParam,
END_CLEANUP;
}
-BOOL STDCALL
-NtUserSendMessageCallback(HWND hWnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam,
- SENDASYNCPROC lpCallBack,
- ULONG_PTR dwData)
+
+BOOL FASTCALL
+UserSendNotifyMessage(HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
{
- UNIMPLEMENTED;
+ BOOL Result = TRUE;
- return 0;
-}
+ if (FindMsgMemory(Msg) != 0)
+ {
+ SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
+ return FALSE;
+ }
-BOOL STDCALL
-NtUserSendNotifyMessage(HWND hWnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam)
-{
- UNIMPLEMENTED;
+ // Basicly the same as IntPostOrSendMessage
+ if (hWnd == HWND_BROADCAST) //Handle Broadcast
+ {
+ HWND *List;
+ PWINDOW_OBJECT DesktopWindow;
+ ULONG i;
- return 0;
+ DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
+ List = IntWinListChildren(DesktopWindow);
+
+ if (List != NULL)
+ {
+ for (i = 0; List[i]; i++)
+ {
+ UserSendNotifyMessage(List[i], Msg, wParam, lParam);
+ }
+ ExFreePool(List);
+ }
+ }
+ else
+ {
+ ULONG_PTR PResult;
+ PTHREADINFO pti;
+ PWINDOW_OBJECT Window;
+ MSG Message;
+
+ if(!(Window = UserGetWindowObject(hWnd))) return FALSE;
+
+ pti = PsGetCurrentThreadWin32Thread();
+ if(Window->MessageQueue != pti->MessageQueue)
+ { // Send message w/o waiting for it.
+ Result = UserPostMessage(hWnd, Msg, wParam, lParam);
+ }
+ else
+ { // Handle message and callback.
+ Message.hwnd = hWnd;
+ Message.message = Msg;
+ Message.wParam = wParam;
+ Message.lParam = lParam;
+
+ Result = co_IntSendMessageTimeoutSingle( hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &PResult);
+ }
+ }
+ return Result;
}
-BOOL STDCALL
+
+BOOL APIENTRY
NtUserWaitMessage(VOID)
{
DECLARE_RETURN(BOOL);
END_CLEANUP;
}
-DWORD STDCALL
-NtUserGetQueueStatus(BOOL ClearChanges)
+DWORD APIENTRY
+IntGetQueueStatus(BOOL ClearChanges)
{
+ PTHREADINFO pti;
PUSER_MESSAGE_QUEUE Queue;
DWORD Result;
DECLARE_RETURN(DWORD);
- DPRINT("Enter NtUserGetQueueStatus\n");
- UserEnterExclusive();
+ DPRINT("Enter IntGetQueueStatus\n");
- Queue = PsGetWin32Thread()->MessageQueue;
+ pti = PsGetCurrentThreadWin32Thread();
+ Queue = pti->MessageQueue;
Result = MAKELONG(Queue->QueueBits, Queue->ChangedBits);
if (ClearChanges)
Queue->ChangedBits = 0;
}
- RETURN( Result);
+ RETURN(Result);
CLEANUP:
- DPRINT("Leave NtUserGetQueueStatus, ret=%i\n",_ret_);
- UserLeave();
+ DPRINT("Leave IntGetQueueStatus, ret=%i\n",_ret_);
END_CLEANUP;
}
-BOOL STDCALL
+BOOL APIENTRY
IntInitMessagePumpHook()
{
- ((PW32THREAD)PsGetCurrentThread()->Tcb.Win32Thread)->MessagePumpHookValue++;
- return TRUE;
+ if (((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti)
+ {
+ ((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook++;
+ return TRUE;
+ }
+ return FALSE;
}
-BOOL STDCALL
+BOOL APIENTRY
IntUninitMessagePumpHook()
{
- if (((PW32THREAD)PsGetCurrentThread()->Tcb.Win32Thread)->MessagePumpHookValue <= 0)
+ if (((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti)
+ {
+ if (((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook <= 0)
+ {
+ return FALSE;
+ }
+ ((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook--;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+BOOL APIENTRY
+NtUserMessageCall(
+ HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ ULONG_PTR ResultInfo,
+ DWORD dwType, // fnID?
+ BOOL Ansi)
+{
+ LRESULT lResult = 0;
+ BOOL Ret = FALSE;
+ BOOL BadChk = FALSE;
+ PWINDOW_OBJECT Window = NULL;
+ USER_REFERENCE_ENTRY Ref;
+
+ UserEnterExclusive();
+
+ /* Validate input */
+ if (hWnd && (hWnd != INVALID_HANDLE_VALUE) && !(Window = UserGetWindowObject(hWnd)))
{
+ UserLeave();
return FALSE;
}
- ((PW32THREAD)PsGetCurrentThread()->Tcb.Win32Thread)->MessagePumpHookValue--;
- return TRUE;
+ switch(dwType)
+ {
+ case FNID_DEFWINDOWPROC:
+ UserRefObjectCo(Window, &Ref);
+ lResult = IntDefWindowProc(Window, Msg, wParam, lParam, Ansi);
+ Ret = TRUE;
+ UserDerefObjectCo(Window);
+ break;
+ case FNID_SENDNOTIFYMESSAGE:
+ Ret = UserSendNotifyMessage(hWnd, Msg, wParam, lParam);
+ break;
+ case FNID_BROADCASTSYSTEMMESSAGE:
+ {
+ BROADCASTPARM parm;
+ DWORD_PTR RetVal = 0;
+
+ if (ResultInfo)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWrite((PVOID)ResultInfo,
+ sizeof(BROADCASTPARM),
+ 1);
+ RtlCopyMemory(&parm, (PVOID)ResultInfo, sizeof(BROADCASTPARM));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ if (BadChk) break;
+ }
+ else
+ break;
+
+ if ( parm.recipients & BSM_ALLDESKTOPS ||
+ parm.recipients == BSM_ALLCOMPONENTS )
+ {
+ }
+ else if (parm.recipients & BSM_APPLICATIONS)
+ {
+ if (parm.flags & BSF_QUERY)
+ {
+ if (parm.flags & BSF_FORCEIFHUNG || parm.flags & BSF_NOHANG)
+ {
+ co_IntSendMessageTimeout( HWND_BROADCAST,
+ Msg,
+ wParam,
+ lParam,
+ SMTO_ABORTIFHUNG,
+ 2000,
+ &RetVal);
+ }
+ else if (parm.flags & BSF_NOTIMEOUTIFNOTHUNG)
+ {
+ co_IntSendMessageTimeout( HWND_BROADCAST,
+ Msg,
+ wParam,
+ lParam,
+ SMTO_NOTIMEOUTIFNOTHUNG,
+ 2000,
+ &RetVal);
+ }
+ else
+ {
+ co_IntSendMessageTimeout( HWND_BROADCAST,
+ Msg,
+ wParam,
+ lParam,
+ SMTO_NORMAL,
+ 2000,
+ &RetVal);
+ }
+ }
+ else if (parm.flags & BSF_POSTMESSAGE)
+ {
+ Ret = UserPostMessage(HWND_BROADCAST, Msg, wParam, lParam);
+ }
+ else if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
+ {
+ Ret = UserSendNotifyMessage(HWND_BROADCAST, Msg, wParam, lParam);
+ }
+ }
+ }
+ break;
+ case FNID_SENDMESSAGECALLBACK:
+ break;
+ // CallNextHook bypass.
+ case FNID_CALLWNDPROC:
+ case FNID_CALLWNDPROCRET:
+ {
+ PCLIENTINFO ClientInfo = GetWin32ClientInfo();
+ PHOOK NextObj, Hook = ClientInfo->phkCurrent;
+
+ if (!ClientInfo || !Hook) break;
+
+ UserReferenceObject(Hook);
+
+ if (Hook->Thread && (Hook->Thread != PsGetCurrentThread()))
+ {
+ UserDereferenceObject(Hook);
+ break;
+ }
+
+ NextObj = IntGetNextHook(Hook);
+ ClientInfo->phkCurrent = NextObj;
+
+ if ( Hook->HookId == WH_CALLWNDPROC)
+ {
+ CWPSTRUCT CWP;
+ CWP.hwnd = hWnd;
+ CWP.message = Msg;
+ CWP.wParam = wParam;
+ CWP.lParam = lParam;
+ DPRINT("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook, NextObj );
+
+ lResult = co_IntCallHookProc( Hook->HookId,
+ HC_ACTION,
+ ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0),
+ (LPARAM)&CWP,
+ Hook->Proc,
+ Hook->Ansi,
+ &Hook->ModuleName);
+ }
+ else
+ {
+ CWPRETSTRUCT CWPR;
+ CWPR.hwnd = hWnd;
+ CWPR.message = Msg;
+ CWPR.wParam = wParam;
+ CWPR.lParam = lParam;
+ CWPR.lResult = ClientInfo->dwHookData;
+
+ lResult = co_IntCallHookProc( Hook->HookId,
+ HC_ACTION,
+ ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0),
+ (LPARAM)&CWPR,
+ Hook->Proc,
+ Hook->Ansi,
+ &Hook->ModuleName);
+ }
+ UserDereferenceObject(Hook);
+ lResult = (LRESULT) NextObj;
+ }
+ break;
+ }
+
+ switch(dwType)
+ {
+ case FNID_DEFWINDOWPROC:
+ case FNID_CALLWNDPROC:
+ case FNID_CALLWNDPROCRET:
+ if (ResultInfo)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWrite((PVOID)ResultInfo, sizeof(LRESULT), 1);
+ RtlCopyMemory((PVOID)ResultInfo, &lResult, sizeof(LRESULT));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ }
+ break;
+ default:
+ break;
+ }
+
+ UserLeave();
+
+ return BadChk ? FALSE : Ret;
+}
+
+#define INFINITE 0xFFFFFFFF
+#define WAIT_FAILED ((DWORD)0xFFFFFFFF)
+
+DWORD
+APIENTRY
+NtUserWaitForInputIdle(
+ IN HANDLE hProcess,
+ IN DWORD dwMilliseconds,
+ IN BOOL Unknown2)
+{
+ PEPROCESS Process;
+ PPROCESSINFO W32Process;
+ NTSTATUS Status;
+ HANDLE Handles[2];
+ LARGE_INTEGER Timeout;
+ ULONGLONG StartTime, Run, Elapsed = 0;
+
+ UserEnterExclusive();
+
+ Status = ObReferenceObjectByHandle(hProcess,
+ PROCESS_QUERY_INFORMATION,
+ PsProcessType,
+ UserMode,
+ (PVOID*)&Process,
+ NULL);
+
+ if (!NT_SUCCESS(Status))
+ {
+ UserLeave();
+ SetLastNtError(Status);
+ return WAIT_FAILED;
+ }
+
+ W32Process = (PPROCESSINFO)Process->Win32Process;
+ if (!W32Process)
+ {
+ ObDereferenceObject(Process);
+ UserLeave();
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return WAIT_FAILED;
+ }
+
+ EngCreateEvent((PEVENT *)&W32Process->InputIdleEvent);
+
+ Handles[0] = Process;
+ Handles[1] = W32Process->InputIdleEvent;
+
+ if (!Handles[1])
+ {
+ ObDereferenceObject(Process);
+ UserLeave();
+ return STATUS_SUCCESS; /* no event to wait on */
+ }
+
+ StartTime = EngGetTickCount();
+
+ Run = dwMilliseconds;
+
+ DPRINT("WFII: waiting for %p\n", Handles[1] );
+ do
+ {
+ Timeout.QuadPart = Run - Elapsed;
+ UserLeave();
+ Status = KeWaitForMultipleObjects( 2,
+ Handles,
+ WaitAny,
+ UserRequest,
+ UserMode,
+ FALSE,
+ dwMilliseconds == INFINITE ? NULL : &Timeout,
+ NULL);
+ UserEnterExclusive();
+
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ Status = WAIT_FAILED;
+ goto WaitExit;
+ }
+
+ switch (Status)
+ {
+ case STATUS_WAIT_0:
+ Status = WAIT_FAILED;
+ goto WaitExit;
+
+ case STATUS_WAIT_2:
+ {
+ USER_MESSAGE Msg;
+ co_IntPeekMessage( &Msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE );
+ break;
+ }
+
+ case STATUS_USER_APC:
+ case STATUS_ALERTED:
+ case STATUS_TIMEOUT:
+ DPRINT1("WFII: timeout\n");
+ Status = STATUS_TIMEOUT;
+ goto WaitExit;
+
+ default:
+ DPRINT1("WFII: finished\n");
+ Status = STATUS_SUCCESS;
+ goto WaitExit;
+ }
+
+ if (dwMilliseconds != INFINITE)
+ {
+ Elapsed = EngGetTickCount() - StartTime;
+
+ if (Elapsed > Run)
+ Status = STATUS_TIMEOUT;
+ break;
+ }
+ }
+ while (1);
+
+WaitExit:
+ if (W32Process->InputIdleEvent)
+ {
+ EngDeleteEvent((PEVENT)W32Process->InputIdleEvent);
+ W32Process->InputIdleEvent = NULL;
+ }
+ ObDereferenceObject(Process);
+ UserLeave();
+ return Status;
}
/* EOF */