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

View file

@ -1097,7 +1097,6 @@ WINAPI
InSendMessage(VOID) InSendMessage(VOID)
{ {
PCLIENTTHREADINFO pcti = GetWin32ClientInfo()->pClientThreadInfo; PCLIENTTHREADINFO pcti = GetWin32ClientInfo()->pClientThreadInfo;
// FIXME("ISM %x\n",pcti);
if ( pcti ) if ( pcti )
{ {
if (pcti->CTI_flags & CTI_INSENDMESSAGE) if (pcti->CTI_flags & CTI_INSENDMESSAGE)
@ -1118,7 +1117,6 @@ InSendMessageEx(
LPVOID lpReserved) LPVOID lpReserved)
{ {
PCLIENTTHREADINFO pcti = GetWin32ClientInfo()->pClientThreadInfo; PCLIENTTHREADINFO pcti = GetWin32ClientInfo()->pClientThreadInfo;
// FIXME("ISMEX %x\n",pcti);
if (pcti && !(pcti->CTI_flags & CTI_INSENDMESSAGE)) if (pcti && !(pcti->CTI_flags & CTI_INSENDMESSAGE))
return ISMEX_NOSEND; return ISMEX_NOSEND;
else else
@ -1442,6 +1440,12 @@ IntCallMessageProc(IN PWND Wnd, IN HWND hWnd, IN UINT Msg, IN WPARAM wParam, IN
Class = DesktopPtrToUser(Wnd->pcls); Class = DesktopPtrToUser(Wnd->pcls);
WndProc = NULL; 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, This is the message exchange for user32. If there's a need to monitor messages,
do it here! do it here!
@ -1586,11 +1590,16 @@ DispatchMessageA(CONST MSG *lpmsg)
MSG UnicodeMsg; MSG UnicodeMsg;
PWND Wnd; PWND Wnd;
if ( lpmsg->message & ~WM_MAXIMUM )
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
if (lpmsg->hwnd != NULL) if (lpmsg->hwnd != NULL)
{ {
Wnd = ValidateHwnd(lpmsg->hwnd); Wnd = ValidateHwnd(lpmsg->hwnd);
if (!Wnd || Wnd->head.pti != GetW32ThreadInfo()) if (!Wnd) return 0;
return 0;
} }
else else
Wnd = NULL; Wnd = NULL;
@ -1602,7 +1611,7 @@ DispatchMessageA(CONST MSG *lpmsg)
if ( lpmsg->message == WM_SYSTIMER ) if ( lpmsg->message == WM_SYSTIMER )
return NtUserDispatchMessage( (PMSG)lpmsg ); return NtUserDispatchMessage( (PMSG)lpmsg );
_SEH2_TRY // wine does this. _SEH2_TRY // wine does this. Hint: Prevents call to another thread....
{ {
Ret = WndProc(lpmsg->hwnd, Ret = WndProc(lpmsg->hwnd,
lpmsg->message, lpmsg->message,
@ -1613,7 +1622,6 @@ DispatchMessageA(CONST MSG *lpmsg)
{ {
} }
_SEH2_END; _SEH2_END;
} }
else if (Wnd != NULL) else if (Wnd != NULL)
{ {
@ -1654,11 +1662,16 @@ DispatchMessageW(CONST MSG *lpmsg)
LRESULT Ret = 0; LRESULT Ret = 0;
PWND Wnd; PWND Wnd;
if ( lpmsg->message & ~WM_MAXIMUM )
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
if (lpmsg->hwnd != NULL) if (lpmsg->hwnd != NULL)
{ {
Wnd = ValidateHwnd(lpmsg->hwnd); Wnd = ValidateHwnd(lpmsg->hwnd);
if (!Wnd || Wnd->head.pti != GetW32ThreadInfo()) if (!Wnd) return 0;
return 0;
} }
else else
Wnd = NULL; Wnd = NULL;
@ -1795,6 +1808,42 @@ GetMessageW(LPMSG lpMsg,
return Res; 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 * @implemented
@ -1812,7 +1861,7 @@ PeekMessageA(LPMSG lpMsg,
PUSER32_THREAD_DATA ThreadData = User32GetThreadData(); PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
MsgConversionCleanup(lpMsg, TRUE, FALSE, NULL); MsgConversionCleanup(lpMsg, TRUE, FALSE, NULL);
Res = NtUserPeekMessage(&Info, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); Res = PeekMessageWorker(&Info, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
if (-1 == (int) Res || !Res) if (-1 == (int) Res || !Res)
{ {
return FALSE; return FALSE;
@ -1865,7 +1914,7 @@ PeekMessageW(
PUSER32_THREAD_DATA ThreadData = User32GetThreadData(); PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
MsgConversionCleanup(lpMsg, FALSE, FALSE, NULL); MsgConversionCleanup(lpMsg, FALSE, FALSE, NULL);
Res = NtUserPeekMessage(&Info, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); Res = PeekMessageWorker(&Info, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
if (-1 == (int) Res || !Res) if (-1 == (int) Res || !Res)
{ {
return FALSE; return FALSE;
@ -2567,7 +2616,8 @@ DWORD
WINAPI WINAPI
RealGetQueueStatus(UINT flags) 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 ); SetLastError( ERROR_INVALID_FLAGS );
return 0; return 0;
@ -2802,6 +2852,8 @@ RealMsgWaitForMultipleObjectsEx(
LPHANDLE RealHandles; LPHANDLE RealHandles;
HANDLE MessageQueueHandle; HANDLE MessageQueueHandle;
DWORD Result; DWORD Result;
PCLIENTINFO pci;
PCLIENTTHREADINFO pcti;
if (dwFlags & ~(MWMO_WAITALL | MWMO_ALERTABLE | MWMO_INPUTAVAILABLE)) if (dwFlags & ~(MWMO_WAITALL | MWMO_ALERTABLE | MWMO_INPUTAVAILABLE))
{ {
@ -2809,14 +2861,21 @@ RealMsgWaitForMultipleObjectsEx(
return WAIT_FAILED; return WAIT_FAILED;
} }
/* pci = GetWin32ClientInfo();
if (dwFlags & MWMO_INPUTAVAILABLE) if (!pci) return WAIT_FAILED;
{
RealGetQueueStatus(dwWakeMask);
}
*/
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) if (MessageQueueHandle == NULL)
{ {
SetLastError(0); /* ? */ SetLastError(0); /* ? */
@ -2840,7 +2899,7 @@ RealMsgWaitForMultipleObjectsEx(
HeapFree(GetProcessHeap(), 0, RealHandles); HeapFree(GetProcessHeap(), 0, RealHandles);
NtUserMsqClearWakeMask(); NtUserMsqClearWakeMask();
//FIXME("Result 0X%x\n",Result);
return Result; return Result;
} }

View file

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

View file

@ -8,10 +8,23 @@
#define MSQ_ISEVENT 2 #define MSQ_ISEVENT 2
#define MSQ_SENTNOWAIT 0x80000000 #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 typedef struct _USER_MESSAGE
{ {
LIST_ENTRY ListEntry; LIST_ENTRY ListEntry;
MSG Msg; MSG Msg;
DWORD QS_Flags;
} USER_MESSAGE, *PUSER_MESSAGE; } USER_MESSAGE, *PUSER_MESSAGE;
struct _USER_MESSAGE_QUEUE; struct _USER_MESSAGE_QUEUE;
@ -20,8 +33,10 @@ typedef struct _USER_SENT_MESSAGE
{ {
LIST_ENTRY ListEntry; LIST_ENTRY ListEntry;
MSG Msg; MSG Msg;
DWORD QS_Flags; // Original QS bits used to create this message.
PKEVENT CompletionEvent; PKEVENT CompletionEvent;
LRESULT* Result; LRESULT* Result;
LRESULT lResult;
struct _USER_MESSAGE_QUEUE* SenderQueue; struct _USER_MESSAGE_QUEUE* SenderQueue;
SENDASYNCPROC CompletionCallback; SENDASYNCPROC CompletionCallback;
ULONG_PTR CompletionCallbackContext; ULONG_PTR CompletionCallbackContext;
@ -31,16 +46,6 @@ typedef struct _USER_SENT_MESSAGE
BOOL HasPackedLParam; BOOL HasPackedLParam;
} USER_SENT_MESSAGE, *PUSER_SENT_MESSAGE; } 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 typedef struct _USER_MESSAGE_QUEUE
{ {
/* Reference counter, only access this variable with interlocked functions! */ /* Reference counter, only access this variable with interlocked functions! */
@ -52,8 +57,6 @@ typedef struct _USER_MESSAGE_QUEUE
LIST_ENTRY SentMessagesListHead; LIST_ENTRY SentMessagesListHead;
/* Queue of messages posted to the queue. */ /* Queue of messages posted to the queue. */
LIST_ENTRY PostedMessagesListHead; LIST_ENTRY PostedMessagesListHead;
/* Queue of sent-message notifies for the queue. */
LIST_ENTRY NotifyMessagesListHead;
/* Queue for hardware messages for the queue. */ /* Queue for hardware messages for the queue. */
LIST_ENTRY HardwareMessagesListHead; LIST_ENTRY HardwareMessagesListHead;
/* Lock for the hardware message list. */ /* Lock for the hardware message list. */
@ -76,8 +79,6 @@ typedef struct _USER_MESSAGE_QUEUE
ULONG LastMsgRead; ULONG LastMsgRead;
/* Current window with focus (ie. receives keyboard input) for this queue. */ /* Current window with focus (ie. receives keyboard input) for this queue. */
HWND FocusWindow; HWND FocusWindow;
/* Count of paints pending. */
ULONG PaintCount;
/* Current active window for this queue. */ /* Current active window for this queue. */
HWND ActiveWindow; HWND ActiveWindow;
/* Current capture window for this queue. */ /* Current capture window for this queue. */
@ -92,9 +93,11 @@ typedef struct _USER_MESSAGE_QUEUE
PTHRDCARETINFO CaretInfo; PTHRDCARETINFO CaretInfo;
/* queue state tracking */ /* queue state tracking */
WORD WakeMask; // Send list QS_SENDMESSAGE
WORD QueueBits; // Post list QS_POSTMESSAGE|QS_HOTKEY|QS_PAINT|QS_TIMER|QS_KEY
WORD ChangedBits; // 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 */ /* extra message information */
LPARAM ExtraInfo; LPARAM ExtraInfo;
@ -130,6 +133,7 @@ MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
IN PWND Window, IN PWND Window,
IN UINT MsgFilterLow, IN UINT MsgFilterLow,
IN UINT MsgFilterHigh, IN UINT MsgFilterHigh,
IN UINT QSflags,
OUT PMSG Message); OUT PMSG Message);
BOOL APIENTRY BOOL APIENTRY
co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
@ -137,6 +141,7 @@ co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
IN PWND Window, IN PWND Window,
IN UINT MsgFilterLow, IN UINT MsgFilterLow,
IN UINT MsgFilterHigh, IN UINT MsgFilterHigh,
IN UINT QSflags,
OUT MSG* pMsg); OUT MSG* pMsg);
BOOL APIENTRY BOOL APIENTRY
co_MsqPeekMouseMove(IN PUSER_MESSAGE_QUEUE MessageQueue, 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 BOOL MsqIsSignaled( PUSER_MESSAGE_QUEUE queue );
__inline VOID MsqSetQueueBits( PUSER_MESSAGE_QUEUE queue, WORD bits ); __inline VOID MsqSetQueueBits( PUSER_MESSAGE_QUEUE queue, WORD bits );
__inline VOID MsqClearQueueBits( PUSER_MESSAGE_QUEUE queue, WORD bits );
BOOL APIENTRY IntInitMessagePumpHook(); BOOL APIENTRY IntInitMessagePumpHook();
BOOL APIENTRY IntUninitMessagePumpHook(); BOOL APIENTRY IntUninitMessagePumpHook();
#define MAKE_LONG(x, y) ((((y) & 0xFFFF) << 16) | ((x) & 0xFFFF)) #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 IdlePing(VOID);
VOID FASTCALL IdlePong(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 */ /* EOF */

View file

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

View file

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

View file

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

View file

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

View file

@ -2,7 +2,7 @@
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* PURPOSE: Messages * PURPOSE: Messages
* FILE: subsys/win32k/ntuser/message.c * FILE: subsystems/win32/win32k/ntuser/message.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISION HISTORY: * REVISION HISTORY:
* 06-06-2001 CSH Created * 06-06-2001 CSH Created
@ -342,7 +342,11 @@ IdlePing(VOID)
pti = PsGetCurrentThreadWin32Thread(); pti = PsGetCurrentThreadWin32Thread();
if ( pti && pti->pDeskInfo && pti == ptiForeground ) if ( pti )
{
pti->pClientInfo->cSpins = 0; // Reset spins.
if ( pti->pDeskInfo && pti == ptiForeground )
{ {
if ( pti->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) || if ( pti->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) ||
pti->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) ) pti->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) )
@ -350,6 +354,7 @@ IdlePing(VOID)
co_HOOK_CallHooks(WH_FOREGROUNDIDLE,HC_ACTION,0,0); co_HOOK_CallHooks(WH_FOREGROUNDIDLE,HC_ACTION,0,0);
} }
} }
}
DPRINT("IdlePing ppi 0x%x\n",ppi); DPRINT("IdlePing ppi 0x%x\n",ppi);
if ( ppi && ppi->InputIdleEvent ) if ( ppi && ppi->InputIdleEvent )
@ -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 static VOID FASTCALL
IntCallWndProc( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) IntCallWndProc( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{ {
@ -424,6 +448,12 @@ IntDispatchMessage(PMSG pMsg)
pti = PsGetCurrentThreadWin32Thread(); pti = PsGetCurrentThreadWin32Thread();
if ( Window->head.pti != pti)
{
SetLastWin32Error( ERROR_MESSAGE_SYNC_ONLY );
return 0;
}
if (((pMsg->message == WM_SYSTIMER) || if (((pMsg->message == WM_SYSTIMER) ||
(pMsg->message == WM_TIMER)) && (pMsg->message == WM_TIMER)) &&
(pMsg->lParam) ) (pMsg->lParam) )
@ -510,17 +540,27 @@ co_IntPeekMessage( PMSG Msg,
PWND Window, PWND Window,
UINT MsgFilterMin, UINT MsgFilterMin,
UINT MsgFilterMax, UINT MsgFilterMax,
UINT RemoveMsg ) UINT RemoveMsg,
BOOL bGMSG )
{ {
PTHREADINFO pti; PTHREADINFO pti;
PCLIENTINFO pci;
LARGE_INTEGER LargeTickCount; LARGE_INTEGER LargeTickCount;
PUSER_MESSAGE_QUEUE ThreadQueue; PUSER_MESSAGE_QUEUE ThreadQueue;
BOOL RemoveMessages; BOOL RemoveMessages;
UINT ProcessMask;
BOOL Hit = FALSE;
pti = PsGetCurrentThreadWin32Thread(); pti = PsGetCurrentThreadWin32Thread();
ThreadQueue = pti->MessageQueue; ThreadQueue = pti->MessageQueue;
pci = pti->pClientInfo;
RemoveMessages = RemoveMsg & PM_REMOVE; 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(); IdlePong();
@ -528,12 +568,45 @@ co_IntPeekMessage( PMSG Msg,
{ {
KeQueryTickCount(&LargeTickCount); KeQueryTickCount(&LargeTickCount);
ThreadQueue->LastMsgRead = LargeTickCount.u.LowPart; ThreadQueue->LastMsgRead = LargeTickCount.u.LowPart;
pti->pcti->tickLastMsgChecked = LargeTickCount.u.LowPart;
/* Dispatch sent messages here. */ /* 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. */ /* Now look for a quit message. */
if (ThreadQueue->QuitPosted) if (ThreadQueue->QuitPosted)
{ {
/* According to the PSDK, WM_QUIT messages are always returned, regardless /* According to the PSDK, WM_QUIT messages are always returned, regardless
@ -545,24 +618,16 @@ co_IntPeekMessage( PMSG Msg,
if (RemoveMessages) if (RemoveMessages)
{ {
ThreadQueue->QuitPosted = FALSE; 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; return TRUE;
} }
/* Check for hardware events. */ /* Check for hardware events. */
if(co_MsqPeekMouseMove(ThreadQueue, if ((ProcessMask & QS_MOUSE) &&
co_MsqPeekMouseMove( ThreadQueue,
RemoveMessages, RemoveMessages,
Window, Window,
MsgFilterMin, MsgFilterMin,
@ -572,11 +637,13 @@ co_IntPeekMessage( PMSG Msg,
return TRUE; return TRUE;
} }
if(co_MsqPeekHardwareMessage(ThreadQueue, if ((ProcessMask & QS_INPUT) &&
co_MsqPeekHardwareMessage( ThreadQueue,
RemoveMessages, RemoveMessages,
Window, Window,
MsgFilterMin, MsgFilterMin,
MsgFilterMax, MsgFilterMax,
ProcessMask,
Msg)) Msg))
{ {
return TRUE; return TRUE;
@ -584,10 +651,15 @@ co_IntPeekMessage( PMSG Msg,
/* Check for sent messages again. */ /* 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. */ /* Check for paint messages. */
if( IntGetPaintMessage( Window, if ((ProcessMask & QS_PAINT) &&
pti->cPaintsReady &&
IntGetPaintMessage( Window,
MsgFilterMin, MsgFilterMin,
MsgFilterMax, MsgFilterMax,
pti, pti,
@ -597,7 +669,11 @@ co_IntPeekMessage( PMSG Msg,
return TRUE; 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; continue;
} }
@ -718,11 +794,12 @@ co_IntWaitMessage( PWND Window,
do do
{ {
if ( co_IntPeekMessage( &Msg, if ( co_IntPeekMessage( &Msg, // Dont reenter!
Window, Window,
MsgFilterMin, MsgFilterMin,
MsgFilterMax, MsgFilterMax,
PM_NOREMOVE)) MAKELONG( PM_NOREMOVE, GetWakeMask( MsgFilterMin, MsgFilterMax)),
TRUE ) ) // act like GetMessage.
{ {
return TRUE; return TRUE;
} }
@ -754,6 +831,7 @@ co_IntGetPeekMessage( PMSG pMsg,
BOOL bGMSG ) BOOL bGMSG )
{ {
PWND Window; PWND Window;
PTHREADINFO pti;
BOOL Present = FALSE; BOOL Present = FALSE;
if ( hWnd == HWND_TOPMOST || hWnd == HWND_BROADCAST ) if ( hWnd == HWND_TOPMOST || hWnd == HWND_BROADCAST )
@ -781,13 +859,19 @@ co_IntGetPeekMessage( PMSG pMsg,
MsgFilterMax = 0; MsgFilterMax = 0;
} }
if (bGMSG)
{
RemoveMsg |= ((GetWakeMask( MsgFilterMin, MsgFilterMax ))<< 16);
}
do do
{ {
Present = co_IntPeekMessage( pMsg, Present = co_IntPeekMessage( pMsg,
Window, Window,
MsgFilterMin, MsgFilterMin,
MsgFilterMax, MsgFilterMax,
RemoveMsg ); RemoveMsg,
bGMSG );
if (Present) if (Present)
{ {
// The WH_GETMESSAGE hook enables an application to monitor messages about to // 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); co_HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, RemoveMsg & PM_REMOVE, (LPARAM)pMsg);
if ( bGMSG ) if ( bGMSG )
return (WM_QUIT != pMsg->message); {
Present = (WM_QUIT != pMsg->message);
break;
}
} }
if ( bGMSG ) if ( bGMSG )
{ {
if ( !co_IntWaitMessage(Window, MsgFilterMin, MsgFilterMax) ) if ( !co_IntWaitMessage(Window, MsgFilterMin, MsgFilterMax) )
return -1; {
Present = -1;
break;
}
} }
else else
{ {
@ -821,6 +911,14 @@ co_IntGetPeekMessage( PMSG pMsg,
} }
while( bGMSG && !Present ); 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; return Present;
} }
@ -1283,7 +1381,9 @@ co_IntSendMessageWithCallBack( HWND hWnd,
Message->Msg.lParam = lParamPacked; Message->Msg.lParam = lParamPacked;
Message->CompletionEvent = NULL; Message->CompletionEvent = NULL;
Message->Result = 0; 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); IntReferenceMessageQueue(Window->head.pti->MessageQueue);
Message->CompletionCallback = CompletionCallback; Message->CompletionCallback = CompletionCallback;
@ -1291,6 +1391,9 @@ co_IntSendMessageWithCallBack( HWND hWnd,
Message->HookMessage = MSQ_NORMAL | MSQ_SENTNOWAIT; Message->HookMessage = MSQ_NORMAL | MSQ_SENTNOWAIT;
Message->HasPackedLParam = (lParamBufferSize > 0); 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); InsertTailList(&Window->head.pti->MessageQueue->SentMessagesListHead, &Message->ListEntry);
IntDereferenceMessageQueue(Window->head.pti->MessageQueue); IntDereferenceMessageQueue(Window->head.pti->MessageQueue);
@ -1468,7 +1571,7 @@ UserSendNotifyMessage( HWND hWnd,
WPARAM wParam, WPARAM wParam,
LPARAM lParam ) LPARAM lParam )
{ {
BOOL Result = TRUE; BOOL Ret = TRUE;
if (FindMsgMemory(Msg) != 0) if (FindMsgMemory(Msg) != 0)
{ {
@ -1491,37 +1594,28 @@ UserSendNotifyMessage( HWND hWnd,
UserSendNotifyMessage(DesktopWindow->head.h, Msg, wParam, lParam); UserSendNotifyMessage(DesktopWindow->head.h, Msg, wParam, lParam);
for (i = 0; List[i]; i++) 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); ExFreePool(List);
} }
} }
else else
{ {
ULONG_PTR PResult; ULONG_PTR lResult = 0;
PTHREADINFO pti; Ret = co_IntSendMessageWithCallBack( hWnd,
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, Msg,
wParam, wParam,
lParam, lParam,
SMTO_NORMAL, NULL,
0, 0,
&PResult ); &lResult);
} }
} return Ret;
return Result;
} }
@ -1537,15 +1631,13 @@ IntGetQueueStatus(DWORD Changes)
// wine: // wine:
Changes &= (QS_ALLINPUT|QS_ALLPOSTMESSAGE|QS_SMRESULT); 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; pti->pcti->fsChangeBits &= ~Changes;
}
Queue->ChangedBits &= ~Changes;
return Result; return Result;
} }
@ -1684,9 +1776,9 @@ NtUserWaitMessage(VOID)
BOOL ret; BOOL ret;
UserEnterExclusive(); UserEnterExclusive();
DPRINT("NtUserWaitMessage Enter\n");
ret = co_IntWaitMessage(NULL, 0, 0); ret = co_IntWaitMessage(NULL, 0, 0);
DPRINT("NtUserWaitMessage Leave\n");
UserLeave(); UserLeave();
return ret; return ret;
@ -2338,6 +2430,13 @@ NtUserWaitForInputIdle( IN HANDLE hProcess,
if (dwMilliseconds != INFINITE) if (dwMilliseconds != INFINITE)
Timeout.QuadPart = (LONGLONG) dwMilliseconds * (LONGLONG) -10000; 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: ppi 0x%x\n",W32Process);
DPRINT("WFII: waiting for %p\n", Handles[1] ); DPRINT("WFII: waiting for %p\n", Handles[1] );
do do
@ -2368,7 +2467,7 @@ NtUserWaitForInputIdle( IN HANDLE hProcess,
case STATUS_WAIT_2: case STATUS_WAIT_2:
{ {
MSG Msg; 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"); DPRINT1("WFII: WAIT 2\n");
} }
break; break;
@ -2387,6 +2486,12 @@ NtUserWaitForInputIdle( IN HANDLE hProcess,
while (TRUE); while (TRUE);
WaitExit: 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); ObDereferenceObject(Process);
UserLeave(); UserLeave();
return Status; return Status;

View file

@ -2,7 +2,7 @@
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* PURPOSE: Misc User funcs * 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) * PROGRAMER: Ge van Geldorp (ge@gse.nl)
* REVISION HISTORY: * REVISION HISTORY:
* 2003/05/22 Created * 2003/05/22 Created
@ -102,6 +102,8 @@ NtUserGetThreadState(
break; break;
case THREADSTATE_INSENDMESSAGE: case THREADSTATE_INSENDMESSAGE:
{ {
PUSER_SENT_MESSAGE Message;
PLIST_ENTRY Entry;
PUSER_MESSAGE_QUEUE MessageQueue = PUSER_MESSAGE_QUEUE MessageQueue =
((PTHREADINFO)PsGetCurrentThreadWin32Thread())->MessageQueue; ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->MessageQueue;
DPRINT1("THREADSTATE_INSENDMESSAGE\n"); DPRINT1("THREADSTATE_INSENDMESSAGE\n");
@ -109,21 +111,39 @@ NtUserGetThreadState(
ret = ISMEX_NOSEND; ret = ISMEX_NOSEND;
if (!IsListEmpty(&MessageQueue->SentMessagesListHead)) if (!IsListEmpty(&MessageQueue->SentMessagesListHead))
{ {
Entry = MessageQueue->SentMessagesListHead.Flink;
Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
if (Message->SenderQueue)
ret = ISMEX_SEND; ret = ISMEX_SEND;
} else
else if (!IsListEmpty(&MessageQueue->NotifyMessagesListHead))
{ {
/* FIXME Need to set message flag when in callback mode with notify */ if (Message->CompletionCallback)
ret = ISMEX_CALLBACK;
else
ret = ISMEX_NOTIFY; ret = ISMEX_NOTIFY;
} }
/* FIXME Need to set message flag if replied to or ReplyMessage */ /* if ReplyMessage */
if (Message->QS_Flags & QS_SMRESULT) ret |= ISMEX_REPLIED;
}
break; break;
} }
case THREADSTATE_GETMESSAGETIME: case THREADSTATE_GETMESSAGETIME:
/* FIXME Needs more work! */
ret = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->timeLast; ret = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->timeLast;
break; 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: case THREADSTATE_GETINPUTSTATE:
ret = LOWORD(IntGetQueueStatus(QS_POSTMESSAGE|QS_TIMER|QS_PAINT|QS_SENDMESSAGE|QS_INPUT)) & (QS_KEY | QS_MOUSEBUTTON); ret = LOWORD(IntGetQueueStatus(QS_POSTMESSAGE|QS_TIMER|QS_PAINT|QS_SENDMESSAGE|QS_INPUT)) & (QS_KEY | QS_MOUSEBUTTON);
break; 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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -41,74 +23,6 @@ static PAGED_LOOKASIDE_LIST MessageLookasideList;
/* FUNCTIONS *****************************************************************/ /* 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 INIT_FUNCTION
NTSTATUS NTSTATUS
NTAPI NTAPI
@ -125,12 +39,153 @@ MsqInitializeImpl(VOID)
return(STATUS_SUCCESS); 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 VOID FASTCALL
MsqPostMouseMove(PUSER_MESSAGE_QUEUE MessageQueue, MSG* Msg) MsqPostMouseMove(PUSER_MESSAGE_QUEUE MessageQueue, MSG* Msg)
{ {
MessageQueue->MouseMoveMsg = *Msg; MessageQueue->MouseMoveMsg = *Msg;
MessageQueue->MouseMoved = TRUE; MessageQueue->MouseMoved = TRUE;
MsqWakeQueue(MessageQueue, QS_MOUSEMOVE); MsqWakeQueue(MessageQueue, QS_MOUSEMOVE, TRUE);
} }
VOID FASTCALL VOID FASTCALL
@ -366,6 +421,7 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
PUSER_SENT_MESSAGE Message; PUSER_SENT_MESSAGE Message;
PLIST_ENTRY Entry; PLIST_ENTRY Entry;
LRESULT Result; LRESULT Result;
PTHREADINFO pti;
if (IsListEmpty(&MessageQueue->SentMessagesListHead)) if (IsListEmpty(&MessageQueue->SentMessagesListHead))
{ {
@ -376,11 +432,20 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
Entry = RemoveHeadList(&MessageQueue->SentMessagesListHead); Entry = RemoveHeadList(&MessageQueue->SentMessagesListHead);
Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry); 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 /* insert it to the list of messages that are currently dispatched by this
message queue */ message queue */
InsertTailList(&MessageQueue->LocalDispatchingMessagesHead, InsertTailList(&MessageQueue->LocalDispatchingMessagesHead,
&Message->ListEntry); &Message->ListEntry);
ClearMsgBitsMask(MessageQueue, Message->QS_Flags);
if (Message->HookMessage == MSQ_ISHOOK) if (Message->HookMessage == MSQ_ISHOOK)
{ // Direct Hook Call processor { // Direct Hook Call processor
Result = co_CallHook( Message->Msg.message, // HookId 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 /* still keep the sender's message queue locked, so the sender can't exit the
MsqSendMessage() function (if timed out) */ MsqSendMessage() function (if timed out) */
if (Message->QS_Flags & QS_SMRESULT)
{
Result = Message->lResult;
}
/* Let the sender know the result. */ /* Let the sender know the result. */
if (Message->Result != NULL) if (Message->Result != NULL)
{ {
@ -456,6 +526,9 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
/* free the message */ /* free the message */
ExFreePoolWithTag(Message, TAG_USRMSG); ExFreePoolWithTag(Message, TAG_USRMSG);
pti->pcti->CTI_flags &= ~CTI_INSENDMESSAGE;
return(TRUE); return(TRUE);
} }
@ -483,6 +556,7 @@ MsqRemoveWindowMessagesFromQueue(PVOID pWindow)
if (PostedMessage->Msg.hwnd == Window->head.h) if (PostedMessage->Msg.hwnd == Window->head.h)
{ {
RemoveEntryList(&PostedMessage->ListEntry); RemoveEntryList(&PostedMessage->ListEntry);
ClearMsgBitsMask(MessageQueue, PostedMessage->QS_Flags);
MsqDestroyMessage(PostedMessage); MsqDestroyMessage(PostedMessage);
CurrentEntry = MessageQueue->PostedMessagesListHead.Flink; 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"); DPRINT("Notify the sender and remove a message from the queue that had not been dispatched\n");
RemoveEntryList(&SentMessage->ListEntry); RemoveEntryList(&SentMessage->ListEntry);
ClearMsgBitsMask(MessageQueue, SentMessage->QS_Flags);
/* remove the message from the dispatching list if neede */ /* remove the message from the dispatching list if neede */
if ((!(SentMessage->HookMessage & MSQ_SENTNOWAIT)) if ((!(SentMessage->HookMessage & MSQ_SENTNOWAIT))
@ -581,6 +656,8 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
Message->Msg.lParam = lParam; Message->Msg.lParam = lParam;
Message->CompletionEvent = &CompletionEvent; Message->CompletionEvent = &CompletionEvent;
Message->Result = &Result; Message->Result = &Result;
Message->lResult = 0;
Message->QS_Flags = 0;
Message->SenderQueue = ThreadQueue; Message->SenderQueue = ThreadQueue;
IntReferenceMessageQueue(ThreadQueue); IntReferenceMessageQueue(ThreadQueue);
Message->CompletionCallback = NULL; Message->CompletionCallback = NULL;
@ -596,7 +673,8 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
/* queue it in the destination's message queue */ /* queue it in the destination's message queue */
InsertTailList(&MessageQueue->SentMessagesListHead, &Message->ListEntry); 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! */ /* 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, InsertTailList(&MessageQueue->HardwareMessagesListHead,
&Message->ListEntry); &Message->ListEntry);
} }
MsqWakeQueue(MessageQueue, MessageBits);
Message->QS_Flags = MessageBits;
MsqWakeQueue(MessageQueue, MessageBits, (MessageBits & QS_TIMER ? FALSE : TRUE));
} }
VOID FASTCALL VOID FASTCALL
@ -754,7 +834,7 @@ MsqPostQuitMessage(PUSER_MESSAGE_QUEUE MessageQueue, ULONG ExitCode)
{ {
MessageQueue->QuitPosted = TRUE; MessageQueue->QuitPosted = TRUE;
MessageQueue->QuitExitCode = ExitCode; 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; *pMsg = msg;
if(Remove) if(Remove)
{
ClearMsgBitsMask(MessageQueue, QS_MOUSEMOVE);
MessageQueue->MouseMoved = FALSE; MessageQueue->MouseMoved = FALSE;
}
return AcceptMessage; 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 BOOL APIENTRY
co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
IN BOOL Remove, IN BOOL Remove,
IN PWND Window, IN PWND Window,
IN UINT MsgFilterLow, IN UINT MsgFilterLow,
IN UINT MsgFilterHigh, IN UINT MsgFilterHigh,
IN UINT QSflags,
OUT MSG* pMsg) OUT MSG* pMsg)
{ {
@ -1141,23 +1242,32 @@ co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
PLIST_ENTRY ListHead, CurrentEntry = NULL; PLIST_ENTRY ListHead, CurrentEntry = NULL;
MSG msg; MSG msg;
if (!filter_contains_hw_range( MsgFilterLow, MsgFilterHigh )) return FALSE;
ListHead = &MessageQueue->HardwareMessagesListHead; ListHead = &MessageQueue->HardwareMessagesListHead;
CurrentEntry = ListHead->Flink; CurrentEntry = ListHead->Flink;
while(CurrentEntry != ListHead) if (IsListEmpty(CurrentEntry)) return FALSE;
{
CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
ListEntry); ListEntry);
do
{
if (IsListEmpty(CurrentEntry)) break;
if (!CurrentMessage) break;
CurrentEntry = CurrentMessage->ListEntry.Flink;
if ( (( MsgFilterLow == 0 && MsgFilterHigh == 0 ) && (CurrentMessage->QS_Flags & QSflags)) ||
( MsgFilterLow <= CurrentMessage->Msg.message && MsgFilterHigh >= CurrentMessage->Msg.message ) )
{
msg = CurrentMessage->Msg; msg = CurrentMessage->Msg;
AcceptMessage = co_IntProcessHardwareMessage(&msg, &Remove, MsgFilterLow, MsgFilterHigh); AcceptMessage = co_IntProcessHardwareMessage(&msg, &Remove, MsgFilterLow, MsgFilterHigh);
CurrentEntry = CurrentMessage->ListEntry.Flink;
if (Remove) if (Remove)
{ {
RemoveEntryList(&CurrentMessage->ListEntry); RemoveEntryList(&CurrentMessage->ListEntry);
ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags);
MsqDestroyMessage(CurrentMessage); MsqDestroyMessage(CurrentMessage);
} }
@ -1166,8 +1276,11 @@ co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
*pMsg = msg; *pMsg = msg;
return TRUE; return TRUE;
} }
} }
CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
ListEntry);
}
while(CurrentEntry != ListHead);
return FALSE; return FALSE;
} }
@ -1178,6 +1291,7 @@ MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
IN PWND Window, IN PWND Window,
IN UINT MsgFilterLow, IN UINT MsgFilterLow,
IN UINT MsgFilterHigh, IN UINT MsgFilterHigh,
IN UINT QSflags,
OUT PMSG Message) OUT PMSG Message)
{ {
PLIST_ENTRY CurrentEntry; PLIST_ENTRY CurrentEntry;
@ -1186,29 +1300,35 @@ MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
CurrentEntry = MessageQueue->PostedMessagesListHead.Flink; CurrentEntry = MessageQueue->PostedMessagesListHead.Flink;
ListHead = &MessageQueue->PostedMessagesListHead; ListHead = &MessageQueue->PostedMessagesListHead;
while (CurrentEntry != ListHead)
{ if (IsListEmpty(CurrentEntry)) return FALSE;
CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
ListEntry); ListEntry);
if ( ( !Window || do
PtrToInt(Window) == 1 || {
Window->head.h == CurrentMessage->Msg.hwnd ) && if (IsListEmpty(CurrentEntry)) break;
( (MsgFilterLow == 0 && MsgFilterHigh == 0) || if (!CurrentMessage) break;
( MsgFilterLow <= CurrentMessage->Msg.message && CurrentEntry = CurrentEntry->Flink;
MsgFilterHigh >= CurrentMessage->Msg.message ) ) )
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) if (Remove)
{ {
RemoveEntryList(&CurrentMessage->ListEntry); RemoveEntryList(&CurrentMessage->ListEntry);
ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags);
MsqDestroyMessage(CurrentMessage); MsqDestroyMessage(CurrentMessage);
} }
return(TRUE); return(TRUE);
} }
CurrentEntry = CurrentEntry->Flink; CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
ListEntry);
} }
while (CurrentEntry != ListHead);
return(FALSE); return(FALSE);
} }
@ -1257,9 +1377,6 @@ MsqInitializeMessageQueue(struct _ETHREAD *Thread, PUSER_MESSAGE_QUEUE MessageQu
KeQueryTickCount(&LargeTickCount); KeQueryTickCount(&LargeTickCount);
MessageQueue->LastMsgRead = LargeTickCount.u.LowPart; MessageQueue->LastMsgRead = LargeTickCount.u.LowPart;
MessageQueue->FocusWindow = NULL; 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; MessageQueue->NewMessagesHandle = NULL;
Status = ZwCreateEvent(&MessageQueue->NewMessagesHandle, EVENT_ALL_ACCESS, Status = ZwCreateEvent(&MessageQueue->NewMessagesHandle, EVENT_ALL_ACCESS,
@ -1288,6 +1405,10 @@ MsqCleanupMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
PLIST_ENTRY CurrentEntry; PLIST_ENTRY CurrentEntry;
PUSER_MESSAGE CurrentMessage; PUSER_MESSAGE CurrentMessage;
PUSER_SENT_MESSAGE CurrentSentMessage; PUSER_SENT_MESSAGE CurrentSentMessage;
PTHREADINFO pti;
pti = MessageQueue->Thread->Tcb.Win32Thread;
/* cleanup posted messages */ /* cleanup posted messages */
while (!IsListEmpty(&MessageQueue->PostedMessagesListHead)) while (!IsListEmpty(&MessageQueue->PostedMessagesListHead))
@ -1391,6 +1512,16 @@ MsqCleanupMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
locked later */ 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 PUSER_MESSAGE_QUEUE FASTCALL
@ -1475,6 +1606,38 @@ MsqGetMessageExtraInfo(VOID)
return MessageQueue->ExtraInfo; 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 HWND FASTCALL
MsqSetStateWindow(PUSER_MESSAGE_QUEUE MessageQueue, ULONG Type, HWND hWnd) MsqSetStateWindow(PUSER_MESSAGE_QUEUE MessageQueue, ULONG Type, HWND hWnd)
{ {

View file

@ -2,7 +2,7 @@
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* PURPOSE: Window painting function * PURPOSE: Window painting function
* FILE: subsys/win32k/ntuser/painting.c * FILE: subsystems/win32/win32k/ntuser/painting.c
* PROGRAMER: Filip Navara (xnavara@volny.cz) * PROGRAMER: Filip Navara (xnavara@volny.cz)
* REVISION HISTORY: * REVISION HISTORY:
* 06/06/2001 Created (?) * 06/06/2001 Created (?)
@ -660,9 +660,7 @@ IntGetPaintMessage(
MSG *Message, MSG *Message,
BOOL Remove) BOOL Remove)
{ {
PUSER_MESSAGE_QUEUE MessageQueue = (PUSER_MESSAGE_QUEUE)Thread->MessageQueue; if (!Thread->cPaintsReady)
if (!MessageQueue->PaintCount)
return FALSE; return FALSE;
if ((MsgFilterMin != 0 || MsgFilterMax != 0) && if ((MsgFilterMin != 0 || MsgFilterMax != 0) &&
@ -673,9 +671,9 @@ IntGetPaintMessage(
if (Message->hwnd == NULL) 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 ! */ /* Hack to stop spamming the debuglog ! */
MessageQueue->PaintCount = 0; Thread->cPaintsReady = 0;
return FALSE; return FALSE;
} }

View file

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

View file

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