* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
Alexandre Julliard
Maarten Lankhorst
- * REVISION HISTORY:
- * 06-06-2001 CSH Created
*/
-/* INCLUDES ******************************************************************/
-
#include <win32k.h>
-
-#define NDEBUG
-#include <debug.h>
+DBG_DEFAULT_CHANNEL(UserMsgQ);
/* GLOBALS *******************************************************************/
static PAGED_LOOKASIDE_LIST MessageLookasideList;
+MOUSEMOVEPOINT MouseHistoryOfMoves[64];
+INT gcur_count = 0;
/* FUNCTIONS *****************************************************************/
return(STATUS_SUCCESS);
}
+PWND FASTCALL
+IntChildrenWindowFromPoint(PWND pWndTop, INT x, INT y)
+{
+ PWND pWnd, pWndChild;
+
+ if (!(pWndTop->style & WS_VISIBLE)) return NULL;
+ if ((pWndTop->style & WS_DISABLED)) return NULL;
+ if (!IntPtInWindow(pWndTop, x, y)) return NULL;
+
+ if (x - pWndTop->rcClient.left < pWndTop->rcClient.right &&
+ y - pWndTop->rcClient.top < pWndTop->rcClient.bottom )
+ {
+ for (pWnd = pWndTop->spwndChild;
+ pWnd != NULL;
+ pWnd = pWnd->spwndNext)
+ {
+ if (pWnd->state2 & WNDS2_INDESTROY || pWnd->state & WNDS_DESTROYED )
+ {
+ TRACE("The Window is in DESTROY!\n");
+ continue;
+ }
+
+ pWndChild = IntChildrenWindowFromPoint(pWnd, x, y);
+
+ if (pWndChild)
+ {
+ return pWndChild;
+ }
+ }
+ }
+ return pWndTop;
+}
+
+PWND FASTCALL
+IntTopLevelWindowFromPoint(INT x, INT y)
+{
+ PWND pWnd, pwndDesktop;
+
+ /* Get the desktop window */
+ pwndDesktop = UserGetDesktopWindow();
+ if (!pwndDesktop)
+ return NULL;
+
+ /* Loop all top level windows */
+ for (pWnd = pwndDesktop->spwndChild;
+ pWnd != NULL;
+ pWnd = pWnd->spwndNext)
+ {
+ if (pWnd->state2 & WNDS2_INDESTROY || pWnd->state & WNDS_DESTROYED)
+ {
+ TRACE("The Window is in DESTROY!\n");
+ continue;
+ }
+
+ if ((pWnd->style & WS_VISIBLE) && IntPtInWindow(pWnd, x, y))
+ return pWnd;
+ }
+
+ /* Window has not been found */
+ return NULL;
+}
+
+PCURICON_OBJECT
+FASTCALL
+UserSetCursor(
+ PCURICON_OBJECT NewCursor,
+ BOOL ForceChange)
+{
+ PCURICON_OBJECT OldCursor;
+ HDC hdcScreen;
+ PTHREADINFO pti;
+ PUSER_MESSAGE_QUEUE MessageQueue;
+ PWND pWnd;
+
+ pti = PsGetCurrentThreadWin32Thread();
+ MessageQueue = pti->MessageQueue;
+
+ /* Get the screen DC */
+ if(!(hdcScreen = IntGetScreenDC()))
+ {
+ return (HCURSOR)0;
+ }
+
+ OldCursor = MessageQueue->CursorObject;
+
+ /* Check if cursors are different */
+ if (OldCursor == NewCursor)
+ return OldCursor;
+
+ /* Update cursor for this message queue */
+ MessageQueue->CursorObject = NewCursor;
+
+ /* If cursor is not visible we have nothing to do */
+ if (MessageQueue->ShowingCursor < 0)
+ return OldCursor;
+
+ /* Update cursor if this message queue controls it */
+ pWnd = IntTopLevelWindowFromPoint(gpsi->ptCursor.x, gpsi->ptCursor.y);
+ if (pWnd && pWnd->head.pti->MessageQueue == MessageQueue)
+ {
+ if (NewCursor)
+ {
+ /* Call GDI to set the new screen cursor */
+ GreSetPointerShape(hdcScreen,
+ NewCursor->IconInfo.hbmMask,
+ NewCursor->IconInfo.hbmColor,
+ NewCursor->IconInfo.xHotspot,
+ NewCursor->IconInfo.yHotspot,
+ gpsi->ptCursor.x,
+ gpsi->ptCursor.y);
+ }
+ else /* Note: OldCursor != NewCursor so we have to hide cursor */
+ {
+ /* Remove the cursor */
+ GreMovePointer(hdcScreen, -1, -1);
+ TRACE("Removing pointer!\n");
+ }
+ IntGetSysCursorInfo()->CurrentCursorObject = NewCursor;
+ }
+
+ /* Return the old cursor */
+ return OldCursor;
+}
+
+/* Called from NtUserCallOneParam with Routine ONEPARAM_ROUTINE_SHOWCURSOR
+ * User32 macro NtUserShowCursor */
+int UserShowCursor(BOOL bShow)
+{
+ HDC hdcScreen;
+ PTHREADINFO pti;
+ PUSER_MESSAGE_QUEUE MessageQueue;
+ PWND pWnd;
+
+ if (!(hdcScreen = IntGetScreenDC()))
+ {
+ return -1; /* No mouse */
+ }
+
+ pti = PsGetCurrentThreadWin32Thread();
+ MessageQueue = pti->MessageQueue;
+
+ /* Update counter */
+ MessageQueue->ShowingCursor += bShow ? 1 : -1;
+
+ /* Check for trivial cases */
+ if ((bShow && MessageQueue->ShowingCursor != 0) ||
+ (!bShow && MessageQueue->ShowingCursor != -1))
+ {
+ /* Note: w don't update global info here because it is used only
+ internally to check if cursor is visible */
+ return MessageQueue->ShowingCursor;
+ }
+
+ /* Check if cursor is above window owned by this MessageQueue */
+ pWnd = IntTopLevelWindowFromPoint(gpsi->ptCursor.x, gpsi->ptCursor.y);
+ if (pWnd && pWnd->head.pti->MessageQueue == MessageQueue)
+ {
+ if (bShow)
+ {
+ /* Show the pointer */
+ GreMovePointer(hdcScreen, gpsi->ptCursor.x, gpsi->ptCursor.y);
+ TRACE("Showing pointer!\n");
+ }
+ else
+ {
+ /* Remove the pointer */
+ GreMovePointer(hdcScreen, -1, -1);
+ TRACE("Removing pointer!\n");
+ }
+
+ /* Update global info */
+ IntGetSysCursorInfo()->ShowingCursor = MessageQueue->ShowingCursor;
+ }
+
+ return MessageQueue->ShowingCursor;
+}
+
+DWORD FASTCALL UserGetKeyState(DWORD key)
+{
+ DWORD ret = 0;
+ PTHREADINFO pti;
+ PUSER_MESSAGE_QUEUE MessageQueue;
+
+ pti = PsGetCurrentThreadWin32Thread();
+ MessageQueue = pti->MessageQueue;
+
+ if (key < 0x100)
+ {
+ ret = (DWORD)MessageQueue->KeyState[key];
+ if (MessageQueue->KeyState[key] & KS_DOWN_BIT)
+ ret |= 0xFF80; // If down, windows returns 0xFF80.
+ if (MessageQueue->KeyState[key] & KS_LOCK_BIT)
+ ret |= 0x1;
+ }
+ else
+ {
+ EngSetLastError(ERROR_INVALID_PARAMETER);
+ }
+ return ret;
+}
+
+/* change the input key state for a given key */
+static void set_input_key_state( PUSER_MESSAGE_QUEUE MessageQueue, UCHAR key, BOOL down )
+{
+ TRACE("set_input_key_state key:%d, down:%d\n", key, down);
+
+ if (down)
+ {
+ if (!(MessageQueue->KeyState[key] & KS_DOWN_BIT))
+ {
+ MessageQueue->KeyState[key] ^= KS_LOCK_BIT;
+ }
+ MessageQueue->KeyState[key] |= KS_DOWN_BIT;
+ }
+ else
+ {
+ MessageQueue->KeyState[key] &= ~KS_DOWN_BIT;
+ }
+}
+
+/* update the input key state for a keyboard message */
+static void update_input_key_state( PUSER_MESSAGE_QUEUE MessageQueue, MSG* msg )
+{
+ UCHAR key;
+ BOOL down = 0;
+
+ TRACE("update_input_key_state message:%d\n", msg->message);
+
+ switch (msg->message)
+ {
+ case WM_LBUTTONDOWN:
+ down = 1;
+ /* fall through */
+ case WM_LBUTTONUP:
+ set_input_key_state( MessageQueue, VK_LBUTTON, down );
+ break;
+ case WM_MBUTTONDOWN:
+ down = 1;
+ /* fall through */
+ case WM_MBUTTONUP:
+ set_input_key_state( MessageQueue, VK_MBUTTON, down );
+ break;
+ case WM_RBUTTONDOWN:
+ down = 1;
+ /* fall through */
+ case WM_RBUTTONUP:
+ set_input_key_state( MessageQueue, VK_RBUTTON, down );
+ break;
+ case WM_XBUTTONDOWN:
+ down = 1;
+ /* fall through */
+ case WM_XBUTTONUP:
+ if (msg->wParam == XBUTTON1)
+ set_input_key_state( MessageQueue, VK_XBUTTON1, down );
+ else if (msg->wParam == XBUTTON2)
+ set_input_key_state( MessageQueue, VK_XBUTTON2, down );
+ break;
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ down = 1;
+ /* fall through */
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ key = (UCHAR)msg->wParam;
+ set_input_key_state( MessageQueue, key, down );
+ switch(key)
+ {
+ case VK_LCONTROL:
+ case VK_RCONTROL:
+ down = (MessageQueue->KeyState[VK_LCONTROL] | MessageQueue->KeyState[VK_RCONTROL]) & KS_DOWN_BIT;
+ set_input_key_state( MessageQueue, VK_CONTROL, down );
+ break;
+ case VK_LMENU:
+ case VK_RMENU:
+ down = (MessageQueue->KeyState[VK_LMENU] | MessageQueue->KeyState[VK_RMENU]) & KS_DOWN_BIT;
+ set_input_key_state( MessageQueue, VK_MENU, down );
+ break;
+ case VK_LSHIFT:
+ case VK_RSHIFT:
+ down = (MessageQueue->KeyState[VK_LSHIFT] | MessageQueue->KeyState[VK_RSHIFT]) & KS_DOWN_BIT;
+ set_input_key_state( MessageQueue, VK_SHIFT, down );
+ break;
+ }
+ break;
+ }
+}
+
HANDLE FASTCALL
IntMsqSetWakeMask(DWORD WakeMask)
{
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);
+ ERR("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;
}
}
VOID FASTCALL
-co_MsqInsertMouseMessage(MSG* Msg)
+co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook)
{
LARGE_INTEGER LargeTickCount;
MSLLHOOKSTRUCT MouseHookData;
+ PDESKTOP pDesk;
PWND pwnd, pwndDesktop;
+ HDC hdcScreen;
+ PSYSTEM_CURSORINFO CurInfo;
KeQueryTickCount(&LargeTickCount);
Msg->time = MsqCalculateMessageTime(&LargeTickCount);
MouseHookData.pt.x = LOWORD(Msg->lParam);
MouseHookData.pt.y = HIWORD(Msg->lParam);
- switch(Msg->message)
+ switch (Msg->message)
{
case WM_MOUSEWHEEL:
MouseHookData.mouseData = MAKELONG(0, GET_WHEEL_DELTA_WPARAM(Msg->wParam));
break;
}
- MouseHookData.flags = 0;
+ MouseHookData.flags = flags; // LLMHF_INJECTED
MouseHookData.time = Msg->time;
- MouseHookData.dwExtraInfo = 0;
+ MouseHookData.dwExtraInfo = dwExtraInfo;
/* If the hook procedure returned non zero, dont send the message */
- if (co_HOOK_CallHooks(WH_MOUSE_LL, HC_ACTION, Msg->message, (LPARAM) &MouseHookData))
- return;
+ if (Hook)
+ {
+ if (co_HOOK_CallHooks(WH_MOUSE_LL, HC_ACTION, Msg->message, (LPARAM) &MouseHookData))
+ return;
+ }
/* Get the desktop window */
pwndDesktop = UserGetDesktopWindow();
- if(!pwndDesktop)
- return;
+ if (!pwndDesktop) return;
+ pDesk = pwndDesktop->head.rpdesk;
/* Check if the mouse is captured */
Msg->hwnd = IntGetCaptureWindow();
- if(Msg->hwnd != NULL)
+ if (Msg->hwnd != NULL)
{
pwnd = UserGetWindowObject(Msg->hwnd);
}
else
{
- /* Loop all top level windows to find which one should receive input */
- for( pwnd = pwndDesktop->spwndChild;
- pwnd != NULL;
- pwnd = pwnd->spwndNext )
- {
- if((pwnd->style & WS_VISIBLE) &&
- IntPtInWindow(pwnd, Msg->pt.x, Msg->pt.y))
- {
- Msg->hwnd = pwnd->head.h;
- break;
- }
- }
+ pwnd = IntTopLevelWindowFromPoint(Msg->pt.x, Msg->pt.y);
+ if (pwnd) Msg->hwnd = pwnd->head.h;
+ }
+
+ if (pwnd)
+ {
+ /* If we a re tracking the mouse and it moves to another top level window */
+ if(pDesk->spwndTrack &&
+ UserGetAncestor(pDesk->spwndTrack, GA_ROOT) != pwnd)
+ {
+ /* Generate a WM_MOUSELEAVE message */
+ if ( pDesk->dwDTFlags & DF_TME_LEAVE )
+ {
+ MSG msgMouseLeave;
+
+ TRACE("co_MsqInsertMouseMessage: generating WM_MOUSELEAVE\n");
+
+ msgMouseLeave.hwnd = UserHMGetHandle(pDesk->spwndTrack);
+ msgMouseLeave.message = WM_MOUSELEAVE;
+ msgMouseLeave.pt = Msg->pt;
+ msgMouseLeave.time = Msg->time;
+ msgMouseLeave.lParam = msgMouseLeave.wParam = 0;
+
+ MsqPostMessage(pwnd->head.pti->MessageQueue, Msg, TRUE, QS_MOUSE);
+ }
+
+ /* Stop tracking */
+ if ( pDesk->dwDTFlags & DF_TME_HOVER )
+ {
+ IntKillTimer(pDesk->spwndTrack, ID_EVENT_SYSTIMER_MOUSEHOVER, TRUE);
+ }
+
+ pDesk->spwndTrack = NULL;
+ pDesk->htEx = 0;
+ }
}
+ hdcScreen = IntGetScreenDC();
+ CurInfo = IntGetSysCursorInfo();
+
/* Check if we found a window */
- if(Msg->hwnd != NULL && pwnd != NULL)
+ if (Msg->hwnd != NULL && pwnd != NULL)
{
- if(Msg->message == WM_MOUSEMOVE)
+ if (Msg->message == WM_MOUSEMOVE)
{
- /* Mouse move is a special case*/
- MsqPostMouseMove(pwnd->head.pti->MessageQueue, Msg);
+ PUSER_MESSAGE_QUEUE MessageQueue = pwnd->head.pti->MessageQueue;
+
+ /* Check if cursor should be visible */
+ if(hdcScreen &&
+ MessageQueue->CursorObject &&
+ MessageQueue->ShowingCursor >= 0)
+ {
+ /* Check if shape has changed */
+ if(CurInfo->CurrentCursorObject != MessageQueue->CursorObject)
+ {
+ /* Call GDI to set the new screen cursor */
+ GreSetPointerShape(hdcScreen,
+ MessageQueue->CursorObject->IconInfo.hbmMask,
+ MessageQueue->CursorObject->IconInfo.hbmColor,
+ MessageQueue->CursorObject->IconInfo.xHotspot,
+ MessageQueue->CursorObject->IconInfo.yHotspot,
+ gpsi->ptCursor.x,
+ gpsi->ptCursor.y);
+ } else
+ GreMovePointer(hdcScreen, Msg->pt.x, Msg->pt.y);
+ }
+ /* Check if w have to hide cursor */
+ else if (CurInfo->ShowingCursor >= 0)
+ GreMovePointer(hdcScreen, -1, -1);
+
+ /* Update global cursor info */
+ CurInfo->ShowingCursor = MessageQueue->ShowingCursor;
+ CurInfo->CurrentCursorObject = MessageQueue->CursorObject;
+
+ /* Mouse move is a special case */
+ MsqPostMouseMove(MessageQueue, Msg);
}
else
{
- DPRINT("Posting mouse message to hwnd=0x%x!\n", UserHMGetHandle(pwnd));
+ TRACE("Posting mouse message to hwnd=0x%x!\n", UserHMGetHandle(pwnd));
MsqPostMessage(pwnd->head.pti->MessageQueue, Msg, TRUE, QS_MOUSEBUTTON);
}
}
+ else if (hdcScreen)
+ {
+ /* always show cursor on background; FIXME: set default pointer */
+ GreMovePointer(hdcScreen, Msg->pt.x, Msg->pt.y);
+ CurInfo->ShowingCursor = 0;
+ }
+
+ /* Do GetMouseMovePointsEx FIFO. */
+ MouseHistoryOfMoves[gcur_count].x = Msg->pt.x;
+ MouseHistoryOfMoves[gcur_count].y = Msg->pt.y;
+ MouseHistoryOfMoves[gcur_count].time = Msg->time;
+ MouseHistoryOfMoves[gcur_count].dwExtraInfo = dwExtraInfo;
+ if (++gcur_count == ARRAYSIZE(MouseHistoryOfMoves))
+ gcur_count = 0; // 0 - 63 is 64, FIFO forwards.
}
//
// Note: Only called from input.c.
//
VOID FASTCALL
-co_MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
+co_MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL bInjected)
{
PUSER_MESSAGE_QUEUE FocusMessageQueue;
MSG Msg;
LARGE_INTEGER LargeTickCount;
KBDLLHOOKSTRUCT KbdHookData;
- DPRINT("MsqPostKeyboardMessage(uMsg 0x%x, wParam 0x%x, lParam 0x%x)\n",
+ TRACE("MsqPostKeyboardMessage(uMsg 0x%x, wParam 0x%x, lParam 0x%x)\n",
uMsg, wParam, lParam);
// Condition may arise when calling MsqPostMessage and waiting for an event.
KbdHookData.vkCode = Msg.wParam;
KbdHookData.scanCode = (Msg.lParam >> 16) & 0xff;
- KbdHookData.flags = (0 == (Msg.lParam & 0x01000000) ? 0 : LLKHF_EXTENDED) |
- (0 == (Msg.lParam & 0x20000000) ? 0 : LLKHF_ALTDOWN) |
- (0 == (Msg.lParam & 0x80000000) ? 0 : LLKHF_UP);
+ KbdHookData.flags = 0;
+ if (Msg.lParam & 0x01000000)
+ KbdHookData.flags |= LLKHF_EXTENDED;
+ if (Msg.lParam & 0x20000000)
+ KbdHookData.flags |= LLKHF_ALTDOWN;
+ if (Msg.lParam & 0x80000000)
+ KbdHookData.flags |= LLKHF_UP;
+ if (bInjected)
+ KbdHookData.flags |= LLKHF_INJECTED;
KbdHookData.time = Msg.time;
KbdHookData.dwExtraInfo = 0;
if (co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, Msg.message, (LPARAM) &KbdHookData))
{
- DPRINT1("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
+ ERR("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
Msg.message, Msg.wParam, Msg.lParam);
return;
}
if (FocusMessageQueue == NULL)
{
- DPRINT("No focus message queue\n");
+ TRACE("No focus message queue\n");
return;
}
if (FocusMessageQueue->FocusWindow != (HWND)0)
{
Msg.hwnd = FocusMessageQueue->FocusWindow;
- DPRINT("Msg.hwnd = %x\n", Msg.hwnd);
+ TRACE("Msg.hwnd = %x\n", Msg.hwnd);
FocusMessageQueue->Desktop->pDeskInfo->LastInputWasKbd = TRUE;
}
else
{
- DPRINT("Invalid focus window handle\n");
+ TRACE("Invalid focus window handle\n");
}
return;
MSG Mesg;
LARGE_INTEGER LargeTickCount;
NTSTATUS Status;
+ INT id;
+ DWORD Type;
Status = ObReferenceObjectByPointer (Thread,
THREAD_ALL_ACCESS,
return;
}
- Mesg.hwnd = hWnd;
- Mesg.message = WM_HOTKEY;
- Mesg.wParam = wParam;
- Mesg.lParam = lParam;
+ id = wParam; // Check for hot keys unrelated to the hot keys set by RegisterHotKey.
+
+ Mesg.hwnd = hWnd;
+ Mesg.message = id != IDHOT_REACTOS ? WM_HOTKEY : WM_SYSCOMMAND;
+ Mesg.wParam = id != IDHOT_REACTOS ? wParam : SC_HOTKEY;
+ Mesg.lParam = id != IDHOT_REACTOS ? lParam : (LPARAM)hWnd;
+ Type = id != IDHOT_REACTOS ? QS_HOTKEY : QS_POSTMESSAGE;
KeQueryTickCount(&LargeTickCount);
- Mesg.time = MsqCalculateMessageTime(&LargeTickCount);
- Mesg.pt = gpsi->ptCursor;
- MsqPostMessage(Window->head.pti->MessageQueue, &Mesg, FALSE, QS_HOTKEY);
+ Mesg.time = MsqCalculateMessageTime(&LargeTickCount);
+ Mesg.pt = gpsi->ptCursor;
+ MsqPostMessage(Window->head.pti->MessageQueue, &Mesg, FALSE, Type);
UserDereferenceObject(Window);
ObDereferenceObject (Thread);
ExFreeToPagedLookasideList(&MessageLookasideList, Message);
}
-VOID FASTCALL
-MsqDestroySentMessage(PUSER_MESSAGE_QUEUE MessageQueue, PUSER_SENT_MESSAGE SentMessage)
-{
- /* remove the message from the dispatching list if needed */
- if (SentMessage->DispatchingListEntry.Flink != NULL)
- {
- RemoveEntryList(&SentMessage->DispatchingListEntry);
- }
-
- /* wake the sender's thread */
- if (SentMessage->CompletionEvent != NULL)
- {
- KeSetEvent(SentMessage->CompletionEvent, IO_NO_INCREMENT, FALSE);
- }
-
- /* dereference message queues */
- IntDereferenceMessageQueue(MessageQueue);
- if (SentMessage->SenderQueue)
- {
- IntDereferenceMessageQueue(SentMessage->SenderQueue);
- }
- if (SentMessage->CallBackSenderQueue)
- {
- IntDereferenceMessageQueue(SentMessage->CallBackSenderQueue);
- }
-
- /* free lParam if needed */
- if (SentMessage->HasPackedLParam == TRUE && SentMessage->Msg.lParam)
- {
- ExFreePool((PVOID)SentMessage->Msg.lParam);
- }
-
- /* free the message */
- ExFreePoolWithTag(SentMessage, TAG_USRMSG);
-}
-
BOOLEAN FASTCALL
co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
{
PUSER_SENT_MESSAGE SaveMsg, Message;
PLIST_ENTRY Entry;
- LRESULT Result;
PTHREADINFO pti;
+ LRESULT Result = 0;
if (IsListEmpty(&MessageQueue->SentMessagesListHead))
{
Message->Msg.wParam,
Message->Msg.lParam);
}
+ else if(Message->HookMessage == MSQ_INJECTMODULE)
+ {
+ Result = IntLoadHookModule(Message->Msg.message,
+ (HHOOK)Message->Msg.lParam,
+ Message->Msg.wParam);
+ }
+ else if ((Message->CompletionCallback)
+ && (Message->CallBackSenderQueue == MessageQueue))
+ { /* Call the callback routine */
+ if (Message->QS_Flags & QS_SMRESULT)
+ {
+ co_IntCallSentMessageCallback(Message->CompletionCallback,
+ Message->Msg.hwnd,
+ Message->Msg.message,
+ Message->CompletionCallbackContext,
+ Message->lResult);
+ /* Set callback to NULL to prevent reentry */
+ Message->CompletionCallback = NULL;
+ }
+ else
+ {
+ /* The message has not been processed yet, reinsert it. */
+ RemoveEntryList(&Message->ListEntry);
+ InsertTailList(&Message->CallBackSenderQueue->SentMessagesListHead, &Message->ListEntry);
+ TRACE("Callback Message not processed yet. Requeuing the message\n");
+ return (FALSE);
+ }
+ }
else
{ /* Call the window procedure. */
Result = co_IntSendMessage( Message->Msg.hwnd,
to be cleaned up on thread termination anymore */
RemoveEntryList(&Message->ListEntry);
+ /* If the message is a callback, insert it in the callback senders MessageQueue */
+ if (Message->CompletionCallback)
+ {
+ if (Message->CallBackSenderQueue)
+ {
+ Message->lResult = Result;
+ Message->QS_Flags |= QS_SMRESULT;
+
+ /* insert it in the callers message queue */
+ InsertTailList(&Message->CallBackSenderQueue->SentMessagesListHead, &Message->ListEntry);
+ MsqWakeQueue(Message->CallBackSenderQueue, QS_SENDMESSAGE, TRUE);
+ IntDereferenceMessageQueue(Message->CallBackSenderQueue);
+ }
+ return (TRUE);
+ }
+
/* remove the message from the dispatching list if needed, so lock the sender's message queue */
- if (Message->DispatchingListEntry.Flink != NULL)
+ if (Message->SenderQueue)
{
- RemoveEntryList(&Message->DispatchingListEntry);
- Message->DispatchingListEntry.Flink = NULL;
+ if (Message->DispatchingListEntry.Flink != NULL)
+ {
+ /* only remove it from the dispatching list if not already removed by a timeout */
+ RemoveEntryList(&Message->DispatchingListEntry);
+ }
}
/* still keep the sender's message queue locked, so the sender can't exit the
MsqSendMessage() function (if timed out) */
*Message->Result = Result;
}
+ if (Message->HasPackedLParam == TRUE)
+ {
+ if (Message->Msg.lParam)
+ ExFreePool((PVOID)Message->Msg.lParam);
+ }
+
/* Notify the sender. */
if (Message->CompletionEvent != NULL)
{
KeSetEvent(Message->CompletionEvent, IO_NO_INCREMENT, FALSE);
- Message->CompletionEvent = NULL; /* prevent MsqDestroySentMessage from setting this event again */
}
- /* Call the callback if the message was sent with SendMessageCallback */
- if (Message->CompletionCallback != NULL)
+ /* if the message has a sender */
+ if (Message->SenderQueue)
{
- co_IntCallSentMessageCallback(Message->CompletionCallback,
- Message->Msg.hwnd,
- Message->Msg.message,
- Message->CompletionCallbackContext,
- Result);
+ /* dereference our and the sender's message queue */
+ IntDereferenceMessageQueue(Message->SenderQueue);
+ IntDereferenceMessageQueue(MessageQueue);
}
- MsqDestroySentMessage(MessageQueue, Message);
+ /* free the message */
+ ExFreePoolWithTag(Message, TAG_USRMSG);
/* do not hangup on the user if this is reentering */
if (!SaveMsg) pti->pcti->CTI_flags &= ~CTI_INSENDMESSAGE;
{
PostedMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
ListEntry);
- /* set CurrentEntry to next before destroying message */
- CurrentEntry = CurrentEntry->Flink;
-
if (PostedMessage->Msg.hwnd == Window->head.h)
{
RemoveEntryList(&PostedMessage->ListEntry);
ClearMsgBitsMask(MessageQueue, PostedMessage->QS_Flags);
MsqDestroyMessage(PostedMessage);
+ CurrentEntry = MessageQueue->PostedMessagesListHead.Flink;
+ }
+ else
+ {
+ CurrentEntry = CurrentEntry->Flink;
}
}
{
SentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
ListEntry);
- /* set CurrentEntry to next before destroying message */
- CurrentEntry = CurrentEntry->Flink;
-
if(SentMessage->Msg.hwnd == Window->head.h)
{
- DPRINT("Notify the sender and remove a message from the queue that had not been dispatched\n");
+ TRACE("Notify the sender and remove a message from the queue that had not been dispatched\n");
RemoveEntryList(&SentMessage->ListEntry);
ClearMsgBitsMask(MessageQueue, SentMessage->QS_Flags);
- MsqDestroySentMessage(MessageQueue, SentMessage);
+ /* if it is a callback and this queue is not the sender queue, dereference queue */
+ if ((SentMessage->CompletionCallback) && (SentMessage->CallBackSenderQueue != MessageQueue))
+ {
+ IntDereferenceMessageQueue(SentMessage->CallBackSenderQueue);
+ }
+ /* Only if the message has a sender was the queue referenced */
+ if ((SentMessage->SenderQueue)
+ && (SentMessage->DispatchingListEntry.Flink != NULL))
+ {
+ RemoveEntryList(&SentMessage->DispatchingListEntry);
+ }
+
+ /* wake the sender's thread */
+ if (SentMessage->CompletionEvent != NULL)
+ {
+ KeSetEvent(SentMessage->CompletionEvent, IO_NO_INCREMENT, FALSE);
+ }
+
+ if (SentMessage->HasPackedLParam == TRUE)
+ {
+ if (SentMessage->Msg.lParam)
+ ExFreePool((PVOID)SentMessage->Msg.lParam);
+ }
+
+ /* if the message has a sender */
+ if (SentMessage->SenderQueue)
+ {
+ /* dereference our and the sender's message queue */
+ IntDereferenceMessageQueue(MessageQueue);
+ IntDereferenceMessageQueue(SentMessage->SenderQueue);
+ }
+
+ /* free the message */
+ ExFreePoolWithTag(SentMessage, TAG_USRMSG);
+
+ CurrentEntry = MessageQueue->SentMessagesListHead.Flink;
+ }
+ else
+ {
+ CurrentEntry = CurrentEntry->Flink;
}
}
}
+BOOL FASTCALL
+co_MsqSendMessageAsync(PTHREADINFO ptiReceiver,
+ HWND hwnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ SENDASYNCPROC CompletionCallback,
+ ULONG_PTR CompletionCallbackContext,
+ BOOL HasPackedLParam,
+ INT HookMessage)
+{
+
+ PTHREADINFO ptiSender;
+ PUSER_SENT_MESSAGE Message;
+
+ if(!(Message = ExAllocatePoolWithTag(NonPagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG)))
+ {
+ ERR("MsqSendMessage(): Not enough memory to allocate a message");
+ return FALSE;
+ }
+
+ ptiSender = PsGetCurrentThreadWin32Thread();
+
+ IntReferenceMessageQueue(ptiReceiver->MessageQueue);
+ /* Take reference on this MessageQueue if its a callback. It will be released
+ when message is processed or removed from target hwnd MessageQueue */
+ if (CompletionCallback)
+ IntReferenceMessageQueue(ptiSender->MessageQueue);
+
+ Message->Msg.hwnd = hwnd;
+ Message->Msg.message = Msg;
+ Message->Msg.wParam = wParam;
+ Message->Msg.lParam = lParam;
+ Message->CompletionEvent = NULL;
+ Message->Result = 0;
+ Message->lResult = 0;
+ Message->SenderQueue = NULL;
+ Message->CallBackSenderQueue = ptiSender->MessageQueue;
+ Message->DispatchingListEntry.Flink = NULL;
+ Message->CompletionCallback = CompletionCallback;
+ Message->CompletionCallbackContext = CompletionCallbackContext;
+ Message->HookMessage = HookMessage;
+ Message->HasPackedLParam = HasPackedLParam;
+ Message->QS_Flags = QS_SENDMESSAGE;
+
+ InsertTailList(&ptiReceiver->MessageQueue->SentMessagesListHead, &Message->ListEntry);
+ MsqWakeQueue(ptiReceiver->MessageQueue, QS_SENDMESSAGE, TRUE);
+ IntDereferenceMessageQueue(ptiReceiver->MessageQueue);
+
+ return TRUE;
+}
+
NTSTATUS FASTCALL
co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
UINT uTimeout, BOOL Block, INT HookMessage,
ULONG_PTR *uResult)
{
- PTHREADINFO pti;
+ PTHREADINFO pti, ptirec;
PUSER_SENT_MESSAGE Message;
KEVENT CompletionEvent;
NTSTATUS WaitStatus;
if(!(Message = ExAllocatePoolWithTag(PagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG)))
{
- DPRINT1("MsqSendMessage(): Not enough memory to allocate a message");
+ ERR("MsqSendMessage(): Not enough memory to allocate a message");
return STATUS_INSUFFICIENT_RESOURCES;
}
pti = PsGetCurrentThreadWin32Thread();
ThreadQueue = pti->MessageQueue;
+ ptirec = MessageQueue->Thread->Tcb.Win32Thread;
ASSERT(ThreadQueue != MessageQueue);
+ ASSERT(ptirec->pcti); // Send must have a client side to receive it!!!!
+
+ /* Don't send from or to a dying thread */
+ if (pti->TIF_flags & TIF_INCLEANUP || ptirec->TIF_flags & TIF_INCLEANUP)
+ {
+ *uResult = -1;
+ return STATUS_TIMEOUT;
+ }
Timeout.QuadPart = (LONGLONG) uTimeout * (LONGLONG) -10000;
- /* FIXME - increase reference counter of sender's message queue here - isn't it done? */
+ /* FIXME - increase reference counter of sender's message queue here */
Message->Msg.hwnd = Wnd;
Message->Msg.message = Msg;
Message->Result = &Result;
Message->lResult = 0;
Message->QS_Flags = 0;
- IntReferenceMessageQueue(ThreadQueue);
Message->SenderQueue = ThreadQueue;
Message->CallBackSenderQueue = NULL;
+ IntReferenceMessageQueue(ThreadQueue);
Message->CompletionCallback = NULL;
Message->CompletionCallbackContext = 0;
Message->HookMessage = HookMessage;
Entry = Entry->Flink;
}
- DPRINT("MsqSendMessage (blocked) timed out\n");
+ TRACE("MsqSendMessage (blocked) timed out 1\n");
}
while (co_MsqDispatchOneSentMessage(ThreadQueue))
;
Entry = Entry->Flink;
}
- DPRINT("MsqSendMessage timed out\n");
+ TRACE("MsqSendMessage timed out 2\n");
break;
}
while (co_MsqDispatchOneSentMessage(ThreadQueue))
{
InsertTailList(&MessageQueue->HardwareMessagesListHead,
&Message->ListEntry);
+
+ update_input_key_state( MessageQueue, Msg );
}
Message->QS_Flags = MessageBits;
PUSER_MESSAGE_QUEUE MessageQueue;
PTHREADINFO pti;
PSYSTEM_CURSORINFO CurInfo;
+ PDESKTOP pDesk;
DECLARE_RETURN(BOOL);
pti = PsGetCurrentThreadWin32Thread();
CurInfo = IntGetSysCursorInfo();
pwndMsg = UserGetWindowObject(msg->hwnd);
clk_msg = MessageQueue->msgDblClk;
+ pDesk = pwndDesktop->head.rpdesk;
/* find the window to dispatch this mouse message to */
if (MessageQueue->CaptureWindow)
pwndMsg = co_WinPosWindowFromPoint(pwndMsg, &msg->pt, &hittest);
}
- DPRINT("Got mouse message for 0x%x, hittest: 0x%x\n", msg->hwnd, hittest );
+ TRACE("Got mouse message for 0x%x, hittest: 0x%x\n", msg->hwnd, hittest );
if (pwndMsg == NULL || pwndMsg->head.pti != pti)
{
RETURN(FALSE);
}
+ /* If we a re tracking the mouse and it moves to another window */
+ if(pDesk->spwndTrack &&
+ pDesk->spwndTrack != pwndMsg &&
+ msg->message != WM_MOUSELEAVE)
+ {
+ /* Generate a WM_MOUSELEAVE message */
+ if ( pDesk->dwDTFlags & DF_TME_LEAVE )
+ {
+ MSG msgMouseLeave;
+
+ TRACE("co_IntProcessMouseMessage: generating WM_MOUSELEAVE\n");
+
+ msgMouseLeave.hwnd = UserHMGetHandle(pDesk->spwndTrack);
+ msgMouseLeave.message = WM_MOUSELEAVE;
+ msgMouseLeave.pt = msg->pt;
+ msgMouseLeave.time = msg->time;
+ msgMouseLeave.lParam = msgMouseLeave.wParam = 0;
+
+ MsqPostMessage(pwndMsg->head.pti->MessageQueue,
+ &msgMouseLeave,
+ TRUE,
+ QS_MOUSE);
+ }
+
+ /* Stop tracking */
+ if ( pDesk->dwDTFlags & DF_TME_HOVER )
+ {
+ IntKillTimer(pDesk->spwndTrack, ID_EVENT_SYSTIMER_MOUSEHOVER, TRUE);
+ }
+
+ pDesk->spwndTrack = NULL;
+ pDesk->htEx = 0;
+ }
+
+ if(pDesk->spwndTrack)
+ {
+ pDesk->htEx = hittest;
+ }
+
msg->hwnd = UserHMGetHandle(pwndMsg);
#if 0
if (!((first == 0 && last == 0) || (message >= first || message <= last)))
{
- DPRINT("Message out of range!!!\n");
+ TRACE("Message out of range!!!\n");
RETURN(FALSE);
}
{
if (!((first == 0 && last == 0) || (message >= first || message <= last)))
{
- DPRINT("Message out of range!!!\n");
+ TRACE("Message out of range!!!\n");
RETURN(FALSE);
}
}
/* message is accepted now (but may still get dropped) */
- pti->rpdesk->htEx = hittest; /* Now set the capture hit. */
-
event.message = msg->message;
event.time = msg->time;
event.hwnd = msg->hwnd;
hook.dwExtraInfo = 0/*extra_info*/;
co_HOOK_CallHooks( WH_CBT, HCBT_CLICKSKIPPED, message, (LPARAM)&hook );
- DPRINT1("WH_MOUSE dorpped mouse message!\n");
+ ERR("WH_MOUSE dorpped mouse message!\n");
/* Remove and skip message */
*RemoveMessages = TRUE;
if(!co_IntMouseActivateWindow(pwndMsg)) eatMsg = TRUE;
break;
default:
- DPRINT1( "unknown WM_MOUSEACTIVATE code %d\n", ret );
+ ERR( "unknown WM_MOUSEACTIVATE code %d\n", ret );
break;
}
}
{
EVENTMSG Event;
+ if (Msg->message == WM_KEYDOWN || Msg->message == WM_SYSKEYDOWN ||
+ Msg->message == WM_KEYUP || Msg->message == WM_SYSKEYUP)
+ {
+ switch (Msg->wParam)
+ {
+ case VK_LSHIFT: case VK_RSHIFT:
+ Msg->wParam = VK_SHIFT;
+ break;
+ case VK_LCONTROL: case VK_RCONTROL:
+ Msg->wParam = VK_CONTROL;
+ break;
+ case VK_LMENU: case VK_RMENU:
+ Msg->wParam = VK_MENU;
+ break;
+ }
+ }
+
Event.message = Msg->message;
Event.hwnd = Msg->hwnd;
Event.time = Msg->time;
HCBT_KEYSKIPPED,
LOWORD(Msg->wParam),
Msg->lParam );
- DPRINT1("KeyboardMessage WH_CBT Call Hook return!\n");
+ ERR("KeyboardMessage WH_CBT Call Hook return!\n");
return FALSE;
}
return TRUE;
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 ) )
+/*
+ MSDN:
+ 1: any window that belongs to the current thread, and any messages on the current thread's message queue whose hwnd value is NULL.
+ 2: retrieves only messages on the current thread's message queue whose hwnd value is NULL.
+ 3: handle to the window whose messages are to be retrieved.
+ */
+ if ( ( !Window || // 1
+ ( Window == HWND_BOTTOM && CurrentMessage->Msg.hwnd == NULL ) || // 2
+ ( Window != HWND_BOTTOM && Window->head.h == CurrentMessage->Msg.hwnd ) ) && // 3
+ ( ( ( MsgFilterLow == 0 && MsgFilterHigh == 0 ) && CurrentMessage->QS_Flags & QSflags ) ||
+ ( MsgFilterLow <= CurrentMessage->Msg.message && MsgFilterHigh >= CurrentMessage->Msg.message ) ) )
{
msg = CurrentMessage->Msg;
if (Remove)
{
+ update_input_key_state(MessageQueue, &msg);
RemoveEntryList(&CurrentMessage->ListEntry);
ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags);
MsqDestroyMessage(CurrentMessage);
if (IsListEmpty(CurrentEntry)) break;
if (!CurrentMessage) break;
CurrentEntry = CurrentEntry->Flink;
-
- if ( ( !Window || Window == HWND_BOTTOM || Window->head.h == CurrentMessage->Msg.hwnd ) &&
+/*
+ MSDN:
+ 1: any window that belongs to the current thread, and any messages on the current thread's message queue whose hwnd value is NULL.
+ 2: retrieves only messages on the current thread's message queue whose hwnd value is NULL.
+ 3: handle to the window whose messages are to be retrieved.
+ */
+ if ( ( !Window || // 1
+ ( Window == HWND_BOTTOM && CurrentMessage->Msg.hwnd == NULL ) || // 2
+ ( Window != HWND_BOTTOM && Window->head.h == CurrentMessage->Msg.hwnd ) ) && // 3
( ( ( MsgFilterLow == 0 && MsgFilterHigh == 0 ) && CurrentMessage->QS_Flags & QSflags ) ||
( MsgFilterLow <= CurrentMessage->Msg.message && MsgFilterHigh >= CurrentMessage->Msg.message ) ) )
{
UINT MsgFilterMin, UINT MsgFilterMax)
{
NTSTATUS ret;
-
UserLeaveCo();
- ret = KeWaitForSingleObject(MessageQueue->NewMessages,
- Executive,
- UserMode,
- FALSE,
- NULL);
+ ret = KeWaitForSingleObject( MessageQueue->NewMessages,
+ UserRequest,
+ UserMode,
+ FALSE,
+ NULL );
UserEnterCo();
return ret;
}
return ((LargeTickCount.u.LowPart - MessageQueue->LastMsgRead) > MSQ_HUNG);
}
+VOID
+CALLBACK
+HungAppSysTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ DoTheScreenSaver();
+ TRACE("HungAppSysTimerProc\n");
+ // Process list of windows that are hung and waiting.
+}
+
BOOLEAN FASTCALL
MsqInitializeMessageQueue(struct _ETHREAD *Thread, PUSER_MESSAGE_QUEUE MessageQueue)
{
InitializeListHead(&MessageQueue->HardwareMessagesListHead);
InitializeListHead(&MessageQueue->DispatchingMessagesHead);
InitializeListHead(&MessageQueue->LocalDispatchingMessagesHead);
- KeInitializeMutex(&MessageQueue->HardwareLock, 0);
MessageQueue->QuitPosted = FALSE;
MessageQueue->QuitExitCode = 0;
KeQueryTickCount(&LargeTickCount);
MessageQueue->LastMsgRead = LargeTickCount.u.LowPart;
MessageQueue->FocusWindow = NULL;
MessageQueue->NewMessagesHandle = NULL;
+ MessageQueue->ShowingCursor = 0;
+ MessageQueue->CursorObject = NULL;
+ RtlCopyMemory(MessageQueue->KeyState, gafAsyncKeyState, sizeof(gafAsyncKeyState));
Status = ZwCreateEvent(&MessageQueue->NewMessagesHandle, EVENT_ALL_ACCESS,
NULL, SynchronizationEvent, FALSE);
CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
ListEntry);
- DPRINT("Notify the sender and remove a message from the queue that had not been dispatched\n");
+ /* if it is a callback and this queue is not the sender queue, dereference queue */
+ if ((CurrentSentMessage->CompletionCallback) && (CurrentSentMessage->CallBackSenderQueue != MessageQueue))
+ {
+ IntDereferenceMessageQueue(CurrentSentMessage->CallBackSenderQueue);
+ }
+
+ TRACE("Notify the sender and remove a message from the queue that had not been dispatched\n");
+ /* Only if the message has a sender was the message in the DispatchingList */
+ if ((CurrentSentMessage->SenderQueue)
+ && (CurrentSentMessage->DispatchingListEntry.Flink != NULL))
+ {
+ RemoveEntryList(&CurrentSentMessage->DispatchingListEntry);
+ }
+
+ /* wake the sender's thread */
+ if (CurrentSentMessage->CompletionEvent != NULL)
+ {
+ KeSetEvent(CurrentSentMessage->CompletionEvent, IO_NO_INCREMENT, FALSE);
+ }
- MsqDestroySentMessage(MessageQueue, CurrentSentMessage);
+ if (CurrentSentMessage->HasPackedLParam == TRUE)
+ {
+ if (CurrentSentMessage->Msg.lParam)
+ ExFreePool((PVOID)CurrentSentMessage->Msg.lParam);
+ }
+
+ /* if the message has a sender */
+ if (CurrentSentMessage->SenderQueue)
+ {
+ /* dereference our and the sender's message queue */
+ IntDereferenceMessageQueue(MessageQueue);
+ IntDereferenceMessageQueue(CurrentSentMessage->SenderQueue);
+ }
+
+ /* free the message */
+ ExFreePool(CurrentSentMessage);
}
/* notify senders of dispatching messages. This needs to be cleaned up if e.g.
CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
ListEntry);
- DPRINT("Notify the sender, the thread has been terminated while dispatching a message!\n");
+ /* if it is a callback and this queue is not the sender queue, dereference queue */
+ if ((CurrentSentMessage->CompletionCallback) && (CurrentSentMessage->CallBackSenderQueue != MessageQueue))
+ {
+ IntDereferenceMessageQueue(CurrentSentMessage->CallBackSenderQueue);
+ }
+
+ /* remove the message from the dispatching list */
+ if(CurrentSentMessage->DispatchingListEntry.Flink != NULL)
+ {
+ RemoveEntryList(&CurrentSentMessage->DispatchingListEntry);
+ }
+
+ TRACE("Notify the sender, the thread has been terminated while dispatching a message!\n");
+
+ /* wake the sender's thread */
+ if (CurrentSentMessage->CompletionEvent != NULL)
+ {
+ KeSetEvent(CurrentSentMessage->CompletionEvent, IO_NO_INCREMENT, FALSE);
+ }
+
+ if (CurrentSentMessage->HasPackedLParam == TRUE)
+ {
+ if (CurrentSentMessage->Msg.lParam)
+ ExFreePool((PVOID)CurrentSentMessage->Msg.lParam);
+ }
+
+ /* if the message has a sender */
+ if (CurrentSentMessage->SenderQueue)
+ {
+ /* dereference our and the sender's message queue */
+ IntDereferenceMessageQueue(MessageQueue);
+ IntDereferenceMessageQueue(CurrentSentMessage->SenderQueue);
+ }
- MsqDestroySentMessage(MessageQueue, CurrentSentMessage);
+ /* free the message */
+ ExFreePool(CurrentSentMessage);
}
/* tell other threads not to bother returning any info to us */
DispatchingListEntry);
CurrentSentMessage->CompletionEvent = NULL;
CurrentSentMessage->Result = NULL;
- CurrentSentMessage->DispatchingListEntry.Flink = NULL; // yeah!
/* do NOT dereference our message queue as it might get attempted to be
locked later */
}
// Clear it all out.
- pti->pcti->fsWakeBits = 0;
- pti->pcti->fsChangeBits = 0;
+ if(pti->pcti)
+ {
+ pti->pcti->fsWakeBits = 0;
+ pti->pcti->fsChangeBits = 0;
+ }
MessageQueue->nCntsQBits[QSRosKey] = 0;
MessageQueue->nCntsQBits[QSRosMouseMove] = 0;
MessageQueue->nCntsQBits[QSRosPostMessage] = 0;
MessageQueue->nCntsQBits[QSRosSendMessage] = 0;
MessageQueue->nCntsQBits[QSRosHotKey] = 0;
+
+ if (MessageQueue->CursorObject)
+ {
+ PCURICON_OBJECT pCursor = MessageQueue->CursorObject;
+
+ /* Change to another cursor if we going to dereference current one
+ Note: we can't use UserSetCursor because it uses current thread
+ message queue instead of queue given for cleanup */
+ if (IntGetSysCursorInfo()->CurrentCursorObject == pCursor)
+ {
+ HDC hdcScreen;
+
+ /* Get the screen DC */
+ hdcScreen = IntGetScreenDC();
+ if (hdcScreen)
+ GreMovePointer(hdcScreen, -1, -1);
+ IntGetSysCursorInfo()->CurrentCursorObject = NULL;
+ }
+
+ UserDereferenceObject(pCursor);
+ }
+
}
PUSER_MESSAGE_QUEUE FASTCALL
{
PDESKTOP desk;
+ MessageQueue->QF_flags |= QF_INDESTROY;
+
/* remove the message queue from any desktops */
if ((desk = InterlockedExchangePointer((PVOID*)&MessageQueue->Desktop, 0)))
{
/* clean it up */
MsqCleanupMessageQueue(MessageQueue);
+ if (MessageQueue->NewMessagesHandle != NULL)
+ ZwClose(MessageQueue->NewMessagesHandle);
+ MessageQueue->NewMessagesHandle = NULL;
/* decrease the reference counter, if it hits zero, the queue will be freed */
IntDereferenceMessageQueue(MessageQueue);
}
return NULL;
}
+SHORT
+APIENTRY
+NtUserGetKeyState(INT key)
+{
+ DWORD Ret;
+
+ UserEnterExclusive();
+
+ Ret = UserGetKeyState(key);
+
+ UserLeave();
+
+ return Ret;
+}
+
+
+DWORD
+APIENTRY
+NtUserGetKeyboardState(LPBYTE lpKeyState)
+{
+ DWORD ret = TRUE;
+ PTHREADINFO pti;
+ PUSER_MESSAGE_QUEUE MessageQueue;
+
+ UserEnterShared();
+
+ pti = PsGetCurrentThreadWin32Thread();
+ MessageQueue = pti->MessageQueue;
+
+ _SEH2_TRY
+ {
+ ProbeForWrite(lpKeyState,sizeof(MessageQueue->KeyState) ,1);
+ RtlCopyMemory(lpKeyState,MessageQueue->KeyState,sizeof(MessageQueue->KeyState));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ ret = FALSE;
+ }
+ _SEH2_END;
+
+ UserLeave();
+
+ return ret;
+}
+
+BOOL
+APIENTRY
+NtUserSetKeyboardState(LPBYTE lpKeyState)
+{
+ DWORD ret = TRUE;
+ PTHREADINFO pti;
+ PUSER_MESSAGE_QUEUE MessageQueue;
+
+ UserEnterExclusive();
+
+ pti = PsGetCurrentThreadWin32Thread();
+ MessageQueue = pti->MessageQueue;
+
+ _SEH2_TRY
+ {
+ ProbeForRead(lpKeyState,sizeof(MessageQueue->KeyState) ,1);
+ RtlCopyMemory(MessageQueue->KeyState,lpKeyState,sizeof(MessageQueue->KeyState));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ ret = FALSE;
+ }
+ _SEH2_END;
+
+ UserLeave();
+
+ return ret;
+}
+
/* EOF */