HBRUSH FASTCALL GetControlColor( PWND pwndParent, PWND pwnd, HDC hdc, UINT CtlMsg) { HBRUSH hBrush; if (!pwndParent) pwndParent = pwnd; if ( pwndParent->head.pti->ppi != PsGetCurrentProcessWin32Process()) { return (HBRUSH)IntDefWindowProc( pwndParent, CtlMsg, (WPARAM)hdc, (LPARAM)UserHMGetHandle(pwnd), FALSE); } hBrush = (HBRUSH)co_IntSendMessage( UserHMGetHandle(pwndParent), CtlMsg, (WPARAM)hdc, (LPARAM)UserHMGetHandle(pwnd)); if (!hBrush || !GreIsHandleValid(hBrush)) { hBrush = (HBRUSH)IntDefWindowProc( pwndParent, CtlMsg, (WPARAM)hdc, (LPARAM)UserHMGetHandle(pwnd), FALSE); } return hBrush; }
/* * co_UserActivateKbl * * Activates given layout in specified thread */ static PKL co_UserActivateKbl(PTHREADINFO pti, PKL pKl, UINT Flags) { PKL pklPrev; pklPrev = pti->KeyboardLayout; if (pklPrev) UserDereferenceObject(pklPrev); pti->KeyboardLayout = pKl; pti->pClientInfo->hKL = pKl->hkl; UserReferenceObject(pKl); if (Flags & KLF_SETFORPROCESS) { // FIXME } // Send WM_INPUTLANGCHANGE to thread's focus window co_IntSendMessage(pti->MessageQueue->spwndFocus ? UserHMGetHandle(pti->MessageQueue->spwndFocus) : 0, WM_INPUTLANGCHANGE, (WPARAM)pKl->iBaseCharset, // FIXME: How to set it? (LPARAM)pKl->hkl); // hkl return pklPrev; }
VOID FASTCALL FindRemoveAsyncMsg(PWND Wnd, WPARAM wParam) { PTHREADINFO pti; PUSER_SENT_MESSAGE Message; PLIST_ENTRY Entry; if (!Wnd) return; pti = Wnd->head.pti; if (!IsListEmpty(&pti->SentMessagesListHead)) { // Scan sent queue messages to see if we received async messages. Entry = pti->SentMessagesListHead.Flink; Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry); do { if (IsListEmpty(Entry)) return; if (!Message) return; Entry = Message->ListEntry.Flink; if (Message->Msg.message == WM_ASYNC_SETACTIVEWINDOW && Message->Msg.hwnd == UserHMGetHandle(Wnd) && Message->Msg.wParam == wParam ) { ERR("ASYNC SAW: Found one in the Sent Msg Queue! %p Activate/Deactivate %d\n", Message->Msg.hwnd,!!wParam); RemoveEntryList(&Message->ListEntry); // Purge the entry. ExFreePoolWithTag(Message, TAG_USRMSG); } Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry); } while (Entry != &pti->SentMessagesListHead); } }
VOID FASTCALL FindRemoveAsyncMsg(PWND Wnd) { PTHREADINFO pti; PUSER_SENT_MESSAGE Message; PLIST_ENTRY Entry; if (!Wnd) return; pti = Wnd->head.pti; if (!IsListEmpty(&pti->SentMessagesListHead)) { // Scan sent queue messages to see if we received async messages. Entry = pti->SentMessagesListHead.Flink; Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry); do { if (Message->Msg.message == WM_ASYNC_SETACTIVEWINDOW && Message->Msg.hwnd == UserHMGetHandle(Wnd) && Message->Msg.wParam == 0 ) { TRACE("ASYNC SAW: Found one in the Sent Msg Queue! %p\n", Message->Msg.hwnd); RemoveEntryList(Entry); // Purge the entry. } Entry = Message->ListEntry.Flink; Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry); } while (Entry != &pti->SentMessagesListHead); } }
static BOOL FASTCALL RemoveTimer(PTIMER pTmr) { BOOL Ret = FALSE; if (pTmr) { /* Set the flag, it will be removed when ready */ RemoveEntryList(&pTmr->ptmrList); if ((pTmr->pWnd == NULL) && (!(pTmr->flags & TMRF_SYSTEM))) // System timers are reusable. { UINT_PTR IDEvent; IDEvent = NUM_WINDOW_LESS_TIMERS - pTmr->nID; IntLockWindowlessTimerBitmap(); RtlClearBit(&WindowLessTimersBitMap, IDEvent); IntUnlockWindowlessTimerBitmap(); } UserDereferenceObject(pTmr); Ret = UserDeleteObject( UserHMGetHandle(pTmr), otTimer); } if (!Ret) ERR("Warning: Unable to delete timer\n"); return Ret; }
// // Dispatch MsgQueue Event Call processor! // LRESULT FASTCALL co_EVENT_CallEvents( DWORD event, HWND hwnd, UINT_PTR idObject, LONG_PTR idChild) { PEVENTHOOK pEH; LRESULT Result; PEVENTPACK pEP = (PEVENTPACK)idChild; pEH = pEP->pEH; Result = co_IntCallEventProc( UserHMGetHandle(pEH), event, hwnd, pEP->idObject, pEP->idChild, PtrToUint(NtCurrentTeb()->ClientId.UniqueThread), (DWORD)EngGetTickCount(), pEH->Proc); ExFreePoolWithTag(pEP, TAG_HOOK); return Result; }
HWND FASTCALL UserGetForegroundWindow(VOID) { PUSER_MESSAGE_QUEUE ForegroundQueue; ForegroundQueue = IntGetFocusMessageQueue(); return( ForegroundQueue ? (ForegroundQueue->spwndActive ? UserHMGetHandle(ForegroundQueue->spwndActive) : 0) : 0); }
HWND FASTCALL UserGetActiveWindow(VOID) { PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; return( ThreadQueue ? (ThreadQueue->spwndActive ? UserHMGetHandle(ThreadQueue->spwndActive) : 0) : 0); }
VOID FASTCALL IntSendFocusMessages( PTHREADINFO pti, PWND pWnd) { PWND pWndPrev; PUSER_MESSAGE_QUEUE ThreadQueue = pti->MessageQueue; // Queue can change... ThreadQueue->QF_flags &= ~QF_FOCUSNULLSINCEACTIVE; if (!pWnd && ThreadQueue->spwndActive) { ThreadQueue->QF_flags |= QF_FOCUSNULLSINCEACTIVE; } pWndPrev = ThreadQueue->spwndFocus; /* check if the specified window can be set in the input data of a given queue */ if (!pWnd || ThreadQueue == pWnd->head.pti->MessageQueue) /* set the current thread focus window */ ThreadQueue->spwndFocus = pWnd; if (pWnd) { if (pWndPrev) { //co_IntPostOrSendMessage(UserHMGetHandle(pWndPrev), WM_KILLFOCUS, (WPARAM)UserHMGetHandle(pWnd), 0); co_IntSendMessage(UserHMGetHandle(pWndPrev), WM_KILLFOCUS, (WPARAM)UserHMGetHandle(pWnd), 0); } if (ThreadQueue->spwndFocus == pWnd) { IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, CHILDID_SELF, 0); //co_IntPostOrSendMessage(UserHMGetHandle(pWnd), WM_SETFOCUS, (WPARAM)(pWndPrev ? UserHMGetHandle(pWndPrev) : NULL), 0); co_IntSendMessage(UserHMGetHandle(pWnd), WM_SETFOCUS, (WPARAM)(pWndPrev ? UserHMGetHandle(pWndPrev) : NULL), 0); } } else { if (pWndPrev) { IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0); //co_IntPostOrSendMessage(UserHMGetHandle(pWndPrev), WM_KILLFOCUS, 0, 0); co_IntSendMessage(UserHMGetHandle(pWndPrev), WM_KILLFOCUS, 0, 0); } } }
HWND FASTCALL IntGetThreadFocusWindow(VOID) { PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; if (!ThreadQueue) return NULL; return ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0; }
LRESULT FASTCALL DefWndGetIcon(PWND pWnd, WPARAM wParam, LPARAM lParam) { HICON hIconRet; if ( wParam > ICON_SMALL2 ) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } switch(wParam) { case ICON_BIG: hIconRet = UserGetProp(UserHMGetHandle(pWnd), gpsi->atomIconProp); break; case ICON_SMALL: case ICON_SMALL2: hIconRet = UserGetProp(UserHMGetHandle(pWnd), gpsi->atomIconSmProp); break; default: break; } return (LRESULT)hIconRet; }
/* IntAttachMonitor * * Creates a new MONITOR and appends it to the list of monitors. * * Arguments * * pGdiDevice Pointer to the PDEVOBJ onto which the monitor was attached * DisplayNumber Display Number (starting with 0) * * Return value * Returns a NTSTATUS */ NTSTATUS IntAttachMonitor(IN PDEVOBJ *pGdiDevice, IN ULONG DisplayNumber) { PMONITOR Monitor; WCHAR Buffer[CCHDEVICENAME]; TRACE("Attaching monitor...\n"); /* create new monitor object */ Monitor = IntCreateMonitorObject(); if (Monitor == NULL) { TRACE("Couldnt create monitor object\n"); return STATUS_INSUFFICIENT_RESOURCES; } _snwprintf(Buffer, CCHDEVICENAME, L"\\\\.\\DISPLAY%d", DisplayNumber + 1); if (!RtlCreateUnicodeString(&Monitor->DeviceName, Buffer)) { TRACE("Couldn't duplicate monitor name!\n"); UserDereferenceObject(Monitor); UserDeleteObject(UserHMGetHandle(Monitor), otMonitor); return STATUS_INSUFFICIENT_RESOURCES; } Monitor->GdiDevice = pGdiDevice; Monitor->cWndStack = 0; if (gMonitorList == NULL) { TRACE("Primary monitor is beeing attached\n"); Monitor->IsPrimary = TRUE; gMonitorList = Monitor; } else { PMONITOR p; TRACE("Additional monitor is beeing attached\n"); for (p = gMonitorList; p->Next != NULL; p = p->Next) { p->Next = Monitor; } Monitor->Prev = p; } IntUpdateMonitorSize(pGdiDevice); return STATUS_SUCCESS; }
// WM_SETICON LRESULT FASTCALL DefWndSetIcon(PWND pWnd, WPARAM wParam, LPARAM lParam) { HICON hIcon, hIconSmall, hIconOld; if ( wParam > ICON_SMALL2 ) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } hIconSmall = UserGetProp(UserHMGetHandle(pWnd), gpsi->atomIconSmProp); hIcon = UserGetProp(UserHMGetHandle(pWnd), gpsi->atomIconProp); hIconOld = wParam == ICON_BIG ? hIcon : hIconSmall; switch(wParam) { case ICON_BIG: hIcon = (HICON)lParam; break; case ICON_SMALL: hIconSmall = (HICON)lParam; break; case ICON_SMALL2: ERR("FIXME: Set ICON_SMALL2 support!\n"); default: break; } NtUserSetProp(UserHMGetHandle(pWnd), gpsi->atomIconProp, hIcon); NtUserSetProp(UserHMGetHandle(pWnd), gpsi->atomIconSmProp, hIconSmall); if ((pWnd->style & WS_CAPTION ) == WS_CAPTION) UserPaintCaption(UserHMGetHandle(pWnd)); /* Repaint caption */ return (LRESULT)hIconOld; }
/* IntDestroyMonitorObject * * Destroys a MONITOR * You have to be the owner of the monitors lock to safely destroy it. * * Arguments * * pMonitor * Pointer to the MONITOR which shall be deleted */ static void IntDestroyMonitorObject(IN PMONITOR pMonitor) { /* Remove monitor region */ if (pMonitor->hrgnMonitor) { GreSetObjectOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_POWNED); GreDeleteObject(pMonitor->hrgnMonitor); } /* Destroy monitor object */ UserDereferenceObject(pMonitor); UserDeleteObject(UserHMGetHandle(pMonitor), TYPE_MONITOR); }
HWND APIENTRY IntGetCapture(VOID) { PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; DECLARE_RETURN(HWND); TRACE("Enter IntGetCapture\n"); pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; RETURN( ThreadQueue ? (ThreadQueue->spwndCapture ? UserHMGetHandle(ThreadQueue->spwndCapture) : 0) : 0); CLEANUP: TRACE("Leave IntGetCapture, ret=%p\n", _ret_); END_CLEANUP; }
static BOOL FASTCALL IntRemoveEvent(PEVENTHOOK pEH) { if (pEH) { TRACE("IntRemoveEvent pEH 0x%x\n",pEH); KeEnterCriticalRegion(); RemoveEntryList(&pEH->Chain); GlobalEvents->Counts--; if (!GlobalEvents->Counts) gpsi->dwInstalledEventHooks = 0; UserDeleteObject(UserHMGetHandle(pEH), otEvent); KeLeaveCriticalRegion(); return TRUE; } return FALSE; }
/* * @implemented */ HWND WINAPI GetDesktopWindow(VOID) { PWND Wnd; HWND Ret = NULL; _SEH2_TRY { Wnd = GetThreadDesktopWnd(); if (Wnd != NULL) Ret = UserHMGetHandle(Wnd); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Do nothing */ } _SEH2_END; return Ret; }
/* * @implemented */ HWND WINAPI GetAncestor(HWND hwnd, UINT gaFlags) { HWND Ret = NULL; PWND Ancestor, Wnd; Wnd = ValidateHwnd(hwnd); if (!Wnd) return NULL; _SEH2_TRY { Ancestor = NULL; switch (gaFlags) { case GA_PARENT: if (Wnd->spwndParent != NULL) Ancestor = DesktopPtrToUser(Wnd->spwndParent); break; default: /* FIXME: Call win32k for now */ Wnd = NULL; break; } if (Ancestor != NULL) Ret = UserHMGetHandle(Ancestor); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Do nothing */ } _SEH2_END; if (!Wnd) /* Fall back */ Ret = NtUserGetAncestor(hwnd, gaFlags); return Ret; }
/* * @implemented */ HWND WINAPI GetLastActivePopup(HWND hWnd) { PWND Wnd; HWND Ret = hWnd; Wnd = ValidateHwnd(hWnd); if (Wnd != NULL) { _SEH2_TRY { if (Wnd->spwndLastActive) { PWND LastActive = DesktopPtrToUser(Wnd->spwndLastActive); Ret = UserHMGetHandle(LastActive); } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Do nothing */ } _SEH2_END; }
HWND APIENTRY NtUserSetActiveWindow(HWND hWnd) { USER_REFERENCE_ENTRY Ref; HWND hWndPrev; PWND Window; DECLARE_RETURN(HWND); TRACE("Enter NtUserSetActiveWindow(%p)\n", hWnd); UserEnterExclusive(); Window = NULL; if (hWnd) { if (!(Window = UserGetWindowObject(hWnd))) { ERR("NtUserSetActiveWindow: Invalid handle 0x%p!\n",hWnd); RETURN( NULL); } } if (!Window || Window->head.pti->MessageQueue == gptiCurrent->MessageQueue) { hWndPrev = gptiCurrent->MessageQueue->spwndActive ? UserHMGetHandle(gptiCurrent->MessageQueue->spwndActive) : NULL; if (Window) UserRefObjectCo(Window, &Ref); UserSetActiveWindow(Window); if (Window) UserDerefObjectCo(Window); RETURN( hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0 ); } RETURN( NULL); CLEANUP: TRACE("Leave NtUserSetActiveWindow, ret=%p\n",_ret_); UserLeave(); END_CLEANUP; }
BOOL APIENTRY NtUserGetGUIThreadInfo( DWORD idThread, /* If NULL use foreground thread */ LPGUITHREADINFO lpgui) { NTSTATUS Status; PTHRDCARETINFO CaretInfo; GUITHREADINFO SafeGui; PDESKTOP Desktop; PUSER_MESSAGE_QUEUE MsgQueue; PTHREADINFO W32Thread; PETHREAD Thread = NULL; DECLARE_RETURN(BOOLEAN); TRACE("Enter NtUserGetGUIThreadInfo\n"); UserEnterShared(); Status = MmCopyFromCaller(&SafeGui, lpgui, sizeof(DWORD)); if(!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN( FALSE); } if(SafeGui.cbSize != sizeof(GUITHREADINFO)) { EngSetLastError(ERROR_INVALID_PARAMETER); RETURN( FALSE); } if (idThread) { Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)idThread, &Thread); if(!NT_SUCCESS(Status)) { EngSetLastError(ERROR_ACCESS_DENIED); RETURN( FALSE); } W32Thread = (PTHREADINFO)Thread->Tcb.Win32Thread; Desktop = W32Thread->rpdesk; if (!Thread || !Desktop ) { if(Thread) ObDereferenceObject(Thread); EngSetLastError(ERROR_ACCESS_DENIED); RETURN( FALSE); } if ( W32Thread->MessageQueue ) MsgQueue = W32Thread->MessageQueue; else { if ( Desktop ) MsgQueue = Desktop->ActiveMessageQueue; } } else { /* Get the foreground thread */ /* FIXME: Handle NULL queue properly? */ MsgQueue = IntGetFocusMessageQueue(); if(!MsgQueue) { EngSetLastError(ERROR_ACCESS_DENIED); RETURN( FALSE); } } CaretInfo = &MsgQueue->CaretInfo; SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0); /* if (W32Thread->pMenuState->pGlobalPopupMenu) { SafeGui.flags |= GUI_INMENUMODE; if (W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify) SafeGui.hwndMenuOwner = UserHMGetHandle(W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify); if (W32Thread->pMenuState->pGlobalPopupMenu->fHasMenuBar) { if (W32Thread->pMenuState->pGlobalPopupMenu->fIsSysMenu) { SafeGui.flags |= GUI_SYSTEMMENUMODE; } } else { SafeGui.flags |= GUI_POPUPMENUMODE; } } */ SafeGui.hwndMenuOwner = MsgQueue->MenuOwner; if (MsgQueue->MenuOwner) SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState; if (MsgQueue->MoveSize) SafeGui.flags |= GUI_INMOVESIZE; /* FIXME: Add flag GUI_16BITTASK */ SafeGui.hwndActive = MsgQueue->spwndActive ? UserHMGetHandle(MsgQueue->spwndActive) : 0; SafeGui.hwndFocus = MsgQueue->spwndFocus ? UserHMGetHandle(MsgQueue->spwndFocus) : 0; SafeGui.hwndCapture = MsgQueue->spwndCapture ? UserHMGetHandle(MsgQueue->spwndCapture) : 0; SafeGui.hwndMoveSize = MsgQueue->MoveSize; SafeGui.hwndCaret = CaretInfo->hWnd; SafeGui.rcCaret.left = CaretInfo->Pos.x; SafeGui.rcCaret.top = CaretInfo->Pos.y; SafeGui.rcCaret.right = SafeGui.rcCaret.left + CaretInfo->Size.cx; SafeGui.rcCaret.bottom = SafeGui.rcCaret.top + CaretInfo->Size.cy; if (idThread) ObDereferenceObject(Thread); Status = MmCopyToCaller(lpgui, &SafeGui, sizeof(GUITHREADINFO)); if(!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN( FALSE); } RETURN( TRUE); CLEANUP: TRACE("Leave NtUserGetGUIThreadInfo, ret=%u\n",_ret_); UserLeave(); END_CLEANUP; }
/* IntGetMonitorsFromRect * * Returns a list of monitor handles/rectangles. The rectangles in the list are * the areas of intersection with the monitors. * * Arguments * * pRect * Rectangle in desktop coordinates. If this is NULL all monitors are * returned and the rect list is filled with the sizes of the monitors. * * phMonitorList * Pointer to an array of HMONITOR which is filled with monitor handles. * Can be NULL * * prcMonitorList * Pointer to an array of RECT which is filled with intersection rects in * desktop coordinates. * Can be NULL, will be ignored if no intersecting monitor is found and * flags is MONITOR_DEFAULTTONEAREST * * dwListSize * Size of the phMonitorList and prcMonitorList arguments. If this is zero * phMonitorList and prcMonitorList are ignored. * * dwFlags * Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL) * * Returns * The number of monitors which intersect the specified region. */ static UINT IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect, OPTIONAL OUT HMONITOR *phMonitorList, OPTIONAL OUT PRECTL prcMonitorList, OPTIONAL IN DWORD dwListSize, OPTIONAL IN DWORD dwFlags) { PMONITOR pMonitor, pNearestMonitor = NULL, pPrimaryMonitor = NULL; UINT cMonitors = 0; ULONG iNearestDistance = 0xffffffff; /* Find monitors which intersects the rectangle */ for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext) { RECTL MonitorRect, IntersectionRect; MonitorRect = pMonitor->rcMonitor; TRACE("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n", MonitorRect.left, MonitorRect.top, MonitorRect.right, MonitorRect.bottom); /* Save primary monitor for later usage */ if (dwFlags == MONITOR_DEFAULTTOPRIMARY && pMonitor->IsPrimary) pPrimaryMonitor = pMonitor; /* Check if a rect is given */ if (pRect == NULL) { /* No rect given, so use the full monitor rect */ IntersectionRect = MonitorRect; } /* We have a rect, calculate intersection */ else if (!RECTL_bIntersectRect(&IntersectionRect, &MonitorRect, pRect)) { /* Rects did not intersect */ if (dwFlags == MONITOR_DEFAULTTONEAREST) { ULONG cx, cy, iDistance; /* Get x and y distance */ cx = min(abs(MonitorRect.left - pRect->right), abs(pRect->left - MonitorRect.right)); cy = min(abs(MonitorRect.top - pRect->bottom), abs(pRect->top - MonitorRect.bottom)); /* Calculate distance square */ iDistance = cx * cx + cy * cy; /* Check if this is the new nearest monitor */ if (iDistance < iNearestDistance) { iNearestDistance = iDistance; pNearestMonitor = pMonitor; } } continue; } /* Check if there's space in the buffer */ if (cMonitors < dwListSize) { /* Save monitor data */ if (phMonitorList != NULL) phMonitorList[cMonitors] = UserHMGetHandle(pMonitor); if (prcMonitorList != NULL) prcMonitorList[cMonitors] = IntersectionRect; } /* Increase count of found monitors */ cMonitors++; } /* Nothing has been found? */ if (cMonitors == 0) { /* Check if we shall default to the nearest monitor */ if (dwFlags == MONITOR_DEFAULTTONEAREST && pNearestMonitor) { if (phMonitorList && dwListSize > 0) phMonitorList[cMonitors] = UserHMGetHandle(pNearestMonitor); cMonitors++; } /* Check if we shall default to the primary monitor */ else if (dwFlags == MONITOR_DEFAULTTOPRIMARY && pPrimaryMonitor) { if (phMonitorList != NULL && dwListSize > 0) phMonitorList[cMonitors] = UserHMGetHandle(pPrimaryMonitor); cMonitors++; } } return cMonitors; }
/* * @unimplemented */ DWORD_PTR APIENTRY NtUserGetThreadState( DWORD Routine) { DWORD_PTR ret = 0; TRACE("Enter NtUserGetThreadState\n"); if (Routine != THREADSTATE_GETTHREADINFO) { UserEnterShared(); } else { UserEnterExclusive(); } switch (Routine) { case THREADSTATE_GETTHREADINFO: GetW32ThreadInfo(); break; case THREADSTATE_FOCUSWINDOW: ret = (DWORD_PTR)IntGetThreadFocusWindow(); break; case THREADSTATE_CAPTUREWINDOW: /* FIXME: Should use UserEnterShared */ ret = (DWORD_PTR)IntGetCapture(); break; case THREADSTATE_PROGMANWINDOW: ret = (DWORD_PTR)GetW32ThreadInfo()->pDeskInfo->hProgmanWindow; break; case THREADSTATE_TASKMANWINDOW: ret = (DWORD_PTR)GetW32ThreadInfo()->pDeskInfo->hTaskManWindow; break; case THREADSTATE_ACTIVEWINDOW: ret = (DWORD_PTR)UserGetActiveWindow(); break; case THREADSTATE_INSENDMESSAGE: { PUSER_SENT_MESSAGE Message = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->pusmCurrent; TRACE("THREADSTATE_INSENDMESSAGE\n"); ret = ISMEX_NOSEND; if (Message) { if (Message->ptiSender) ret = ISMEX_SEND; else { if (Message->CompletionCallback) ret = ISMEX_CALLBACK; else ret = ISMEX_NOTIFY; } /* If ReplyMessage */ if (Message->QS_Flags & QS_SMRESULT) ret |= ISMEX_REPLIED; } break; } case THREADSTATE_GETMESSAGETIME: ret = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->timeLast; break; case THREADSTATE_UPTIMELASTREAD: { PTHREADINFO pti; pti = PsGetCurrentThreadWin32Thread(); pti->timeLast = EngGetTickCount32(); pti->pcti->tickLastMsgChecked = pti->timeLast; } break; case THREADSTATE_GETINPUTSTATE: ret = LOWORD(IntGetQueueStatus(QS_POSTMESSAGE|QS_TIMER|QS_PAINT|QS_SENDMESSAGE|QS_INPUT)) & (QS_KEY | QS_MOUSEBUTTON); break; case THREADSTATE_FOREGROUNDTHREAD: ret = (gpqForeground == GetW32ThreadInfo()->MessageQueue); break; case THREADSTATE_GETCURSOR: ret = (DWORD_PTR) (GetW32ThreadInfo()->MessageQueue->CursorObject ? UserHMGetHandle(GetW32ThreadInfo()->MessageQueue->CursorObject) : 0); break; case THREADSTATE_GETMESSAGEEXTRAINFO: ret = (DWORD_PTR)MsqGetMessageExtraInfo(); break; } TRACE("Leave NtUserGetThreadState, ret=%lu\n", ret); UserLeave(); return ret; }
/* Win32k counterpart of User DefWindowProc */ LRESULT FASTCALL IntDefWindowProc( PWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL Ansi) { LRESULT lResult = 0; USER_REFERENCE_ENTRY Ref; if (Msg > WM_USER) return 0; switch (Msg) { case WM_SYSCOMMAND: { ERR("hwnd %p WM_SYSCOMMAND %lx %lx\n", Wnd->head.h, wParam, lParam ); lResult = DefWndHandleSysCommand(Wnd, wParam, lParam); break; } case WM_SHOWWINDOW: { if ((Wnd->style & WS_VISIBLE) && wParam) break; if (!(Wnd->style & WS_VISIBLE) && !wParam) break; if (!Wnd->spwndOwner) break; if (LOWORD(lParam)) { if (wParam) { if (!(Wnd->state & WNDS_HIDDENPOPUP)) break; Wnd->state &= ~WNDS_HIDDENPOPUP; } else Wnd->state |= WNDS_HIDDENPOPUP; co_WinPosShowWindow(Wnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE); } } break; case WM_CLIENTSHUTDOWN: return IntClientShutdown(Wnd, wParam, lParam); case WM_APPCOMMAND: ERR("WM_APPCOMMAND\n"); if ( (Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD && Wnd != co_GetDesktopWindow(Wnd) ) { if (!co_HOOK_CallHooks(WH_SHELL, HSHELL_APPCOMMAND, wParam, lParam)) co_IntShellHookNotify(HSHELL_APPCOMMAND, wParam, lParam); break; } UserRefObjectCo(Wnd->spwndParent, &Ref); lResult = co_IntSendMessage(UserHMGetHandle(Wnd->spwndParent), WM_APPCOMMAND, wParam, lParam); UserDerefObjectCo(Wnd->spwndParent); break; case WM_CTLCOLORMSGBOX: case WM_CTLCOLOREDIT: case WM_CTLCOLORLISTBOX: case WM_CTLCOLORBTN: case WM_CTLCOLORDLG: case WM_CTLCOLORSTATIC: case WM_CTLCOLORSCROLLBAR: return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX); case WM_CTLCOLOR: return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam)); case WM_GETHOTKEY: return DefWndGetHotKey(Wnd); case WM_SETHOTKEY: return DefWndSetHotKey(Wnd, wParam); case WM_NCHITTEST: { POINT Point; Point.x = GET_X_LPARAM(lParam); Point.y = GET_Y_LPARAM(lParam); return GetNCHitEx(Wnd, Point); } case WM_SYNCPAINT: { HRGN hRgn; Wnd->state &= ~WNDS_SYNCPAINTPENDING; ERR("WM_SYNCPAINT\n"); hRgn = IntSysCreateRectRgn(0, 0, 0, 0); if (co_UserGetUpdateRgn(Wnd, hRgn, FALSE) != NULLREGION) { if (!wParam) wParam = (RDW_ERASENOW | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN); co_UserRedrawWindow(Wnd, NULL, hRgn, wParam); } GreDeleteObject(hRgn); return 0; } case WM_SETREDRAW: if (wParam) { if (!(Wnd->style & WS_VISIBLE)) { IntSetStyle( Wnd, WS_VISIBLE, 0 ); Wnd->state |= WNDS_SENDNCPAINT; } } else { if (Wnd->style & WS_VISIBLE) { co_UserRedrawWindow( Wnd, NULL, NULL, RDW_ALLCHILDREN | RDW_VALIDATE ); IntSetStyle( Wnd, 0, WS_VISIBLE ); } } return 0; /* ReactOS only. */ case WM_CBT: { switch (wParam) { case HCBT_MOVESIZE: { RECTL rt; if (lParam) { _SEH2_TRY { ProbeForRead((PVOID)lParam, sizeof(RECT), 1); RtlCopyMemory(&rt, (PVOID)lParam, sizeof(RECT)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { lResult = 1; } _SEH2_END; } if (!lResult) lResult = co_HOOK_CallHooks(WH_CBT, HCBT_MOVESIZE, (WPARAM)Wnd->head.h, lParam ? (LPARAM)&rt : 0); } break; } break; } break; } return lResult; }
BOOL FASTCALL co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOOL Async) { USER_REFERENCE_ENTRY Ref, RefPrev; HANDLE OldTID, NewTID; PTHREADINFO pti, ptiOld, ptiNew; BOOL InAAPM = FALSE; if (Window) { pti = PsGetCurrentThreadWin32Thread(); UserRefObjectCo(Window, &Ref); if (WindowPrev) UserRefObjectCo(WindowPrev, &RefPrev); /* Send palette messages */ if (gpsi->PUSIFlags & PUSIF_PALETTEDISPLAY && //co_IntPostOrSendMessage(UserHMGetHandle(Window), WM_QUERYNEWPALETTE, 0, 0)) co_IntSendMessage(UserHMGetHandle(Window), WM_QUERYNEWPALETTE, 0, 0)) { UserSendNotifyMessage( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)UserHMGetHandle(Window), 0); } //// Fixes bug 7089. if (!(Window->style & WS_CHILD)) { PWND pwndTemp = co_GetDesktopWindow(Window)->spwndChild; while (pwndTemp && !(pwndTemp->style & WS_VISIBLE)) pwndTemp = pwndTemp->spwndNext; if (Window != pwndTemp || (WindowPrev && !IntIsWindowVisible(WindowPrev))) { if (!Async || pti->MessageQueue == gpqForeground) { UINT flags = SWP_NOSIZE | SWP_NOMOVE; if (Window == pwndTemp) flags |= SWP_NOACTIVATE; //ERR("co_IntSendActivateMessages SetWindowPos! Async %d pti Q == FGQ %d\n",Async,pti->MessageQueue == gpqForeground); co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, flags); } } } //// //// CORE-1161 and CORE-6651 if (Window->spwndPrev) { HWND *phwndTopLevel, *phwndCurrent; PWND pwndCurrent, pwndDesktop; pwndDesktop = UserGetDesktopWindow(); if (Window->spwndParent == pwndDesktop ) { phwndTopLevel = IntWinListChildren(pwndDesktop); phwndCurrent = phwndTopLevel; while(*phwndCurrent) { pwndCurrent = UserGetWindowObject(*phwndCurrent); if (pwndCurrent && pwndCurrent->spwndOwner == Window ) { co_WinPosSetWindowPos(pwndCurrent, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE); } phwndCurrent++; } ExFreePool(phwndTopLevel); } } //// OldTID = WindowPrev ? IntGetWndThreadId(WindowPrev) : NULL; NewTID = IntGetWndThreadId(Window); ptiOld = WindowPrev ? WindowPrev->head.pti : NULL; ptiNew = Window->head.pti; //ERR("SendActivateMessage Old -> %x, New -> %x\n", OldTID, NewTID); if (!(pti->TIF_flags & TIF_INACTIVATEAPPMSG) && (!WindowPrev || OldTID != NewTID) ) { PWND cWindow; HWND *List, *phWnd; List = IntWinListChildren(UserGetDesktopWindow()); if ( List ) { if ( OldTID ) { ptiOld->TIF_flags |= TIF_INACTIVATEAPPMSG; // Note: Do not set pci flags, this does crash! for (phWnd = List; *phWnd; ++phWnd) { cWindow = ValidateHwndNoErr(*phWnd); if (cWindow && cWindow->head.pti == ptiOld) { // FALSE if the window is being deactivated, // ThreadId that owns the window being activated. co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, FALSE, (LPARAM)NewTID); } } ptiOld->TIF_flags &= ~TIF_INACTIVATEAPPMSG; } if ( NewTID ) { //// Prevents a resource crash due to reentrance! InAAPM = TRUE; pti->TIF_flags |= TIF_INACTIVATEAPPMSG; //// for (phWnd = List; *phWnd; ++phWnd) { cWindow = ValidateHwndNoErr(*phWnd); if (cWindow && cWindow->head.pti == ptiNew) { // TRUE if the window is being activated, // ThreadId that owns the window being deactivated. co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, TRUE, (LPARAM)OldTID); } } } ExFreePoolWithTag(List, USERTAG_WINDOWLIST); } } if (WindowPrev) UserDerefObjectCo(WindowPrev); // Now allow the previous window to die. if (Window->state & WNDS_ACTIVEFRAME) { // If already active frame do not allow NCPaint. //ERR("SendActivateMessage Is Active Frame!\n"); Window->state |= WNDS_NONCPAINT; } if (Window->style & WS_MINIMIZE) { TRACE("Widow was minimized\n"); } co_IntMakeWindowActive(Window); /* FIXME: IntIsWindow */ co_IntSendMessageNoWait( UserHMGetHandle(Window), WM_NCACTIVATE, (WPARAM)(Window == (gpqForeground ? gpqForeground->spwndActive : NULL)), 0); //(LPARAM)hWndPrev); co_IntSendMessageNoWait( UserHMGetHandle(Window), WM_ACTIVATE, MAKEWPARAM(MouseActivate ? WA_CLICKACTIVE : WA_ACTIVE, Window->style & WS_MINIMIZE), (LPARAM)(WindowPrev ? UserHMGetHandle(WindowPrev) : 0)); if (!Window->spwndOwner && !IntGetParent(Window)) { // FIXME lParam; The value is TRUE if the window is in full-screen mode, or FALSE otherwise. co_IntShellHookNotify(HSHELL_WINDOWACTIVATED, (WPARAM) UserHMGetHandle(Window), FALSE); } Window->state &= ~WNDS_NONCPAINT; UserDerefObjectCo(Window); } return InAAPM; }
/* IntGetMonitorsFromRect * * Returns a list of monitor handles/rectangles. The rectangles in the list are * the areas of intersection with the monitors. * * Arguments * * pRect * Rectangle in desktop coordinates. If this is NULL all monitors are * returned and the rect list is filled with the sizes of the monitors. * * hMonitorList * Pointer to an array of HMONITOR which is filled with monitor handles. * Can be NULL * * monitorRectList * Pointer to an array of RECT which is filled with intersection rects in * desktop coordinates. * Can be NULL, will be ignored if no intersecting monitor is found and * flags is MONITOR_DEFAULTTONEAREST * * listSize * Size of the hMonitorList and monitorRectList arguments. If this is zero * hMonitorList and monitorRectList are ignored. * * flags * Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL) * * Returns * The number of monitors which intersect the specified region. */ static UINT IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect, OPTIONAL OUT HMONITOR *hMonitorList, OPTIONAL OUT PRECTL monitorRectList, OPTIONAL IN DWORD listSize, OPTIONAL IN DWORD flags) { PMONITOR Monitor, NearestMonitor = NULL, PrimaryMonitor = NULL; UINT iCount = 0; ULONG iNearestDistance = 0xffffffff; /* Find monitors which intersect the rectangle */ for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next) { RECTL MonitorRect, IntersectionRect; ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&Monitor->Lock); MonitorRect = Monitor->rcMonitor; ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&Monitor->Lock); TRACE("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n", MonitorRect.left, MonitorRect.top, MonitorRect.right, MonitorRect.bottom); if (flags == MONITOR_DEFAULTTOPRIMARY && Monitor->IsPrimary) { PrimaryMonitor = Monitor; } /* Check if a rect is given */ if (pRect == NULL) { /* No rect given, so use the full monitor rect */ IntersectionRect = MonitorRect; } /* We have a rect, calculate intersection */ else if (!RECTL_bIntersectRect(&IntersectionRect, &MonitorRect, pRect)) { /* Rects did not intersect */ if (flags == MONITOR_DEFAULTTONEAREST) { ULONG cx, cy, iDistance; /* Get x and y distance */ cx = min(abs(MonitorRect.left - pRect->right), abs(pRect->left - MonitorRect.right)); cy = min(abs(MonitorRect.top - pRect->bottom), abs(pRect->top - MonitorRect.bottom)); /* Calculate distance square */ iDistance = cx * cx + cy * cy; /* Check if this is the new nearest monitor */ if (iDistance < iNearestDistance) { iNearestDistance = iDistance; NearestMonitor = Monitor; } } continue; } /* Check if there's space in the buffer */ if (iCount < listSize) { if (hMonitorList != NULL) hMonitorList[iCount] = UserHMGetHandle(Monitor); if (monitorRectList != NULL) monitorRectList[iCount] = IntersectionRect; } /* Increase count of found monitors */ iCount++; } /* Found nothing intersecting? */ if (iCount == 0) { /* Check if we shall default to the nearest monitor */ if (flags == MONITOR_DEFAULTTONEAREST && NearestMonitor) { if (hMonitorList && listSize > 0) hMonitorList[iCount] = UserHMGetHandle(NearestMonitor); iCount++; } /* Check if we shall default to the primary monitor */ else if (flags == MONITOR_DEFAULTTOPRIMARY && PrimaryMonitor) { if (hMonitorList != NULL && listSize > 0) hMonitorList[iCount] = UserHMGetHandle(PrimaryMonitor); iCount++; } } return iCount; }
HWND FASTCALL IntGetCaptureWindow(VOID) { PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); return ( ForegroundQueue ? (ForegroundQueue->spwndCapture ? UserHMGetHandle(ForegroundQueue->spwndCapture) : 0) : 0); }
HWND FASTCALL co_UserSetFocus(PWND Window) { HWND hWndPrev = 0; PWND pwndTop; PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; if (Window) ASSERT_REFS_CO(Window); pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; ASSERT(ThreadQueue != 0); TRACE("Enter SetFocus hWnd 0x%p pti 0x%p\n",Window ? UserHMGetHandle(Window) : 0, pti ); hWndPrev = ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0; if (Window != 0) { if (hWndPrev == UserHMGetHandle(Window)) { return hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0; /* Nothing to do */ } if (Window->head.pti->MessageQueue != ThreadQueue) { ERR("SetFocus Must have the same Q!\n"); return 0; } /* Check if we can set the focus to this window */ for (pwndTop = Window; pwndTop != NULL; pwndTop = pwndTop->spwndParent) { if (pwndTop->style & (WS_MINIMIZED|WS_DISABLED)) return 0; if ((pwndTop->style & (WS_POPUP|WS_CHILD)) != WS_CHILD) break; } if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev)) { ERR("SetFocus 1 WH_CBT Call Hook return!\n"); return 0; } /* Activate pwndTop if needed. */ if (pwndTop != ThreadQueue->spwndActive) { PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); // Keep it based on desktop. if (ThreadQueue != ForegroundQueue && IsAllowedFGActive(pti, pwndTop)) // Rule 2 & 3. { //ERR("SetFocus: Set Foreground!\n"); if (!(pwndTop->style & WS_VISIBLE)) { pti->ppi->W32PF_flags |= W32PF_ALLOWFOREGROUNDACTIVATE; } if (!co_IntSetForegroundAndFocusWindow(pwndTop, FALSE)) { ERR("SetFocus: Set Foreground and Focus Failed!\n"); return 0; } } /* Set Active when it is needed. */ if (pwndTop != ThreadQueue->spwndActive) { //ERR("SetFocus: Set Active!\n"); if (!co_IntSetActiveWindow(pwndTop, FALSE, FALSE, FALSE)) { ERR("SetFocus: Set Active Failed!\n"); return 0; } } /* Abort if window destroyed */ if (Window->state2 & WNDS2_INDESTROY) return 0; /* Do not change focus if the window is no longer active */ if (pwndTop != ThreadQueue->spwndActive) { ERR("SetFocus: Top window did not go active!\n"); return 0; } } // Check again! SetActiveWindow could have set the focus via WM_ACTIVATE. hWndPrev = ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0; IntSendFocusMessages( pti, Window); TRACE("Focus: %p -> %p\n", hWndPrev, Window->head.h); } else /* NULL hwnd passed in */ { if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev)) { ERR("SetFocus: 2 WH_CBT Call Hook return!\n"); return 0; } /* set the current thread focus window null */ IntSendFocusMessages( pti, NULL); } return hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0; }
BOOL FASTCALL co_IntSetActiveWindow(PWND Wnd OPTIONAL, BOOL bMouse, BOOL bFocus, BOOL Async) { PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; PWND pWndChg, WndPrev; // State changes. HWND hWndPrev; HWND hWnd = 0; BOOL InAAPM; CBTACTIVATESTRUCT cbt; //ERR("co_IntSetActiveWindow 1\n"); if (Wnd) { ASSERT_REFS_CO(Wnd); hWnd = UserHMGetHandle(Wnd); if ((Wnd->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE; if (Wnd == UserGetDesktopWindow()) return FALSE; //ERR("co_IntSetActiveWindow 1a hWnd 0x%p\n",hWnd); } //ERR("co_IntSetActiveWindow 2\n"); pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; ASSERT(ThreadQueue != 0); hWndPrev = ThreadQueue->spwndActive ? UserHMGetHandle(ThreadQueue->spwndActive) : NULL; pWndChg = ThreadQueue->spwndActive; // Keep to notify of a preemptive switch. while (Wnd) { BOOL Ret, DoFG, AllowFG; if (Wnd->state & WNDS_BEINGACTIVATED) return TRUE; if (ThreadQueue == Wnd->head.pti->MessageQueue) { if (IsAllowedFGActive(pti, Wnd)) { DoFG = TRUE; } else { //ERR("co_IntSetActiveWindow 3 Go Out!\n"); break; } AllowFG = !pti->cVisWindows; // Nothing is visable. //ERR("co_IntSetActiveWindow 3a DoFG = %d AllowFG = %d\n",DoFG,AllowFG); } else //if (ThreadQueue != Wnd->head.pti->MessageQueue) { //PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); // Rule 1 & 4, We are foreground so set this FG window or NULL foreground.... //if (!ForegroundQueue || ForegroundQueue == ThreadQueue) if (!gpqForeground || gpqForeground == ThreadQueue) { DoFG = TRUE; } else DoFG = FALSE; if (DoFG) { if (pti->TIF_flags & TIF_ALLOWFOREGROUNDACTIVATE || pti->cVisWindows) AllowFG = TRUE; else AllowFG = FALSE; } else AllowFG = FALSE; //ERR("co_IntSetActiveWindow 3b DoFG = %d AllowFG = %d\n",DoFG,AllowFG); } Ret = FALSE; if (DoFG) { pti->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; //ERR("co_IntSetActiveWindow 3c FG set\n"); Ret = co_IntSetForegroundAndFocusWindow(Wnd, bMouse); if (AllowFG) { pti->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; } else { pti->TIF_flags &= ~TIF_ALLOWFOREGROUNDACTIVATE; } } return Ret; } /* Call CBT hook chain */ cbt.fMouse = bMouse; cbt.hWndActive = hWndPrev; if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt)) { ERR("SetActiveWindow: WH_CBT Call Hook return!\n"); return FALSE; } if ( ThreadQueue->spwndActive && ThreadQueue->spwndActive->state & WNDS_DESTROYED ) ThreadQueue->spwndActive = NULL; else ThreadQueue->spwndActivePrev = ThreadQueue->spwndActive; WndPrev = ThreadQueue->spwndActive; // Keep to save changing active. if (WndPrev) { if (ThreadQueue == gpqForeground) gpqForegroundPrev = ThreadQueue; if (!co_IntSendDeactivateMessages(UserHMGetHandle(WndPrev), hWnd)) return FALSE; } WndPrev = ThreadQueue->spwndActive; // Again keep to save changing active. // While in calling message proc or hook: // Fail if a preemptive switch was made, current active not made previous, // focus window is dead or no longer the same thread queue. if ( ThreadQueue->spwndActivePrev != ThreadQueue->spwndActive || pWndChg != WndPrev || (Wnd && !VerifyWnd(Wnd)) || ThreadQueue != pti->MessageQueue ) { ERR("SetActiveWindow: Summery ERROR, active state changed!\n"); return FALSE; } if (!WndPrev) ThreadQueue->QF_flags &= ~QF_FOCUSNULLSINCEACTIVE; if (Wnd) Wnd->state |= WNDS_BEINGACTIVATED; IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); //// Breaks Atl-Esc/Tab via User32. ////FindRemoveAsyncMsg(Wnd,(WPARAM)Wnd); // Clear out activate ASYNC messages. /* check if the specified window can be set in the input data of a given queue */ if ( !Wnd || ThreadQueue == Wnd->head.pti->MessageQueue) { /* set the current thread active window */ ThreadQueue->spwndActive = Wnd; } WndPrev = VerifyWnd(ThreadQueue->spwndActivePrev); // Now should be set but verify it again. InAAPM = co_IntSendActivateMessages(WndPrev, Wnd, bMouse, Async); /* now change focus if necessary */ if (bFocus && !(ThreadQueue->QF_flags & QF_FOCUSNULLSINCEACTIVE)) { /* Do not change focus if the window is no longer active */ if (ThreadQueue->spwndActive == Wnd) { if (!ThreadQueue->spwndFocus || !Wnd || UserGetAncestor(ThreadQueue->spwndFocus, GA_ROOT) != Wnd) { co_UserSetFocus(Wnd); } } } if (InAAPM) { pti->TIF_flags &= ~TIF_INACTIVATEAPPMSG; } // FIXME: Used in the menu loop!!! //ThreadQueue->QF_flags |= QF_ACTIVATIONCHANGE; //ERR("co_IntSetActiveWindow Exit\n"); if (Wnd) Wnd->state &= ~WNDS_BEINGACTIVATED; return (ThreadQueue->spwndActive == Wnd); }
/* MSDN: The system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true: * The process is the foreground process. * The process was started by the foreground process. * The process received the last input event. * There is no foreground process. * The foreground process is being debugged. * The foreground is not locked (see LockSetForegroundWindow). * The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo). * No menus are active. */ static BOOL FASTCALL co_IntSetForegroundAndFocusWindow( _In_ PWND Wnd, _In_ BOOL MouseActivate) { HWND hWnd = Wnd ? UserHMGetHandle(Wnd) : NULL; HWND hWndPrev = NULL; PWND pWndPrev = NULL; PUSER_MESSAGE_QUEUE PrevForegroundQueue; PTHREADINFO pti; BOOL fgRet = FALSE, Ret = FALSE; if (Wnd) ASSERT_REFS_CO(Wnd); //ERR("SetForegroundAndFocusWindow(%x, %s)\n", hWnd, (MouseActivate ? "TRUE" : "FALSE")); PrevForegroundQueue = IntGetFocusMessageQueue(); // Use this active desktop. pti = PsGetCurrentThreadWin32Thread(); if (PrevForegroundQueue) { // Same Window Q as foreground just do active. if (Wnd && Wnd->head.pti->MessageQueue == PrevForegroundQueue) { //ERR("Same Window Q as foreground just do active.\n"); if (pti->MessageQueue == PrevForegroundQueue) { // Same WQ and TQ go active. //ERR("Same WQ and TQ go active.\n"); Ret = co_IntSetActiveWindow(Wnd, MouseActivate, TRUE, FALSE); } else if (Wnd->head.pti->MessageQueue->spwndActive == Wnd) { // Same WQ and it is active. //ERR("Same WQ and it is active.\n"); Ret = TRUE; } else { // Same WQ as FG but not the same TQ send active. //ERR("Same WQ as FG but not the same TQ send active.\n"); co_IntSendMessage(hWnd, WM_ASYNC_SETACTIVEWINDOW, (WPARAM)Wnd, (LPARAM)MouseActivate ); Ret = TRUE; } return Ret; } hWndPrev = PrevForegroundQueue->spwndActive ? UserHMGetHandle(PrevForegroundQueue->spwndActive) : 0; pWndPrev = PrevForegroundQueue->spwndActive; } if ( (( !IsFGLocked() || pti->ppi == gppiInputProvider ) && ( CanForceFG(pti->ppi) || pti->TIF_flags & (TIF_SYSTEMTHREAD|TIF_CSRSSTHREAD|TIF_ALLOWFOREGROUNDACTIVATE) )) || pti->ppi == ppiScrnSaver ) { //ToggleFGActivate(pti); // win.c line 2662 fail if (Wnd) { IntSetFocusMessageQueue(Wnd->head.pti->MessageQueue); gptiForeground = Wnd->head.pti; //ERR("Set Foreground pti 0x%p Q 0x%p hWnd 0x%p\n",Wnd->head.pti, Wnd->head.pti->MessageQueue,Wnd->head.h); } else { IntSetFocusMessageQueue(NULL); gptiForeground = NULL; //ERR("Set Foreground pti 0x0 Q 0x0 hWnd 0x0\n"); } /* Henri Verbeet, What happens is that we get the WM_WINE_SETACTIVEWINDOW message sent by the other thread after we already changed the foreground window back to our own window. */ //ERR("SFAFW: 1\n"); FindRemoveAsyncMsg(Wnd, 0); // Do this to fix test_SFW todos! fgRet = TRUE; } // Fix FG Bounce with regedit. if (hWndPrev != hWnd ) { if (PrevForegroundQueue && fgRet && PrevForegroundQueue->spwndActive) { //ERR("SFGW: Send NULL to 0x%x\n",hWndPrev); if (pti->MessageQueue == PrevForegroundQueue) { //ERR("SFGW: TI same as Prev TI\n"); co_IntSetActiveWindow(NULL, FALSE, TRUE, FALSE); } else if (pWndPrev) { //ERR("SFGW Deactivate: TI not same as Prev TI\n"); // No real reason to wait here. co_IntSendMessageNoWait(hWndPrev, WM_ASYNC_SETACTIVEWINDOW, 0, 0 ); } } } if (!Wnd) return FALSE; // Always return false. if (pti->MessageQueue == Wnd->head.pti->MessageQueue) { //ERR("Same PQ and WQ go active.\n"); Ret = co_IntSetActiveWindow(Wnd, MouseActivate, TRUE, FALSE); } else if (Wnd->head.pti->MessageQueue->spwndActive == Wnd) { //ERR("Same Active and Wnd.\n"); Ret = TRUE; } else { //ERR("Activate Not same PQ and WQ and Wnd.\n"); co_IntSendMessageNoWait(hWnd, WM_ASYNC_SETACTIVEWINDOW, (WPARAM)Wnd, (LPARAM)MouseActivate ); Ret = TRUE; } return Ret && fgRet; }