Index: subsystems/win32/win32k/ntuser/message.c =================================================================== --- subsystems/win32/win32k/ntuser/message.c (revision 47121) +++ subsystems/win32/win32k/ntuser/message.c (working copy) @@ -165,7 +165,7 @@ } static NTSTATUS -PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam) +PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL NonPagedPoolNeeded) { NCCALCSIZE_PARAMS *UnpackedNcCalcsize; NCCALCSIZE_PARAMS *PackedNcCalcsize; @@ -173,28 +173,34 @@ CREATESTRUCTW *PackedCs; PUNICODE_STRING WindowName; PUNICODE_STRING ClassName; + POOL_TYPE PoolType; UINT Size; PCHAR CsData; *lParamPacked = lParam; + + if (NonPagedPoolNeeded) + PoolType = NonPagedPool; + else + PoolType = PagedPool; + if (WM_NCCALCSIZE == Msg && wParam) { + UnpackedNcCalcsize = (NCCALCSIZE_PARAMS *) lParam; - if (UnpackedNcCalcsize->lppos != (PWINDOWPOS) (UnpackedNcCalcsize + 1)) + PackedNcCalcsize = ExAllocatePoolWithTag(PoolType, + sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS), + TAG_MSG); + + if (NULL == PackedNcCalcsize) { - PackedNcCalcsize = ExAllocatePoolWithTag(PagedPool, - sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS), - TAG_MSG); - if (NULL == PackedNcCalcsize) - { - DPRINT1("Not enough memory to pack lParam\n"); - return STATUS_NO_MEMORY; - } - RtlCopyMemory(PackedNcCalcsize, UnpackedNcCalcsize, sizeof(NCCALCSIZE_PARAMS)); - PackedNcCalcsize->lppos = (PWINDOWPOS) (PackedNcCalcsize + 1); - RtlCopyMemory(PackedNcCalcsize->lppos, UnpackedNcCalcsize->lppos, sizeof(WINDOWPOS)); - *lParamPacked = (LPARAM) PackedNcCalcsize; + DPRINT1("Not enough memory to pack lParam\n"); + return STATUS_NO_MEMORY; } + RtlCopyMemory(PackedNcCalcsize, UnpackedNcCalcsize, sizeof(NCCALCSIZE_PARAMS)); + PackedNcCalcsize->lppos = (PWINDOWPOS) (PackedNcCalcsize + 1); + RtlCopyMemory(PackedNcCalcsize->lppos, UnpackedNcCalcsize->lppos, sizeof(WINDOWPOS)); + *lParamPacked = (LPARAM) PackedNcCalcsize; } else if (WM_CREATE == Msg || WM_NCCREATE == Msg) { @@ -210,7 +216,7 @@ { Size += sizeof(WCHAR) + ClassName->Length + sizeof(WCHAR); } - PackedCs = ExAllocatePoolWithTag(PagedPool, Size, TAG_MSG); + PackedCs = ExAllocatePoolWithTag(PoolType, Size, TAG_MSG); if (NULL == PackedCs) { DPRINT1("Not enough memory to pack lParam\n"); @@ -244,11 +250,28 @@ *lParamPacked = (LPARAM) PackedCs; } + else if (PoolType == NonPagedPool) + { + PMSGMEMORY MsgMemoryEntry; + PVOID PackedData; + + MsgMemoryEntry = FindMsgMemory(Msg); + + if ((!MsgMemoryEntry) || (MsgMemoryEntry->Size < 0)) + { + /* Keep previous behavior */ + return STATUS_SUCCESS; + } + PackedData = ExAllocatePoolWithTag(NonPagedPool, MsgMemorySize(MsgMemoryEntry, wParam, lParam), TAG_MSG); + RtlCopyMemory(PackedData, (PVOID)lParam, MsgMemorySize(MsgMemoryEntry, wParam, lParam)); + *lParamPacked = (LPARAM)PackedData; + } + return STATUS_SUCCESS; } static NTSTATUS -UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam) +UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL NonPagedPoolUsed) { NCCALCSIZE_PARAMS *UnpackedParams; NCCALCSIZE_PARAMS *PackedParams; @@ -277,7 +300,24 @@ return STATUS_SUCCESS; } + else if (NonPagedPoolUsed) + { + PMSGMEMORY MsgMemoryEntry; + MsgMemoryEntry = FindMsgMemory(Msg); + if (MsgMemoryEntry->Size < 0) + { + /* Keep previous behavior */ + return STATUS_INVALID_PARAMETER; + } + if (MsgMemory->Flags == MMS_FLAG_READWRITE) + { + //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemory->Size); + } + ExFreePool((PVOID) lParamPacked); + return STATUS_SUCCESS; + } + ASSERT(FALSE); return STATUS_INVALID_PARAMETER; @@ -394,7 +434,7 @@ lParamBufferSize = MsgMemorySize(MsgMemoryEntry, pMsg->wParam, pMsg->lParam); } - if (! NT_SUCCESS(PackParam(&lParamPacked, pMsg->message, pMsg->wParam, pMsg->lParam))) + if (! NT_SUCCESS(PackParam(&lParamPacked, pMsg->message, pMsg->wParam, pMsg->lParam, FALSE))) { DPRINT1("Failed to pack message parameters\n"); return 0; @@ -408,7 +448,7 @@ lParamPacked, lParamBufferSize); - if (! NT_SUCCESS(UnpackParam(lParamPacked, pMsg->message, pMsg->wParam, pMsg->lParam))) + if (! NT_SUCCESS(UnpackParam(lParamPacked, pMsg->message, pMsg->wParam, pMsg->lParam, FALSE))) { DPRINT1("Failed to unpack message parameters\n"); } @@ -1372,7 +1412,7 @@ lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam); } - if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam))) + if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, FALSE))) { DPRINT1("Failed to pack message parameters\n"); RETURN( FALSE); @@ -1392,7 +1432,7 @@ IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult); - if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam))) + if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE))) { DPRINT1("Failed to unpack message parameters\n"); RETURN( TRUE); @@ -1499,7 +1539,149 @@ return (LRESULT) TRUE; } +LRESULT FASTCALL co_IntSendMessageNoWait(HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + ULONG_PTR Result = 0; + co_IntSendMessageWithCallBack(hWnd, + Msg, + wParam, + lParam, + NULL, + 0, + &Result); + return Result; +} +LRESULT FASTCALL +co_IntSendMessageWithCallBack( HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam, + SENDASYNCPROC CompletionCallback, + ULONG_PTR CompletionCallbackContext, + ULONG_PTR *uResult) +{ + ULONG_PTR Result; + PWINDOW_OBJECT Window = NULL; + PMSGMEMORY MsgMemoryEntry; + INT lParamBufferSize; + LPARAM lParamPacked; + PTHREADINFO Win32Thread; + DECLARE_RETURN(LRESULT); + USER_REFERENCE_ENTRY Ref; + PUSER_SENT_MESSAGE Message; + + if (!(Window = UserGetWindowObject(hWnd))) + { + RETURN(FALSE); + } + + UserRefObjectCo(Window, &Ref); + + if (Window->state & WINDOWSTATUS_DESTROYING) + { + /* FIXME - last error? */ + DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd); + RETURN(FALSE); + } + + Win32Thread = PsGetCurrentThreadWin32Thread(); + + IntCallWndProc( Window, hWnd, Msg, wParam, lParam); + + if (Win32Thread == NULL) + { + ASSERT(FALSE); + RETURN(FALSE); + } + + if (Win32Thread->TIF_flags & TIF_INCLEANUP) + { + /* Never send messages to exiting threads */ + RETURN(FALSE); + } + + /* See if this message type is present in the table */ + MsgMemoryEntry = FindMsgMemory(Msg); + if (NULL == MsgMemoryEntry) + { + lParamBufferSize = -1; + } + else + { + lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam); + } + + if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, Window->pti->MessageQueue != Win32Thread->MessageQueue))) + { + DPRINT1("Failed to pack message parameters\n"); + RETURN( FALSE); + } + + /* If this is not a callback and it can be sent now, then send it. */ + if ((Window->pti->MessageQueue == Win32Thread->MessageQueue) && (CompletionCallback == NULL)) + { + + Result = (ULONG_PTR)co_IntCallWindowProc( Window->Wnd->lpfnWndProc, + !Window->Wnd->Unicode, + hWnd, + Msg, + wParam, + lParamPacked, + lParamBufferSize ); + if(uResult) + { + *uResult = Result; + } + } + + IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult); + + if (Window->pti->MessageQueue == Win32Thread->MessageQueue) + { + if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE))) + { + DPRINT1("Failed to unpack message parameters\n"); + RETURN(TRUE); + } + RETURN(TRUE); + } + + if(!(Message = ExAllocatePoolWithTag(NonPagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG))) + { + DPRINT1("MsqSendMessage(): Not enough memory to allocate a message"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + Message->Msg.hwnd = hWnd; + Message->Msg.message = Msg; + Message->Msg.wParam = wParam; + Message->Msg.lParam = lParamPacked; + Message->CompletionEvent = NULL; + Message->Result = 0; + Message->SenderQueue = Win32Thread->MessageQueue; + IntReferenceMessageQueue(Message->SenderQueue); + IntReferenceMessageQueue(Window->pti->MessageQueue); + Message->CompletionCallback = CompletionCallback; + Message->CompletionCallbackContext = CompletionCallbackContext; + Message->HookMessage = MSQ_NORMAL | MSQ_SENTNOWAIT; + Message->HasPackedLParam = (lParamBufferSize > 0); + + InsertTailList(&Window->pti->MessageQueue->SentMessagesListHead, &Message->ListEntry); + InsertTailList(&Win32Thread->MessageQueue->DispatchingMessagesHead, &Message->DispatchingListEntry); + IntDereferenceMessageQueue(Window->pti->MessageQueue); + IntDereferenceMessageQueue(Message->SenderQueue); + + RETURN(TRUE); + +CLEANUP: + if (Window) UserDerefObjectCo(Window); + END_CLEANUP; +} + /* This function posts a message if the destination's message queue belongs to another thread, otherwise it sends the message. It does not support broadcast messages! */ Index: subsystems/win32/win32k/ntuser/focus.c =================================================================== --- subsystems/win32/win32k/ntuser/focus.c (revision 47121) +++ subsystems/win32/win32k/ntuser/focus.c (working copy) @@ -53,8 +53,8 @@ { if (hWndPrev) { - co_IntPostOrSendMessage(hWndPrev, WM_NCACTIVATE, FALSE, 0); - co_IntPostOrSendMessage(hWndPrev, WM_ACTIVATE, + co_IntSendMessageNoWait(hWndPrev, WM_NCACTIVATE, FALSE, 0); + co_IntSendMessageNoWait(hWndPrev, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, UserGetWindowLong(hWndPrev, GWL_STYLE, FALSE) & WS_MINIMIZE), (LPARAM)hWnd); } @@ -105,38 +105,19 @@ if (Window && WindowPrev) { - PWINDOW_OBJECT cWindow; - HWND *List, *phWnd; HANDLE OldTID = IntGetWndThreadId(WindowPrev); HANDLE NewTID = IntGetWndThreadId(Window); - DPRINT("SendActiveMessage Old -> %x, New -> %x\n", OldTID, NewTID); + DPRINT1("SendActiveMessage Old -> %x, New -> %x\n", OldTID, NewTID); + if (Window->Wnd->style & WS_MINIMIZE) + { + DPRINT1("Widow was nminimized\n"); + } if (OldTID != NewTID) { - List = IntWinListChildren(UserGetWindowObject(IntGetDesktopWindow())); - if (List) - { - for (phWnd = List; *phWnd; ++phWnd) - { - cWindow = UserGetWindowObject(*phWnd); - if (cWindow && (IntGetWndThreadId(cWindow) == OldTID)) - { // FALSE if the window is being deactivated, - // ThreadId that owns the window being activated. - co_IntPostOrSendMessage(*phWnd, WM_ACTIVATEAPP, FALSE, (LPARAM)NewTID); - } - } - for (phWnd = List; *phWnd; ++phWnd) - { - cWindow = UserGetWindowObject(*phWnd); - if (cWindow && (IntGetWndThreadId(cWindow) == NewTID)) - { // TRUE if the window is being activated, - // ThreadId that owns the window being deactivated. - co_IntPostOrSendMessage(*phWnd, WM_ACTIVATEAPP, TRUE, (LPARAM)OldTID); - } - } - ExFreePool(List); - } + co_IntSendMessageNoWait(hWndPrev, WM_ACTIVATEAPP, FALSE, (LPARAM)NewTID); + co_IntSendMessageNoWait(hWnd, WM_ACTIVATEAPP, TRUE, (LPARAM)OldTID); } UserDerefObjectCo(WindowPrev); // Now allow the previous window to die. } @@ -144,10 +125,9 @@ UserDerefObjectCo(Window); /* FIXME: IntIsWindow */ - - co_IntPostOrSendMessage(hWnd, WM_NCACTIVATE, (WPARAM)(hWnd == UserGetForegroundWindow()), 0); + co_IntSendMessageNoWait(hWnd, WM_NCACTIVATE, (WPARAM)(hWnd == UserGetForegroundWindow()), 0); /* FIXME: WA_CLICKACTIVE */ - co_IntPostOrSendMessage(hWnd, WM_ACTIVATE, + co_IntSendMessageNoWait(hWnd, WM_ACTIVATE, MAKEWPARAM(MouseActivate ? WA_CLICKACTIVE : WA_ACTIVE, UserGetWindowLong(hWnd, GWL_STYLE, FALSE) & WS_MINIMIZE), (LPARAM)hWndPrev); @@ -241,7 +221,9 @@ co_IntSendDeactivateMessages(hWndPrev, hWnd); co_IntSendKillFocusMessages(hWndFocusPrev, hWndFocus); + IntSetFocusMessageQueue(Window->pti->MessageQueue); + if (Window->pti->MessageQueue) { Window->pti->MessageQueue->ActiveWindow = hWnd; Index: subsystems/win32/win32k/ntuser/winpos.c =================================================================== --- subsystems/win32/win32k/ntuser/winpos.c (revision 47121) +++ subsystems/win32/win32k/ntuser/winpos.c (working copy) @@ -69,9 +69,6 @@ return TRUE; } - - - BOOL FASTCALL UserGetClientOrigin(PWINDOW_OBJECT Window, LPPOINT Point) { @@ -120,6 +117,8 @@ style = Wnd->Wnd->style; if (!(style & WS_VISIBLE) && Wnd->pti->pEThread->ThreadsProcess != CsrProcess) return FALSE; + if ((style & WS_MINIMIZE) && + Wnd->pti->pEThread->ThreadsProcess != CsrProcess) return FALSE; if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE; return !(style & WS_DISABLED); } @@ -164,6 +163,13 @@ if (can_activate_window( WndTo )) break; } + if (WndTo == NULL) + { + WndTo = Window->spwndPrev; + if (!can_activate_window( WndTo )) + WndTo = NULL; + } + done: if (WndTo) UserRefObjectCo(WndTo, &Ref); @@ -172,7 +178,7 @@ if ((!Fg || Window->hSelf == Fg) && WndTo)//fixme: ok if WndTo is NULL?? { /* fixme: wine can pass WndTo=NULL to co_IntSetForegroundWindow. hmm */ - if (co_IntSetForegroundWindow(WndTo)) + if (co_IntMouseActivateWindow(WndTo)) { UserDerefObjectCo(WndTo); return; @@ -203,7 +209,7 @@ xspacing = UserGetSystemMetrics(SM_CXMINSPACING); yspacing = UserGetSystemMetrics(SM_CYMINSPACING); - DPRINT("X:%d Y:%d XS:%d YS:%d\n",x,y,xspacing,yspacing); + DPRINT1("X:%d Y:%d XS:%d YS:%d\n",x,y,xspacing,yspacing); for( i = 0; List[i]; i++) { @@ -312,7 +318,7 @@ if (Wnd->style & WS_MINIMIZE) { - if (!co_IntSendMessage(Window->hSelf, WM_QUERYOPEN, 0, 0)) + if (!co_IntSendMessageNoWait(Window->hSelf, WM_QUERYOPEN, 0, 0)) { return(SWP_NOSIZE | SWP_NOMOVE); } @@ -531,7 +537,7 @@ params.lppos = &winposCopy; winposCopy = *WinPos; - wvrFlags = co_IntSendMessage(Window->hSelf, WM_NCCALCSIZE, TRUE, (LPARAM) ¶ms); + wvrFlags = co_IntSendMessageNoWait(Window->hSelf, WM_NCCALCSIZE, TRUE, (LPARAM) ¶ms); /* If the application send back garbage, ignore it */ if (params.rgrc[0].left <= params.rgrc[0].right && @@ -590,7 +596,7 @@ if (!(WinPos->flags & SWP_NOSENDCHANGING)) { - co_IntPostOrSendMessage(Window->hSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM) WinPos); + co_IntSendMessageNoWait(Window->hSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM) WinPos); } *WindowRect = Wnd->rcWindow; @@ -1320,7 +1326,7 @@ { if ((Window->Wnd->style & (WS_CHILD | WS_POPUP)) == WS_CHILD) { - co_IntSendMessage(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0); + co_IntSendMessageNoWait(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0); } else { @@ -1330,7 +1336,7 @@ } if ((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) - co_IntPostOrSendMessage(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos); + co_IntSendMessageNoWait(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos); return TRUE; } @@ -1343,7 +1349,7 @@ ASSERT_REFS_CO(Window); *ClientRect = *WindowRect; - Result = co_IntSendMessage(Window->hSelf, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect); + Result = co_IntSendMessageNoWait(Window->hSelf, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect); FixClientRect(ClientRect, WindowRect); @@ -1462,7 +1468,7 @@ if (ShowFlag != WasVisible) { - co_IntSendMessage(Window->hSelf, WM_SHOWWINDOW, ShowFlag, 0); + co_IntSendMessageNoWait(Window->hSelf, WM_SHOWWINDOW, ShowFlag, 0); } /* We can't activate a child window */ @@ -1476,7 +1482,7 @@ ? HWND_TOPMOST : HWND_TOP, NewPos.left, NewPos.top, NewPos.right, NewPos.bottom, LOWORD(Swp)); - if (Cmd == SW_HIDE) + if ((Cmd == SW_HIDE) || (Cmd == SW_MINIMIZE)) { PWINDOW_OBJECT ThreadFocusWindow; @@ -1520,12 +1526,12 @@ wParam = SIZE_MINIMIZED; } - co_IntSendMessage(Window->hSelf, WM_SIZE, wParam, + co_IntSendMessageNoWait(Window->hSelf, WM_SIZE, wParam, MAKELONG(Wnd->rcClient.right - Wnd->rcClient.left, Wnd->rcClient.bottom - Wnd->rcClient.top)); - co_IntSendMessage(Window->hSelf, WM_MOVE, 0, + co_IntSendMessageNoWait(Window->hSelf, WM_MOVE, 0, MAKELONG(Wnd->rcClient.left, Wnd->rcClient.top)); IntEngWindowChanged(Window, WOC_RGN_CLIENT); Index: subsystems/win32/win32k/ntuser/msgqueue.c =================================================================== --- subsystems/win32/win32k/ntuser/msgqueue.c (revision 47121) +++ subsystems/win32/win32k/ntuser/msgqueue.c (working copy) @@ -969,7 +969,7 @@ /* remove the message from the dispatching list, so lock the sender's message queue */ SenderReturned = (Message->DispatchingListEntry.Flink == NULL); - if(!SenderReturned) + if (!SenderReturned) { /* only remove it from the dispatching list if not already removed by a timeout */ RemoveEntryList(&Message->DispatchingListEntry); @@ -983,6 +983,12 @@ *Message->Result = Result; } + if (Message->HasPackedLParam == TRUE) + { + if (Message->Msg.lParam) + ExFreePool((PVOID)Message->Msg.lParam); + } + /* Notify the sender. */ if (Message->CompletionEvent != NULL) { @@ -1010,9 +1016,12 @@ Notified: - /* dereference both sender and our queue */ - IntDereferenceMessageQueue(MessageQueue); - IntDereferenceMessageQueue(Message->SenderQueue); + /* Only if it is not a no wait message */ + if (!(Message->HookMessage & MSQ_SENTNOWAIT)) + { + IntDereferenceMessageQueue(Message->SenderQueue); + IntDereferenceMessageQueue(MessageQueue); + } /* free the message */ ExFreePool(Message); @@ -1147,6 +1156,7 @@ IntReferenceMessageQueue(ThreadQueue); Message->CompletionCallback = NULL; Message->HookMessage = HookMessage; + Message->HasPackedLParam = FALSE; IntReferenceMessageQueue(MessageQueue); Index: subsystems/win32/win32k/include/msgqueue.h =================================================================== --- subsystems/win32/win32k/include/msgqueue.h (revision 47121) +++ subsystems/win32/win32k/include/msgqueue.h (working copy) @@ -6,6 +6,7 @@ #define MSQ_NORMAL 0 #define MSQ_ISHOOK 1 #define MSQ_ISEVENT 2 +#define MSQ_SENTNOWAIT 0x80000000 typedef struct _USER_MESSAGE { @@ -28,6 +29,7 @@ /* entry in the dispatching list of the sender's message queue */ LIST_ENTRY DispatchingListEntry; INT HookMessage; + BOOL HasPackedLParam; } USER_SENT_MESSAGE, *PUSER_SENT_MESSAGE; typedef struct _USER_SENT_MESSAGE_NOTIFY @@ -184,7 +186,21 @@ UINT uFlags, UINT uTimeout, ULONG_PTR *uResult); + +LRESULT FASTCALL co_IntSendMessageNoWait(HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam); LRESULT FASTCALL +co_IntSendMessageWithCallBack(HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam, + SENDASYNCPROC CompletionCallback, + ULONG_PTR CompletionCallbackContext, + ULONG_PTR *uResult); + +LRESULT FASTCALL IntDispatchMessage(MSG* Msg); BOOL FASTCALL IntTranslateKbdMessage(LPMSG lpMsg, UINT flags);