[Win32k|User32]

- Fixed SendNotifyMessage, thanks to Michael Martin callback changes. Fixed DispatchMessage when dealing with thread errors. Fixed all but one of the Get/PeekMessage wine tests. Fixed attaching threads to process information. Plus other fixes.
- Implemented support for QS bits, ReplyMessage (not fully correct), and others.
- Tested everything here, please post regressions so I can add more applications to the test list. This patch is synced with 49720 and 49772. After that there are graphic issues.
- Credits goes to wine for helping with diagnosing issues in the ReactOS message system.

svn path=/trunk/; revision=49929
This commit is contained in:
James Tabor 2010-12-03 15:34:06 +00:00
parent 3972c628bb
commit 7d1736a1a2
14 changed files with 657 additions and 279 deletions

View file

@ -3182,7 +3182,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
SetCapture(mt.OwnerWnd);
(void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, mt.OwnerWnd);
ERR("MenuTrackMenu 1\n");
FIXME("MenuTrackMenu 1\n");
while (! fEndMenu)
{
PVOID menu = ValidateHandle(mt.CurrentMenu, VALIDATE_TYPE_MENU);
@ -3210,6 +3210,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
}
WaitMessage();
}
//FIXME("MenuTrackMenu loop 1\n");
}
/* check if EndMenu() tried to cancel us, by posting this message */
@ -3417,6 +3418,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
{
PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE );
DispatchMessageW( &msg );
//FIXME("MenuTrackMenu loop 2\n");
continue;
}
@ -3427,8 +3429,9 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
if (fRemove && !(mt.TrackFlags & TF_SKIPREMOVE) )
PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE );
else mt.TrackFlags &= ~TF_SKIPREMOVE;
//FIXME("MenuTrackMenu loop 3\n");
}
ERR("MenuTrackMenu 2\n");
FIXME("MenuTrackMenu 2\n");
(void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, NULL);
SetCapture(NULL); /* release the capture */

View file

