2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
36 #include "user_private.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(win);
43 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
44 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
46 /**********************************************************************/
48 /* helper for Get/SetWindowLong */
49 static inline LONG_PTR get_win_data( const void *ptr, UINT size )
51 if (size == sizeof(WORD))
54 memcpy( &ret, ptr, sizeof(ret) );
57 else if (size == sizeof(DWORD))
60 memcpy( &ret, ptr, sizeof(ret) );
66 memcpy( &ret, ptr, sizeof(ret) );
71 /* helper for Get/SetWindowLong */
72 static inline void set_win_data( void *ptr, LONG_PTR val, UINT size )
74 if (size == sizeof(WORD))
77 memcpy( ptr, &newval, sizeof(newval) );
79 else if (size == sizeof(DWORD))
82 memcpy( ptr, &newval, sizeof(newval) );
86 memcpy( ptr, &val, sizeof(val) );
91 static void *user_handles[NB_USER_HANDLES];
93 /***********************************************************************
94 * create_window_handle
96 * Create a window handle with the server.
98 static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
99 HINSTANCE instance, BOOL unicode )
103 HWND full_parent = 0, full_owner = 0;
104 struct tagCLASS *class = NULL;
105 user_handle_t handle = 0;
108 /* if 16-bit instance, map to module handle */
109 if (instance && !HIWORD(instance))
110 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
112 SERVER_START_REQ( create_window )
114 req->parent = parent;
116 req->instance = instance;
117 if (!(req->atom = get_int_atom_value( name )) && name)
118 wine_server_add_data( req, name, strlenW(name)*sizeof(WCHAR) );
119 if (!wine_server_call_err( req ))
121 handle = reply->handle;
122 full_parent = reply->parent;
123 full_owner = reply->owner;
124 extra_bytes = reply->extra;
125 class = reply->class_ptr;
132 WARN( "error %d creating window\n", GetLastError() );
136 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
138 SERVER_START_REQ( destroy_window )
140 req->handle = handle;
141 wine_server_call( req );
144 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
148 if (!parent) /* if parent is 0 we don't have a desktop window yet */
150 struct user_thread_info *thread_info = get_user_thread_info();
152 if (!thread_info->desktop) thread_info->desktop = full_parent ? full_parent : handle;
153 else assert( full_parent == thread_info->desktop );
154 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
155 ERR( "failed to create desktop window\n" );
160 index = USER_HANDLE_TO_INDEX(handle);
161 assert( index < NB_USER_HANDLES );
162 user_handles[index] = win;
163 win->hwndSelf = handle;
164 win->parent = full_parent;
165 win->owner = full_owner;
166 win->dwMagic = WND_MAGIC;
168 win->cbWndExtra = extra_bytes;
169 memset( win->wExtra, 0, extra_bytes );
170 CLASS_AddWindow( class, win, unicode );
175 /***********************************************************************
178 * Free a window handle.
180 static WND *free_window_handle( HWND hwnd )
183 WORD index = USER_HANDLE_TO_INDEX(hwnd);
185 if (index >= NB_USER_HANDLES) return NULL;
187 if ((ptr = user_handles[index]))
189 SERVER_START_REQ( destroy_window )
192 if (!wine_server_call_err( req ))
194 user_handles[index] = NULL;
203 HeapFree( GetProcessHeap(), 0, ptr );
208 /*******************************************************************
209 * list_window_children
211 * Build an array of the children of a given window. The array must be
212 * freed with HeapFree. Returns NULL when no windows are found.
214 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
223 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
225 SERVER_START_REQ( get_window_children )
230 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
231 if (!wine_server_call( req )) count = reply->count;
234 if (count && count < size)
239 HeapFree( GetProcessHeap(), 0, list );
241 size = count + 1; /* restart with a large enough buffer */
247 /*******************************************************************
248 * list_window_parents
250 * Build an array of all parents of a given window, starting with
251 * the immediate parent. The array must be freed with HeapFree.
253 static HWND *list_window_parents( HWND hwnd )
257 int pos = 0, size = 16, count = 0;
259 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
264 if (!(win = WIN_GetPtr( current ))) goto empty;
265 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
266 if (win == WND_DESKTOP)
268 if (!pos) goto empty;
272 list[pos] = current = win->parent;
273 WIN_ReleasePtr( win );
274 if (++pos == size - 1)
276 /* need to grow the list */
277 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
278 if (!new_list) goto empty;
284 /* at least one parent belongs to another process, have to query the server */
289 SERVER_START_REQ( get_window_parents )
292 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
293 if (!wine_server_call( req )) count = reply->count;
296 if (!count) goto empty;
302 HeapFree( GetProcessHeap(), 0, list );
304 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
308 HeapFree( GetProcessHeap(), 0, list );
313 /*******************************************************************
316 static void send_parent_notify( HWND hwnd, UINT msg )
318 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
319 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
321 HWND parent = GetParent(hwnd);
322 if (parent && parent != GetDesktopWindow())
323 SendMessageW( parent, WM_PARENTNOTIFY,
324 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
329 /*******************************************************************
330 * get_server_window_text
332 * Retrieve the window text from the server.
334 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
338 SERVER_START_REQ( get_window_text )
341 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
342 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
345 text[len / sizeof(WCHAR)] = 0;
349 /***********************************************************************
352 * Return a pointer to the WND structure if local to the process,
353 * or WND_OTHER_PROCESS if handle may be valid in other process.
354 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
356 WND *WIN_GetPtr( HWND hwnd )
359 WORD index = USER_HANDLE_TO_INDEX(hwnd);
361 if (index >= NB_USER_HANDLES) return NULL;
364 if ((ptr = user_handles[index]))
366 if (ptr->dwMagic == WND_MAGIC &&
367 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
371 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
373 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
376 else ptr = WND_OTHER_PROCESS;
382 /***********************************************************************
383 * WIN_IsCurrentProcess
385 * Check whether a given window belongs to the current process (and return the full handle).
387 HWND WIN_IsCurrentProcess( HWND hwnd )
392 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
394 WIN_ReleasePtr( ptr );
399 /***********************************************************************
400 * WIN_IsCurrentThread
402 * Check whether a given window belongs to the current thread (and return the full handle).
404 HWND WIN_IsCurrentThread( HWND hwnd )
409 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
410 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
411 WIN_ReleasePtr( ptr );
416 /***********************************************************************
419 * Convert a 16-bit window handle to a full 32-bit handle.
421 HWND WIN_Handle32( HWND16 hwnd16 )
424 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
426 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
427 /* do sign extension for -2 and -3 */
428 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
430 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
432 if (ptr == WND_DESKTOP) return GetDesktopWindow();
434 if (ptr != WND_OTHER_PROCESS)
436 hwnd = ptr->hwndSelf;
437 WIN_ReleasePtr( ptr );
439 else /* may belong to another process */
441 SERVER_START_REQ( get_window_info )
444 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
452 /***********************************************************************
455 * Change the owner of a window.
457 HWND WIN_SetOwner( HWND hwnd, HWND owner )
459 WND *win = WIN_GetPtr( hwnd );
462 if (!win || win == WND_DESKTOP) return 0;
463 if (win == WND_OTHER_PROCESS)
465 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
468 SERVER_START_REQ( set_window_owner )
472 if (!wine_server_call( req ))
474 win->owner = reply->full_owner;
475 ret = reply->prev_owner;
479 WIN_ReleasePtr( win );
484 /***********************************************************************
487 * Change the style of a window.
489 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
492 ULONG new_style, old_style = 0;
493 WND *win = WIN_GetPtr( hwnd );
495 if (!win || win == WND_DESKTOP) return 0;
496 if (win == WND_OTHER_PROCESS)
499 ERR( "cannot set style %x/%x on other process window %p\n",
500 set_bits, clear_bits, hwnd );
503 new_style = (win->dwStyle | set_bits) & ~clear_bits;
504 if (new_style == win->dwStyle)
506 WIN_ReleasePtr( win );
509 SERVER_START_REQ( set_window_info )
512 req->flags = SET_WIN_STYLE;
513 req->style = new_style;
514 req->extra_offset = -1;
515 if ((ok = !wine_server_call( req )))
517 old_style = reply->old_style;
518 win->dwStyle = new_style;
522 WIN_ReleasePtr( win );
523 if (ok) USER_Driver->pSetWindowStyle( hwnd, old_style );
528 /***********************************************************************
531 * Get the window and client rectangles.
533 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
535 WND *win = WIN_GetPtr( hwnd );
538 if (!win) return FALSE;
539 if (win == WND_DESKTOP)
542 rect.left = rect.top = 0;
543 rect.right = GetSystemMetrics(SM_CXSCREEN);
544 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
545 if (rectWindow) *rectWindow = rect;
546 if (rectClient) *rectClient = rect;
548 else if (win == WND_OTHER_PROCESS)
550 SERVER_START_REQ( get_window_rectangles )
553 if ((ret = !wine_server_call( req )))
557 rectWindow->left = reply->window.left;
558 rectWindow->top = reply->window.top;
559 rectWindow->right = reply->window.right;
560 rectWindow->bottom = reply->window.bottom;
564 rectClient->left = reply->client.left;
565 rectClient->top = reply->client.top;
566 rectClient->right = reply->client.right;
567 rectClient->bottom = reply->client.bottom;
575 if (rectWindow) *rectWindow = win->rectWindow;
576 if (rectClient) *rectClient = win->rectClient;
577 WIN_ReleasePtr( win );
583 /***********************************************************************
586 * Destroy storage associated to a window. "Internals" p.358
588 LRESULT WIN_DestroyWindow( HWND hwnd )
592 HMENU menu = 0, sys_menu;
594 TRACE("%p\n", hwnd );
596 /* free child windows */
597 if ((list = WIN_ListChildren( hwnd )))
600 for (i = 0; list[i]; i++)
602 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
603 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
605 HeapFree( GetProcessHeap(), 0, list );
608 /* Unlink now so we won't bother with the children later on */
609 SERVER_START_REQ( set_parent )
613 wine_server_call( req );
618 * Send the WM_NCDESTROY to the window being destroyed.
620 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
622 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
624 WINPOS_CheckInternalPos( hwnd );
626 /* free resources associated with the window */
628 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
629 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
630 menu = (HMENU)wndPtr->wIDmenu;
631 sys_menu = wndPtr->hSysMenu;
632 WIN_ReleasePtr( wndPtr );
634 if (menu) DestroyMenu( menu );
635 if (sys_menu) DestroyMenu( sys_menu );
637 USER_Driver->pDestroyWindow( hwnd );
639 free_window_handle( hwnd );
643 /***********************************************************************
644 * WIN_DestroyThreadWindows
646 * Destroy all children of 'wnd' owned by the current thread.
648 void WIN_DestroyThreadWindows( HWND hwnd )
653 if (!(list = WIN_ListChildren( hwnd ))) return;
654 for (i = 0; list[i]; i++)
656 if (WIN_IsCurrentThread( list[i] ))
657 DestroyWindow( list[i] );
659 WIN_DestroyThreadWindows( list[i] );
661 HeapFree( GetProcessHeap(), 0, list );
665 /***********************************************************************
668 * Fix the coordinates - Helper for WIN_CreateWindowEx.
669 * returns default show mode in sw.
671 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
673 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
676 if (cs->dwExStyle & WS_EX_MDICHILD)
680 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
681 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
683 TRACE("MDI child id %04x\n", id);
686 if (cs->style & (WS_CHILD | WS_POPUP))
688 if (cs->dwExStyle & WS_EX_MDICHILD)
690 if (IS_DEFAULT(cs->x))
695 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
696 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
700 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
701 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
704 else /* overlapped window */
707 MONITORINFO mon_info;
710 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
712 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
713 mon_info.cbSize = sizeof(mon_info);
714 GetMonitorInfoW( monitor, &mon_info );
715 GetStartupInfoW( &info );
717 if (IS_DEFAULT(cs->x))
719 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
720 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
721 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
724 if (IS_DEFAULT(cs->cx))
726 if (info.dwFlags & STARTF_USESIZE)
728 cs->cx = info.dwXSize;
729 cs->cy = info.dwYSize;
733 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
734 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
737 /* neither x nor cx are default. Check the y values .
738 * In the trace we see Outlook and Outlook Express using
739 * cy set to CW_USEDEFAULT when opening the address book.
741 else if (IS_DEFAULT(cs->cy))
743 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
744 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
750 /***********************************************************************
753 static void dump_window_styles( DWORD style, DWORD exstyle )
756 if(style & WS_POPUP) TRACE(" WS_POPUP");
757 if(style & WS_CHILD) TRACE(" WS_CHILD");
758 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
759 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
760 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
761 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
762 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
763 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
764 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
767 if(style & WS_BORDER) TRACE(" WS_BORDER");
768 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
770 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
771 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
772 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
773 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
774 if (style & WS_CHILD)
776 if(style & WS_GROUP) TRACE(" WS_GROUP");
777 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
781 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
782 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
785 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
786 #define DUMPED_STYLES \
806 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
811 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
812 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
813 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
814 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
815 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
816 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
817 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
818 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
819 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
820 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
821 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
822 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
823 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
824 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
825 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
826 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
827 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
828 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
830 #define DUMPED_EX_STYLES \
831 (WS_EX_DLGMODALFRAME | \
833 WS_EX_NOPARENTNOTIFY | \
835 WS_EX_ACCEPTFILES | \
836 WS_EX_TRANSPARENT | \
841 WS_EX_CONTEXTHELP | \
844 WS_EX_LEFTSCROLLBAR | \
845 WS_EX_CONTROLPARENT | \
850 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
852 #undef DUMPED_EX_STYLES
856 /***********************************************************************
859 * Implementation of CreateWindowEx().
861 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
865 HWND hwnd, parent, owner, top_child = 0;
866 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
867 MDICREATESTRUCTA mdi_cs;
869 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
870 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
871 debugstr_w(className),
872 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
873 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
874 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
876 /* Fix the styles for MDI children */
877 if (cs->dwExStyle & WS_EX_MDICHILD)
881 wndPtr = WIN_GetPtr(cs->hwndParent);
882 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
884 flags = wndPtr->flags;
885 WIN_ReleasePtr(wndPtr);
888 if (!(flags & WIN_ISMDICLIENT))
890 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
894 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
895 * MDICREATESTRUCT members have the originally passed values.
897 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
898 * have the same layout.
900 mdi_cs.szClass = cs->lpszClass;
901 mdi_cs.szTitle = cs->lpszName;
902 mdi_cs.hOwner = cs->hInstance;
907 mdi_cs.style = cs->style;
908 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
910 cs->lpCreateParams = (LPVOID)&mdi_cs;
912 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
914 if (cs->style & WS_POPUP)
916 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
919 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
923 cs->style &= ~WS_POPUP;
924 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
925 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
928 top_child = GetWindow(cs->hwndParent, GW_CHILD);
932 /* Restore current maximized child */
933 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
935 TRACE("Restoring current maximized child %p\n", top_child);
936 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
937 ShowWindow( top_child, SW_SHOWNORMAL );
938 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
943 /* Find the parent window */
945 parent = cs->hwndParent;
948 if (cs->hwndParent == HWND_MESSAGE)
950 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
951 * message window (style: WS_POPUP|WS_DISABLED)
953 FIXME("Parent is HWND_MESSAGE\n");
954 parent = GetDesktopWindow();
956 else if (cs->hwndParent)
958 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
960 parent = GetDesktopWindow();
961 owner = cs->hwndParent;
966 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
968 WARN("No parent for child window\n" );
969 SetLastError(ERROR_TLW_WITH_WSCHILD);
970 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
972 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM) /* are we creating the desktop itself? */
973 parent = GetDesktopWindow();
976 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
978 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
979 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
980 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
981 cs->dwExStyle |= WS_EX_WINDOWEDGE;
983 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
985 /* Create the window structure */
987 if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
989 hwnd = wndPtr->hwndSelf;
991 /* Fill the window structure */
993 wndPtr->tid = GetCurrentThreadId();
994 wndPtr->hInstance = cs->hInstance;
996 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
997 wndPtr->dwExStyle = cs->dwExStyle;
999 wndPtr->helpContext = 0;
1000 wndPtr->pVScroll = NULL;
1001 wndPtr->pHScroll = NULL;
1002 wndPtr->userdata = 0;
1004 wndPtr->hIconSmall = 0;
1005 wndPtr->hSysMenu = 0;
1006 wndPtr->flags |= (flags & WIN_ISWIN32);
1008 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1011 * Correct the window styles.
1013 * It affects only the style loaded into the WIN structure.
1016 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1018 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1019 if (!(wndPtr->dwStyle & WS_POPUP))
1020 wndPtr->dwStyle |= WS_CAPTION;
1024 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1025 * why does the user get to set it?
1028 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1029 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1030 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1032 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1034 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1035 wndPtr->flags |= WIN_NEED_SIZE;
1037 SERVER_START_REQ( set_window_info )
1040 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1041 req->style = wndPtr->dwStyle;
1042 req->ex_style = wndPtr->dwExStyle;
1043 req->instance = (void *)wndPtr->hInstance;
1044 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1045 req->extra_offset = -1;
1046 wine_server_call( req );
1050 /* Set the window menu */
1052 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1056 if (!MENU_SetMenu(hwnd, cs->hMenu))
1058 WIN_ReleasePtr( wndPtr );
1059 free_window_handle( hwnd );
1065 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1068 if (!cs->hInstance || HIWORD(cs->hInstance))
1069 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1071 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1073 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1077 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1078 WIN_ReleasePtr( wndPtr );
1080 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1082 WIN_DestroyWindow( hwnd );
1086 /* Notify the parent window only */
1088 send_parent_notify( hwnd, WM_CREATE );
1089 if (!IsWindow( hwnd )) return 0;
1091 if (cs->style & WS_VISIBLE)
1093 if (cs->style & WS_MAXIMIZE)
1095 else if (cs->style & WS_MINIMIZE)
1096 sw = SW_SHOWMINIMIZED;
1098 ShowWindow( hwnd, sw );
1099 if (cs->dwExStyle & WS_EX_MDICHILD)
1101 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1102 /* ShowWindow won't activate child windows */
1103 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1107 /* Call WH_SHELL hook */
1109 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1110 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1112 TRACE("created window %p\n", hwnd);
1117 /***********************************************************************
1118 * CreateWindow (USER.41)
1120 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1121 DWORD style, INT16 x, INT16 y, INT16 width,
1122 INT16 height, HWND16 parent, HMENU16 menu,
1123 HINSTANCE16 instance, LPVOID data )
1125 return CreateWindowEx16( 0, className, windowName, style,
1126 x, y, width, height, parent, menu, instance, data );
1130 /***********************************************************************
1131 * CreateWindowEx (USER.452)
1133 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1134 LPCSTR windowName, DWORD style, INT16 x,
1135 INT16 y, INT16 width, INT16 height,
1136 HWND16 parent, HMENU16 menu,
1137 HINSTANCE16 instance, LPVOID data )
1142 /* Fix the coordinates */
1144 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1145 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1146 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1147 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1149 /* Create the window */
1151 cs.lpCreateParams = data;
1152 cs.hInstance = HINSTANCE_32(instance);
1153 cs.hMenu = HMENU_32(menu);
1154 cs.hwndParent = WIN_Handle32( parent );
1156 cs.lpszName = windowName;
1157 cs.lpszClass = className;
1158 cs.dwExStyle = exStyle;
1160 if (!IS_INTRESOURCE(className))
1164 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1166 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1170 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1172 ERR( "bad atom %x\n", LOWORD(className));
1175 cs.lpszClass = buffer;
1176 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1181 /***********************************************************************
1182 * CreateWindowExA (USER32.@)
1184 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1185 LPCSTR windowName, DWORD style, INT x,
1186 INT y, INT width, INT height,
1187 HWND parent, HMENU menu,
1188 HINSTANCE instance, LPVOID data )
1192 cs.lpCreateParams = data;
1193 cs.hInstance = instance;
1195 cs.hwndParent = parent;
1201 cs.lpszName = windowName;
1202 cs.lpszClass = className;
1203 cs.dwExStyle = exStyle;
1205 if (!IS_INTRESOURCE(className))
1208 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1210 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1212 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1216 /***********************************************************************
1217 * CreateWindowExW (USER32.@)
1219 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1220 LPCWSTR windowName, DWORD style, INT x,
1221 INT y, INT width, INT height,
1222 HWND parent, HMENU menu,
1223 HINSTANCE instance, LPVOID data )
1227 cs.lpCreateParams = data;
1228 cs.hInstance = instance;
1230 cs.hwndParent = parent;
1236 cs.lpszName = windowName;
1237 cs.lpszClass = className;
1238 cs.dwExStyle = exStyle;
1240 /* Note: we rely on the fact that CREATESTRUCTA and */
1241 /* CREATESTRUCTW have the same layout. */
1242 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1246 /***********************************************************************
1247 * WIN_SendDestroyMsg
1249 static void WIN_SendDestroyMsg( HWND hwnd )
1253 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1255 if (hwnd == info.hwndCaret) DestroyCaret();
1256 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1260 * Send the WM_DESTROY to the window.
1262 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1265 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1266 * make sure that the window still exists when we come back.
1273 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1275 for (i = 0; pWndArray[i]; i++)
1277 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1279 HeapFree( GetProcessHeap(), 0, pWndArray );
1282 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1286 /***********************************************************************
1287 * DestroyWindow (USER32.@)
1289 BOOL WINAPI DestroyWindow( HWND hwnd )
1293 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1295 SetLastError( ERROR_ACCESS_DENIED );
1299 TRACE("(%p)\n", hwnd);
1303 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1305 if (MENU_IsMenuActive() == hwnd)
1308 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1312 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1313 send_parent_notify( hwnd, WM_DESTROY );
1315 else if (!GetWindow( hwnd, GW_OWNER ))
1317 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1318 /* FIXME: clean up palette - see "Internals" p.352 */
1321 if (!IsWindow(hwnd)) return TRUE;
1323 /* Hide the window */
1324 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1326 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1328 ShowWindow( hwnd, SW_HIDE );
1330 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1331 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1334 if (!IsWindow(hwnd)) return TRUE;
1336 /* Recursively destroy owned windows */
1343 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1346 for (i = 0; list[i]; i++)
1348 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1349 if (WIN_IsCurrentThread( list[i] ))
1351 DestroyWindow( list[i] );
1355 WIN_SetOwner( list[i], 0 );
1357 HeapFree( GetProcessHeap(), 0, list );
1359 if (!got_one) break;
1363 /* Send destroy messages */
1365 WIN_SendDestroyMsg( hwnd );
1366 if (!IsWindow( hwnd )) return TRUE;
1368 if (GetClipboardOwner() == hwnd)
1369 CLIPBOARD_ReleaseOwner();
1371 /* Destroy the window storage */
1373 WIN_DestroyWindow( hwnd );
1378 /***********************************************************************
1379 * CloseWindow (USER32.@)
1381 BOOL WINAPI CloseWindow( HWND hwnd )
1383 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1384 ShowWindow( hwnd, SW_MINIMIZE );
1389 /***********************************************************************
1390 * OpenIcon (USER32.@)
1392 BOOL WINAPI OpenIcon( HWND hwnd )
1394 if (!IsIconic( hwnd )) return FALSE;
1395 ShowWindow( hwnd, SW_SHOWNORMAL );
1400 /***********************************************************************
1403 * Implementation of FindWindow() and FindWindowEx().
1405 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1410 WCHAR *buffer = NULL;
1412 if (!parent) parent = GetDesktopWindow();
1415 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1416 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1419 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1423 child = WIN_GetFullHandle( child );
1424 while (list[i] && list[i] != child) i++;
1425 if (!list[i]) goto done;
1426 i++; /* start from next window */
1433 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1440 HeapFree( GetProcessHeap(), 0, list );
1441 HeapFree( GetProcessHeap(), 0, buffer );
1447 /***********************************************************************
1448 * FindWindowA (USER32.@)
1450 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1452 HWND ret = FindWindowExA( 0, 0, className, title );
1453 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1458 /***********************************************************************
1459 * FindWindowExA (USER32.@)
1461 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1462 LPCSTR className, LPCSTR title )
1471 /* If the atom doesn't exist, then no class */
1472 /* with this name exists either. */
1473 if (!(atom = GlobalFindAtomA( className )))
1475 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1479 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1481 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1482 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1483 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1484 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1485 HeapFree( GetProcessHeap(), 0, buffer );
1490 /***********************************************************************
1491 * FindWindowExW (USER32.@)
1493 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1494 LPCWSTR className, LPCWSTR title )
1500 /* If the atom doesn't exist, then no class */
1501 /* with this name exists either. */
1502 if (!(atom = GlobalFindAtomW( className )))
1504 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1508 return WIN_FindWindow( parent, child, atom, title );
1512 /***********************************************************************
1513 * FindWindowW (USER32.@)
1515 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1517 return FindWindowExW( 0, 0, className, title );
1521 /**********************************************************************
1522 * GetDesktopWindow (USER32.@)
1524 HWND WINAPI GetDesktopWindow(void)
1526 struct user_thread_info *thread_info = get_user_thread_info();
1528 if (thread_info->desktop) return thread_info->desktop;
1530 SERVER_START_REQ( get_desktop_window )
1533 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1537 if (!thread_info->desktop)
1539 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1541 PROCESS_INFORMATION pi;
1542 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1544 memset( &si, 0, sizeof(si) );
1546 GetSystemDirectoryW( cmdline, MAX_PATH );
1547 lstrcatW( cmdline, command_line );
1548 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1549 NULL, NULL, &si, &pi ))
1551 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1552 WaitForInputIdle( pi.hProcess, 10000 );
1553 CloseHandle( pi.hThread );
1554 CloseHandle( pi.hProcess );
1557 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1559 SERVER_START_REQ( get_desktop_window )
1562 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1567 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1568 ERR( "failed to create desktop window\n" );
1570 return thread_info->desktop;
1574 /*******************************************************************
1575 * EnableWindow (USER32.@)
1577 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1582 if (is_broadcast(hwnd))
1584 SetLastError( ERROR_INVALID_PARAMETER );
1588 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1589 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1593 TRACE("( %p, %d )\n", hwnd, enable);
1595 retvalue = !IsWindowEnabled( hwnd );
1597 if (enable && retvalue)
1599 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1600 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1602 else if (!enable && !retvalue)
1606 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1608 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1610 if (hwnd == GetFocus())
1611 SetFocus( 0 ); /* A disabled window can't have the focus */
1613 capture_wnd = GetCapture();
1614 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1615 ReleaseCapture(); /* A disabled window can't capture the mouse */
1617 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1623 /***********************************************************************
1624 * IsWindowEnabled (USER32.@)
1626 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1628 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1632 /***********************************************************************
1633 * IsWindowUnicode (USER32.@)
1635 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1638 BOOL retvalue = FALSE;
1640 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1642 if (wndPtr == WND_DESKTOP) return TRUE;
1644 if (wndPtr != WND_OTHER_PROCESS)
1646 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1647 WIN_ReleasePtr( wndPtr );
1651 SERVER_START_REQ( get_window_info )
1654 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1662 /**********************************************************************
1665 * Helper function for GetWindowLong().
1667 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1669 LONG_PTR retvalue = 0;
1672 if (offset == GWLP_HWNDPARENT)
1674 HWND parent = GetAncestor( hwnd, GA_PARENT );
1675 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1676 return (ULONG_PTR)parent;
1679 if (!(wndPtr = WIN_GetPtr( hwnd )))
1681 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1685 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1687 if (offset == GWLP_WNDPROC)
1689 SetLastError( ERROR_ACCESS_DENIED );
1692 SERVER_START_REQ( set_window_info )
1695 req->flags = 0; /* don't set anything, just retrieve */
1696 req->extra_offset = (offset >= 0) ? offset : -1;
1697 req->extra_size = (offset >= 0) ? size : 0;
1698 if (!wine_server_call_err( req ))
1702 case GWL_STYLE: retvalue = reply->old_style; break;
1703 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1704 case GWLP_ID: retvalue = reply->old_id; break;
1705 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1706 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1708 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1709 else SetLastError( ERROR_INVALID_INDEX );
1718 /* now we have a valid wndPtr */
1722 if (offset > (int)(wndPtr->cbWndExtra - size))
1724 WARN("Invalid offset %d\n", offset );
1725 WIN_ReleasePtr( wndPtr );
1726 SetLastError( ERROR_INVALID_INDEX );
1729 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1731 /* Special case for dialog window procedure */
1732 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1733 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1734 WIN_ReleasePtr( wndPtr );
1740 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1741 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1742 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1743 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1744 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1746 /* This looks like a hack only for the edit control (see tests). This makes these controls
1747 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1748 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1750 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1751 retvalue = (ULONG_PTR)wndPtr->winproc;
1753 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1756 WARN("Unknown offset %d\n", offset );
1757 SetLastError( ERROR_INVALID_INDEX );
1760 WIN_ReleasePtr(wndPtr);
1765 /**********************************************************************
1768 * Helper function for SetWindowLong().
1770 * 0 is the failure code. However, in the case of failure SetLastError
1771 * must be set to distinguish between a 0 return value and a failure.
1773 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1777 LONG_PTR retval = 0;
1780 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1782 if (is_broadcast(hwnd))
1784 SetLastError( ERROR_INVALID_PARAMETER );
1788 if (!(wndPtr = WIN_GetPtr( hwnd )))
1790 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1793 if (wndPtr == WND_DESKTOP)
1795 /* can't change anything on the desktop window */
1796 SetLastError( ERROR_ACCESS_DENIED );
1799 if (wndPtr == WND_OTHER_PROCESS)
1801 if (offset == GWLP_WNDPROC)
1803 SetLastError( ERROR_ACCESS_DENIED );
1806 if (offset > 32767 || offset < -32767)
1808 SetLastError( ERROR_INVALID_INDEX );
1811 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1814 /* first some special cases */
1820 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1821 style.styleNew = newval;
1822 WIN_ReleasePtr( wndPtr );
1823 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1824 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1825 newval = style.styleNew;
1827 case GWLP_HWNDPARENT:
1828 if (wndPtr->parent == GetDesktopWindow())
1830 WIN_ReleasePtr( wndPtr );
1831 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1835 WIN_ReleasePtr( wndPtr );
1836 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1841 UINT old_flags = wndPtr->flags;
1842 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
1843 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1844 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1845 if (proc) wndPtr->winproc = proc;
1846 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1847 else wndPtr->flags &= ~WIN_ISUNICODE;
1848 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1850 WIN_ReleasePtr( wndPtr );
1853 /* update is_unicode flag on the server side */
1857 case GWLP_HINSTANCE:
1861 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1862 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1864 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1865 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1866 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1867 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1868 WIN_ReleasePtr( wndPtr );
1873 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1875 WARN("Invalid offset %d\n", offset );
1876 WIN_ReleasePtr( wndPtr );
1877 SetLastError( ERROR_INVALID_INDEX );
1880 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1882 /* already set to the same value */
1883 WIN_ReleasePtr( wndPtr );
1889 SERVER_START_REQ( set_window_info )
1892 req->extra_offset = -1;
1896 req->flags = SET_WIN_STYLE;
1897 req->style = newval;
1900 req->flags = SET_WIN_EXSTYLE;
1901 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
1902 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
1903 req->ex_style = newval;
1906 req->flags = SET_WIN_ID;
1909 case GWLP_HINSTANCE:
1910 req->flags = SET_WIN_INSTANCE;
1911 req->instance = (void *)newval;
1914 req->flags = SET_WIN_UNICODE;
1915 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1918 req->flags = SET_WIN_USERDATA;
1919 req->user_data = newval;
1922 req->flags = SET_WIN_EXTRA;
1923 req->extra_offset = offset;
1924 req->extra_size = size;
1925 set_win_data( &req->extra_value, newval, size );
1927 if ((ok = !wine_server_call_err( req )))
1932 wndPtr->dwStyle = newval;
1933 retval = reply->old_style;
1936 wndPtr->dwExStyle = newval;
1937 retval = reply->old_ex_style;
1940 wndPtr->wIDmenu = newval;
1941 retval = reply->old_id;
1943 case GWLP_HINSTANCE:
1944 wndPtr->hInstance = (HINSTANCE)newval;
1945 retval = (ULONG_PTR)reply->old_instance;
1950 wndPtr->userdata = newval;
1951 retval = reply->old_user_data;
1954 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
1955 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
1961 WIN_ReleasePtr( wndPtr );
1965 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
1967 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
1968 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
1974 /**********************************************************************
1975 * GetWindowLong (USER.135)
1977 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1981 BOOL is_winproc = (offset == GWLP_WNDPROC);
1985 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
1987 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1990 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
1992 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1995 * Some programs try to access last element from 16 bit
1996 * code using illegal offset value. Hopefully this is
1997 * what those programs really expect.
1999 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2001 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2002 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2007 WARN("Invalid offset %d\n", offset );
2008 WIN_ReleasePtr( wndPtr );
2009 SetLastError( ERROR_INVALID_INDEX );
2013 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2014 WIN_ReleasePtr( wndPtr );
2017 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2018 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2023 /**********************************************************************
2024 * GetWindowWord (USER32.@)
2026 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2031 case GWLP_HINSTANCE:
2032 case GWLP_HWNDPARENT:
2037 WARN("Invalid offset %d\n", offset );
2038 SetLastError( ERROR_INVALID_INDEX );
2043 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2047 /**********************************************************************
2048 * GetWindowLongA (USER32.@)
2050 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2052 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2056 /**********************************************************************
2057 * GetWindowLongW (USER32.@)
2059 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2061 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2065 /**********************************************************************
2066 * SetWindowLong (USER.136)
2068 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2071 BOOL is_winproc = (offset == GWLP_WNDPROC);
2073 if (offset == DWLP_DLGPROC)
2075 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2077 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2080 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2082 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2083 (wndPtr->flags & WIN_ISDIALOG));
2084 WIN_ReleasePtr( wndPtr );
2090 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2091 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2092 return (LONG)WINPROC_GetProc16( (WNDPROC)old_proc, FALSE );
2094 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2098 /**********************************************************************
2099 * SetWindowWord (USER32.@)
2101 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2106 case GWLP_HINSTANCE:
2107 case GWLP_HWNDPARENT:
2112 WARN("Invalid offset %d\n", offset );
2113 SetLastError( ERROR_INVALID_INDEX );
2118 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2122 /**********************************************************************
2123 * SetWindowLongA (USER32.@)
2125 * See SetWindowLongW.
2127 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2129 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2133 /**********************************************************************
2134 * SetWindowLongW (USER32.@) Set window attribute
2136 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2137 * value in a window's extra memory.
2139 * The _hwnd_ parameter specifies the window. is the handle to a
2140 * window that has extra memory. The _newval_ parameter contains the
2141 * new attribute or extra memory value. If positive, the _offset_
2142 * parameter is the byte-addressed location in the window's extra
2143 * memory to set. If negative, _offset_ specifies the window
2144 * attribute to set, and should be one of the following values:
2146 * GWL_EXSTYLE The window's extended window style
2148 * GWL_STYLE The window's window style.
2150 * GWLP_WNDPROC Pointer to the window's window procedure.
2152 * GWLP_HINSTANCE The window's pplication instance handle.
2154 * GWLP_ID The window's identifier.
2156 * GWLP_USERDATA The window's user-specified data.
2158 * If the window is a dialog box, the _offset_ parameter can be one of
2159 * the following values:
2161 * DWLP_DLGPROC The address of the window's dialog box procedure.
2163 * DWLP_MSGRESULT The return value of a message
2164 * that the dialog box procedure processed.
2166 * DWLP_USER Application specific information.
2170 * If successful, returns the previous value located at _offset_. Otherwise,
2175 * Extra memory for a window class is specified by a nonzero cbWndExtra
2176 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2177 * time of class creation.
2179 * Using GWL_WNDPROC to set a new window procedure effectively creates
2180 * a window subclass. Use CallWindowProc() in the new windows procedure
2181 * to pass messages to the superclass's window procedure.
2183 * The user data is reserved for use by the application which created
2186 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2187 * instead, call the EnableWindow() function to change the window's
2190 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2191 * SetParent() instead.
2194 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2195 * it sends WM_STYLECHANGING before changing the settings
2196 * and WM_STYLECHANGED afterwards.
2197 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2199 LONG WINAPI SetWindowLongW(
2200 HWND hwnd, /* [in] window to alter */
2201 INT offset, /* [in] offset, in bytes, of location to alter */
2202 LONG newval /* [in] new value of location */
2204 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2208 /*******************************************************************
2209 * GetWindowTextA (USER32.@)
2211 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2215 if (!lpString) return 0;
2217 if (WIN_IsCurrentProcess( hwnd ))
2218 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2220 /* when window belongs to other process, don't send a message */
2221 if (nMaxCount <= 0) return 0;
2222 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2223 get_server_window_text( hwnd, buffer, nMaxCount );
2224 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2225 lpString[nMaxCount-1] = 0;
2226 HeapFree( GetProcessHeap(), 0, buffer );
2227 return strlen(lpString);
2231 /*******************************************************************
2232 * InternalGetWindowText (USER32.@)
2234 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2238 if (nMaxCount <= 0) return 0;
2239 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2240 if (win == WND_DESKTOP) lpString[0] = 0;
2241 else if (win != WND_OTHER_PROCESS)
2243 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2244 else lpString[0] = 0;
2245 WIN_ReleasePtr( win );
2249 get_server_window_text( hwnd, lpString, nMaxCount );
2251 return strlenW(lpString);
2255 /*******************************************************************
2256 * GetWindowTextW (USER32.@)
2258 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2260 if (!lpString) return 0;
2262 if (WIN_IsCurrentProcess( hwnd ))
2263 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2265 /* when window belongs to other process, don't send a message */
2266 if (nMaxCount <= 0) return 0;
2267 get_server_window_text( hwnd, lpString, nMaxCount );
2268 return strlenW(lpString);
2272 /*******************************************************************
2273 * SetWindowTextA (USER32.@)
2274 * SetWindowText (USER32.@)
2276 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2278 if (is_broadcast(hwnd))
2280 SetLastError( ERROR_INVALID_PARAMETER );
2283 if (!WIN_IsCurrentProcess( hwnd ))
2284 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2285 debugstr_a(lpString), hwnd );
2286 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2290 /*******************************************************************
2291 * SetWindowTextW (USER32.@)
2293 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2295 if (is_broadcast(hwnd))
2297 SetLastError( ERROR_INVALID_PARAMETER );
2300 if (!WIN_IsCurrentProcess( hwnd ))
2301 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2302 debugstr_w(lpString), hwnd );
2303 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2307 /*******************************************************************
2308 * GetWindowTextLengthA (USER32.@)
2310 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2312 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2315 /*******************************************************************
2316 * GetWindowTextLengthW (USER32.@)
2318 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2320 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2324 /*******************************************************************
2325 * IsWindow (USER32.@)
2327 BOOL WINAPI IsWindow( HWND hwnd )
2332 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2333 if (ptr == WND_DESKTOP) return TRUE;
2335 if (ptr != WND_OTHER_PROCESS)
2337 WIN_ReleasePtr( ptr );
2341 /* check other processes */
2342 SERVER_START_REQ( get_window_info )
2345 ret = !wine_server_call_err( req );
2352 /***********************************************************************
2353 * GetWindowThreadProcessId (USER32.@)
2355 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2360 if (!(ptr = WIN_GetPtr( hwnd )))
2362 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2366 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2368 /* got a valid window */
2370 if (process) *process = GetCurrentProcessId();
2371 WIN_ReleasePtr( ptr );
2375 /* check other processes */
2376 SERVER_START_REQ( get_window_info )
2379 if (!wine_server_call_err( req ))
2381 tid = (DWORD)reply->tid;
2382 if (process) *process = (DWORD)reply->pid;
2390 /*****************************************************************
2391 * GetParent (USER32.@)
2393 HWND WINAPI GetParent( HWND hwnd )
2398 if (!(wndPtr = WIN_GetPtr( hwnd )))
2400 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2403 if (wndPtr == WND_DESKTOP) return 0;
2404 if (wndPtr == WND_OTHER_PROCESS)
2406 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2407 if (style & (WS_POPUP | WS_CHILD))
2409 SERVER_START_REQ( get_window_tree )
2412 if (!wine_server_call_err( req ))
2414 if (style & WS_POPUP) retvalue = reply->owner;
2415 else if (style & WS_CHILD) retvalue = reply->parent;
2423 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2424 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2425 WIN_ReleasePtr( wndPtr );
2431 /*****************************************************************
2432 * GetAncestor (USER32.@)
2434 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2437 HWND *list, ret = 0;
2442 if (!(win = WIN_GetPtr( hwnd )))
2444 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2447 if (win == WND_DESKTOP) return 0;
2448 if (win != WND_OTHER_PROCESS)
2451 WIN_ReleasePtr( win );
2453 else /* need to query the server */
2455 SERVER_START_REQ( get_window_tree )
2458 if (!wine_server_call_err( req )) ret = reply->parent;
2465 if (!(list = list_window_parents( hwnd ))) return 0;
2467 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2471 while (list[count]) count++;
2472 ret = list[count - 2]; /* get the one before the desktop */
2474 HeapFree( GetProcessHeap(), 0, list );
2478 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2481 HWND parent = GetParent( ret );
2491 /*****************************************************************
2492 * SetParent (USER32.@)
2494 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2497 HWND old_parent = 0;
2502 if (is_broadcast(hwnd) || is_broadcast(parent))
2504 SetLastError(ERROR_INVALID_PARAMETER);
2508 if (!parent) parent = GetDesktopWindow();
2509 else parent = WIN_GetFullHandle( parent );
2511 if (!IsWindow( parent ))
2513 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2517 /* Some applications try to set a child as a parent */
2518 if (IsChild(hwnd, parent))
2520 SetLastError( ERROR_INVALID_PARAMETER );
2524 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2525 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2527 /* Windows hides the window first, then shows it again
2528 * including the WM_SHOWWINDOW messages and all */
2529 was_visible = ShowWindow( hwnd, SW_HIDE );
2531 wndPtr = WIN_GetPtr( hwnd );
2532 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2534 SERVER_START_REQ( set_parent )
2537 req->parent = parent;
2538 if ((ret = !wine_server_call( req )))
2540 old_parent = reply->old_parent;
2541 wndPtr->parent = parent = reply->full_parent;
2546 WIN_ReleasePtr( wndPtr );
2549 USER_Driver->pSetParent( full_handle, parent, old_parent );
2551 /* SetParent additionally needs to make hwnd the topmost window
2552 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2553 WM_WINDOWPOSCHANGED notification messages.
2555 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2556 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2557 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2558 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2564 /*******************************************************************
2565 * IsChild (USER32.@)
2567 BOOL WINAPI IsChild( HWND parent, HWND child )
2569 HWND *list = list_window_parents( child );
2573 if (!list) return FALSE;
2574 parent = WIN_GetFullHandle( parent );
2575 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2576 ret = list[i] && list[i+1];
2577 HeapFree( GetProcessHeap(), 0, list );
2582 /***********************************************************************
2583 * IsWindowVisible (USER32.@)
2585 BOOL WINAPI IsWindowVisible( HWND hwnd )
2591 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2592 if (!(list = list_window_parents( hwnd ))) return TRUE;
2593 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2595 for (i = 0; list[i+1]; i++)
2596 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2597 retval = !list[i+1];
2599 HeapFree( GetProcessHeap(), 0, list );
2604 /***********************************************************************
2605 * WIN_IsWindowDrawable
2607 * hwnd is drawable when it is visible, all parents are not
2608 * minimized, and it is itself not minimized unless we are
2609 * trying to draw its default class icon.
2611 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2616 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2618 if (!(style & WS_VISIBLE)) return FALSE;
2619 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2621 if (!(list = list_window_parents( hwnd ))) return TRUE;
2622 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2624 for (i = 0; list[i+1]; i++)
2625 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2627 retval = !list[i+1];
2629 HeapFree( GetProcessHeap(), 0, list );
2634 /*******************************************************************
2635 * GetTopWindow (USER32.@)
2637 HWND WINAPI GetTopWindow( HWND hwnd )
2639 if (!hwnd) hwnd = GetDesktopWindow();
2640 return GetWindow( hwnd, GW_CHILD );
2644 /*******************************************************************
2645 * GetWindow (USER32.@)
2647 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2651 if (rel == GW_OWNER) /* this one may be available locally */
2653 WND *wndPtr = WIN_GetPtr( hwnd );
2656 SetLastError( ERROR_INVALID_HANDLE );
2659 if (wndPtr == WND_DESKTOP) return 0;
2660 if (wndPtr != WND_OTHER_PROCESS)
2662 retval = wndPtr->owner;
2663 WIN_ReleasePtr( wndPtr );
2666 /* else fall through to server call */
2669 SERVER_START_REQ( get_window_tree )
2672 if (!wine_server_call_err( req ))
2677 retval = reply->first_sibling;
2680 retval = reply->last_sibling;
2683 retval = reply->next_sibling;
2686 retval = reply->prev_sibling;
2689 retval = reply->owner;
2692 retval = reply->first_child;
2702 /*******************************************************************
2703 * ShowOwnedPopups (USER32.@)
2705 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2709 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2711 if (!win_array) return TRUE;
2713 while (win_array[count]) count++;
2714 while (--count >= 0)
2716 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2717 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2718 if (pWnd == WND_OTHER_PROCESS) continue;
2721 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2723 WIN_ReleasePtr( pWnd );
2724 /* In Windows, ShowOwnedPopups(TRUE) generates
2725 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2726 * regardless of the state of the owner
2728 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2734 if (pWnd->dwStyle & WS_VISIBLE)
2736 WIN_ReleasePtr( pWnd );
2737 /* In Windows, ShowOwnedPopups(FALSE) generates
2738 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2739 * regardless of the state of the owner
2741 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2745 WIN_ReleasePtr( pWnd );
2747 HeapFree( GetProcessHeap(), 0, win_array );
2752 /*******************************************************************
2753 * GetLastActivePopup (USER32.@)
2755 HWND WINAPI GetLastActivePopup( HWND hwnd )
2759 SERVER_START_REQ( get_window_info )
2762 if (!wine_server_call_err( req )) retval = reply->last_active;
2769 /*******************************************************************
2772 * Build an array of the children of a given window. The array must be
2773 * freed with HeapFree. Returns NULL when no windows are found.
2775 HWND *WIN_ListChildren( HWND hwnd )
2777 return list_window_children( hwnd, 0, 0 );
2781 /*******************************************************************
2782 * EnumWindows (USER32.@)
2784 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2790 USER_CheckNotLock();
2792 /* We have to build a list of all windows first, to avoid */
2793 /* unpleasant side-effects, for instance if the callback */
2794 /* function changes the Z-order of the windows. */
2796 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2798 /* Now call the callback function for every window */
2800 for (i = 0; list[i]; i++)
2802 /* Make sure that the window still exists */
2803 if (!IsWindow( list[i] )) continue;
2804 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2806 HeapFree( GetProcessHeap(), 0, list );
2811 /**********************************************************************
2812 * EnumThreadWindows (USER32.@)
2814 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2819 USER_CheckNotLock();
2821 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2823 /* Now call the callback function for every window */
2825 for (i = 0; list[i]; i++)
2826 if (!func( list[i], lParam )) break;
2827 HeapFree( GetProcessHeap(), 0, list );
2832 /**********************************************************************
2833 * WIN_EnumChildWindows
2835 * Helper function for EnumChildWindows().
2837 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2842 for ( ; *list; list++)
2844 /* Make sure that the window still exists */
2845 if (!IsWindow( *list )) continue;
2846 /* Build children list first */
2847 childList = WIN_ListChildren( *list );
2849 ret = func( *list, lParam );
2853 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2854 HeapFree( GetProcessHeap(), 0, childList );
2856 if (!ret) return FALSE;
2862 /**********************************************************************
2863 * EnumChildWindows (USER32.@)
2865 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2870 USER_CheckNotLock();
2872 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2873 ret = WIN_EnumChildWindows( list, func, lParam );
2874 HeapFree( GetProcessHeap(), 0, list );
2879 /*******************************************************************
2880 * AnyPopup (USER.52)
2882 BOOL16 WINAPI AnyPopup16(void)
2888 /*******************************************************************
2889 * AnyPopup (USER32.@)
2891 BOOL WINAPI AnyPopup(void)
2895 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2897 if (!list) return FALSE;
2898 for (i = 0; list[i]; i++)
2900 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2902 retvalue = (list[i] != 0);
2903 HeapFree( GetProcessHeap(), 0, list );
2908 /*******************************************************************
2909 * FlashWindow (USER32.@)
2911 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2915 TRACE("%p\n", hWnd);
2917 if (IsIconic( hWnd ))
2919 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2921 wndPtr = WIN_GetPtr(hWnd);
2922 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2923 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2925 wndPtr->flags |= WIN_NCACTIVATED;
2929 wndPtr->flags &= ~WIN_NCACTIVATED;
2931 WIN_ReleasePtr( wndPtr );
2938 wndPtr = WIN_GetPtr(hWnd);
2939 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2940 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2942 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2943 else wparam = (hWnd == GetForegroundWindow());
2945 WIN_ReleasePtr( wndPtr );
2946 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2951 /*******************************************************************
2952 * FlashWindowEx (USER32.@)
2954 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
2956 FIXME("%p\n", pfwi);
2960 /*******************************************************************
2961 * GetWindowContextHelpId (USER32.@)
2963 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2966 WND *wnd = WIN_GetPtr( hwnd );
2967 if (!wnd || wnd == WND_DESKTOP) return 0;
2968 if (wnd == WND_OTHER_PROCESS)
2970 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2973 retval = wnd->helpContext;
2974 WIN_ReleasePtr( wnd );
2979 /*******************************************************************
2980 * SetWindowContextHelpId (USER32.@)
2982 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2984 WND *wnd = WIN_GetPtr( hwnd );
2985 if (!wnd || wnd == WND_DESKTOP) return FALSE;
2986 if (wnd == WND_OTHER_PROCESS)
2988 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2991 wnd->helpContext = id;
2992 WIN_ReleasePtr( wnd );
2997 /*******************************************************************
2998 * DragDetect (USER32.@)
3000 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3004 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3005 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3007 rect.left = pt.x - wDragWidth;
3008 rect.right = pt.x + wDragWidth;
3010 rect.top = pt.y - wDragHeight;
3011 rect.bottom = pt.y + wDragHeight;
3017 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3019 if( msg.message == WM_LBUTTONUP )
3024 if( msg.message == WM_MOUSEMOVE )
3027 tmp.x = (short)LOWORD(msg.lParam);
3028 tmp.y = (short)HIWORD(msg.lParam);
3029 if( !PtInRect( &rect, tmp ))
3041 /******************************************************************************
3042 * GetWindowModuleFileNameA (USER32.@)
3044 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3046 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3047 hwnd, lpszFileName, cchFileNameMax);
3051 /******************************************************************************
3052 * GetWindowModuleFileNameW (USER32.@)
3054 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3056 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3057 hwnd, lpszFileName, cchFileNameMax);
3061 /******************************************************************************
3062 * GetWindowInfo (USER32.@)
3064 * Note: tests show that Windows doesn't check cbSize of the structure.
3066 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3068 if (!pwi) return FALSE;
3069 if (!IsWindow(hwnd)) return FALSE;
3071 GetWindowRect(hwnd, &pwi->rcWindow);
3072 GetClientRect(hwnd, &pwi->rcClient);
3073 /* translate to screen coordinates */
3074 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3076 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3077 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3078 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3080 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3081 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3083 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3084 pwi->wCreatorVersion = 0x0400;
3089 /******************************************************************************
3090 * SwitchDesktop (USER32.@)
3092 * NOTES: Sets the current input or interactive desktop.
3094 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3096 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3100 /*****************************************************************************
3101 * SetLayeredWindowAttributes (USER32.@)
3103 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3104 BYTE bAlpha, DWORD dwFlags )
3106 FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3110 /*****************************************************************************
3111 * UpdateLayeredWindow (USER32.@)
3113 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3114 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3121 FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3122 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3127 /* 64bit versions */
3129 #ifdef GetWindowLongPtrW
3130 #undef GetWindowLongPtrW
3133 #ifdef GetWindowLongPtrA
3134 #undef GetWindowLongPtrA
3137 #ifdef SetWindowLongPtrW
3138 #undef SetWindowLongPtrW
3141 #ifdef SetWindowLongPtrA
3142 #undef SetWindowLongPtrA
3145 /*****************************************************************************
3146 * GetWindowLongPtrW (USER32.@)
3148 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3150 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3153 /*****************************************************************************
3154 * GetWindowLongPtrA (USER32.@)
3156 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3158 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3161 /*****************************************************************************
3162 * SetWindowLongPtrW (USER32.@)
3164 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3166 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3169 /*****************************************************************************
3170 * SetWindowLongPtrA (USER32.@)
3172 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3174 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );