if( key < 0x100 )
{
- ret = ((DWORD)(MessageQueue->KeyState[key] & KS_DOWN_BIT) << 8 ) |
- (MessageQueue->KeyState[key] & KS_LOCK_BIT);
+ ret = (DWORD)MessageQueue->KeyState[key];
}
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 )
{
+ DPRINT("set_input_key_state key:%d, down:%d\n", key, down);
+
if (down)
{
- if (!(MessageQueue->KeyState[key] & KS_DOWN_BIT))
+ if (!(MessageQueue->KeyState[key] & KS_DOWN_BIT))
{
MessageQueue->KeyState[key] ^= KS_LOCK_BIT;
}
UCHAR key;
BOOL down = 0;
+ DPRINT("update_input_key_state message:%d\n", msg->message);
+
switch (msg->message)
{
case WM_LBUTTONDOWN:
down = 1;
/* fall through */
case WM_XBUTTONUP:
- if (msg->wParam == XBUTTON1)
+ if (msg->wParam == XBUTTON1)
set_input_key_state( MessageQueue, VK_XBUTTON1, down );
- else if (msg->wParam == XBUTTON2)
+ else if (msg->wParam == XBUTTON2)
set_input_key_state( MessageQueue, VK_XBUTTON2, down );
break;
case WM_KEYDOWN:
pti = Queue->Thread->Tcb.Win32Thread;
if (MessageBits & QS_KEY)
- {
+ {
if (--Queue->nCntsQBits[QSRosKey] == 0) ClrMask |= QS_KEY;
}
if (MessageBits & QS_MOUSEMOVE) // ReactOS hard coded.
}
VOID FASTCALL
-co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo)
+co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook)
{
LARGE_INTEGER LargeTickCount;
MSLLHOOKSTRUCT MouseHookData;
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(Msg->hwnd != NULL)
{
pwnd = UserGetWindowObject(Msg->hwnd);
- if ((pwnd->style & WS_VISIBLE) &&
+ if ((pwnd->style & WS_VISIBLE) &&
IntPtInWindow(pwnd, Msg->pt.x, Msg->pt.y))
{
pDesk->htEx = HTCLIENT;
continue;
}
- if((pwnd->style & WS_VISIBLE) &&
+ if((pwnd->style & WS_VISIBLE) &&
IntPtInWindow(pwnd, Msg->pt.x, Msg->pt.y))
{
Msg->hwnd = pwnd->head.h;
FocusMessageQueue->Desktop->pDeskInfo->LastInputWasKbd = TRUE;
Msg.pt = gpsi->ptCursor;
+ update_input_key_state(FocusMessageQueue, &Msg);
MsqPostMessage(FocusMessageQueue, &Msg, TRUE, QS_KEY);
}
else
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);
{
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->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);
+ DPRINT("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->SenderQueue)
{
KeSetEvent(Message->CompletionEvent, IO_NO_INCREMENT, FALSE);
}
- /* Call the callback if the message was sent with SendMessageCallback */
- if (Message->CompletionCallback != NULL)
- {
- co_IntCallSentMessageCallback(Message->CompletionCallback,
- Message->Msg.hwnd,
- Message->Msg.message,
- Message->CompletionCallbackContext,
- Result);
- }
-
- /* Only if the message has a sender was the queue referenced */
+ /* if the message has a sender */
if (Message->SenderQueue)
{
+ /* dereference our and the sender's message queue */
IntDereferenceMessageQueue(Message->SenderQueue);
IntDereferenceMessageQueue(MessageQueue);
}
RemoveEntryList(&SentMessage->ListEntry);
ClearMsgBitsMask(MessageQueue, SentMessage->QS_Flags);
+ /* 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))
ExFreePool((PVOID)SentMessage->Msg.lParam);
}
- /* Only if the message has a sender was the queue referenced */
+ /* if the message has a sender */
if (SentMessage->SenderQueue)
{
/* dereference our and the sender's message queue */
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 */
if (pwndParent == pwndDesktop) break;
pt.x += pwnd->rcClient.left - pwndParent->rcClient.left;
pt.y += pwnd->rcClient.top - pwndParent->rcClient.top;
-
+
pwnd = pwndParent;
co_IntSendMessage( UserHMGetHandle(pwnd), WM_PARENTNOTIFY,
MAKEWPARAM( event, idChild ), MAKELPARAM( pt.x, pt.y ) );
}
DPRINT("Got mouse message for 0x%x, hittest: 0x%x\n", msg->hwnd, hittest );
-
+
if (pwndMsg == NULL || pwndMsg->head.pti != pti)
{
/* Remove and ignore the message */
}
}
- if (!((first == 0 && last == 0) || (message >= first || message <= last)))
+ if (!((first == 0 && last == 0) || (message >= first || message <= last)))
{
DPRINT("Message out of range!!!\n");
RETURN(FALSE);
if (pwndTop && pwndTop != pwndDesktop)
{
- LONG ret = co_IntSendMessage( msg->hwnd,
- WM_MOUSEACTIVATE,
+ LONG ret = co_IntSendMessage( msg->hwnd,
+ WM_MOUSEACTIVATE,
(WPARAM)UserHMGetHandle(pwndTop),
MAKELONG( hittest, msg->message));
switch(ret)
{
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;
+ case VK_F10:
+ if (Msg->message == WM_KEYUP) Msg->message = WM_SYSKEYUP;
+ if (Msg->message == WM_KEYDOWN) Msg->message = WM_SYSKEYDOWN;
+ break;
+ }
+ }
+
Event.message = Msg->message;
Event.hwnd = Msg->hwnd;
Event.time = Msg->time;
CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
ListEntry);
- do
+ do
{
if (IsListEmpty(CurrentEntry)) break;
if (!CurrentMessage) break;
if (Remove)
{
- update_input_key_state(MessageQueue, pMsg);
+ update_input_key_state(MessageQueue, &msg);
RemoveEntryList(&CurrentMessage->ListEntry);
- ClearMsgBitsMask(MessageQueue, QS_INPUT);
+ ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags);
MsqDestroyMessage(CurrentMessage);
}
PLIST_ENTRY CurrentEntry;
PUSER_MESSAGE CurrentMessage;
PLIST_ENTRY ListHead;
-
+
CurrentEntry = MessageQueue->PostedMessagesListHead.Flink;
ListHead = &MessageQueue->PostedMessagesListHead;
if (Remove)
{
RemoveEntryList(&CurrentMessage->ListEntry);
- ClearMsgBitsMask(MessageQueue, QS_POSTMESSAGE);
+ ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags);
MsqDestroyMessage(CurrentMessage);
}
return(TRUE);
ret = KeWaitForSingleObject( MessageQueue->NewMessages,
UserRequest,
UserMode,
- FALSE,
+ FALSE,
NULL );
UserEnterCo();
return ret;
PUSER_MESSAGE CurrentMessage;
PUSER_SENT_MESSAGE CurrentSentMessage;
PTHREADINFO pti;
-
+
pti = MessageQueue->Thread->Tcb.Win32Thread;
CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
ListEntry);
+ /* if it is a callback and this queue is not the sender queue, dereference queue */
+ if ((CurrentSentMessage->CompletionCallback) && (CurrentSentMessage->CallBackSenderQueue != MessageQueue))
+ {
+ IntDereferenceMessageQueue(CurrentSentMessage->CallBackSenderQueue);
+ }
+
DPRINT("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 queue referenced */
- if ((CurrentSentMessage->SenderQueue)
+ /* Only if the message has a sender was the message in the DispatchingList */
+ if ((CurrentSentMessage->SenderQueue)
&& (CurrentSentMessage->DispatchingListEntry.Flink != NULL))
{
RemoveEntryList(&CurrentSentMessage->DispatchingListEntry);
ExFreePool((PVOID)CurrentSentMessage->Msg.lParam);
}
- /* Only if the message has a sender was the queue referenced */
+ /* if the message has a sender */
if (CurrentSentMessage->SenderQueue)
{
/* dereference our and the sender's message queue */
CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
ListEntry);
+ /* 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)
{
ExFreePool((PVOID)CurrentSentMessage->Msg.lParam);
}
- /* Only if the message has a sender was the queue referenced */
+ /* if the message has a sender */
if (CurrentSentMessage->SenderQueue)
{
/* dereference our and the sender's message queue */
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 */