@ -1097,7 +1097,6 @@ WINAPI
InSendMessage(VOID)
{
PCLIENTTHREADINFO pcti = GetWin32ClientInfo()->pClientThreadInfo;
// FIXME("ISM %x\n",pcti);
if ( pcti )
{
if (pcti->CTI_flags & CTI_INSENDMESSAGE)
@ -1118,7 +1117,6 @@ InSendMessageEx(
LPVOID lpReserved)
{
PCLIENTTHREADINFO pcti = GetWin32ClientInfo()->pClientThreadInfo;
// FIXME("ISMEX %x\n",pcti);
if (pcti && !(pcti->CTI_flags & CTI_INSENDMESSAGE))
return ISMEX_NOSEND;
else
@ -1442,6 +1440,12 @@ IntCallMessageProc(IN PWND Wnd, IN HWND hWnd, IN UINT Msg, IN WPARAM wParam, IN
Class = DesktopPtrToUser(Wnd->pcls);
WndProc = NULL;
if ( Wnd->head.pti != GetW32ThreadInfo())
{ // Must be inside the same thread!
SetLastError( ERROR_MESSAGE_SYNC_ONLY );
return 0;
}
/*
This is the message exchange for user32. If there's a need to monitor messages,
do it here!
@ -1586,11 +1590,16 @@ DispatchMessageA(CONST MSG *lpmsg)
MSG UnicodeMsg;
PWND Wnd;
if ( lpmsg->message & ~WM_MAXIMUM )
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
if (lpmsg->hwnd != NULL)
{
Wnd = ValidateHwnd(lpmsg->hwnd);
if (!Wnd || Wnd->head.pti != GetW32ThreadInfo())
return 0;
if (!Wnd) return 0;
}
else
Wnd = NULL;
@ -1602,7 +1611,7 @@ DispatchMessageA(CONST MSG *lpmsg)
if ( lpmsg->message == WM_SYSTIMER )
return NtUserDispatchMessage( (PMSG)lpmsg );
_SEH2_TRY // wine does this.
_SEH2_TRY // wine does this. Hint: Prevents call to another thread....
{
Ret = WndProc(lpmsg->hwnd,
lpmsg->message,
@ -1613,7 +1622,6 @@ DispatchMessageA(CONST MSG *lpmsg)
{
}
_SEH2_END;
}
else if (Wnd != NULL)
{
@ -1654,11 +1662,16 @@ DispatchMessageW(CONST MSG *lpmsg)
LRESULT Ret = 0;
PWND Wnd;
if ( lpmsg->message & ~WM_MAXIMUM )
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
if (lpmsg->hwnd != NULL)
{
Wnd = ValidateHwnd(lpmsg->hwnd);
if (!Wnd || Wnd->head.pti != GetW32ThreadInfo())
return 0;
if (!Wnd) return 0;
}
else
Wnd = NULL;
@ -1795,6 +1808,42 @@ GetMessageW(LPMSG lpMsg,
return Res;
}
BOOL WINAPI
PeekMessageWorker(PNTUSERGETMESSAGEINFO pInfo,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg)
{
PCLIENTINFO pci;
PCLIENTTHREADINFO pcti;
pci = GetWin32ClientInfo();
pcti = pci->pClientThreadInfo;
if (!hWnd && pci && pcti)
{
pci->cSpins++;
if ((pci->cSpins >= 100) && (pci->dwTIFlags & TIF_SPINNING))
{ // Yield after 100 spin cycles and ready to swap vinyl.
if (!(pci->dwTIFlags & TIF_WAITFORINPUTIDLE))
{ // Not waiting for idle event.
if (!pcti->fsChangeBits && !pcti->fsWakeBits)
{ // No messages are available.
if ((GetTickCount() - pcti->tickLastMsgChecked) > 1000)
{ // Up the msg read count if over 1 sec.
NtUserGetThreadState(THREADSTATE_UPTIMELASTREAD);
}
pci->cSpins = 0;
ZwYieldExecution();
FIXME("seeSpins!\n");
return FALSE;
}
}
}
}
return NtUserPeekMessage(pInfo, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
}
/*
* @implemented
@ -1812,7 +1861,7 @@ PeekMessageA(LPMSG lpMsg,
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
MsgConversionCleanup(lpMsg, TRUE, FALSE, NULL);
Res = NtUserPeekMessage(&Info, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
Res = PeekMessageWorker(&Info, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
if (-1 == (int) Res || !Res)
{
return FALSE;
@ -1865,7 +1914,7 @@ PeekMessageW(
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
MsgConversionCleanup(lpMsg, FALSE, FALSE, NULL);
Res = NtUserPeekMessage(&Info, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
Res = PeekMessageWorker(&Info, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
if (-1 == (int) Res || !Res)
{
return FALSE;
@ -2567,7 +2616,8 @@ DWORD
WINAPI
RealGetQueueStatus(UINT flags)
{
if (flags & ~(QS_SMRESULT|QS_ALLPOSTMESSAGE|QS_ALLINPUT))
#define QS_TEMPALLINPUT 255 // ATM, do not support QS_RAWINPUT
if (flags & ~(QS_SMRESULT|QS_ALLPOSTMESSAGE|QS_TEMPALLINPUT))
{
SetLastError( ERROR_INVALID_FLAGS );
return 0;
@ -2802,6 +2852,8 @@ RealMsgWaitForMultipleObjectsEx(
LPHANDLE RealHandles;
HANDLE MessageQueueHandle;
DWORD Result;
PCLIENTINFO pci;
PCLIENTTHREADINFO pcti;
if (dwFlags & ~(MWMO_WAITALL | MWMO_ALERTABLE | MWMO_INPUTAVAILABLE))
{
@ -2809,14 +2861,21 @@ RealMsgWaitForMultipleObjectsEx(
return WAIT_FAILED;
}
/*
if (dwFlags & MWMO_INPUTAVAILABLE)
{
RealGetQueueStatus(dwWakeMask);
}
*/
pci = GetWin32ClientInfo();
if (!pci) return WAIT_FAILED;
MessageQueueHandle = NtUserMsqSetWakeMask(dwWakeMask);
pcti = pci->pClientThreadInfo;
if (pcti && ( !nCount || !(dwFlags & MWMO_WAITALL) ))
{
if ( (pcti->fsChangeBits & LOWORD(dwWakeMask)) ||
( (dwFlags & MWMO_INPUTAVAILABLE) && (pcti->fsWakeBits & LOWORD(dwWakeMask)) ) )
{
//FIXME("Chg 0x%x Wake 0x%x Mask 0x%x nCnt %d\n",pcti->fsChangeBits, pcti->fsWakeBits, dwWakeMask, nCount);
return nCount;
}
}
MessageQueueHandle = NtUserMsqSetWakeMask(MAKELONG(dwWakeMask, dwFlags));
if (MessageQueueHandle == NULL)
{
SetLastError(0); /* ? */
@ -2840,7 +2899,7 @@ RealMsgWaitForMultipleObjectsEx(
HeapFree(GetProcessHeap(), 0, RealHandles);
NtUserMsqClearWakeMask();
//FIXME("Result 0X%x\n",Result);
return Result;
}

View file

@ -2104,7 +2104,8 @@ enum ThreadStateRoutines
THREADSTATE_PROGMANWINDOW,
THREADSTATE_TASKMANWINDOW,
THREADSTATE_GETMESSAGETIME,
THREADSTATE_GETINPUTSTATE
THREADSTATE_GETINPUTSTATE,
THREADSTATE_UPTIMELASTREAD
};
DWORD_PTR

View file

@ -8,10 +8,23 @@
#define MSQ_ISEVENT 2
#define MSQ_SENTNOWAIT 0x80000000
#define QSIDCOUNTS 6
typedef enum _QS_ROS_TYPES
{
QSRosKey = 0,
QSRosMouseMove,
QSRosMouseButton,
QSRosPostMessage,
QSRosSendMessage,
QSRosHotKey,
}QS_ROS_TYPES,*PQS_ROS_TYPES;
typedef struct _USER_MESSAGE
{
LIST_ENTRY ListEntry;
MSG Msg;
DWORD QS_Flags;
} USER_MESSAGE, *PUSER_MESSAGE;
struct _USER_MESSAGE_QUEUE;
@ -20,8 +33,10 @@ typedef struct _USER_SENT_MESSAGE
{
LIST_ENTRY ListEntry;
MSG Msg;
DWORD QS_Flags; // Original QS bits used to create this message.
PKEVENT CompletionEvent;
LRESULT* Result;
LRESULT lResult;
struct _USER_MESSAGE_QUEUE* SenderQueue;
SENDASYNCPROC CompletionCallback;
ULONG_PTR CompletionCallbackContext;
@ -31,16 +46,6 @@ typedef struct _USER_SENT_MESSAGE
BOOL HasPackedLParam;
} USER_SENT_MESSAGE, *PUSER_SENT_MESSAGE;
typedef struct _USER_SENT_MESSAGE_NOTIFY
{
SENDASYNCPROC CompletionCallback;
ULONG_PTR CompletionCallbackContext;
LRESULT Result;
HWND hWnd;
UINT Msg;
LIST_ENTRY ListEntry;
} USER_SENT_MESSAGE_NOTIFY, *PUSER_SENT_MESSAGE_NOTIFY;
typedef struct _USER_MESSAGE_QUEUE
{
/* Reference counter, only access this variable with interlocked functions! */
@ -52,8 +57,6 @@ typedef struct _USER_MESSAGE_QUEUE
LIST_ENTRY SentMessagesListHead;
/* Queue of messages posted to the queue. */
LIST_ENTRY PostedMessagesListHead;
/* Queue of sent-message notifies for the queue. */
LIST_ENTRY NotifyMessagesListHead;
/* Queue for hardware messages for the queue. */
LIST_ENTRY HardwareMessagesListHead;
/* Lock for the hardware message list. */
@ -76,8 +79,6 @@ typedef struct _USER_MESSAGE_QUEUE
ULONG LastMsgRead;
/* Current window with focus (ie. receives keyboard input) for this queue. */
HWND FocusWindow;
/* Count of paints pending. */
ULONG PaintCount;
/* Current active window for this queue. */
HWND ActiveWindow;
/* Current capture window for this queue. */
@ -92,9 +93,11 @@ typedef struct _USER_MESSAGE_QUEUE
PTHRDCARETINFO CaretInfo;
/* queue state tracking */
WORD WakeMask;
WORD QueueBits;
WORD ChangedBits;
// Send list QS_SENDMESSAGE
// Post list QS_POSTMESSAGE|QS_HOTKEY|QS_PAINT|QS_TIMER|QS_KEY
// Hard list QS_MOUSE|QS_KEY only
// Accounting of queue bit sets, the rest are flags. QS_TIMER QS_PAINT counts are handled in thread information.
DWORD nCntsQBits[QSIDCOUNTS]; // QS_KEY QS_MOUSEMOVE QS_MOUSEBUTTON QS_POSTMESSAGE QS_SENDMESSAGE QS_HOTKEY
/* extra message information */
LPARAM ExtraInfo;
@ -130,6 +133,7 @@ MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
IN PWND Window,
IN UINT MsgFilterLow,
IN UINT MsgFilterHigh,
IN UINT QSflags,
OUT PMSG Message);
BOOL APIENTRY
co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
@ -137,6 +141,7 @@ co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
IN PWND Window,
IN UINT MsgFilterLow,
IN UINT MsgFilterHigh,
IN UINT QSflags,
OUT MSG* pMsg);
BOOL APIENTRY
co_MsqPeekMouseMove(IN PUSER_MESSAGE_QUEUE MessageQueue,
@ -220,7 +225,6 @@ MsqSetStateWindow(PUSER_MESSAGE_QUEUE MessageQueue, ULONG Type, HWND hWnd);
__inline BOOL MsqIsSignaled( PUSER_MESSAGE_QUEUE queue );
__inline VOID MsqSetQueueBits( PUSER_MESSAGE_QUEUE queue, WORD bits );
__inline VOID MsqClearQueueBits( PUSER_MESSAGE_QUEUE queue, WORD bits );
BOOL APIENTRY IntInitMessagePumpHook();
BOOL APIENTRY IntUninitMessagePumpHook();
#define MAKE_LONG(x, y) ((((y) & 0xFFFF) << 16) | ((x) & 0xFFFF))
@ -285,5 +289,9 @@ MsqCalculateMessageTime(IN PLARGE_INTEGER TickCount)
VOID FASTCALL IdlePing(VOID);
VOID FASTCALL IdlePong(VOID);
BOOL FASTCALL co_MsqReplyMessage(LRESULT);
UINT FASTCALL GetWakeMask(UINT, UINT);
VOID FASTCALL MsqWakeQueue(PUSER_MESSAGE_QUEUE,DWORD,BOOL);
VOID FASTCALL ClearMsgBitsMask(PUSER_MESSAGE_QUEUE,UINT);
/* EOF */

View file

@ -161,6 +161,7 @@ typedef struct _PROCESSINFO
struct _DESKTOP* rpdeskStartup;
PCLS pclsPrivateList;
PCLS pclsPublicList;
INT cThreads;
DWORD dwhmodLibLoadedMask;
HANDLE ahmodLibLoaded[CLIBS];
struct _WINSTATION_OBJECT *prpwinsta;

View file

@ -268,6 +268,9 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
Win32Thread->TIF_flags &= ~TIF_INCLEANUP;
co_IntDestroyCaret(Win32Thread);
Win32Thread->ppi = PsGetCurrentProcessWin32Process();
Win32Thread->ptiSibling = Win32Thread->ppi->ptiList;
Win32Thread->ppi->ptiList = Win32Thread;
Win32Thread->ppi->cThreads++;
if (Win32Thread->rpdesk && !Win32Thread->pDeskInfo)
{
Win32Thread->pDeskInfo = Win32Thread->rpdesk->pDeskInfo;
@ -298,16 +301,39 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
else
{
DPRINT1("No TEB for this Thread!\n");
// System thread running! Now SendMessage should be okay.
Win32Thread->pcti = &Win32Thread->cti;
}
Win32Thread->pEThread = Thread;
}
else
{
PTHREADINFO pti;
PSINGLE_LIST_ENTRY e;
DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
Win32Thread->TIF_flags |= TIF_INCLEANUP;
pti = Win32Thread->ppi->ptiList;
if (pti == Win32Thread)
{
Win32Thread->ppi->ptiList = Win32Thread->ptiSibling;
Win32Thread->ppi->cThreads--;
}
else
{
do
{
if (pti->ptiSibling == Win32Thread)
{
pti->ptiSibling = Win32Thread->ptiSibling;
Win32Thread->ppi->cThreads--;
break;
}
pti = pti->ptiSibling;
}
while (pti);
}
DceFreeThreadDCE(Win32Thread);
HOOK_DestroyThreadHooks(Thread);
EVENT_DestroyThreadEvents(Thread);
@ -332,9 +358,7 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
e = PopEntryList(&Win32Thread->ReferencesList);
}
IntSetThreadDesktop(NULL,
TRUE);
IntSetThreadDesktop(NULL, TRUE);
PsSetThreadWin32Thread(Thread, NULL);
}

View file

@ -1926,7 +1926,7 @@ IntSetThreadDesktop(IN PDESKTOP DesktopObject,
RtlZeroMemory(&ctiSave, sizeof(CLIENTTHREADINFO));
if (W32Thread->pcti && OldDesktop)
if (W32Thread->pcti && OldDesktop && NtCurrentTeb())
{
RtlCopyMemory(&ctiSave, W32Thread->pcti, sizeof(CLIENTTHREADINFO));
DPRINT("Free ClientThreadInfo\n");
@ -1934,7 +1934,7 @@ IntSetThreadDesktop(IN PDESKTOP DesktopObject,
W32Thread->pcti = NULL;
}
if (!W32Thread->pcti && DesktopObject)
if (!W32Thread->pcti && DesktopObject && NtCurrentTeb())
{
DPRINT("Allocate ClientThreadInfo\n");
W32Thread->pcti = DesktopHeapAlloc( DesktopObject,

View file

@ -2,7 +2,7 @@
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Window classes
* FILE: subsys/win32k/ntuser/class.c
* FILE: subsystems/win32/win32k/ntuser/input.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISION HISTORY:
* 06-06-2001 CSH Created
@ -206,13 +206,6 @@ MouseThreadMain(PVOID StartContext)
NTSTATUS Status;
MOUSE_ATTRIBUTES MouseAttr;
Status = Win32kInitWin32Thread(PsGetCurrentThread());
if (!NT_SUCCESS(Status))
{
DPRINT1("Win32K: Failed making keyboard thread a win32 thread.\n");
return; //(Status);
}
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
LOW_REALTIME_PRIORITY + 3);
@ -1399,8 +1392,9 @@ IntKeyboardInput(KEYBDINPUT *ki)
FocusMessageQueue->Desktop->pDeskInfo->LastInputWasKbd = TRUE;
Msg.pt = gpsi->ptCursor;
MsqPostMessage(FocusMessageQueue, &Msg, FALSE, QS_KEY);
// Post to hardware queue, based on the first part of wine "some GetMessage tests"
// in test_PeekMessage()
MsqPostMessage(FocusMessageQueue, &Msg, TRUE, QS_KEY);
}
else
{

View file

@ -2,7 +2,7 @@
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Messages
* FILE: subsys/win32k/ntuser/message.c
* FILE: subsystems/win32/win32k/ntuser/message.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISION HISTORY:
* 06-06-2001 CSH Created
@ -342,12 +342,17 @@ IdlePing(VOID)
pti = PsGetCurrentThreadWin32Thread();
if ( pti && pti->pDeskInfo && pti == ptiForeground )
if ( pti )
{
if ( pti->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) ||
pti->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) )
pti->pClientInfo->cSpins = 0; // Reset spins.
if ( pti->pDeskInfo && pti == ptiForeground )
{
co_HOOK_CallHooks(WH_FOREGROUNDIDLE,HC_ACTION,0,0);
if ( pti->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) ||
pti->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) )
{
co_HOOK_CallHooks(WH_FOREGROUNDIDLE,HC_ACTION,0,0);
}
}
}
@ -371,6 +376,25 @@ IdlePong(VOID)
}
}
UINT FASTCALL
GetWakeMask(UINT first, UINT last )
{
UINT mask = QS_POSTMESSAGE | QS_SENDMESSAGE; /* Always selected */
if (first || last)
{
if ((first <= WM_KEYLAST) && (last >= WM_KEYFIRST)) mask |= QS_KEY;
if ( ((first <= WM_MOUSELAST) && (last >= WM_MOUSEFIRST)) ||
((first <= WM_NCMOUSELAST) && (last >= WM_NCMOUSEFIRST)) ) mask |= QS_MOUSE;
if ((first <= WM_TIMER) && (last >= WM_TIMER)) mask |= QS_TIMER;
if ((first <= WM_SYSTIMER) && (last >= WM_SYSTIMER)) mask |= QS_TIMER;
if ((first <= WM_PAINT) && (last >= WM_PAINT)) mask |= QS_PAINT;
}
else mask = QS_ALLINPUT;
return mask;
}
static VOID FASTCALL
IntCallWndProc( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
@ -424,6 +448,12 @@ IntDispatchMessage(PMSG pMsg)
pti = PsGetCurrentThreadWin32Thread();
if ( Window->head.pti != pti)
{
SetLastWin32Error( ERROR_MESSAGE_SYNC_ONLY );
return 0;
}
if (((pMsg->message == WM_SYSTIMER) ||
(pMsg->message == WM_TIMER)) &&
(pMsg->lParam) )
@ -503,24 +533,34 @@ IntDispatchMessage(PMSG pMsg)
}
/*
* Internal version of PeekMessage() doing all the work
*/
* Internal version of PeekMessage() doing all the work
*/
BOOL FASTCALL
co_IntPeekMessage( PMSG Msg,
PWND Window,
UINT MsgFilterMin,
UINT MsgFilterMax,
UINT RemoveMsg )
UINT RemoveMsg,
BOOL bGMSG )
{
PTHREADINFO pti;
PCLIENTINFO pci;
LARGE_INTEGER LargeTickCount;
PUSER_MESSAGE_QUEUE ThreadQueue;
BOOL RemoveMessages;
UINT ProcessMask;
BOOL Hit = FALSE;
pti = PsGetCurrentThreadWin32Thread();
ThreadQueue = pti->MessageQueue;
pci = pti->pClientInfo;
RemoveMessages = RemoveMsg & PM_REMOVE;
ProcessMask = HIWORD(RemoveMsg);
/* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
all available messages (that is, no range filtering is performed)". */
if (!ProcessMask) ProcessMask = (QS_ALLPOSTMESSAGE|QS_ALLINPUT);
IdlePong();
@ -528,16 +568,49 @@ co_IntPeekMessage( PMSG Msg,
{
KeQueryTickCount(&LargeTickCount);
ThreadQueue->LastMsgRead = LargeTickCount.u.LowPart;
pti->pcti->tickLastMsgChecked = LargeTickCount.u.LowPart;
/* Dispatch sent messages here. */
while (co_MsqDispatchOneSentMessage(ThreadQueue)) ;
while ( co_MsqDispatchOneSentMessage(ThreadQueue) )
{
/* if some PM_QS* flags were specified, only handle sent messages from now on */
if (HIWORD(RemoveMsg) && !bGMSG) Hit = TRUE; // wine does this; ProcessMask = QS_SENDMESSAGE;
}
if (Hit) return FALSE;
/* Clear changed bits so we can wait on them if we don't find a message */
if (ProcessMask & QS_POSTMESSAGE)
{
pti->pcti->fsChangeBits &= ~(QS_POSTMESSAGE | QS_HOTKEY | QS_TIMER);
if (MsgFilterMin == 0 && MsgFilterMax == 0) // wine hack does this; ~0U)
{
pti->pcti->fsChangeBits &= ~QS_ALLPOSTMESSAGE;
}
}
if (ProcessMask & QS_INPUT)
{
pti->pcti->fsChangeBits &= ~QS_INPUT;
}
/* Now check for normal messages. */
if ((ProcessMask & QS_POSTMESSAGE) &&
MsqPeekMessage( ThreadQueue,
RemoveMessages,
Window,
MsgFilterMin,
MsgFilterMax,
ProcessMask,
Msg ))
{
return TRUE;
}
/* Now look for a quit message. */
if (ThreadQueue->QuitPosted)
{
/* According to the PSDK, WM_QUIT messages are always returned, regardless
of the filter specified */
of the filter specified */
Msg->hwnd = NULL;
Msg->message = WM_QUIT;
Msg->wParam = ThreadQueue->QuitExitCode;
@ -545,49 +618,48 @@ co_IntPeekMessage( PMSG Msg,
if (RemoveMessages)
{
ThreadQueue->QuitPosted = FALSE;
ClearMsgBitsMask(ThreadQueue, QS_POSTMESSAGE);
pti->pcti->fsWakeBits &= ~QS_ALLPOSTMESSAGE;
pti->pcti->fsChangeBits &= ~QS_ALLPOSTMESSAGE;
}
return TRUE;
}
/* Now check for normal messages. */
if (MsqPeekMessage( ThreadQueue,
RemoveMessages,
Window,
MsgFilterMin,
MsgFilterMax,
Msg ))
{
return TRUE;
}
/* Check for hardware events. */
if(co_MsqPeekMouseMove(ThreadQueue,
RemoveMessages,
Window,
MsgFilterMin,
MsgFilterMax,
Msg ))
if ((ProcessMask & QS_MOUSE) &&
co_MsqPeekMouseMove( ThreadQueue,
RemoveMessages,
Window,
MsgFilterMin,
MsgFilterMax,
Msg ))
{
return TRUE;
}
if(co_MsqPeekHardwareMessage(ThreadQueue,
RemoveMessages,
Window,
MsgFilterMin,
MsgFilterMax,
Msg))
if ((ProcessMask & QS_INPUT) &&
co_MsqPeekHardwareMessage( ThreadQueue,
RemoveMessages,
Window,
MsgFilterMin,
MsgFilterMax,
ProcessMask,
Msg))
{
return TRUE;
}
/* Check for sent messages again. */
while (co_MsqDispatchOneSentMessage(ThreadQueue))
;
while ( co_MsqDispatchOneSentMessage(ThreadQueue) )
{
if (HIWORD(RemoveMsg) && !bGMSG) Hit = TRUE;
}
if (Hit) return FALSE;
/* Check for paint messages. */
if( IntGetPaintMessage( Window,
if ((ProcessMask & QS_PAINT) &&
pti->cPaintsReady &&
IntGetPaintMessage( Window,
MsgFilterMin,
MsgFilterMax,
pti,
@ -597,7 +669,11 @@ co_IntPeekMessage( PMSG Msg,
return TRUE;
}
if (PostTimerMessages(Window))
/* This is correct, check for the current threads timers waiting to be
posted to this threads message queue. If any we loop again.
*/
if ((ProcessMask & QS_TIMER) &&
PostTimerMessages(Window))
{
continue;
}
@ -718,11 +794,12 @@ co_IntWaitMessage( PWND Window,
do
{
if ( co_IntPeekMessage( &Msg,
Window,
MsgFilterMin,
MsgFilterMax,
PM_NOREMOVE))
if ( co_IntPeekMessage( &Msg, // Dont reenter!
Window,
MsgFilterMin,
MsgFilterMax,
MAKELONG( PM_NOREMOVE, GetWakeMask( MsgFilterMin, MsgFilterMax)),
TRUE ) ) // act like GetMessage.
{
return TRUE;
}
@ -754,6 +831,7 @@ co_IntGetPeekMessage( PMSG pMsg,
BOOL bGMSG )
{
PWND Window;
PTHREADINFO pti;
BOOL Present = FALSE;
if ( hWnd == HWND_TOPMOST || hWnd == HWND_BROADCAST )
@ -781,13 +859,19 @@ co_IntGetPeekMessage( PMSG pMsg,
MsgFilterMax = 0;
}
if (bGMSG)
{
RemoveMsg |= ((GetWakeMask( MsgFilterMin, MsgFilterMax ))<< 16);
}
do
{
Present = co_IntPeekMessage( pMsg,
Window,
MsgFilterMin,
MsgFilterMax,
RemoveMsg );
RemoveMsg,
bGMSG );
if (Present)
{
// The WH_GETMESSAGE hook enables an application to monitor messages about to
@ -796,13 +880,19 @@ co_IntGetPeekMessage( PMSG pMsg,
co_HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, RemoveMsg & PM_REMOVE, (LPARAM)pMsg);
if ( bGMSG )
return (WM_QUIT != pMsg->message);
{
Present = (WM_QUIT != pMsg->message);
break;
}
}
if ( bGMSG )
{
if ( !co_IntWaitMessage(Window, MsgFilterMin, MsgFilterMax) )
return -1;
{
Present = -1;
break;
}
}
else
{
@ -821,6 +911,14 @@ co_IntGetPeekMessage( PMSG pMsg,
}
while( bGMSG && !Present );
pti = PsGetCurrentThreadWin32Thread();
// Been spinning, time to swap vinyl...
if (pti->pClientInfo->cSpins >= 100)
{
// Clear the spin cycle to fix the mix.
pti->pClientInfo->cSpins = 0;
//if (!(pti->TIF_flags & TIF_SPINNING)) FIXME need to swap vinyl..
}
return Present;
}
@ -947,7 +1045,7 @@ UserPostMessage( HWND Wnd,
MsqPostQuitMessage(Window->head.pti->MessageQueue, wParam);
}
else
{
{
Message.hwnd = Wnd;
Message.message = Msg;
Message.wParam = wParam;
@ -1283,7 +1381,9 @@ co_IntSendMessageWithCallBack( HWND hWnd,
Message->Msg.lParam = lParamPacked;
Message->CompletionEvent = NULL;
Message->Result = 0;
Message->SenderQueue = NULL; //Win32Thread->MessageQueue;
Message->lResult = 0;
Message->QS_Flags = 0;
Message->SenderQueue = NULL; // mjmartin, you are right! This is null. Win32Thread->MessageQueue;
IntReferenceMessageQueue(Window->head.pti->MessageQueue);
Message->CompletionCallback = CompletionCallback;
@ -1291,6 +1391,9 @@ co_IntSendMessageWithCallBack( HWND hWnd,
Message->HookMessage = MSQ_NORMAL | MSQ_SENTNOWAIT;
Message->HasPackedLParam = (lParamBufferSize > 0);
Message->QS_Flags = QS_SENDMESSAGE;
MsqWakeQueue(Window->head.pti->MessageQueue, QS_SENDMESSAGE, FALSE);
InsertTailList(&Window->head.pti->MessageQueue->SentMessagesListHead, &Message->ListEntry);
IntDereferenceMessageQueue(Window->head.pti->MessageQueue);
@ -1468,7 +1571,7 @@ UserSendNotifyMessage( HWND hWnd,
WPARAM wParam,
LPARAM lParam )
{
BOOL Result = TRUE;
BOOL Ret = TRUE;
if (FindMsgMemory(Msg) != 0)
{
@ -1491,37 +1594,28 @@ UserSendNotifyMessage( HWND hWnd,
UserSendNotifyMessage(DesktopWindow->head.h, Msg, wParam, lParam);
for (i = 0; List[i]; i++)
{
UserSendNotifyMessage(List[i], Msg, wParam, lParam);
Ret = UserSendNotifyMessage(List[i], Msg, wParam, lParam);
if (!Ret)
{
DPRINT1("SendNotifyMessage: Failed in Broadcast!\n");
break;
}
}
ExFreePool(List);
}
}
else
{
ULONG_PTR PResult;
PTHREADINFO pti;
PWND Window;
if ( !(Window = UserGetWindowObject(hWnd)) ) return FALSE;
pti = PsGetCurrentThreadWin32Thread();
if (Window->head.pti->MessageQueue != pti->MessageQueue)
{ // Send message w/o waiting for it.
Result = UserPostMessage(hWnd, Msg, wParam, lParam);
}
else
{ // Handle message and callback.
Result = co_IntSendMessageTimeoutSingle( hWnd,
Msg,
wParam,
lParam,
SMTO_NORMAL,
0,
&PResult );
}
ULONG_PTR lResult = 0;
Ret = co_IntSendMessageWithCallBack( hWnd,
Msg,
wParam,
lParam,
NULL,
0,
&lResult);
}
return Result;
return Ret;
}
@ -1537,15 +1631,13 @@ IntGetQueueStatus(DWORD Changes)
// wine:
Changes &= (QS_ALLINPUT|QS_ALLPOSTMESSAGE|QS_SMRESULT);
Result = MAKELONG(Queue->ChangedBits & Changes, Queue->QueueBits & Changes);
/* High word, types of messages currently in the queue.
Low word, types of messages that have been added to the queue and that
are still in the queue
*/
Result = MAKELONG(pti->pcti->fsChangeBits & Changes, pti->pcti->fsWakeBits & Changes);
if (pti->pcti)
{
pti->pcti->fsChangeBits = Queue->ChangedBits;
pti->pcti->fsChangeBits &= ~Changes;
}
Queue->ChangedBits &= ~Changes;
pti->pcti->fsChangeBits &= ~Changes;
return Result;
}
@ -1684,9 +1776,9 @@ NtUserWaitMessage(VOID)
BOOL ret;
UserEnterExclusive();
DPRINT("NtUserWaitMessage Enter\n");
ret = co_IntWaitMessage(NULL, 0, 0);
DPRINT("NtUserWaitMessage Leave\n");
UserLeave();
return ret;
@ -2338,6 +2430,13 @@ NtUserWaitForInputIdle( IN HANDLE hProcess,
if (dwMilliseconds != INFINITE)
Timeout.QuadPart = (LONGLONG) dwMilliseconds * (LONGLONG) -10000;
W32Process->W32PF_flags |= W32PF_WAITFORINPUTIDLE;
for (pti = W32Process->ptiList; pti; pti = pti->ptiSibling)
{
pti->TIF_flags |= TIF_WAITFORINPUTIDLE;
pti->pClientInfo->dwTIFlags = pti->TIF_flags;
}
DPRINT("WFII: ppi 0x%x\n",W32Process);
DPRINT("WFII: waiting for %p\n", Handles[1] );
do
@ -2368,7 +2467,7 @@ NtUserWaitForInputIdle( IN HANDLE hProcess,
case STATUS_WAIT_2:
{
MSG Msg;
co_IntPeekMessage( &Msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE );
co_IntGetPeekMessage( &Msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE, FALSE);
DPRINT1("WFII: WAIT 2\n");
}
break;
@ -2387,6 +2486,12 @@ NtUserWaitForInputIdle( IN HANDLE hProcess,
while (TRUE);
WaitExit:
for (pti = W32Process->ptiList; pti; pti = pti->ptiSibling)
{
pti->TIF_flags &= ~TIF_WAITFORINPUTIDLE;
pti->pClientInfo->dwTIFlags = pti->TIF_flags;
}
W32Process->W32PF_flags &= ~W32PF_WAITFORINPUTIDLE;
ObDereferenceObject(Process);
UserLeave();
return Status;

View file

@ -2,7 +2,7 @@
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Misc User funcs
* FILE: subsystem/win32/win32k/ntuser/misc.c
* FILE: subsystems/win32/win32k/ntuser/misc.c
* PROGRAMER: Ge van Geldorp (ge@gse.nl)
* REVISION HISTORY:
* 2003/05/22 Created
@ -102,6 +102,8 @@ NtUserGetThreadState(
break;
case THREADSTATE_INSENDMESSAGE:
{
PUSER_SENT_MESSAGE Message;
PLIST_ENTRY Entry;
PUSER_MESSAGE_QUEUE MessageQueue =
((PTHREADINFO)PsGetCurrentThreadWin32Thread())->MessageQueue;
DPRINT1("THREADSTATE_INSENDMESSAGE\n");
@ -109,21 +111,39 @@ NtUserGetThreadState(
ret = ISMEX_NOSEND;
if (!IsListEmpty(&MessageQueue->SentMessagesListHead))
{
ret = ISMEX_SEND;
Entry = MessageQueue->SentMessagesListHead.Flink;
Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
if (Message->SenderQueue)
ret = ISMEX_SEND;
else
{
if (Message->CompletionCallback)
ret = ISMEX_CALLBACK;
else
ret = ISMEX_NOTIFY;
}
/* if ReplyMessage */
if (Message->QS_Flags & QS_SMRESULT) ret |= ISMEX_REPLIED;
}
else if (!IsListEmpty(&MessageQueue->NotifyMessagesListHead))
{
/* FIXME Need to set message flag when in callback mode with notify */
ret = ISMEX_NOTIFY;
}
/* FIXME Need to set message flag if replied to or ReplyMessage */
break;
}
case THREADSTATE_GETMESSAGETIME:
/* FIXME Needs more work! */
case THREADSTATE_GETMESSAGETIME:
ret = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->timeLast;
break;
case THREADSTATE_UPTIMELASTREAD:
{
PTHREADINFO pti;
LARGE_INTEGER LargeTickCount;
pti = PsGetCurrentThreadWin32Thread();
KeQueryTickCount(&LargeTickCount);
pti->MessageQueue->LastMsgRead = LargeTickCount.u.LowPart;
pti->pcti->tickLastMsgChecked = LargeTickCount.u.LowPart;
}
break;
case THREADSTATE_GETINPUTSTATE:
ret = LOWORD(IntGetQueueStatus(QS_POSTMESSAGE|QS_TIMER|QS_PAINT|QS_SENDMESSAGE|QS_INPUT)) & (QS_KEY | QS_MOUSEBUTTON);
break;

View file

@ -1,21 +1,3 @@
/*
* ReactOS W32 Subsystem
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -41,74 +23,6 @@ static PAGED_LOOKASIDE_LIST MessageLookasideList;
/* FUNCTIONS *****************************************************************/
HANDLE FASTCALL
IntMsqSetWakeMask(DWORD WakeMask)
{
PTHREADINFO Win32Thread;
PUSER_MESSAGE_QUEUE MessageQueue;
HANDLE MessageEventHandle;
Win32Thread = PsGetCurrentThreadWin32Thread();
if (Win32Thread == NULL || Win32Thread->MessageQueue == NULL)
return 0;
MessageQueue = Win32Thread->MessageQueue;
MessageQueue->WakeMask = WakeMask;
MessageEventHandle = MessageQueue->NewMessagesHandle;
if (Win32Thread->pcti)
Win32Thread->pcti->fsWakeMask = WakeMask;
IdlePing();
return MessageEventHandle;
}
BOOL FASTCALL
IntMsqClearWakeMask(VOID)
{
PTHREADINFO Win32Thread;
PUSER_MESSAGE_QUEUE MessageQueue;
Win32Thread = PsGetCurrentThreadWin32Thread();
if (Win32Thread == NULL || Win32Thread->MessageQueue == NULL)
return FALSE;
MessageQueue = Win32Thread->MessageQueue;
// HACK!!!!!!! Newbies that wrote this should hold your head down in shame! (jt)
MessageQueue->WakeMask = ~0;
if (Win32Thread->pcti)
Win32Thread->pcti->fsWakeMask = 0;
IdlePong();
return TRUE;
}
VOID FASTCALL
MsqWakeQueue(PUSER_MESSAGE_QUEUE Queue, DWORD MessageBits)
{
Queue->QueueBits |= MessageBits;
Queue->ChangedBits |= MessageBits;
if (Queue->WakeMask & MessageBits)
KeSetEvent(Queue->NewMessages, IO_NO_INCREMENT, FALSE);
}
VOID FASTCALL
MsqIncPaintCountQueue(PUSER_MESSAGE_QUEUE Queue)
{
Queue->PaintCount++;
MsqWakeQueue(Queue, QS_PAINT);
}
VOID FASTCALL
MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue)
{
Queue->PaintCount--;
}
INIT_FUNCTION
NTSTATUS
NTAPI
@ -125,12 +39,153 @@ MsqInitializeImpl(VOID)
return(STATUS_SUCCESS);
}
HANDLE FASTCALL
IntMsqSetWakeMask(DWORD WakeMask)
{
PTHREADINFO Win32Thread;
PUSER_MESSAGE_QUEUE MessageQueue;
HANDLE MessageEventHandle;
DWORD dwFlags = HIWORD(WakeMask);
Win32Thread = PsGetCurrentThreadWin32Thread();
if (Win32Thread == NULL || Win32Thread->MessageQueue == NULL)
return 0;
MessageQueue = Win32Thread->MessageQueue;
// Win32Thread->pEventQueueServer; IntMsqSetWakeMask returns Win32Thread->hEventQueueClient
MessageEventHandle = MessageQueue->NewMessagesHandle;
if (Win32Thread->pcti)
{
if ( (Win32Thread->pcti->fsChangeBits & LOWORD(WakeMask)) ||
( (dwFlags & MWMO_INPUTAVAILABLE) && (Win32Thread->pcti->fsWakeBits & LOWORD(WakeMask)) ) )
{
DPRINT1("Chg 0x%x Wake 0x%x Mask 0x%x\n",Win32Thread->pcti->fsChangeBits, Win32Thread->pcti->fsWakeBits, WakeMask);
KeSetEvent(MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE); // Wake it up!
return MessageEventHandle;
}
}
IdlePing();
return MessageEventHandle;
}
BOOL FASTCALL
IntMsqClearWakeMask(VOID)
{
PTHREADINFO Win32Thread;
Win32Thread = PsGetCurrentThreadWin32Thread();
if (Win32Thread == NULL || Win32Thread->MessageQueue == NULL)
return FALSE;
// Very hacky, but that is what they do.
Win32Thread->pcti->fsWakeBits = 0;
IdlePong();
return TRUE;
}
/*
Due to the uncertainty of knowing what was set in our multilevel message queue,
and even if the bits are all cleared. The same as cTimers/cPaintsReady.
I think this is the best solution... (jt) */
VOID FASTCALL
MsqWakeQueue(PUSER_MESSAGE_QUEUE Queue, DWORD MessageBits, BOOL KeyEvent)
{
PTHREADINFO pti;
pti = Queue->Thread->Tcb.Win32Thread;
pti->pcti->fsWakeBits |= MessageBits;
pti->pcti->fsChangeBits |= MessageBits;
// Start bit accounting to help clear the main set of bits.
if (MessageBits & QS_KEY) Queue->nCntsQBits[QSRosKey]++;
if (MessageBits & QS_MOUSEMOVE) Queue->nCntsQBits[QSRosMouseMove]++;
if (MessageBits & QS_MOUSEBUTTON) Queue->nCntsQBits[QSRosMouseButton]++;
if (MessageBits & QS_POSTMESSAGE) Queue->nCntsQBits[QSRosPostMessage]++;
if (MessageBits & QS_SENDMESSAGE) Queue->nCntsQBits[QSRosSendMessage]++;
if (MessageBits & QS_HOTKEY) Queue->nCntsQBits[QSRosHotKey]++;
if (KeyEvent)
KeSetEvent(Queue->NewMessages, IO_NO_INCREMENT, FALSE);
}
VOID FASTCALL
ClearMsgBitsMask(PUSER_MESSAGE_QUEUE Queue, UINT MessageBits)
{
PTHREADINFO pti;
UINT ClrMask = 0;
pti = Queue->Thread->Tcb.Win32Thread;
if (MessageBits & QS_KEY)
{
if (--Queue->nCntsQBits[QSRosKey] == 0) ClrMask |= QS_KEY;
}
if (MessageBits & QS_MOUSEMOVE) // ReactOS hard coded.
{ // Account for tracking mouse moves..
if (--Queue->nCntsQBits[QSRosMouseMove] == 0) ClrMask |= QS_MOUSEMOVE;
// Handle mouse move bits here.
if (Queue->MouseMoved) ClrMask |= QS_MOUSEMOVE;
}
if (MessageBits & QS_MOUSEBUTTON)
{
if (--Queue->nCntsQBits[QSRosMouseButton] == 0) ClrMask |= QS_MOUSEBUTTON;
}
if (MessageBits & QS_POSTMESSAGE)
{
if (--Queue->nCntsQBits[QSRosPostMessage] == 0) ClrMask |= QS_POSTMESSAGE;
}
if (MessageBits & QS_TIMER) // ReactOS hard coded.
{ // Handle timer bits here.
if ( pti->cTimersReady )
{
if (--pti->cTimersReady == 0) ClrMask |= QS_TIMER;
}
}
if (MessageBits & QS_PAINT) // ReactOS hard coded.
{ // Handle paint bits here.
if ( pti->cPaintsReady )
{
if (--pti->cPaintsReady == 0) ClrMask |= QS_PAINT;
}
}
if (MessageBits & QS_SENDMESSAGE)
{
if (--Queue->nCntsQBits[QSRosSendMessage] == 0) ClrMask |= QS_SENDMESSAGE;
}
if (MessageBits & QS_HOTKEY)
{
if (--Queue->nCntsQBits[QSRosHotKey] == 0) ClrMask |= QS_HOTKEY;
}
pti->pcti->fsWakeBits &= ~ClrMask;
pti->pcti->fsChangeBits &= ~ClrMask;
}
VOID FASTCALL
MsqIncPaintCountQueue(PUSER_MESSAGE_QUEUE Queue)
{
PTHREADINFO pti;
pti = Queue->Thread->Tcb.Win32Thread;
pti->cPaintsReady++;
MsqWakeQueue(Queue, QS_PAINT, TRUE);
}
VOID FASTCALL
MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue)
{
ClearMsgBitsMask(Queue, QS_PAINT);
}
VOID FASTCALL
MsqPostMouseMove(PUSER_MESSAGE_QUEUE MessageQueue, MSG* Msg)
{
MessageQueue->MouseMoveMsg = *Msg;
MessageQueue->MouseMoved = TRUE;
MsqWakeQueue(MessageQueue, QS_MOUSEMOVE);
MsqWakeQueue(MessageQueue, QS_MOUSEMOVE, TRUE);
}
VOID FASTCALL
@ -366,6 +421,7 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
PUSER_SENT_MESSAGE Message;
PLIST_ENTRY Entry;
LRESULT Result;
PTHREADINFO pti;
if (IsListEmpty(&MessageQueue->SentMessagesListHead))
{
@ -376,11 +432,20 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
Entry = RemoveHeadList(&MessageQueue->SentMessagesListHead);
Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
pti = MessageQueue->Thread->Tcb.Win32Thread;
// Processing a message sent to it from another thread.
if ( MessageQueue != Message->SenderQueue ) // most likely, but, to be sure.
{
pti->pcti->CTI_flags |= CTI_INSENDMESSAGE; // Let the user know...
}
/* insert it to the list of messages that are currently dispatched by this
message queue */
InsertTailList(&MessageQueue->LocalDispatchingMessagesHead,
&Message->ListEntry);
ClearMsgBitsMask(MessageQueue, Message->QS_Flags);
if (Message->HookMessage == MSQ_ISHOOK)
{ // Direct Hook Call processor
Result = co_CallHook( Message->Msg.message, // HookId
@ -419,6 +484,11 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
/* still keep the sender's message queue locked, so the sender can't exit the
MsqSendMessage() function (if timed out) */
if (Message->QS_Flags & QS_SMRESULT)
{
Result = Message->lResult;
}
/* Let the sender know the result. */
if (Message->Result != NULL)
{
@ -456,6 +526,9 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
/* free the message */
ExFreePoolWithTag(Message, TAG_USRMSG);
pti->pcti->CTI_flags &= ~CTI_INSENDMESSAGE;
return(TRUE);
}
@ -483,6 +556,7 @@ MsqRemoveWindowMessagesFromQueue(PVOID pWindow)
if (PostedMessage->Msg.hwnd == Window->head.h)
{
RemoveEntryList(&PostedMessage->ListEntry);
ClearMsgBitsMask(MessageQueue, PostedMessage->QS_Flags);
MsqDestroyMessage(PostedMessage);
CurrentEntry = MessageQueue->PostedMessagesListHead.Flink;
}
@ -504,6 +578,7 @@ MsqRemoveWindowMessagesFromQueue(PVOID pWindow)
DPRINT("Notify the sender and remove a message from the queue that had not been dispatched\n");
RemoveEntryList(&SentMessage->ListEntry);
ClearMsgBitsMask(MessageQueue, SentMessage->QS_Flags);
/* remove the message from the dispatching list if neede */
if ((!(SentMessage->HookMessage & MSQ_SENTNOWAIT))
@ -581,6 +656,8 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
Message->Msg.lParam = lParam;
Message->CompletionEvent = &CompletionEvent;
Message->Result = &Result;
Message->lResult = 0;
Message->QS_Flags = 0;
Message->SenderQueue = ThreadQueue;
IntReferenceMessageQueue(ThreadQueue);
Message->CompletionCallback = NULL;
@ -596,7 +673,8 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
/* queue it in the destination's message queue */
InsertTailList(&MessageQueue->SentMessagesListHead, &Message->ListEntry);
MsqWakeQueue(MessageQueue, QS_SENDMESSAGE);
Message->QS_Flags = QS_SENDMESSAGE;
MsqWakeQueue(MessageQueue, QS_SENDMESSAGE, TRUE);
/* we can't access the Message anymore since it could have already been deleted! */
@ -746,7 +824,9 @@ MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue, MSG* Msg, BOOLEAN HardwareMessa
InsertTailList(&MessageQueue->HardwareMessagesListHead,
&Message->ListEntry);
}
MsqWakeQueue(MessageQueue, MessageBits);
Message->QS_Flags = MessageBits;
MsqWakeQueue(MessageQueue, MessageBits, (MessageBits & QS_TIMER ? FALSE : TRUE));
}
VOID FASTCALL
@ -754,7 +834,7 @@ MsqPostQuitMessage(PUSER_MESSAGE_QUEUE MessageQueue, ULONG ExitCode)
{
MessageQueue->QuitPosted = TRUE;
MessageQueue->QuitExitCode = ExitCode;
MsqWakeQueue(MessageQueue, QS_POSTMESSAGE);
MsqWakeQueue(MessageQueue, QS_POSTMESSAGE|QS_ALLPOSTMESSAGE, TRUE);
}
/***********************************************************************
@ -1122,17 +1202,38 @@ co_MsqPeekMouseMove(IN PUSER_MESSAGE_QUEUE MessageQueue,
*pMsg = msg;
if(Remove)
{
ClearMsgBitsMask(MessageQueue, QS_MOUSEMOVE);
MessageQueue->MouseMoved = FALSE;
}
return AcceptMessage;
}
/* check whether a message filter contains at least one potential hardware message */
static INT FASTCALL
filter_contains_hw_range( UINT first, UINT last )
{
/* hardware message ranges are (in numerical order):
* WM_NCMOUSEFIRST .. WM_NCMOUSELAST
* WM_KEYFIRST .. WM_KEYLAST
* WM_MOUSEFIRST .. WM_MOUSELAST
*/
if (!last) --last;
if (last < WM_NCMOUSEFIRST) return 0;
if (first > WM_NCMOUSELAST && last < WM_KEYFIRST) return 0;
if (first > WM_KEYLAST && last < WM_MOUSEFIRST) return 0;
if (first > WM_MOUSELAST) return 0;
return 1;
}
BOOL APIENTRY
co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
IN BOOL Remove,
IN PWND Window,
IN UINT MsgFilterLow,
IN UINT MsgFilterHigh,
IN UINT QSflags,
OUT MSG* pMsg)
{
@ -1141,33 +1242,45 @@ co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
PLIST_ENTRY ListHead, CurrentEntry = NULL;
MSG msg;
if (!filter_contains_hw_range( MsgFilterLow, MsgFilterHigh )) return FALSE;
ListHead = &MessageQueue->HardwareMessagesListHead;
CurrentEntry = ListHead->Flink;
while(CurrentEntry != ListHead)
{
CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
if (IsListEmpty(CurrentEntry)) return FALSE;
CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
ListEntry);
msg = CurrentMessage->Msg;
AcceptMessage = co_IntProcessHardwareMessage(&msg, &Remove, MsgFilterLow, MsgFilterHigh);
do
{
if (IsListEmpty(CurrentEntry)) break;
if (!CurrentMessage) break;
CurrentEntry = CurrentMessage->ListEntry.Flink;
if (Remove)
if ( (( MsgFilterLow == 0 && MsgFilterHigh == 0 ) && (CurrentMessage->QS_Flags & QSflags)) ||
( MsgFilterLow <= CurrentMessage->Msg.message && MsgFilterHigh >= CurrentMessage->Msg.message ) )
{
RemoveEntryList(&CurrentMessage->ListEntry);
MsqDestroyMessage(CurrentMessage);
}
msg = CurrentMessage->Msg;
if(AcceptMessage)
{
*pMsg = msg;
return TRUE;
}
AcceptMessage = co_IntProcessHardwareMessage(&msg, &Remove, MsgFilterLow, MsgFilterHigh);
if (Remove)
{
RemoveEntryList(&CurrentMessage->ListEntry);
ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags);
MsqDestroyMessage(CurrentMessage);
}
if (AcceptMessage)
{
*pMsg = msg;
return TRUE;
}
}
CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
ListEntry);
}
while(CurrentEntry != ListHead);
return FALSE;
}
@ -1178,6 +1291,7 @@ MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
IN PWND Window,
IN UINT MsgFilterLow,
IN UINT MsgFilterHigh,
IN UINT QSflags,
OUT PMSG Message)
{
PLIST_ENTRY CurrentEntry;
@ -1186,29 +1300,35 @@ MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
CurrentEntry = MessageQueue->PostedMessagesListHead.Flink;
ListHead = &MessageQueue->PostedMessagesListHead;
while (CurrentEntry != ListHead)
{
CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
if (IsListEmpty(CurrentEntry)) return FALSE;
CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
ListEntry);
if ( ( !Window ||
PtrToInt(Window) == 1 ||
Window->head.h == CurrentMessage->Msg.hwnd ) &&
( (MsgFilterLow == 0 && MsgFilterHigh == 0) ||
( MsgFilterLow <= CurrentMessage->Msg.message &&
MsgFilterHigh >= CurrentMessage->Msg.message ) ) )
do
{
if (IsListEmpty(CurrentEntry)) break;
if (!CurrentMessage) break;
CurrentEntry = CurrentEntry->Flink;
if ( ( !Window || Window == HWND_BOTTOM || Window->head.h == CurrentMessage->Msg.hwnd ) &&
( ( ( MsgFilterLow == 0 && MsgFilterHigh == 0 ) && CurrentMessage->QS_Flags & QSflags ) ||
( MsgFilterLow <= CurrentMessage->Msg.message && MsgFilterHigh >= CurrentMessage->Msg.message ) ) )
{
*Message= CurrentMessage->Msg;
*Message = CurrentMessage->Msg;
if (Remove)
{
RemoveEntryList(&CurrentMessage->ListEntry);
ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags);
MsqDestroyMessage(CurrentMessage);
}
return(TRUE);
}
CurrentEntry = CurrentEntry->Flink;
CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
ListEntry);
}
while (CurrentEntry != ListHead);
return(FALSE);
}
@ -1257,9 +1377,6 @@ MsqInitializeMessageQueue(struct _ETHREAD *Thread, PUSER_MESSAGE_QUEUE MessageQu
KeQueryTickCount(&LargeTickCount);
MessageQueue->LastMsgRead = LargeTickCount.u.LowPart;
MessageQueue->FocusWindow = NULL;
MessageQueue->PaintCount = 0;
// HACK!!!!!!! Newbies that wrote this should hold your head down in shame! (jt)
MessageQueue->WakeMask = ~0;
MessageQueue->NewMessagesHandle = NULL;
Status = ZwCreateEvent(&MessageQueue->NewMessagesHandle, EVENT_ALL_ACCESS,
@ -1288,6 +1405,10 @@ MsqCleanupMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
PLIST_ENTRY CurrentEntry;
PUSER_MESSAGE CurrentMessage;
PUSER_SENT_MESSAGE CurrentSentMessage;
PTHREADINFO pti;
pti = MessageQueue->Thread->Tcb.Win32Thread;
/* cleanup posted messages */
while (!IsListEmpty(&MessageQueue->PostedMessagesListHead))
@ -1391,6 +1512,16 @@ MsqCleanupMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
locked later */
}
// Clear it all out.
pti->pcti->fsWakeBits = 0;
pti->pcti->fsChangeBits = 0;
MessageQueue->nCntsQBits[QSRosKey] = 0;
MessageQueue->nCntsQBits[QSRosMouseMove] = 0;
MessageQueue->nCntsQBits[QSRosMouseButton] = 0;
MessageQueue->nCntsQBits[QSRosPostMessage] = 0;
MessageQueue->nCntsQBits[QSRosSendMessage] = 0;
MessageQueue->nCntsQBits[QSRosHotKey] = 0;
}
PUSER_MESSAGE_QUEUE FASTCALL
@ -1475,6 +1606,38 @@ MsqGetMessageExtraInfo(VOID)
return MessageQueue->ExtraInfo;
}
BOOL FASTCALL
co_MsqReplyMessage( LRESULT lResult )
{
PUSER_SENT_MESSAGE Message;
PLIST_ENTRY Entry;
PTHREADINFO pti;
PUSER_MESSAGE_QUEUE MessageQueue;
pti = PsGetCurrentThreadWin32Thread();
MessageQueue = pti->MessageQueue;
if(!MessageQueue) return FALSE;
if (IsListEmpty(&MessageQueue->SentMessagesListHead))
{
return(FALSE);
}
// Do we loop through all msgs or just set the first one?
Entry = MessageQueue->SentMessagesListHead.Flink;
Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
if (Message->QS_Flags & QS_SMRESULT) return FALSE;
if (Message->SenderQueue || Message->CompletionCallback)
{
Message->lResult = lResult;
Message->QS_Flags |= QS_SMRESULT;
MsqWakeQueue(MessageQueue, 0, TRUE); // Wake it up!? Bits?
}
return TRUE;
}
HWND FASTCALL
MsqSetStateWindow(PUSER_MESSAGE_QUEUE MessageQueue, ULONG Type, HWND hWnd)
{

View file

@ -2,7 +2,7 @@
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Window painting function
* FILE: subsys/win32k/ntuser/painting.c
* FILE: subsystems/win32/win32k/ntuser/painting.c
* PROGRAMER: Filip Navara (xnavara@volny.cz)
* REVISION HISTORY:
* 06/06/2001 Created (?)
@ -660,9 +660,7 @@ IntGetPaintMessage(
MSG *Message,
BOOL Remove)
{
PUSER_MESSAGE_QUEUE MessageQueue = (PUSER_MESSAGE_QUEUE)Thread->MessageQueue;
if (!MessageQueue->PaintCount)
if (!Thread->cPaintsReady)
return FALSE;
if ((MsgFilterMin != 0 || MsgFilterMax != 0) &&
@ -673,9 +671,9 @@ IntGetPaintMessage(
if (Message->hwnd == NULL)
{
DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n");
DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found! Counts %d\n",Thread->cPaintsReady);
/* Hack to stop spamming the debuglog ! */
MessageQueue->PaintCount = 0;
Thread->cPaintsReady = 0;
return FALSE;
}

View file

@ -333,6 +333,8 @@ NtUserCallOneParam(
_SEH2_END;
RETURN(Ret);
}
case ONEPARAM_ROUTINE_REPLYMESSAGE:
RETURN (co_MsqReplyMessage((LRESULT) Param));
}
DPRINT1("Calling invalid routine number 0x%x in NtUserCallOneParam(), Param=0x%x\n",
Routine, Param);

View file

@ -361,7 +361,7 @@ PostTimerMessages(PWND Window)
MsqPostMessage(ThreadQueue, &Msg, FALSE, QS_TIMER);
pTmr->flags &= ~TMRF_READY;
ThreadQueue->WakeMask = ~QS_TIMER;
pti->cTimersReady++;
Hit = TRUE;
break;
}