[Win32k|User32]

- Fix Get/SetWindowPlacement and everything related. Which exposed the scroll bar over write issue, it's not refreshing the client window when it is maximized. Next thing to fix.
- Fix ShowWindowAsync, now restore and minimize all works. This is based on wine but in reality it's based on Windows queuing event messages used in server side internal calls. Also this patch includes the server side hooking points.
- Removed one ugly API.
- Fixes bug 6239, 6739 and client window restore from maximize and the incremental crawling down issue when parent window is minimized then restored.

svn path=/trunk/; revision=54637
This commit is contained in:
James Tabor 2011-12-10 07:41:56 +00:00
parent e1207737c2
commit 527f83f57d
12 changed files with 922 additions and 473 deletions

View file

@ -557,8 +557,6 @@ keybd_event(
BYTE bScan,
DWORD dwFlags,
ULONG_PTR dwExtraInfo)
{
INPUT Input;

View file

@ -959,6 +959,13 @@ GetClientRect(HWND hWnd, LPRECT lpRect)
PWND Wnd = ValidateHwnd(hWnd);
if (!Wnd) return FALSE;
if (Wnd->style & WS_MINIMIZED)
{
lpRect->left = lpRect->top = 0;
lpRect->right = GetSystemMetrics(SM_CXMINIMIZED);
lpRect->bottom = GetSystemMetrics(SM_CYMINIMIZED);
return TRUE;
}
if ( hWnd != GetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP )
{
/* lpRect->left = lpRect->top = 0;

View file

@ -68,26 +68,110 @@ WinPosActivateOtherWindow(HWND hwnd)
if (!SetActiveWindow( hwndTo )) SetActiveWindow(0);
}
#define EMPTYPOINT(pt) ((pt).x == -1 && (pt).y == -1)
UINT WINAPI
WinPosGetMinMaxInfo(HWND hWnd, POINT* MaxSize, POINT* MaxPos,
POINT* MinTrack, POINT* MaxTrack)
WinPosGetMinMaxInfo(HWND hwnd, POINT* maxSize, POINT* maxPos,
POINT* minTrack, POINT* maxTrack)
{
MINMAXINFO MinMax;
HMONITOR monitor;
INT xinc, yinc;
LONG style = GetWindowLongW( hwnd, GWL_STYLE );
LONG adjustedStyle;
LONG exstyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
RECT rc;
WND *win;
if(NtUserGetMinMaxInfo(hWnd, &MinMax, TRUE))
/* Compute default values */
GetWindowRect(hwnd, &rc);
MinMax.ptReserved.x = rc.left;
MinMax.ptReserved.y = rc.top;
if ((style & WS_CAPTION) == WS_CAPTION)
adjustedStyle = style & ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
else
adjustedStyle = style;
GetClientRect(GetAncestor(hwnd,GA_PARENT), &rc);
AdjustWindowRectEx(&rc, adjustedStyle, ((style & WS_POPUP) && GetMenu(hwnd)), exstyle);
xinc = -rc.left;
yinc = -rc.top;
MinMax.ptMaxSize.x = rc.right - rc.left;
MinMax.ptMaxSize.y = rc.bottom - rc.top;
if (style & (WS_DLGFRAME | WS_BORDER))
{
MinMax.ptMaxTrackSize.x = max(MinMax.ptMaxTrackSize.x,
MinMax.ptMinTrackSize.x);
MinMax.ptMaxTrackSize.y = max(MinMax.ptMaxTrackSize.y,
MinMax.ptMinTrackSize.y);
if (MaxSize) *MaxSize = MinMax.ptMaxSize;
if (MaxPos) *MaxPos = MinMax.ptMaxPosition;
if (MinTrack) *MinTrack = MinMax.ptMinTrackSize;
if (MaxTrack) *MaxTrack = MinMax.ptMaxTrackSize;
MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
}
else
{
MinMax.ptMinTrackSize.x = 2 * xinc;
MinMax.ptMinTrackSize.y = 2 * yinc;
}
MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXMAXTRACK);
MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYMAXTRACK);
MinMax.ptMaxPosition.x = -xinc;
MinMax.ptMaxPosition.y = -yinc;
if ((win = ValidateHwnd( hwnd )) )//&& win != WND_DESKTOP && win != WND_OTHER_PROCESS)
{
if (!EMPTYPOINT(win->InternalPos.MaxPos)) MinMax.ptMaxPosition = win->InternalPos.MaxPos;
}
SendMessageW( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
/* if the app didn't change the values, adapt them for the current monitor */
if ((monitor = MonitorFromWindow( hwnd, MONITOR_DEFAULTTOPRIMARY )))
{
RECT rc_work;
MONITORINFO mon_info;
mon_info.cbSize = sizeof(mon_info);
GetMonitorInfoW( monitor, &mon_info );
rc_work = mon_info.rcMonitor;
if (style & WS_MAXIMIZEBOX)
{
if ((style & WS_CAPTION) == WS_CAPTION || !(style & (WS_CHILD | WS_POPUP)))
rc_work = mon_info.rcWork;
}
if (MinMax.ptMaxSize.x == GetSystemMetrics(SM_CXSCREEN) + 2 * xinc &&
MinMax.ptMaxSize.y == GetSystemMetrics(SM_CYSCREEN) + 2 * yinc)
{
MinMax.ptMaxSize.x = (rc_work.right - rc_work.left) + 2 * xinc;
MinMax.ptMaxSize.y = (rc_work.bottom - rc_work.top) + 2 * yinc;
}
if (MinMax.ptMaxPosition.x == -xinc && MinMax.ptMaxPosition.y == -yinc)
{
MinMax.ptMaxPosition.x = rc_work.left - xinc;
MinMax.ptMaxPosition.y = rc_work.top - yinc;
}
}
/* Some sanity checks */
TRACE("%d %d / %d %d / %d %d / %d %d\n",
MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
MinMax.ptMinTrackSize.x );
MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
MinMax.ptMinTrackSize.y );
if (maxSize) *maxSize = MinMax.ptMaxSize;
if (maxPos) *maxPos = MinMax.ptMaxPosition;
if (minTrack) *minTrack = MinMax.ptMinTrackSize;
if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
return 0; //FIXME: what does it return?
}

View file

@ -132,6 +132,7 @@ typedef struct _DESKTOPINFO
WCHAR szDesktopName[1];
} DESKTOPINFO, *PDESKTOPINFO;
#define CTI_THREADSYSLOCK 0x0001
#define CTI_INSENDMESSAGE 0x0002
typedef struct _CLIENTTHREADINFO
@ -567,6 +568,9 @@ typedef struct _SBINFOEX
#define WS_EX2_CONSOLEWINDOW 0X00000400
#define WS_EX2_CHILDNOACTIVATE 0X00000800
#define WPF_MININIT 0x0008
#define WPF_MAXINIT 0x0010
typedef struct _WND
{
THRDESKHEAD head;
@ -622,10 +626,10 @@ typedef struct _WND
RECT NormalRect;
POINT IconPos;
POINT MaxPos;
UINT flags; // WPF_ flags.
} InternalPos;
UINT Unicode : 1; // !(WNDS_ANSICREATOR|WNDS_ANSIWINDOWPROC) ?
/* Indicates whether the window is derived from a system class */
UINT InternalPosInitialized : 1;
UINT HideFocus : 1; // WS_EX_UISTATEFOCUSRECTHIDDEN ?
UINT HideAccel : 1; // WS_EX_UISTATEKBACCELHIDDEN ?
@ -3258,13 +3262,6 @@ NtUserGetMenuDefaultItem(
UINT fByPos,
UINT gmdiFlags);
BOOL
NTAPI
NtUserGetMinMaxInfo(
HWND hwnd,
MINMAXINFO *MinMaxInfo,
BOOL SendMessage);
BOOL
NTAPI
NtUserGetMonitorInfo(

View file

@ -142,6 +142,13 @@ typedef struct _USER_MESSAGE_QUEUE
#define QF_CAPTURELOCKED 0x00100000
#define QF_ACTIVEWNDTRACKING 0x00200000
/* internal messages codes */
enum internal_event_message
{
WM_ASYNC_SHOWWINDOW = 0x80000000,
WM_ASYNC_SETWINDOWPOS
};
BOOL FASTCALL MsqIsHung(PUSER_MESSAGE_QUEUE MessageQueue);
VOID CALLBACK HungAppSysTimerProc(HWND,UINT,UINT_PTR,DWORD);
NTSTATUS FASTCALL co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,

View file

@ -54,4 +54,3 @@ BOOLEAN FASTCALL co_WinPosShowWindow(PWND Window, INT Cmd);
void FASTCALL co_WinPosSendSizeMove(PWND Window);
PWND FASTCALL co_WinPosWindowFromPoint(PWND ScopeWin, POINT *WinPoint, USHORT* HitTest);
VOID FASTCALL co_WinPosActivateOtherWindow(PWND Window);
VOID FASTCALL WinPosInitInternalPos(PWND WindowObject, POINT *pt, RECTL *RestoreRect);

View file

@ -99,6 +99,7 @@ static inline int is_pointer_message( UINT message )
if (message >= 8*sizeof(message_pointer_flags)) return FALSE;
return (message_pointer_flags[message / 32] & SET(message)) != 0;
}
#undef SET
#define MMS_SIZE_WPARAM -1
#define MMS_SIZE_WPARAMWCHAR -2
@ -590,6 +591,39 @@ IntCallWndProcRet ( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPar
co_HOOK_CallHooks( WH_CALLWNDPROCRET, HC_ACTION, SameThread, (LPARAM)&CWPR );
}
static LRESULT handle_internal_message( PWND pWnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
LRESULT lRes;
if (!pWnd ||
pWnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
pWnd == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
return 0;
ERR("Internal Event Msg %p\n",msg);
switch(msg)
{
case WM_ASYNC_SHOWWINDOW:
return co_WinPosShowWindow( pWnd, wparam );
case WM_ASYNC_SETWINDOWPOS:
{
PWINDOWPOS winpos = (PWINDOWPOS)lparam;
if (!winpos) return 0;
lRes = co_WinPosSetWindowPos( pWnd,
winpos->hwndInsertAfter,
winpos->x,
winpos->y,
winpos->cx,
winpos->cy,
winpos->flags);
ExFreePoolWithTag(winpos, USERTAG_SWP);
return lRes;
}
}
return 0;
}
LRESULT FASTCALL
IntDispatchMessage(PMSG pMsg)
{
@ -648,6 +682,13 @@ IntDispatchMessage(PMSG pMsg)
// Need a window!
if ( !Window ) return 0;
if (pMsg->message == WM_PAINT) Window->state |= WNDS_PAINTNOTPROCESSED;
if ( Window->state & WNDS_SERVERSIDEWINDOWPROC )
{
TRACE("Dispatch: Server Side Window Procedure\n");
}
/* Since we are doing a callback on the same thread right away, there is
no need to copy the lparam to kernel mode and then back to usermode.
We just pretend it isn't a pointer */
@ -662,6 +703,7 @@ IntDispatchMessage(PMSG pMsg)
if (pMsg->message == WM_PAINT)
{
Window->state2 &= ~WNDS2_WMPAINTSENT;
/* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
HRGN hrgn = IntSysCreateRectRgn( 0, 0, 0, 0 );
co_UserGetUpdateRgn( Window, hrgn, TRUE );
@ -1096,7 +1138,7 @@ UserPostMessage( HWND Wnd,
PWND DesktopWindow;
ULONG i;
DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
DesktopWindow = UserGetDesktopWindow();
List = IntWinListChildren(DesktopWindow);
if (List != NULL)
@ -1104,6 +1146,13 @@ UserPostMessage( HWND Wnd,
UserPostMessage(DesktopWindow->head.h, Msg, wParam, lParam);
for (i = 0; List[i]; i++)
{
PWND pwnd = UserGetWindowObject(List[i]);
if (!pwnd) continue;
if ( pwnd->fnid == FNID_MENU || // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_SWITCH] )
continue;
UserPostMessage(List[i], Msg, wParam, lParam);
}
ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
@ -1145,7 +1194,6 @@ UserPostMessage( HWND Wnd,
return TRUE;
}
LRESULT FASTCALL
co_IntSendMessage( HWND hWnd,
UINT Msg,
@ -1175,7 +1223,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
INT lParamBufferSize;
LPARAM lParamPacked;
PTHREADINFO Win32Thread;
ULONG_PTR Result = 0;
ULONG_PTR Hi, Lo, Result = 0;
DECLARE_RETURN(LRESULT);
USER_REFERENCE_ENTRY Ref;
@ -1188,8 +1236,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
Win32Thread = PsGetCurrentThreadWin32Thread();
if ( NULL != Win32Thread &&
if ( Win32Thread &&
Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
{
if (Win32Thread->TIF_flags & TIF_INCLEANUP)
@ -1198,8 +1245,29 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
RETURN( FALSE);
}
if (Msg & 0x80000000)
{
ERR("SMTS: Internal Message!\n");
Result = (ULONG_PTR)handle_internal_message( Window, Msg, wParam, lParam );
if (uResult) *uResult = Result;
RETURN( TRUE);
}
// Only happens when calling the client!
IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
if ( Window->state & WNDS_SERVERSIDEWINDOWPROC )
{
TRACE("SMT: Server Side Window Procedure\n");
IoGetStackLimits(&Lo, &Hi);
// Handle it here. Safeguard against excessive recursions.
if (((ULONG_PTR)&uResult - Lo) < 4096 )
{
ERR("Server Callback Exceeded Stack!\n");
RETURN( FALSE);
}
/* Return after server side call, IntCallWndProcRet will not be called. */
}
/* See if this message type is present in the table */
MsgMemoryEntry = FindMsgMemory(Msg);
if (NULL == MsgMemoryEntry)
@ -1229,14 +1297,15 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
*uResult = Result;
}
IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
{
ERR("Failed to unpack message parameters\n");
RETURN( TRUE);
}
// Only happens when calling the client!
IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
RETURN( TRUE);
}
@ -1283,7 +1352,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
EngSetLastError(ERROR_TIMEOUT);
RETURN( FALSE);
}
else if (! NT_SUCCESS(Status))
else if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN( FALSE);
@ -1309,20 +1378,23 @@ co_IntSendMessageTimeout( HWND hWnd,
HWND *Children;
HWND *Child;
if (HWND_BROADCAST != hWnd)
if (hWnd != HWND_BROADCAST && hWnd != HWND_TOPMOST)
{
return co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, uFlags, uTimeout, uResult);
}
DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
DesktopWindow = UserGetDesktopWindow();
if (NULL == DesktopWindow)
{
EngSetLastError(ERROR_INTERNAL_ERROR);
return 0;
}
if (hWnd != HWND_TOPMOST)
{
/* Send message to the desktop window too! */
co_IntSendMessageTimeoutSingle(DesktopWindow->head.h, Msg, wParam, lParam, uFlags, uTimeout, uResult);
}
Children = IntWinListChildren(DesktopWindow);
if (NULL == Children)
@ -1332,8 +1404,27 @@ co_IntSendMessageTimeout( HWND hWnd,
for (Child = Children; NULL != *Child; Child++)
{
if (hWnd == HWND_TOPMOST)
{
DesktopWindow = UserGetWindowObject(*Child);
if (DesktopWindow && DesktopWindow->ExStyle & WS_EX_TOPMOST)
{
ERR("HWND_TOPMOST Found\n");
co_IntSendMessageTimeoutSingle(*Child, Msg, wParam, lParam, uFlags, uTimeout, uResult);
}
}
else
{
PWND pwnd = UserGetWindowObject(*Child);
if (!pwnd) continue;
if ( pwnd->fnid == FNID_MENU ||
pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_SWITCH] )
continue;
co_IntSendMessageTimeoutSingle(*Child, Msg, wParam, lParam, uFlags, uTimeout, uResult);
}
}
ExFreePool(Children);
@ -1347,13 +1438,16 @@ co_IntSendMessageNoWait(HWND hWnd,
LPARAM lParam)
{
ULONG_PTR Result = 0;
co_IntSendMessageWithCallBack(hWnd,
if (!co_IntSendMessageWithCallBack( hWnd,
Msg,
wParam,
lParam,
NULL,
0,
&Result);
&Result))
{
Result = ((ULONG_PTR)-1);
}
return Result;
}
/* MSDN:
@ -1430,8 +1524,21 @@ co_IntSendMessageWithCallBack( HWND hWnd,
RETURN(FALSE);
}
if (Msg & 0x80000000)
{
ERR("SMWCB: Internal Message!\n");
Result = (ULONG_PTR)handle_internal_message( Window, Msg, wParam, lParam );
if (uResult) *uResult = Result;
RETURN( TRUE);
}
IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
if ( Window->state & WNDS_SERVERSIDEWINDOWPROC )
{
TRACE("SMWCB: Server Side Window Procedure\n");
}
Result = (ULONG_PTR)co_IntCallWindowProc( Window->lpfnWndProc,
!Window->Unicode,
hWnd,
@ -1505,9 +1612,12 @@ CLEANUP:
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! */
/*
This HACK 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!
*/
LRESULT FASTCALL
co_IntPostOrSendMessage( HWND hWnd,
UINT Msg,
@ -1561,7 +1671,7 @@ co_IntDoSendMessage( HWND hWnd,
MSG KernelModeMsg;
PMSGMEMORY MsgMemoryEntry;
if (HWND_BROADCAST != hWnd)
if (hWnd != HWND_BROADCAST && hWnd != HWND_TOPMOST)
{
Window = UserGetWindowObject(hWnd);
if ( !Window )
@ -1641,7 +1751,7 @@ UserSendNotifyMessage( HWND hWnd,
PWND DesktopWindow;
ULONG i;
DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
DesktopWindow = UserGetDesktopWindow();
List = IntWinListChildren(DesktopWindow);
if (List != NULL)
@ -1649,6 +1759,13 @@ UserSendNotifyMessage( HWND hWnd,
UserSendNotifyMessage(DesktopWindow->head.h, Msg, wParam, lParam);
for (i = 0; List[i]; i++)
{
PWND pwnd = UserGetWindowObject(List[i]);
if (!pwnd) continue;
if ( pwnd->fnid == FNID_MENU ||
pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_SWITCH] )
continue;
Ret = UserSendNotifyMessage(List[i], Msg, wParam, lParam);
}
ExFreePool(List);
@ -1656,14 +1773,8 @@ UserSendNotifyMessage( HWND hWnd,
}
else
{
ULONG_PTR lResult = 0;
Ret = co_IntSendMessageWithCallBack( hWnd,
Msg,
wParam,
lParam,
NULL,
0,
&lResult);
Ret = co_IntSendMessageNoWait( hWnd, Msg, wParam, lParam);
if (-1 == (int) Ret || !Ret) Ret = FALSE;
}
return Ret;
}
@ -2255,7 +2366,7 @@ NtUserMessageCall( HWND hWnd,
ULONG i;
UINT fuFlags;
pwndDesk = UserGetWindowObject(IntGetDesktopWindow());
pwndDesk = UserGetDesktopWindow();
List = IntWinListChildren(pwndDesk);
if (parm.flags & BSF_QUERY)

View file

@ -1040,21 +1040,6 @@ NtUserSetImeOwnerWindow(DWORD Unknown0,
return 0;
}
/*
* @unimplemented
*/
DWORD APIENTRY
NtUserSetInternalWindowPos(
HWND hwnd,
UINT showCmd,
LPRECT rect,
LPPOINT pt)
{
STUB
return 0;
}
/*
* @unimplemented
*/

View file

@ -1262,51 +1262,6 @@ IntUnlinkWindow(PWND Wnd)
Wnd->spwndPrev = Wnd->spwndNext = NULL;
}
BOOL
FASTCALL
IntGetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *lpwndpl)
{
POINT Size;
if (!Wnd) return FALSE;
if(lpwndpl->length != sizeof(WINDOWPLACEMENT))
{
return FALSE;
}
lpwndpl->flags = 0;
if (0 == (Wnd->style & WS_VISIBLE))
{
lpwndpl->showCmd = SW_HIDE;
}
else if (0 != (Wnd->state2 & WNDS2_MAXIMIZEBUTTONDOWN) ||
0 != (Wnd->style & WS_MAXIMIZE))
{
lpwndpl->showCmd = SW_MAXIMIZE;
}
else if (0 != (Wnd->style & WS_MINIMIZE))
{
lpwndpl->showCmd = SW_MINIMIZE;
}
else if (0 != (Wnd->style & WS_VISIBLE))
{
lpwndpl->showCmd = SW_SHOWNORMAL;
}
Size.x = Wnd->rcWindow.left;
Size.y = Wnd->rcWindow.top;
WinPosInitInternalPos(Wnd, &Size,
&Wnd->rcWindow);
lpwndpl->rcNormalPosition = Wnd->InternalPos.NormalRect;
lpwndpl->ptMinPosition = Wnd->InternalPos.IconPos;
lpwndpl->ptMaxPosition = Wnd->InternalPos.MaxPos;
return TRUE;
}
/* FUNCTIONS *****************************************************************/
/*
@ -3019,80 +2974,6 @@ CLEANUP:
}
/*
* @implemented
*/
DWORD APIENTRY
NtUserGetInternalWindowPos( HWND hWnd,
LPRECT rectWnd,
LPPOINT ptIcon)
{
PWND Window;
DWORD Ret = 0;
BOOL Hit = FALSE;
WINDOWPLACEMENT wndpl;
UserEnterShared();
if (!(Window = UserGetWindowObject(hWnd)))
{
Hit = FALSE;
goto Exit;
}
_SEH2_TRY
{
if(rectWnd)
{
ProbeForWrite(rectWnd,
sizeof(RECT),
1);
}
if(ptIcon)
{
ProbeForWrite(ptIcon,
sizeof(POINT),
1);
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
SetLastNtError(_SEH2_GetExceptionCode());
Hit = TRUE;
}
_SEH2_END;
wndpl.length = sizeof(WINDOWPLACEMENT);
if (IntGetWindowPlacement(Window, &wndpl) && !Hit)
{
_SEH2_TRY
{
if (rectWnd)
{
RtlCopyMemory(rectWnd, &wndpl.rcNormalPosition , sizeof(RECT));
}
if (ptIcon)
{
RtlCopyMemory(ptIcon, &wndpl.ptMinPosition, sizeof(POINT));
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
SetLastNtError(_SEH2_GetExceptionCode());
Hit = TRUE;
}
_SEH2_END;
if (!Hit) Ret = wndpl.showCmd;
}
Exit:
UserLeave();
return Ret;
}
DWORD
APIENTRY
NtUserGetListBoxInfo(
@ -3595,82 +3476,6 @@ CLEANUP:
END_CLEANUP;
}
/*
* @implemented
*/
BOOL APIENTRY
NtUserGetWindowPlacement(HWND hWnd,
WINDOWPLACEMENT *lpwndpl)
{
PWND Wnd;
POINT Size;
WINDOWPLACEMENT Safepl;
NTSTATUS Status;
DECLARE_RETURN(BOOL);
TRACE("Enter NtUserGetWindowPlacement\n");
UserEnterShared();
if (!(Wnd = UserGetWindowObject(hWnd)))
{
RETURN( FALSE);
}
Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
if(!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN( FALSE);
}
if(Safepl.length != sizeof(WINDOWPLACEMENT))
{
RETURN( FALSE);
}
Safepl.flags = 0;
if (0 == (Wnd->style & WS_VISIBLE))
{
Safepl.showCmd = SW_HIDE;
}
else if ((0 != (Wnd->state2 & WNDS2_MAXIMIZEBUTTONDOWN) ||
0 != (Wnd->style & WS_MAXIMIZE)) &&
0 == (Wnd->style & WS_MINIMIZE))
{
Safepl.showCmd = SW_SHOWMAXIMIZED;
}
else if (0 != (Wnd->style & WS_MINIMIZE))
{
Safepl.showCmd = SW_SHOWMINIMIZED;
}
else if (0 != (Wnd->style & WS_VISIBLE))
{
Safepl.showCmd = SW_SHOWNORMAL;
}
Size.x = Wnd->rcWindow.left;
Size.y = Wnd->rcWindow.top;
WinPosInitInternalPos(Wnd, &Size,
&Wnd->rcWindow);
Safepl.rcNormalPosition = Wnd->InternalPos.NormalRect;
Safepl.ptMinPosition = Wnd->InternalPos.IconPos;
Safepl.ptMaxPosition = Wnd->InternalPos.MaxPos;
Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT));
if(!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN( FALSE);
}
RETURN( TRUE);
CLEANUP:
TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
QueryWindow based on KJK::Hyperion and James Tabor.
@ -3827,7 +3632,6 @@ CLEANUP:
END_CLEANUP;
}
/*
* @implemented
*/
@ -3872,57 +3676,6 @@ CLEANUP:
END_CLEANUP;
}
/*
* @implemented
*/
HWND APIENTRY
NtUserWindowFromPoint(LONG X, LONG Y)
{
POINT pt;
HWND Ret;
PWND DesktopWindow = NULL, Window = NULL;
USHORT hittest;
DECLARE_RETURN(HWND);
USER_REFERENCE_ENTRY Ref;
TRACE("Enter NtUserWindowFromPoint\n");
UserEnterExclusive();
if ((DesktopWindow = UserGetWindowObject(IntGetDesktopWindow())))
{
//PTHREADINFO pti;
pt.x = X;
pt.y = Y;
//hmm... threads live on desktops thus we have a reference on the desktop and indirectly the desktop window
//its possible this referencing is useless, thou it shouldnt hurt...
UserRefObjectCo(DesktopWindow, &Ref);
//pti = PsGetCurrentThreadWin32Thread();
Window = co_WinPosWindowFromPoint(DesktopWindow, &pt, &hittest);
if(Window)
{
Ret = Window->head.h;
RETURN( Ret);
}
}
RETURN( NULL);
CLEANUP:
if (Window) UserDereferenceObject(Window);
if (DesktopWindow) UserDerefObjectCo(DesktopWindow);
TRACE("Leave NtUserWindowFromPoint, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* NtUserDefSetText
*

View file

@ -24,6 +24,9 @@ DBG_DEFAULT_CHANNEL(UserWinpos);
(SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
#define EMPTYPOINT(pt) ((pt).x == -1 && (pt).y == -1)
#define PLACE_MIN 0x0001
#define PLACE_MAX 0x0002
#define PLACE_RECT 0x0004
/* FUNCTIONS *****************************************************************/
@ -125,6 +128,25 @@ done:
if (WndTo) UserDerefObjectCo(WndTo);
}
BOOL
FASTCALL
WinPosShowIconTitle( PWND pWnd, BOOL bShow )
{
HICON hIcon;
if (!pWnd->pcls || pWnd->fnid == FNID_DESKTOP) return FALSE;
if (!hIcon) hIcon = pWnd->pcls->hIconSm;
if (!hIcon) hIcon = pWnd->pcls->hIcon;
if (!hIcon) return FALSE;
if ( bShow )
{
// FIXME: Draw ICON!
}
else if (hIcon)
return FALSE;
return FALSE;
}
UINT
FASTCALL
@ -163,9 +185,13 @@ co_WinPosArrangeIconicWindows(PWND parent)
USER_REFERENCE_ENTRY Ref;
UserRefObjectCo(Child, &Ref);
co_WinPosSetWindowPos(Child, 0, x + (xspacing - UserGetSystemMetrics(SM_CXICON)) / 2,
y - yspacing - UserGetSystemMetrics(SM_CYICON) / 2
, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
co_WinPosSetWindowPos( Child,
0,
x + (xspacing - UserGetSystemMetrics(SM_CXICON)) / 2,
y - yspacing - UserGetSystemMetrics(SM_CYICON) / 2,
0,
0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
UserDerefObjectCo(Child);
@ -186,64 +212,320 @@ co_WinPosArrangeIconicWindows(PWND parent)
static VOID FASTCALL
WinPosFindIconPos(PWND Window, POINT *Pos)
{
ERR("WinPosFindIconPos FIXME!\n");
RECT rect, rectParent;
PWND pwndChild, pwndParent;
HRGN hrgn, tmp;
int xspacing, yspacing;
pwndParent = Window->spwndParent;
if (pwndParent == UserGetDesktopWindow())
{
/* ReactOS doesn't support iconic minimize to desktop */
Pos->x = Pos->y = -32000;
return;
}
IntGetClientRect( pwndParent, &rectParent );
if ((Pos->x >= rectParent.left) && (Pos->x + UserGetSystemMetrics(SM_CXICON) < rectParent.right) &&
(Pos->y >= rectParent.top) && (Pos->y + UserGetSystemMetrics(SM_CYICON) < rectParent.bottom))
return; /* The icon already has a suitable position */
xspacing = UserGetSystemMetrics(SM_CXICONSPACING);
yspacing = UserGetSystemMetrics(SM_CYICONSPACING);
/* Check if another icon already occupies this spot */
/* FIXME: this is completely inefficient */
hrgn = IntSysCreateRectRgn( 0, 0, 0, 0 );
tmp = IntSysCreateRectRgn( 0, 0, 0, 0 );
for (pwndChild = pwndParent->spwndChild; pwndChild; pwndChild = pwndChild->spwndNext)
{
if (pwndChild == Window) continue;
if ((pwndChild->style & (WS_VISIBLE|WS_MINIMIZE)) != (WS_VISIBLE|WS_MINIMIZE))
continue;
if ( pwndChild->spwndParent )
{
PWND Parent = pwndChild->spwndParent;
rect.left = rect.top = 0;
rect.right = Parent->rcWindow.right - Parent->rcWindow.left;
rect.bottom = Parent->rcWindow.bottom - Parent->rcWindow.top;
NtGdiSetRectRgn( tmp, rect.left, rect.top, rect.right, rect.bottom );
NtGdiCombineRgn( hrgn, hrgn, tmp, RGN_OR );
}
}
GreDeleteObject( tmp );
for (rect.bottom = rectParent.bottom; rect.bottom >= yspacing; rect.bottom -= yspacing)
{
for (rect.left = rectParent.left; rect.left <= rectParent.right - xspacing; rect.left += xspacing)
{
rect.right = rect.left + xspacing;
rect.top = rect.bottom - yspacing;
if (!IntRectInRegion( hrgn, &rect ))
{
/* No window was found, so it's OK for us */
Pos->x = rect.left + (xspacing - UserGetSystemMetrics(SM_CXICON)) / 2;
Pos->y = rect.top + (yspacing - UserGetSystemMetrics(SM_CYICON)) / 2;
GreDeleteObject( hrgn );
return;
}
}
}
GreDeleteObject( hrgn );
Pos->x = Pos->y = 0;
return;
}
VOID FASTCALL
WinPosInitInternalPos(PWND Wnd, POINT *pt, RECTL *RestoreRect)
WinPosInitInternalPos(PWND Wnd, RECTL *RestoreRect)
{
PWND Parent;
UINT XInc, YInc;
POINT Size;
RECTL Rect = *RestoreRect;
if (Wnd->spwndParent != UserGetDesktopWindow())
{
RECTL_vOffsetRect(&Rect,
-Wnd->spwndParent->rcClient.left,
-Wnd->spwndParent->rcClient.top);
}
Size.x = Rect.left;
Size.y = Rect.top;
if (!Wnd->InternalPosInitialized)
{
RECTL WorkArea;
Parent = Wnd->spwndParent;
if(Parent)
{
if(IntIsDesktopWindow(Parent))
UserSystemParametersInfo(SPI_GETWORKAREA, 0, &WorkArea, 0);
else
WorkArea = Parent->rcClient;
}
else
UserSystemParametersInfo(SPI_GETWORKAREA, 0, &WorkArea, 0);
Wnd->InternalPos.NormalRect = Wnd->rcWindow;
IntGetWindowBorderMeasures(Wnd, &XInc, &YInc);
Wnd->InternalPos.MaxPos.x = WorkArea.left - XInc;
Wnd->InternalPos.MaxPos.y = WorkArea.top - YInc;
Wnd->InternalPos.IconPos.x = WorkArea.left;
Wnd->InternalPos.IconPos.y = WorkArea.bottom - UserGetSystemMetrics(SM_CYMINIMIZED);
// FIXME: Use check point Atom..
Wnd->InternalPos.flags = 0;
Wnd->InternalPos.MaxPos.x = Wnd->InternalPos.MaxPos.y = -1;
Wnd->InternalPos.IconPos.x = Wnd->InternalPos.IconPos.y = -1;
Wnd->InternalPos.NormalRect = Rect;
Wnd->InternalPosInitialized = TRUE;
}
if (Wnd->style & WS_MINIMIZE)
{
Wnd->InternalPos.IconPos = *pt;
Wnd->InternalPos.IconPos = Size;
Wnd->InternalPos.flags |= WPF_MININIT;
}
else if (Wnd->style & WS_MAXIMIZE)
{
Wnd->InternalPos.MaxPos = *pt;
}
else if (RestoreRect != NULL)
Wnd->InternalPos.flags |= WPF_MAXINIT;
if ( Wnd->spwndParent == Wnd->head.rpdesk->pDeskInfo->spwnd )
{
Wnd->InternalPos.NormalRect = *RestoreRect;
if (Wnd->state & WNDS_MAXIMIZESTOMONITOR)
{
Wnd->InternalPos.flags &= ~WPF_MAXINIT;
Wnd->InternalPos.MaxPos.x = Wnd->InternalPos.MaxPos.y = -1;
}
else
{
RECTL WorkArea;
PMONITOR pmonitor = IntMonitorFromRect(&Rect, MONITOR_DEFAULTTOPRIMARY );
// FIXME: support DPI aware, rcWorkDPI/Real etc..
if (!(Wnd->style & WS_MAXIMIZEBOX) || (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen)
WorkArea = pmonitor->rcMonitor;
else
WorkArea = pmonitor->rcWork;
Wnd->InternalPos.MaxPos.x = Rect.left - WorkArea.left;
Wnd->InternalPos.MaxPos.y = Rect.top - WorkArea.top;
TRACE("WinPosIP 2 X %d Y %d\n",Wnd->InternalPos.MaxPos.x,Wnd->InternalPos.MaxPos.y);
}
}
else
Wnd->InternalPos.MaxPos = Size;
}
else
{
Wnd->InternalPos.NormalRect = Rect;
}
}
BOOL
FASTCALL
IntGetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *lpwndpl)
{
if (!Wnd) return FALSE;
if(lpwndpl->length != sizeof(WINDOWPLACEMENT))
{
return FALSE;
}
lpwndpl->flags = 0;
WinPosInitInternalPos(Wnd, &Wnd->rcWindow);
lpwndpl->showCmd = SW_HIDE;
if ( Wnd->style & WS_MINIMIZE )
lpwndpl->showCmd = SW_SHOWMINIMIZED;
else
lpwndpl->showCmd = ( Wnd->style & WS_MAXIMIZE ) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
lpwndpl->rcNormalPosition = Wnd->InternalPos.NormalRect;
if (Wnd->InternalPos.flags & WPF_MININIT) // Return if it was set!
{
lpwndpl->ptMinPosition.x = Wnd->InternalPos.IconPos.x;
lpwndpl->ptMinPosition.y = Wnd->InternalPos.IconPos.y;
}
else
lpwndpl->ptMinPosition.x = lpwndpl->ptMinPosition.y = -1;
if ( Wnd->InternalPos.flags & WPF_MAXINIT && // Return if set and not maximized to monitor!
!(Wnd->state & WNDS_MAXIMIZESTOMONITOR))
{
lpwndpl->ptMaxPosition.x = Wnd->InternalPos.MaxPos.x;
lpwndpl->ptMaxPosition.y = Wnd->InternalPos.MaxPos.y;
}
else
lpwndpl->ptMaxPosition.x = lpwndpl->ptMaxPosition.y = -1;
if ( Wnd->spwndParent == Wnd->head.rpdesk->pDeskInfo->spwnd &&
!(Wnd->ExStyle & WS_EX_TOOLWINDOW))
{
PMONITOR pmonitor = IntMonitorFromRect(&lpwndpl->rcNormalPosition, MONITOR_DEFAULTTOPRIMARY );
// FIXME: support DPI aware, rcWorkDPI/Real etc..
if (Wnd->InternalPos.flags & WPF_MININIT)
{
lpwndpl->ptMinPosition.x -= (pmonitor->rcWork.left - pmonitor->rcMonitor.left);
lpwndpl->ptMinPosition.y -= (pmonitor->rcWork.top - pmonitor->rcMonitor.top);
}
RECTL_vOffsetRect(&lpwndpl->rcNormalPosition,
pmonitor->rcMonitor.left - pmonitor->rcWork.left,
pmonitor->rcMonitor.top - pmonitor->rcWork.top);
}
if ( Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED || Wnd->style & WS_MAXIMIZE )
lpwndpl->flags |= WPF_RESTORETOMAXIMIZED;
if ( ((Wnd->style & (WS_CHILD|WS_POPUP)) == WS_CHILD) && Wnd->InternalPos.flags & WPF_SETMINPOSITION)
lpwndpl->flags |= WPF_SETMINPOSITION;
return TRUE;
}
/* make sure the specified rect is visible on screen */
static void make_rect_onscreen( RECT *rect )
{
PMONITOR pmonitor = IntMonitorFromRect( rect, MONITOR_DEFAULTTONEAREST ); // Wine uses this.
// FIXME: support DPI aware, rcWorkDPI/Real etc..
if (!pmonitor) return;
/* FIXME: map coordinates from rcWork to rcMonitor */
if (rect->right <= pmonitor->rcWork.left)
{
rect->right += pmonitor->rcWork.left - rect->left;
rect->left = pmonitor->rcWork.left;
}
else if (rect->left >= pmonitor->rcWork.right)
{
rect->left += pmonitor->rcWork.right - rect->right;
rect->right = pmonitor->rcWork.right;
}
if (rect->bottom <= pmonitor->rcWork.top)
{
rect->bottom += pmonitor->rcWork.top - rect->top;
rect->top = pmonitor->rcWork.top;
}
else if (rect->top >= pmonitor->rcWork.bottom)
{
rect->top += pmonitor->rcWork.bottom - rect->bottom;
rect->bottom = pmonitor->rcWork.bottom;
}
}
/* make sure the specified point is visible on screen */
static void make_point_onscreen( POINT *pt )
{
RECT rect;
RECTL_vSetRect( &rect, pt->x, pt->y, pt->x + 1, pt->y + 1 );
make_rect_onscreen( &rect );
pt->x = rect.left;
pt->y = rect.top;
}
BOOL FASTCALL
IntSetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *wpl, UINT Flags)
{
BOOL sAsync;
UINT SWP_Flags;
if ( Flags & PLACE_MIN) make_point_onscreen( &wpl->ptMinPosition );
if ( Flags & PLACE_MAX) make_point_onscreen( &wpl->ptMaxPosition );
if ( Flags & PLACE_RECT) make_rect_onscreen( &wpl->rcNormalPosition );
if (!Wnd || Wnd == Wnd->head.rpdesk->pDeskInfo->spwnd) return FALSE;
if ( Flags & PLACE_MIN ) Wnd->InternalPos.IconPos = wpl->ptMinPosition;
if ( Flags & PLACE_MAX ) Wnd->InternalPos.MaxPos = wpl->ptMaxPosition;
if ( Flags & PLACE_RECT) Wnd->InternalPos.NormalRect = wpl->rcNormalPosition;
SWP_Flags = SWP_NOZORDER | SWP_NOACTIVATE | ((wpl->flags & WPF_ASYNCWINDOWPLACEMENT) ? SWP_ASYNCWINDOWPOS : 0);
if (Wnd->style & WS_MINIMIZE )
{
if (Flags & PLACE_MIN)
{
co_WinPosSetWindowPos(Wnd, HWND_TOP,
wpl->ptMinPosition.x, wpl->ptMinPosition.y, 0, 0,
SWP_NOSIZE | SWP_Flags);
Wnd->InternalPos.flags |= WPF_MININIT;
}
}
else if (Wnd->style & WS_MAXIMIZE )
{
if (Flags & PLACE_MAX)
{
co_WinPosSetWindowPos(Wnd, HWND_TOP,
wpl->ptMaxPosition.x, wpl->ptMaxPosition.y, 0, 0,
SWP_NOSIZE | SWP_Flags);
Wnd->InternalPos.flags |= WPF_MAXINIT;
}
}
else if (Flags & PLACE_RECT)
{
co_WinPosSetWindowPos(Wnd, HWND_TOP,
wpl->rcNormalPosition.left, wpl->rcNormalPosition.top,
wpl->rcNormalPosition.right - wpl->rcNormalPosition.left,
wpl->rcNormalPosition.bottom - wpl->rcNormalPosition.top,
SWP_Flags);
}
sAsync = (Wnd->head.pti->MessageQueue != gptiCurrent->MessageQueue && wpl->flags & WPF_ASYNCWINDOWPLACEMENT);
if ( sAsync )
co_IntSendMessageNoWait( UserHMGetHandle(Wnd), WM_ASYNC_SHOWWINDOW, wpl->showCmd, 0 );
else
co_WinPosShowWindow(Wnd, wpl->showCmd);
if ( Wnd->style & WS_MINIMIZE && !sAsync )
{
if ( wpl->flags & WPF_SETMINPOSITION )
Wnd->InternalPos.flags |= WPF_SETMINPOSITION;
if ( wpl->flags & WPF_RESTORETOMAXIMIZED )
Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED;
}
return TRUE;
}
UINT FASTCALL
co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
{
POINT Size;
WINDOWPLACEMENT wpl;
UINT SwpFlags = 0;
ASSERT_REFS_CO(Wnd);
Size.x = Wnd->rcWindow.left;
Size.y = Wnd->rcWindow.top;
WinPosInitInternalPos(Wnd, &Size, &Wnd->rcWindow);
wpl.length = sizeof(wpl);
IntGetWindowPlacement( Wnd, &wpl );
if (co_HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)Wnd->head.h, ShowFlag))
{
@ -252,6 +534,8 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
}
if (Wnd->style & WS_MINIMIZE)
{
if (ShowFlag == SW_MINIMIZE) return SWP_NOSIZE | SWP_NOMOVE;
if (!co_IntSendMessageNoWait(Wnd->head.h, WM_QUERYOPEN, 0, 0))
{
return(SWP_NOSIZE | SWP_NOMOVE);
@ -264,18 +548,18 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
{
if (Wnd->style & WS_MAXIMIZE)
{
Wnd->state2 |= WNDS2_MAXIMIZEBUTTONDOWN;
Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED;
Wnd->style &= ~WS_MAXIMIZE;
}
else
{
Wnd->state2 &= ~WNDS2_MAXIMIZEBUTTONDOWN;
Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
}
co_UserRedrawWindow(Wnd, NULL, 0, RDW_VALIDATE | RDW_NOERASE |
RDW_NOINTERNALPAINT);
Wnd->style |= WS_MINIMIZE;
WinPosFindIconPos(Wnd, &Wnd->InternalPos.IconPos);
RECTL_vSetRect(NewPos, Wnd->InternalPos.IconPos.x, Wnd->InternalPos.IconPos.y,
WinPosFindIconPos(Wnd, &wpl.ptMinPosition);
RECTL_vSetRect(NewPos, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
UserGetSystemMetrics(SM_CXMINIMIZED),
UserGetSystemMetrics(SM_CYMINIMIZED));
SwpFlags |= SWP_NOCOPYBITS;
@ -284,17 +568,16 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
case SW_MAXIMIZE:
{
co_WinPosGetMinMaxInfo(Wnd, &Size, &Wnd->InternalPos.MaxPos,
NULL, NULL);
co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL);
TRACE("Maximize: %d,%d %dx%d\n",
Wnd->InternalPos.MaxPos.x, Wnd->InternalPos.MaxPos.y, Size.x, Size.y);
wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
if (Wnd->style & WS_MINIMIZE)
{
Wnd->style &= ~WS_MINIMIZE;
}
Wnd->style |= WS_MAXIMIZE;
RECTL_vSetRect(NewPos, Wnd->InternalPos.MaxPos.x, Wnd->InternalPos.MaxPos.y,
Size.x, Size.y);
RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
break;
}
@ -303,18 +586,17 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
if (Wnd->style & WS_MINIMIZE)
{
Wnd->style &= ~WS_MINIMIZE;
if (Wnd->state2 & WNDS2_MAXIMIZEBUTTONDOWN)
if (Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED)
{
co_WinPosGetMinMaxInfo(Wnd, &Size,
&Wnd->InternalPos.MaxPos, NULL, NULL);
co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL);
Wnd->style |= WS_MAXIMIZE;
RECTL_vSetRect(NewPos, Wnd->InternalPos.MaxPos.x,
Wnd->InternalPos.MaxPos.y, Size.x, Size.y);
RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
break;
}
else
{
*NewPos = Wnd->InternalPos.NormalRect;
*NewPos = wpl.rcNormalPosition;
NewPos->right -= NewPos->left;
NewPos->bottom -= NewPos->top;
break;
@ -327,8 +609,8 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
return 0;
}
Wnd->style &= ~WS_MAXIMIZE;
Wnd->state2 &= ~WNDS2_MAXIMIZEBUTTONDOWN;
*NewPos = Wnd->InternalPos.NormalRect;
Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
*NewPos = wpl.rcNormalPosition;
NewPos->right -= NewPos->left;
NewPos->bottom -= NewPos->top;
break;
@ -946,6 +1228,7 @@ co_WinPosSetWindowPos(
if ( Window->head.h == IntGetDesktopWindow() &&
Window->head.pti->pEThread->ThreadsProcess != PsGetCurrentProcess())
{
ERR("Desktop Window...\n");
return FALSE;
}
bPointerInWindow = IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y);
@ -1337,7 +1620,7 @@ co_WinPosGetNonClientSize(PWND Window, RECT* WindowRect, RECT* ClientRect)
ASSERT_REFS_CO(Window);
*ClientRect = *WindowRect;
Result = co_IntSendMessageNoWait(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect);
Result = co_IntSendMessage(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect);
FixClientRect(ClientRect, WindowRect);
@ -1347,8 +1630,12 @@ co_WinPosGetNonClientSize(PWND Window, RECT* WindowRect, RECT* ClientRect)
void FASTCALL
co_WinPosSendSizeMove(PWND Wnd)
{
RECTL Rect;
LPARAM lParam;
WPARAM wParam = SIZE_RESTORED;
IntGetClientRect(Wnd, &Rect);
Wnd->state &= ~WNDS_SENDSIZEMOVEMSGS;
if (Wnd->style & WS_MAXIMIZE)
{
@ -1359,14 +1646,14 @@ co_WinPosSendSizeMove(PWND Wnd)
wParam = SIZE_MINIMIZED;
}
co_IntSendMessageNoWait(Wnd->head.h, WM_SIZE, wParam,
MAKELONG(Wnd->rcClient.right -
Wnd->rcClient.left,
Wnd->rcClient.bottom -
Wnd->rcClient.top));
co_IntSendMessageNoWait(Wnd->head.h, WM_MOVE, 0,
MAKELONG(Wnd->rcClient.left,
Wnd->rcClient.top));
co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_SIZE, wParam, MAKELONG(Rect.right-Rect.left, Rect.bottom-Rect.top));
if (Wnd->spwndParent == UserGetDesktopWindow()) // Wnd->spwndParent->fnid != FNID_DESKTOP )
lParam = MAKELONG(Wnd->rcClient.left, Wnd->rcClient.top);
else
lParam = MAKELONG(Wnd->rcClient.left-Wnd->spwndParent->rcClient.left, Wnd->rcClient.top-Wnd->spwndParent->rcClient.top);
co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_MOVE, 0, lParam);
IntEngWindowChanged(Wnd, WOC_RGN_CLIENT);
}
@ -1454,7 +1741,7 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd)
break;
case SW_SHOWNOACTIVATE:
Wnd->state2 &= ~WNDS2_MAXIMIZEBUTTONDOWN;
Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
//Swp |= SWP_NOZORDER;
Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
/* Fall through. */
@ -1734,7 +2021,7 @@ END:
return retvalue;
}
BOOL FASTCALL IntEndDeferWindowPosEx( HDWP hdwp )
BOOL FASTCALL IntEndDeferWindowPosEx( HDWP hdwp, BOOL sAsync )
{
PSMWP pDWP;
PCVR winpos;
@ -1764,6 +2051,23 @@ BOOL FASTCALL IntEndDeferWindowPosEx( HDWP hdwp )
UserRefObjectCo(pwnd, &Ref);
if ( sAsync )
{
LRESULT lRes;
PWINDOWPOS ppos = ExAllocatePoolWithTag(PagedPool, sizeof(WINDOWPOS), USERTAG_SWP);
if ( ppos )
{
*ppos = winpos->pos;
/* Yes it's a pointer inside Win32k! */
lRes = co_IntSendMessageNoWait( winpos->pos.hwnd, WM_ASYNC_SETWINDOWPOS, 0, (LPARAM)ppos);
/* We handle this the same way as Event Hooks and Hooks. */
if ( -1 == (int) lRes )
{
ExFreePoolWithTag(ppos, USERTAG_SWP);
}
}
}
else
res = co_WinPosSetWindowPos( pwnd,
winpos->pos.hwndInsertAfter,
winpos->pos.x,
@ -1780,6 +2084,7 @@ BOOL FASTCALL IntEndDeferWindowPosEx( HDWP hdwp )
return res;
}
/*
* @implemented
*/
@ -1856,7 +2161,7 @@ NtUserEndDeferWindowPosEx(HDWP WinPosInfo,
BOOL Ret;
TRACE("Enter NtUserEndDeferWindowPosEx\n");
UserEnterExclusive();
Ret = IntEndDeferWindowPosEx(WinPosInfo);
Ret = IntEndDeferWindowPosEx(WinPosInfo, (BOOL)Unknown1);
TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret);
UserLeave();
return Ret;
@ -1920,6 +2225,128 @@ Exit:
return Ret;
}
/*
* @implemented
*/
DWORD APIENTRY
NtUserGetInternalWindowPos( HWND hWnd,
LPRECT rectWnd,
LPPOINT ptIcon)
{
PWND Window;
DWORD Ret = 0;
BOOL Hit = FALSE;
WINDOWPLACEMENT wndpl;
UserEnterShared();
if (!(Window = UserGetWindowObject(hWnd)))
{
Hit = FALSE;
goto Exit;
}
_SEH2_TRY
{
if(rectWnd)
{
ProbeForWrite(rectWnd,
sizeof(RECT),
1);
}
if(ptIcon)
{
ProbeForWrite(ptIcon,
sizeof(POINT),
1);
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
SetLastNtError(_SEH2_GetExceptionCode());
Hit = TRUE;
}
_SEH2_END;
wndpl.length = sizeof(WINDOWPLACEMENT);
if (IntGetWindowPlacement(Window, &wndpl) && !Hit)
{
_SEH2_TRY
{
if (rectWnd)
{
RtlCopyMemory(rectWnd, &wndpl.rcNormalPosition , sizeof(RECT));
}
if (ptIcon)
{
RtlCopyMemory(ptIcon, &wndpl.ptMinPosition, sizeof(POINT));
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
SetLastNtError(_SEH2_GetExceptionCode());
Hit = TRUE;
}
_SEH2_END;
if (!Hit) Ret = wndpl.showCmd;
}
Exit:
UserLeave();
return Ret;
}
/*
* @implemented
*/
BOOL APIENTRY
NtUserGetWindowPlacement(HWND hWnd,
WINDOWPLACEMENT *lpwndpl)
{
PWND Wnd;
WINDOWPLACEMENT Safepl;
NTSTATUS Status;
DECLARE_RETURN(BOOL);
TRACE("Enter NtUserGetWindowPlacement\n");
UserEnterShared();
if (!(Wnd = UserGetWindowObject(hWnd)))
{
RETURN( FALSE);
}
Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
if(!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN( FALSE);
}
if(Safepl.length != sizeof(WINDOWPLACEMENT))
{
RETURN( FALSE);
}
IntGetWindowPlacement(Wnd, &Safepl);
Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT));
if(!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN( FALSE);
}
RETURN( TRUE);
CLEANUP:
TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
DWORD
APIENTRY
NtUserMinMaximize(
@ -2085,8 +2512,9 @@ NtUserSetWindowRgn(
if (GreIsHandleValid(hRgn))
{
hrgnCopy = IntSysCreateRectRgn(0, 0, 0, 0);
NtGdiCombineRgn(hrgnCopy, hRgn, 0, RGN_COPY);
/* The coordinates of a window's window region are relative to the
upper-left corner of the window, not the client area of the window. */
NtGdiCombineRgn( hrgnCopy, hRgn, 0, RGN_COPY);
}
else
RETURN( 0);
@ -2096,9 +2524,6 @@ NtUserSetWindowRgn(
hrgnCopy = NULL;
}
/* Delete the region passed by the caller */
GreDeleteObject(hRgn);
if (Window->hrgnClip)
{
/* Delete no longer needed region handle */
@ -2123,6 +2548,81 @@ CLEANUP:
END_CLEANUP;
}
/*
* @implemented
*/
DWORD APIENTRY
NtUserSetInternalWindowPos(
HWND hwnd,
UINT showCmd,
LPRECT lprect,
LPPOINT lppt)
{
WINDOWPLACEMENT wndpl;
UINT flags;
PWND Wnd;
RECT rect;
POINT pt = {0};
DECLARE_RETURN(BOOL);
USER_REFERENCE_ENTRY Ref;
TRACE("Enter NtUserSetWindowPlacement\n");
UserEnterExclusive();
if (!(Wnd = UserGetWindowObject(hwnd)) || // FIXME:
Wnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
Wnd == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
{
RETURN( FALSE);
}
_SEH2_TRY
{
if (lppt)
{
ProbeForRead(lppt, sizeof(POINT), 1);
RtlCopyMemory(&pt, lppt, sizeof(POINT));
}
if (lprect)
{
ProbeForRead(lprect, sizeof(RECT), 1);
RtlCopyMemory(&rect, lprect, sizeof(RECT));
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
SetLastNtError(_SEH2_GetExceptionCode());
_SEH2_YIELD(RETURN( FALSE));
}
_SEH2_END
wndpl.length = sizeof(wndpl);
wndpl.showCmd = showCmd;
wndpl.flags = flags = 0;
if ( lppt )
{
flags |= PLACE_MIN;
wndpl.flags |= WPF_SETMINPOSITION;
wndpl.ptMinPosition = pt;
}
if ( lprect )
{
flags |= PLACE_RECT;
wndpl.rcNormalPosition = rect;
}
UserRefObjectCo(Wnd, &Ref);
IntSetWindowPlacement(Wnd, &wndpl, flags);
UserDerefObjectCo(Wnd);
RETURN(TRUE);
CLEANUP:
TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* @implemented
*/
@ -2132,6 +2632,7 @@ NtUserSetWindowPlacement(HWND hWnd,
{
PWND Wnd;
WINDOWPLACEMENT Safepl;
UINT Flags;
DECLARE_RETURN(BOOL);
USER_REFERENCE_ENTRY Ref;
@ -2162,25 +2663,10 @@ NtUserSetWindowPlacement(HWND hWnd,
RETURN( FALSE);
}
Flags = PLACE_MAX | PLACE_RECT;
if (Safepl.flags & WPF_SETMINPOSITION) Flags |= PLACE_MIN;
UserRefObjectCo(Wnd, &Ref);
if ((Wnd->style & (WS_MAXIMIZE | WS_MINIMIZE)) == 0)
{
co_WinPosSetWindowPos(Wnd, NULL,
Safepl.rcNormalPosition.left, Safepl.rcNormalPosition.top,
Safepl.rcNormalPosition.right - Safepl.rcNormalPosition.left,
Safepl.rcNormalPosition.bottom - Safepl.rcNormalPosition.top,
SWP_NOZORDER | SWP_NOACTIVATE);
}
/* FIXME - change window status */
co_WinPosShowWindow(Wnd, Safepl.showCmd);
Wnd->InternalPosInitialized = TRUE;
Wnd->InternalPos.NormalRect = Safepl.rcNormalPosition;
Wnd->InternalPos.IconPos = Safepl.ptMinPosition;
Wnd->InternalPos.MaxPos = Safepl.ptMaxPosition;
IntSetWindowPlacement(Wnd, &Safepl, Flags);
UserDerefObjectCo(Wnd);
RETURN(TRUE);
@ -2191,17 +2677,43 @@ CLEANUP:
}
/*
* @unimplemented
* @implemented
*/
BOOL APIENTRY
NtUserShowWindowAsync(HWND hWnd, LONG nCmdShow)
{
#if 0
STUB
return 0;
#else
return NtUserShowWindow(hWnd, nCmdShow);
#endif
PWND Window;
BOOL ret;
DECLARE_RETURN(BOOL);
USER_REFERENCE_ENTRY Ref;
TRACE("Enter NtUserShowWindowAsync\n");
UserEnterExclusive();
if (!(Window = UserGetWindowObject(hWnd)) || // FIXME:
Window == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
Window == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
{
RETURN(FALSE);
}
if ( nCmdShow > SW_MAX )
{
EngSetLastError(ERROR_INVALID_PARAMETER);
RETURN(FALSE);
}
UserRefObjectCo(Window, &Ref);
ret = co_IntSendMessageNoWait( hWnd, WM_ASYNC_SHOWWINDOW, nCmdShow, 0 );
UserDerefObjectCo(Window);
if (-1 == (int) ret || !ret) ret = FALSE;
RETURN(ret);
CLEANUP:
TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
@ -2243,56 +2755,54 @@ CLEANUP:
END_CLEANUP;
}
//// Ugly NtUser API ////
BOOL
APIENTRY
NtUserGetMinMaxInfo(
HWND hWnd,
MINMAXINFO *MinMaxInfo,
BOOL SendMessage)
/*
* @implemented
*/
HWND APIENTRY
NtUserWindowFromPoint(LONG X, LONG Y)
{
POINT Size;
PWND Window = NULL;
MINMAXINFO SafeMinMax;
NTSTATUS Status;
BOOL ret;
POINT pt;
HWND Ret;
PWND DesktopWindow = NULL, Window = NULL;
USHORT hittest;
DECLARE_RETURN(HWND);
USER_REFERENCE_ENTRY Ref;
TRACE("Enter NtUserGetMinMaxInfo\n");
TRACE("Enter NtUserWindowFromPoint\n");
UserEnterExclusive();
if(!(Window = UserGetWindowObject(hWnd)))
if ((DesktopWindow = UserGetWindowObject(IntGetDesktopWindow())))
{
ret = FALSE;
goto cleanup;
//PTHREADINFO pti;
pt.x = X;
pt.y = Y;
//hmm... threads live on desktops thus we have a reference on the desktop and indirectly the desktop window
//its possible this referencing is useless, thou it shouldnt hurt...
UserRefObjectCo(DesktopWindow, &Ref);
//pti = PsGetCurrentThreadWin32Thread();
Window = co_WinPosWindowFromPoint(DesktopWindow, &pt, &hittest);
if(Window)
{
Ret = Window->head.h;
RETURN( Ret);
}
}
UserRefObjectCo(Window, &Ref);
RETURN( NULL);
Size.x = Window->rcWindow.left;
Size.y = Window->rcWindow.top;
WinPosInitInternalPos(Window, &Size,
&Window->rcWindow);
CLEANUP:
if (Window) UserDereferenceObject(Window);
if (DesktopWindow) UserDerefObjectCo(DesktopWindow);
co_WinPosGetMinMaxInfo(Window, &SafeMinMax.ptMaxSize, &SafeMinMax.ptMaxPosition,
&SafeMinMax.ptMinTrackSize, &SafeMinMax.ptMaxTrackSize);
Status = MmCopyToCaller(MinMaxInfo, &SafeMinMax, sizeof(MINMAXINFO));
if(!NT_SUCCESS(Status))
{
SetLastNtError(Status);
ret = FALSE;
goto cleanup;
}
ret = TRUE;
cleanup:
if (Window) UserDerefObjectCo(Window);
TRACE("Leave NtUserGetMinMaxInfo, ret=%i\n", ret);
TRACE("Leave NtUserWindowFromPoint, ret=%i\n",_ret_);
UserLeave();
return ret;
END_CLEANUP;
}
/* EOF */

View file

@ -683,7 +683,6 @@ NtGdiOffsetWindowOrgEx 4
#
NtUserBuildMenuItemList 4
NtUserGetMenuDefaultItem 3
NtUserGetMinMaxInfo 3
NtUserGetMonitorInfo 2
NtUserMenuInfo 3
NtUserMenuItemInfo 5

View file

@ -683,7 +683,6 @@ SVC_(GdiOffsetWindowOrgEx, 4)
SVC_(UserBuildMenuItemList, 4)
SVC_(UserGetMenuDefaultItem, 3)
SVC_(UserGetMinMaxInfo, 3)
SVC_(UserGetMonitorInfo, 2)
SVC_(UserMenuInfo, 3)
SVC_(UserMenuItemInfo, 5)