Store in the server all the window information accessible with
Get/SetWindowLong.
diff --git a/windows/win.c b/windows/win.c
index dc85efc..0c8deea 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -362,7 +362,6 @@
*/
void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
{
- BOOL ret;
WND *wndPtr = WIN_GetPtr( hwnd );
if (!wndPtr) return;
@@ -377,10 +376,17 @@
req->handle = hwnd;
req->parent = parent;
req->previous = hwndInsertAfter;
- ret = !SERVER_CALL_ERR();
+ if (!SERVER_CALL())
+ {
+ if (req->full_parent && req->full_parent != wndPtr->parent)
+ {
+ wndPtr->owner = 0; /* reset owner when changing parent */
+ wndPtr->parent = req->full_parent;
+ }
+ }
+
}
SERVER_END_REQ;
- if (ret && parent) wndPtr->parent = WIN_GetFullHandle(parent);
WIN_ReleasePtr( wndPtr );
}
@@ -392,12 +398,102 @@
*/
void WIN_SetOwner( HWND hwnd, HWND owner )
{
- WND *win = WIN_FindWndPtr( hwnd );
- if (win)
+ WND *win = WIN_GetPtr( hwnd );
+
+ if (!win) return;
+ if (win == WND_OTHER_PROCESS)
{
- win->owner = owner;
- WIN_ReleaseWndPtr( win );
+ if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
+ return;
}
+ SERVER_START_REQ( set_window_owner )
+ {
+ req->handle = hwnd;
+ req->owner = owner;
+ if (!SERVER_CALL()) win->owner = req->full_owner;
+ }
+ SERVER_END_REQ;
+ WIN_ReleasePtr( win );
+}
+
+
+/***********************************************************************
+ * WIN_SetStyle
+ *
+ * Change the style of a window.
+ */
+LONG WIN_SetStyle( HWND hwnd, LONG style )
+{
+ BOOL ok;
+ LONG ret = 0;
+ WND *win = WIN_GetPtr( hwnd );
+
+ if (!win) return 0;
+ if (win == WND_OTHER_PROCESS)
+ {
+ if (IsWindow(hwnd))
+ ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
+ return 0;
+ }
+ if (style == win->dwStyle)
+ {
+ WIN_ReleasePtr( win );
+ return style;
+ }
+ SERVER_START_REQ( set_window_info )
+ {
+ req->handle = hwnd;
+ req->flags = SET_WIN_STYLE;
+ req->style = style;
+ if ((ok = !SERVER_CALL()))
+ {
+ ret = req->old_style;
+ win->dwStyle = style;
+ }
+ }
+ SERVER_END_REQ;
+ WIN_ReleasePtr( win );
+ if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
+ return ret;
+}
+
+
+/***********************************************************************
+ * WIN_SetExStyle
+ *
+ * Change the extended style of a window.
+ */
+LONG WIN_SetExStyle( HWND hwnd, LONG style )
+{
+ LONG ret = 0;
+ WND *win = WIN_GetPtr( hwnd );
+
+ if (!win) return 0;
+ if (win == WND_OTHER_PROCESS)
+ {
+ if (IsWindow(hwnd))
+ ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
+ return 0;
+ }
+ if (style == win->dwExStyle)
+ {
+ WIN_ReleasePtr( win );
+ return style;
+ }
+ SERVER_START_REQ( set_window_info )
+ {
+ req->handle = hwnd;
+ req->flags = SET_WIN_EXSTYLE;
+ req->ex_style = style;
+ if (!SERVER_CALL())
+ {
+ ret = req->old_ex_style;
+ win->dwExStyle = style;
+ }
+ }
+ SERVER_END_REQ;
+ WIN_ReleasePtr( win );
+ return ret;
}
@@ -603,11 +699,10 @@
wndPtr->hmemTaskQ = 0;
if (!(wndPtr->dwStyle & WS_CHILD))
- if (wndPtr->wIDmenu)
- {
- DestroyMenu( wndPtr->wIDmenu );
- wndPtr->wIDmenu = 0;
- }
+ {
+ HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
+ if (menu) DestroyMenu( menu );
+ }
if (wndPtr->hSysMenu)
{
DestroyMenu( wndPtr->hSysMenu );
@@ -682,8 +777,7 @@
pWndDesktop->hmemTaskQ = 0;
pWndDesktop->hrgnUpdate = 0;
pWndDesktop->hwndLastActive = hwndDesktop;
- pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
- WS_CLIPSIBLINGS;
+ pWndDesktop->dwStyle = 0;
pWndDesktop->dwExStyle = 0;
pWndDesktop->clsStyle = clsStyle;
pWndDesktop->dce = NULL;
@@ -712,6 +806,7 @@
SetRect( &rect, 0, 0, cs.cx, cs.cy );
WIN_SetRectangles( hwndDesktop, &rect, &rect );
+ WIN_SetStyle( hwndDesktop, WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
@@ -798,11 +893,9 @@
struct tagCLASS *classPtr;
WND *wndPtr;
HWND hwnd, hwndLinkAfter, parent, owner;
- POINT maxSize, maxPos, minTrack, maxTrack;
INT wndExtra;
DWORD clsStyle;
WNDPROC winproc;
- RECT rect;
DCE *dce;
BOOL unicode = (type == WIN_PROC_32W);
@@ -924,8 +1017,8 @@
TRACE("CBT-hook returned 0\n");
free_window_handle( hwnd );
CLASS_RemoveWindow( classPtr );
- hwnd = 0;
- goto end;
+ WIN_ReleaseWndPtr(wndPtr);
+ return 0;
}
}
@@ -940,6 +1033,16 @@
wndPtr->flags |= WIN_NEED_SIZE;
}
}
+ SERVER_START_REQ( set_window_info )
+ {
+ req->handle = hwnd;
+ req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
+ req->style = wndPtr->dwStyle;
+ req->ex_style = wndPtr->dwExStyle;
+ req->instance = (void *)wndPtr->hInstance;
+ SERVER_CALL();
+ }
+ SERVER_END_REQ;
/* Get class or window DC if needed */
@@ -947,28 +1050,6 @@
else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
else wndPtr->dce = NULL;
- /* Initialize the dimensions before sending WM_GETMINMAXINFO */
-
- SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
- WIN_SetRectangles( hwnd, &rect, &rect );
-
- /* Send the WM_GETMINMAXINFO message and fix the size if needed */
-
- if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
- {
- WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
- if (maxSize.x < cs->cx) cs->cx = maxSize.x;
- if (maxSize.y < cs->cy) cs->cy = maxSize.y;
- if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
- if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
- }
-
- if (cs->cx < 0) cs->cx = 0;
- if (cs->cy < 0) cs->cy = 0;
-
- SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
- WIN_SetRectangles( hwnd, &rect, &rect );
-
/* Set the window menu */
if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
@@ -988,41 +1069,35 @@
}
}
}
- else wndPtr->wIDmenu = (UINT)cs->hMenu;
+ else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
+ WIN_ReleaseWndPtr( wndPtr );
if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
{
- WARN("aborted by WM_xxCREATE!\n");
- WIN_ReleaseWndPtr( wndPtr );
WIN_DestroyWindow( hwnd );
- CLASS_RemoveWindow( classPtr );
return 0;
}
/* Notify the parent window only */
send_parent_notify( hwnd, WM_CREATE );
- if( !IsWindow(hwnd) )
- {
- hwnd = 0;
- goto end;
- }
+ if (!IsWindow( hwnd )) return 0;
if (cs->style & WS_VISIBLE)
{
/* in case WS_VISIBLE got set in the meantime */
- wndPtr->dwStyle &= ~WS_VISIBLE;
+ if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
+ WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
+ WIN_ReleasePtr( wndPtr );
ShowWindow( hwnd, sw );
}
/* Call WH_SHELL hook */
- if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
+ if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
TRACE("created window %04x\n", hwnd);
- end:
- WIN_ReleaseWndPtr(wndPtr);
return hwnd;
}
@@ -1524,27 +1599,31 @@
{
WND *wndPtr;
BOOL retvalue;
+ LONG style;
+ HWND full_handle;
+
+ if (!(full_handle = WIN_IsCurrentThread( hwnd )))
+ return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
+
+ hwnd = full_handle;
TRACE("( %x, %d )\n", hwnd, enable);
- if (USER_Driver.pEnableWindow)
- return USER_Driver.pEnableWindow( hwnd, enable );
+ if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
+ style = wndPtr->dwStyle;
+ retvalue = ((style & WS_DISABLED) != 0);
+ WIN_ReleasePtr( wndPtr );
- if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
- hwnd = wndPtr->hwndSelf; /* make it a full handle */
-
- retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
-
- if (enable && (wndPtr->dwStyle & WS_DISABLED))
+ if (enable && retvalue)
{
- wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
+ WIN_SetStyle( hwnd, style & ~WS_DISABLED );
SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
}
- else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
+ else if (!enable && !retvalue)
{
SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
- wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
+ WIN_SetStyle( hwnd, style | WS_DISABLED );
if (hwnd == GetFocus())
SetFocus( 0 ); /* A disabled window can't have the focus */
@@ -1554,7 +1633,6 @@
SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
}
- WIN_ReleaseWndPtr(wndPtr);
return retvalue;
}
@@ -1588,22 +1666,32 @@
*/
WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
{
- WORD retvalue;
- WND * wndPtr = WIN_FindWndPtr( hwnd );
- if (!wndPtr) return 0;
if (offset >= 0)
{
- if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
+ WORD retvalue = 0;
+ WND *wndPtr = WIN_GetPtr( hwnd );
+ if (!wndPtr)
+ {
+ SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ return 0;
+ }
+ if (wndPtr == WND_OTHER_PROCESS)
+ {
+ if (IsWindow( hwnd ))
+ FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
+ SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ return 0;
+ }
+ if (offset > wndPtr->cbWndExtra - sizeof(WORD))
{
WARN("Invalid offset %d\n", offset );
- retvalue = 0;
+ SetLastError( ERROR_INVALID_INDEX );
}
else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
- WIN_ReleaseWndPtr(wndPtr);
+ WIN_ReleasePtr( wndPtr );
return retvalue;
}
- WIN_ReleaseWndPtr(wndPtr);
switch(offset)
{
case GWL_HWNDPARENT:
@@ -1629,24 +1717,8 @@
WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
{
WORD *ptr, retval;
- WND * wndPtr = WIN_FindWndPtr( hwnd );
- if (!wndPtr) return 0;
- if (offset >= 0)
- {
- if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
- {
- WARN("Invalid offset %d\n", offset );
- WIN_ReleaseWndPtr(wndPtr);
- return 0;
- }
- ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
- retval = *ptr;
- *ptr = newval;
- WIN_ReleaseWndPtr(wndPtr);
- return retval;
- }
+ WND * wndPtr;
- WIN_ReleaseWndPtr(wndPtr);
switch(offset)
{
case GWL_ID:
@@ -1654,9 +1726,40 @@
case GWL_HWNDPARENT:
return SetWindowLongW( hwnd, offset, (UINT)newval );
default:
+ if (offset < 0)
+ {
+ WARN("Invalid offset %d\n", offset );
+ SetLastError( ERROR_INVALID_INDEX );
+ return 0;
+ }
+ }
+
+ wndPtr = WIN_GetPtr( hwnd );
+ if (wndPtr == WND_OTHER_PROCESS)
+ {
+ if (IsWindow(hwnd))
+ FIXME( "set %d <- %x not supported yet on other process window %x\n",
+ offset, newval, hwnd );
+ wndPtr = NULL;
+ }
+ if (!wndPtr)
+ {
+ SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ return 0;
+ }
+
+ if (offset > wndPtr->cbWndExtra - sizeof(WORD))
+ {
WARN("Invalid offset %d\n", offset );
+ WIN_ReleasePtr(wndPtr);
+ SetLastError( ERROR_INVALID_INDEX );
return 0;
}
+ ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
+ retval = *ptr;
+ *ptr = newval;
+ WIN_ReleasePtr(wndPtr);
+ return retval;
}
@@ -1667,49 +1770,87 @@
*/
static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
{
- LONG retvalue;
- WND * wndPtr = WIN_FindWndPtr( hwnd );
- if (!wndPtr) return 0;
+ LONG retvalue = 0;
+ WND *wndPtr;
+
+ if (offset == GWL_HWNDPARENT) return (LONG)GetParent( hwnd );
+
+ if (!(wndPtr = WIN_GetPtr( hwnd )))
+ {
+ SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ return 0;
+ }
+
+ if (wndPtr == WND_OTHER_PROCESS)
+ {
+ if (offset >= 0)
+ {
+ FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
+ SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ return 0;
+ }
+ if (offset == GWL_WNDPROC)
+ {
+ SetLastError( ERROR_ACCESS_DENIED );
+ return 0;
+ }
+ SERVER_START_REQ( set_window_info )
+ {
+ req->handle = hwnd;
+ req->flags = 0; /* don't set anything, just retrieve */
+ if (!SERVER_CALL_ERR())
+ {
+ switch(offset)
+ {
+ case GWL_STYLE: retvalue = req->style; break;
+ case GWL_EXSTYLE: retvalue = req->ex_style; break;
+ case GWL_ID: retvalue = req->id; break;
+ case GWL_HINSTANCE: retvalue = (ULONG_PTR)req->instance; break;
+ case GWL_USERDATA: retvalue = (ULONG_PTR)req->user_data; break;
+ default:
+ SetLastError( ERROR_INVALID_INDEX );
+ break;
+ }
+ }
+ }
+ SERVER_END_REQ;
+ return retvalue;
+ }
+
+ /* now we have a valid wndPtr */
+
if (offset >= 0)
{
- if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
+ if (offset > wndPtr->cbWndExtra - sizeof(LONG))
{
WARN("Invalid offset %d\n", offset );
- retvalue = 0;
- goto end;
+ WIN_ReleasePtr( wndPtr );
+ SetLastError( ERROR_INVALID_INDEX );
+ return 0;
}
- retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
/* Special case for dialog window procedure */
if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
- {
retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
- goto end;
+ else
+ retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
+ WIN_ReleasePtr( wndPtr );
+ return retvalue;
}
- goto end;
- }
+
switch(offset)
{
- case GWL_USERDATA: retvalue = wndPtr->userdata;
- goto end;
- case GWL_STYLE: retvalue = wndPtr->dwStyle;
- goto end;
- case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
- goto end;
- case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
- goto end;
- case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
- type );
- goto end;
- case GWL_HWNDPARENT: retvalue = (LONG)GetParent(hwnd);
- goto end;
- case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
- goto end;
- default:
- WARN("Unknown offset %d\n", offset );
+ case GWL_USERDATA: retvalue = wndPtr->userdata; break;
+ case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
+ case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
+ case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
+ case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
+ case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
+ default:
+ WARN("Unknown offset %d\n", offset );
+ SetLastError( ERROR_INVALID_INDEX );
+ break;
}
- retvalue = 0;
-end:
- WIN_ReleaseWndPtr(wndPtr);
+ WIN_ReleasePtr(wndPtr);
return retvalue;
}
@@ -1721,99 +1862,148 @@
*
* 0 is the failure code. However, in the case of failure SetLastError
* must be set to distinguish between a 0 return value and a failure.
- *
- * FIXME: The error values for SetLastError may not be right. Can
- * someone check with the real thing?
*/
static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
WINDOWPROCTYPE type )
{
- LONG *ptr, retval;
- WND * wndPtr = WIN_FindWndPtr( hwnd );
- STYLESTRUCT style;
+ LONG retval = 0;
+ WND *wndPtr;
- TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
+ TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
- if (!wndPtr)
+ if (!WIN_IsCurrentThread( hwnd ))
{
- /* Is this the right error? */
- SetLastError( ERROR_INVALID_WINDOW_HANDLE );
- return 0;
+ ERR("set %x %d %x\n", hwnd, offset, newval );
+ return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
}
+ wndPtr = WIN_GetPtr( hwnd );
+
if (offset >= 0)
{
- if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
+ LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
+ if (offset > wndPtr->cbWndExtra - sizeof(LONG))
{
WARN("Invalid offset %d\n", offset );
-
- /* Is this the right error? */
- SetLastError( ERROR_OUTOFMEMORY );
-
- retval = 0;
- goto end;
+ WIN_ReleasePtr( wndPtr );
+ SetLastError( ERROR_INVALID_INDEX );
+ return 0;
}
- ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
/* Special case for dialog window procedure */
if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
{
retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
type, WIN_PROC_WINDOW );
- goto end;
+ WIN_ReleasePtr( wndPtr );
+ return retval;
}
+ retval = *ptr;
+ *ptr = newval;
+ WIN_ReleasePtr( wndPtr );
}
- else switch(offset)
+ else
{
- case GWL_ID:
- ptr = (DWORD*)&wndPtr->wIDmenu;
- break;
- case GWL_HINSTANCE:
- ptr = (DWORD*)&wndPtr->hInstance;
- break;
- case GWL_USERDATA:
- ptr = &wndPtr->userdata;
- break;
- case GWL_HWNDPARENT:
- retval = SetParent( hwnd, (HWND)newval );
- goto end;
- case GWL_WNDPROC:
- retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
- WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
- type, WIN_PROC_WINDOW );
- goto end;
- case GWL_STYLE:
- retval = wndPtr->dwStyle;
- style.styleOld = wndPtr->dwStyle;
- style.styleNew = newval;
- SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
- wndPtr->dwStyle = style.styleNew;
- if (USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, retval );
- SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
- retval = style.styleOld;
- goto end;
+ STYLESTRUCT style;
+ BOOL ok;
+
+ /* first some special cases */
+ switch( offset )
+ {
+ case GWL_STYLE:
case GWL_EXSTYLE:
- style.styleOld = wndPtr->dwExStyle;
- style.styleNew = newval;
- SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
- wndPtr->dwExStyle = style.styleNew;
- SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
- retval = style.styleOld;
- goto end;
-
- default:
+ style.styleOld = wndPtr->dwStyle;
+ style.styleNew = newval;
+ WIN_ReleasePtr( wndPtr );
+ SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
+ if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
+ newval = style.styleNew;
+ break;
+ case GWL_HWNDPARENT:
+ WIN_ReleasePtr( wndPtr );
+ return (LONG)SetParent( hwnd, (HWND)newval );
+ case GWL_WNDPROC:
+ retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
+ WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
+ type, WIN_PROC_WINDOW );
+ WIN_ReleasePtr( wndPtr );
+ return retval;
+ case GWL_ID:
+ case GWL_HINSTANCE:
+ case GWL_USERDATA:
+ break;
+ default:
+ WIN_ReleasePtr( wndPtr );
WARN("Invalid offset %d\n", offset );
+ SetLastError( ERROR_INVALID_INDEX );
+ return 0;
+ }
- /* Don't think this is right error but it should do */
- SetLastError( ERROR_OUTOFMEMORY );
+ SERVER_START_REQ( set_window_info )
+ {
+ req->handle = hwnd;
+ switch(offset)
+ {
+ case GWL_STYLE:
+ req->flags = SET_WIN_STYLE;
+ req->style = newval;
+ break;
+ case GWL_EXSTYLE:
+ req->flags = SET_WIN_EXSTYLE;
+ req->ex_style = newval;
+ break;
+ case GWL_ID:
+ req->flags = SET_WIN_ID;
+ req->id = newval;
+ break;
+ case GWL_HINSTANCE:
+ req->flags = SET_WIN_INSTANCE;
+ req->instance = (void *)newval;
+ break;
+ case GWL_USERDATA:
+ req->flags = SET_WIN_USERDATA;
+ req->user_data = (void *)newval;
+ break;
+ }
+ if ((ok = !SERVER_CALL_ERR()))
+ {
+ switch(offset)
+ {
+ case GWL_STYLE:
+ wndPtr->dwStyle = newval;
+ retval = req->old_style;
+ break;
+ case GWL_EXSTYLE:
+ wndPtr->dwExStyle = newval;
+ retval = req->old_ex_style;
+ break;
+ case GWL_ID:
+ wndPtr->wIDmenu = newval;
+ retval = req->old_id;
+ break;
+ case GWL_HINSTANCE:
+ wndPtr->hInstance = newval;
+ retval = (HINSTANCE)req->old_instance;
+ break;
+ case GWL_USERDATA:
+ wndPtr->userdata = newval;
+ retval = (ULONG_PTR)req->old_user_data;
+ break;
+ }
+ }
+ }
+ SERVER_END_REQ;
+ WIN_ReleasePtr( wndPtr );
- retval = 0;
- goto end;
+ if (!ok) return 0;
+
+ if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
+ USER_Driver.pSetWindowStyle( hwnd, retval );
+
+ if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
+ SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
+
}
- retval = *ptr;
- *ptr = newval;
-end:
- WIN_ReleaseWndPtr(wndPtr);
return retval;
}
@@ -1928,15 +2118,6 @@
* it sends WM_STYLECHANGING before changing the settings
* and WM_STYLECHANGED afterwards.
* App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
- *
- * BUGS
- *
- * GWL_STYLE does not dispatch WM_STYLE... messages.
- *
- * CONFORMANCE
- *
- * ECMA-234, Win32
- *
*/
LONG WINAPI SetWindowLongW(
HWND hwnd, /* [in] window to alter */
@@ -2089,13 +2270,33 @@
WND *wndPtr;
HWND retvalue = 0;
- if ((wndPtr = WIN_FindWndPtr(hwnd)))
+ if (!(wndPtr = WIN_GetPtr( hwnd )))
{
- if (wndPtr->dwStyle & WS_CHILD)
- retvalue = wndPtr->parent;
- else if (wndPtr->dwStyle & WS_POPUP)
- retvalue = wndPtr->owner;
- WIN_ReleaseWndPtr(wndPtr);
+ SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ return 0;
+ }
+ if (wndPtr == WND_OTHER_PROCESS)
+ {
+ LONG style = GetWindowLongW( hwnd, GWL_STYLE );
+ if (style & (WS_POPUP | WS_CHILD))
+ {
+ SERVER_START_REQ( get_window_tree )
+ {
+ req->handle = hwnd;
+ if (!SERVER_CALL_ERR())
+ {
+ if (style & WS_CHILD) retvalue = req->parent;
+ else retvalue = req->owner;
+ }
+ }
+ SERVER_END_REQ;
+ }
+ }
+ else
+ {
+ if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
+ else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
+ WIN_ReleasePtr( wndPtr );
}
return retvalue;
}
@@ -2106,8 +2307,30 @@
*/
HWND WINAPI GetAncestor( HWND hwnd, UINT type )
{
+ WND *win;
HWND ret = 0;
- size_t size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE;
+ size_t size;
+
+ for (;;)
+ {
+ if (!(win = WIN_GetPtr( hwnd )))
+ {
+ SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ return 0;
+ }
+ if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
+ ret = win->parent;
+ WIN_ReleasePtr( win );
+ if (type == GA_PARENT) return ret;
+ if (!ret || ret == GetDesktopWindow())
+ {
+ ret = hwnd; /* if ret is the desktop, hwnd is the root ancestor */
+ goto done;
+ }
+ hwnd = ret; /* restart with parent as hwnd */
+ }
+
+ size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE;
SERVER_START_VAR_REQ( get_window_parents, size )
{
@@ -2134,6 +2357,7 @@
}
SERVER_END_VAR_REQ;
+ done:
if (ret && type == GA_ROOTOWNER)
{
for (;;)
@@ -2148,16 +2372,28 @@
/*****************************************************************
- * WIN_SetParent
- *
- * Implementation of SetParent, runs in the thread owning the window.
+ * SetParent (USER32.@)
*/
-HWND WIN_SetParent( HWND hwnd, HWND parent )
+HWND WINAPI SetParent( HWND hwnd, HWND parent )
{
WND *wndPtr;
- HWND retvalue;
+ HWND retvalue, full_handle;
BOOL was_visible;
+ if (!parent) parent = GetDesktopWindow();
+ else parent = WIN_GetFullHandle( parent );
+
+ if (!IsWindow( parent ))
+ {
+ SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ return 0;
+ }
+
+ if (!(full_handle = WIN_IsCurrentThread( hwnd )))
+ return SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
+
+ hwnd = full_handle;
+
if (USER_Driver.pSetParent)
return USER_Driver.pSetParent( hwnd, parent );
@@ -2196,34 +2432,6 @@
}
-/*****************************************************************
- * SetParent (USER32.@)
- */
-HWND WINAPI SetParent( HWND hwnd, HWND parent )
-{
- HWND full_handle;
-
- if (!parent) parent = GetDesktopWindow();
- else parent = WIN_GetFullHandle( parent );
-
- if (!IsWindow( parent ))
- {
- SetLastError( ERROR_INVALID_WINDOW_HANDLE );
- return 0;
- }
-
- if ((full_handle = WIN_IsCurrentThread( hwnd )))
- return WIN_SetParent( full_handle, parent );
-
- if ((full_handle = WIN_GetFullHandle(hwnd)) == GetDesktopWindow())
- {
- SetLastError( ERROR_INVALID_WINDOW_HANDLE );
- return 0;
- }
- return SendMessageW( full_handle, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
-}
-
-
/*******************************************************************
* IsChild (USER32.@)
*/
@@ -2305,13 +2513,21 @@
{
HWND retval = 0;
- if (rel == GW_OWNER) /* special case: not fully supported in the server yet */
+ if (rel == GW_OWNER) /* this one may be available locally */
{
- WND *wndPtr = WIN_FindWndPtr( hwnd );
- if (!wndPtr) return 0;
- retval = wndPtr->owner;
- WIN_ReleaseWndPtr( wndPtr );
- return retval;
+ WND *wndPtr = WIN_GetPtr( hwnd );
+ if (!wndPtr)
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return 0;
+ }
+ if (wndPtr != WND_OTHER_PROCESS)
+ {
+ retval = wndPtr->owner;
+ WIN_ReleasePtr( wndPtr );
+ return retval;
+ }
+ /* else fall through to server call */
}
SERVER_START_REQ( get_window_tree )
@@ -2333,6 +2549,9 @@
case GW_HWNDPREV:
retval = req->prev_sibling;
break;
+ case GW_OWNER:
+ retval = req->owner;
+ break;
case GW_CHILD:
retval = req->first_child;
break;