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 SetRectEmpty( &win->rectWindow );
170 SetRectEmpty( &win->rectClient );
171 memset( win->wExtra, 0, extra_bytes );
172 CLASS_AddWindow( class, win, unicode );
177 /***********************************************************************
180 * Free a window handle.
182 static WND *free_window_handle( HWND hwnd )
185 WORD index = USER_HANDLE_TO_INDEX(hwnd);
187 if (index >= NB_USER_HANDLES) return NULL;
189 if ((ptr = user_handles[index]))
191 SERVER_START_REQ( destroy_window )
194 if (!wine_server_call_err( req ))
196 user_handles[index] = NULL;
205 HeapFree( GetProcessHeap(), 0, ptr );
210 /*******************************************************************
211 * list_window_children
213 * Build an array of the children of a given window. The array must be
214 * freed with HeapFree. Returns NULL when no windows are found.
216 static HWND *list_window_children( HWND hwnd, LPCWSTR class, DWORD tid )
225 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
227 SERVER_START_REQ( get_window_children )
231 if (!(req->atom = get_int_atom_value( class )) && class)
232 wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
233 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
234 if (!wine_server_call( req )) count = reply->count;
237 if (count && count < size)
242 HeapFree( GetProcessHeap(), 0, list );
244 size = count + 1; /* restart with a large enough buffer */
250 /*******************************************************************
251 * list_window_parents
253 * Build an array of all parents of a given window, starting with
254 * the immediate parent. The array must be freed with HeapFree.
256 static HWND *list_window_parents( HWND hwnd )
260 int pos = 0, size = 16, count = 0;
262 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
267 if (!(win = WIN_GetPtr( current ))) goto empty;
268 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
269 if (win == WND_DESKTOP)
271 if (!pos) goto empty;
275 list[pos] = current = win->parent;
276 WIN_ReleasePtr( win );
277 if (++pos == size - 1)
279 /* need to grow the list */
280 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
281 if (!new_list) goto empty;
287 /* at least one parent belongs to another process, have to query the server */
292 SERVER_START_REQ( get_window_parents )
295 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
296 if (!wine_server_call( req )) count = reply->count;
299 if (!count) goto empty;
305 HeapFree( GetProcessHeap(), 0, list );
307 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
311 HeapFree( GetProcessHeap(), 0, list );
316 /*******************************************************************
319 static void send_parent_notify( HWND hwnd, UINT msg )
321 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
322 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
324 HWND parent = GetParent(hwnd);
325 if (parent && parent != GetDesktopWindow())
326 SendMessageW( parent, WM_PARENTNOTIFY,
327 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
332 /*******************************************************************
333 * get_server_window_text
335 * Retrieve the window text from the server.
337 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
341 SERVER_START_REQ( get_window_text )
344 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
345 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
348 text[len / sizeof(WCHAR)] = 0;
352 /***********************************************************************
355 * Return a pointer to the WND structure if local to the process,
356 * or WND_OTHER_PROCESS if handle may be valid in other process.
357 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
359 WND *WIN_GetPtr( HWND hwnd )
362 WORD index = USER_HANDLE_TO_INDEX(hwnd);
364 if (index >= NB_USER_HANDLES) return NULL;
367 if ((ptr = user_handles[index]))
369 if (ptr->dwMagic == WND_MAGIC &&
370 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
374 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
376 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
379 else ptr = WND_OTHER_PROCESS;
385 /***********************************************************************
386 * WIN_IsCurrentProcess
388 * Check whether a given window belongs to the current process (and return the full handle).
390 HWND WIN_IsCurrentProcess( HWND hwnd )
395 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
397 WIN_ReleasePtr( ptr );
402 /***********************************************************************
403 * WIN_IsCurrentThread
405 * Check whether a given window belongs to the current thread (and return the full handle).
407 HWND WIN_IsCurrentThread( HWND hwnd )
412 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
413 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
414 WIN_ReleasePtr( ptr );
419 /***********************************************************************
422 * Convert a 16-bit window handle to a full 32-bit handle.
424 HWND WIN_Handle32( HWND16 hwnd16 )
427 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
429 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
430 /* do sign extension for -2 and -3 */
431 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
433 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
435 if (ptr == WND_DESKTOP) return GetDesktopWindow();
437 if (ptr != WND_OTHER_PROCESS)
439 hwnd = ptr->hwndSelf;
440 WIN_ReleasePtr( ptr );
442 else /* may belong to another process */
444 SERVER_START_REQ( get_window_info )
447 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
455 /***********************************************************************
458 * Change the owner of a window.
460 HWND WIN_SetOwner( HWND hwnd, HWND owner )
462 WND *win = WIN_GetPtr( hwnd );
465 if (!win || win == WND_DESKTOP) return 0;
466 if (win == WND_OTHER_PROCESS)
468 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
471 SERVER_START_REQ( set_window_owner )
475 if (!wine_server_call( req ))
477 win->owner = reply->full_owner;
478 ret = reply->prev_owner;
482 WIN_ReleasePtr( win );
487 /***********************************************************************
490 * Change the style of a window.
492 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
495 ULONG new_style, old_style = 0;
496 WND *win = WIN_GetPtr( hwnd );
498 if (!win || win == WND_DESKTOP) return 0;
499 if (win == WND_OTHER_PROCESS)
502 ERR( "cannot set style %x/%x on other process window %p\n",
503 set_bits, clear_bits, hwnd );
506 new_style = (win->dwStyle | set_bits) & ~clear_bits;
507 if (new_style == win->dwStyle)
509 WIN_ReleasePtr( win );
512 SERVER_START_REQ( set_window_info )
515 req->flags = SET_WIN_STYLE;
516 req->style = new_style;
517 req->extra_offset = -1;
518 if ((ok = !wine_server_call( req )))
520 old_style = reply->old_style;
521 win->dwStyle = new_style;
525 WIN_ReleasePtr( win );
526 if (ok) USER_Driver->pSetWindowStyle( hwnd, old_style );
531 /***********************************************************************
534 * Get the window and client rectangles.
536 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
538 WND *win = WIN_GetPtr( hwnd );
541 if (!win) return FALSE;
542 if (win == WND_DESKTOP)
545 rect.left = rect.top = 0;
546 rect.right = GetSystemMetrics(SM_CXSCREEN);
547 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
548 if (rectWindow) *rectWindow = rect;
549 if (rectClient) *rectClient = rect;
551 else if (win == WND_OTHER_PROCESS)
553 SERVER_START_REQ( get_window_rectangles )
556 if ((ret = !wine_server_call( req )))
560 rectWindow->left = reply->window.left;
561 rectWindow->top = reply->window.top;
562 rectWindow->right = reply->window.right;
563 rectWindow->bottom = reply->window.bottom;
567 rectClient->left = reply->client.left;
568 rectClient->top = reply->client.top;
569 rectClient->right = reply->client.right;
570 rectClient->bottom = reply->client.bottom;
578 if (rectWindow) *rectWindow = win->rectWindow;
579 if (rectClient) *rectClient = win->rectClient;
580 WIN_ReleasePtr( win );
586 /***********************************************************************
589 * Destroy storage associated to a window. "Internals" p.358
591 LRESULT WIN_DestroyWindow( HWND hwnd )
595 HMENU menu = 0, sys_menu;
597 TRACE("%p\n", hwnd );
599 /* free child windows */
600 if ((list = WIN_ListChildren( hwnd )))
603 for (i = 0; list[i]; i++)
605 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
606 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
608 HeapFree( GetProcessHeap(), 0, list );
611 /* Unlink now so we won't bother with the children later on */
612 SERVER_START_REQ( set_parent )
616 wine_server_call( req );
621 * Send the WM_NCDESTROY to the window being destroyed.
623 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
625 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
627 WINPOS_CheckInternalPos( hwnd );
629 /* free resources associated with the window */
631 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
632 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
633 menu = (HMENU)wndPtr->wIDmenu;
634 sys_menu = wndPtr->hSysMenu;
635 WIN_ReleasePtr( wndPtr );
637 if (menu) DestroyMenu( menu );
638 if (sys_menu) DestroyMenu( sys_menu );
640 USER_Driver->pDestroyWindow( hwnd );
642 free_window_handle( hwnd );
646 /***********************************************************************
647 * WIN_DestroyThreadWindows
649 * Destroy all children of 'wnd' owned by the current thread.
651 void WIN_DestroyThreadWindows( HWND hwnd )
656 if (!(list = WIN_ListChildren( hwnd ))) return;
657 for (i = 0; list[i]; i++)
659 if (WIN_IsCurrentThread( list[i] ))
660 DestroyWindow( list[i] );
662 WIN_DestroyThreadWindows( list[i] );
664 HeapFree( GetProcessHeap(), 0, list );
668 /***********************************************************************
671 * Fix the coordinates - Helper for WIN_CreateWindowEx.
672 * returns default show mode in sw.
674 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
676 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
679 if (cs->dwExStyle & WS_EX_MDICHILD)
683 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
684 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
686 TRACE("MDI child id %04x\n", id);
689 if (cs->style & (WS_CHILD | WS_POPUP))
691 if (cs->dwExStyle & WS_EX_MDICHILD)
693 if (IS_DEFAULT(cs->x))
698 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
699 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
703 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
704 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
707 else /* overlapped window */
710 MONITORINFO mon_info;
713 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
715 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
716 mon_info.cbSize = sizeof(mon_info);
717 GetMonitorInfoW( monitor, &mon_info );
718 GetStartupInfoW( &info );
720 if (IS_DEFAULT(cs->x))
722 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
723 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
724 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
727 if (IS_DEFAULT(cs->cx))
729 if (info.dwFlags & STARTF_USESIZE)
731 cs->cx = info.dwXSize;
732 cs->cy = info.dwYSize;
736 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
737 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
740 /* neither x nor cx are default. Check the y values .
741 * In the trace we see Outlook and Outlook Express using
742 * cy set to CW_USEDEFAULT when opening the address book.
744 else if (IS_DEFAULT(cs->cy))
746 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
747 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
753 /***********************************************************************
756 static void dump_window_styles( DWORD style, DWORD exstyle )
759 if(style & WS_POPUP) TRACE(" WS_POPUP");
760 if(style & WS_CHILD) TRACE(" WS_CHILD");
761 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
762 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
763 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
764 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
765 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
766 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
767 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
770 if(style & WS_BORDER) TRACE(" WS_BORDER");
771 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
773 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
774 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
775 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
776 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
777 if (style & WS_CHILD)
779 if(style & WS_GROUP) TRACE(" WS_GROUP");
780 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
784 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
785 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
788 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
789 #define DUMPED_STYLES \
809 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
814 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
815 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
816 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
817 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
818 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
819 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
820 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
821 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
822 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
823 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
824 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
825 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
826 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
827 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
828 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
829 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
830 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
831 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
833 #define DUMPED_EX_STYLES \
834 (WS_EX_DLGMODALFRAME | \
836 WS_EX_NOPARENTNOTIFY | \
838 WS_EX_ACCEPTFILES | \
839 WS_EX_TRANSPARENT | \
844 WS_EX_CONTEXTHELP | \
847 WS_EX_LEFTSCROLLBAR | \
848 WS_EX_CONTROLPARENT | \
853 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
855 #undef DUMPED_EX_STYLES
859 /***********************************************************************
862 * Implementation of CreateWindowEx().
864 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
868 HWND hwnd, parent, owner, top_child = 0;
869 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
870 MDICREATESTRUCTA mdi_cs;
872 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
873 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
874 debugstr_w(className),
875 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
876 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
877 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
879 /* Fix the styles for MDI children */
880 if (cs->dwExStyle & WS_EX_MDICHILD)
884 wndPtr = WIN_GetPtr(cs->hwndParent);
885 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
887 flags = wndPtr->flags;
888 WIN_ReleasePtr(wndPtr);
891 if (!(flags & WIN_ISMDICLIENT))
893 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
897 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
898 * MDICREATESTRUCT members have the originally passed values.
900 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
901 * have the same layout.
903 mdi_cs.szClass = cs->lpszClass;
904 mdi_cs.szTitle = cs->lpszName;
905 mdi_cs.hOwner = cs->hInstance;
910 mdi_cs.style = cs->style;
911 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
913 cs->lpCreateParams = (LPVOID)&mdi_cs;
915 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
917 if (cs->style & WS_POPUP)
919 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
922 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
926 cs->style &= ~WS_POPUP;
927 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
928 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
931 top_child = GetWindow(cs->hwndParent, GW_CHILD);
935 /* Restore current maximized child */
936 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
938 TRACE("Restoring current maximized child %p\n", top_child);
939 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
940 ShowWindow( top_child, SW_SHOWNORMAL );
941 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
946 /* Find the parent window */
948 parent = cs->hwndParent;
951 if (cs->hwndParent == HWND_MESSAGE)
953 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
954 * message window (style: WS_POPUP|WS_DISABLED)
956 FIXME("Parent is HWND_MESSAGE\n");
957 parent = GetDesktopWindow();
959 else if (cs->hwndParent)
961 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
963 parent = GetDesktopWindow();
964 owner = cs->hwndParent;
969 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
971 WARN("No parent for child window\n" );
972 SetLastError(ERROR_TLW_WITH_WSCHILD);
973 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
975 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM) /* are we creating the desktop itself? */
976 parent = GetDesktopWindow();
979 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
981 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
982 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
983 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
984 cs->dwExStyle |= WS_EX_WINDOWEDGE;
986 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
988 /* Create the window structure */
990 if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
992 hwnd = wndPtr->hwndSelf;
994 /* Fill the window structure */
996 wndPtr->tid = GetCurrentThreadId();
997 wndPtr->hInstance = cs->hInstance;
999 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1000 wndPtr->dwExStyle = cs->dwExStyle;
1001 wndPtr->wIDmenu = 0;
1002 wndPtr->helpContext = 0;
1003 wndPtr->pVScroll = NULL;
1004 wndPtr->pHScroll = NULL;
1005 wndPtr->userdata = 0;
1007 wndPtr->hIconSmall = 0;
1008 wndPtr->hSysMenu = 0;
1009 wndPtr->flags |= (flags & WIN_ISWIN32);
1011 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1014 * Correct the window styles.
1016 * It affects only the style loaded into the WIN structure.
1019 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1021 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1022 if (!(wndPtr->dwStyle & WS_POPUP))
1023 wndPtr->dwStyle |= WS_CAPTION;
1027 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1028 * why does the user get to set it?
1031 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1032 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1033 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1035 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1037 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1038 wndPtr->flags |= WIN_NEED_SIZE;
1040 SERVER_START_REQ( set_window_info )
1043 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1044 req->style = wndPtr->dwStyle;
1045 req->ex_style = wndPtr->dwExStyle;
1046 req->instance = (void *)wndPtr->hInstance;
1047 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1048 req->extra_offset = -1;
1049 wine_server_call( req );
1053 /* Set the window menu */
1055 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1059 if (!MENU_SetMenu(hwnd, cs->hMenu))
1061 WIN_ReleasePtr( wndPtr );
1062 free_window_handle( hwnd );
1068 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1071 if (!cs->hInstance || HIWORD(cs->hInstance))
1072 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1074 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1076 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1080 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1081 WIN_ReleasePtr( wndPtr );
1083 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1085 WIN_DestroyWindow( hwnd );
1089 /* Notify the parent window only */
1091 send_parent_notify( hwnd, WM_CREATE );
1092 if (!IsWindow( hwnd )) return 0;
1094 if (cs->style & WS_VISIBLE)
1096 if (cs->style & WS_MAXIMIZE)
1098 else if (cs->style & WS_MINIMIZE)
1099 sw = SW_SHOWMINIMIZED;
1101 ShowWindow( hwnd, sw );
1102 if (cs->dwExStyle & WS_EX_MDICHILD)
1104 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1105 /* ShowWindow won't activate child windows */
1106 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1110 /* Call WH_SHELL hook */
1112 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1113 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1115 TRACE("created window %p\n", hwnd);
1120 /***********************************************************************
1121 * CreateWindow (USER.41)
1123 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1124 DWORD style, INT16 x, INT16 y, INT16 width,
1125 INT16 height, HWND16 parent, HMENU16 menu,
1126 HINSTANCE16 instance, LPVOID data )
1128 return CreateWindowEx16( 0, className, windowName, style,
1129 x, y, width, height, parent, menu, instance, data );
1133 /***********************************************************************
1134 * CreateWindowEx (USER.452)
1136 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1137 LPCSTR windowName, DWORD style, INT16 x,
1138 INT16 y, INT16 width, INT16 height,
1139 HWND16 parent, HMENU16 menu,
1140 HINSTANCE16 instance, LPVOID data )
1145 /* Fix the coordinates */
1147 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1148 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1149 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1150 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1152 /* Create the window */
1154 cs.lpCreateParams = data;
1155 cs.hInstance = HINSTANCE_32(instance);
1156 cs.hMenu = HMENU_32(menu);
1157 cs.hwndParent = WIN_Handle32( parent );
1159 cs.lpszName = windowName;
1160 cs.lpszClass = className;
1161 cs.dwExStyle = exStyle;
1163 if (!IS_INTRESOURCE(className))
1167 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1169 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1173 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1175 ERR( "bad atom %x\n", LOWORD(className));
1178 cs.lpszClass = buffer;
1179 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1184 /***********************************************************************
1185 * CreateWindowExA (USER32.@)
1187 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1188 LPCSTR windowName, DWORD style, INT x,
1189 INT y, INT width, INT height,
1190 HWND parent, HMENU menu,
1191 HINSTANCE instance, LPVOID data )
1195 cs.lpCreateParams = data;
1196 cs.hInstance = instance;
1198 cs.hwndParent = parent;
1204 cs.lpszName = windowName;
1205 cs.lpszClass = className;
1206 cs.dwExStyle = exStyle;
1208 if (!IS_INTRESOURCE(className))
1211 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1213 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1215 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1219 /***********************************************************************
1220 * CreateWindowExW (USER32.@)
1222 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1223 LPCWSTR windowName, DWORD style, INT x,
1224 INT y, INT width, INT height,
1225 HWND parent, HMENU menu,
1226 HINSTANCE instance, LPVOID data )
1230 cs.lpCreateParams = data;
1231 cs.hInstance = instance;
1233 cs.hwndParent = parent;
1239 cs.lpszName = windowName;
1240 cs.lpszClass = className;
1241 cs.dwExStyle = exStyle;
1243 /* Note: we rely on the fact that CREATESTRUCTA and */
1244 /* CREATESTRUCTW have the same layout. */
1245 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1249 /***********************************************************************
1250 * WIN_SendDestroyMsg
1252 static void WIN_SendDestroyMsg( HWND hwnd )
1256 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1258 if (hwnd == info.hwndCaret) DestroyCaret();
1259 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1263 * Send the WM_DESTROY to the window.
1265 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1268 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1269 * make sure that the window still exists when we come back.
1276 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1278 for (i = 0; pWndArray[i]; i++)
1280 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1282 HeapFree( GetProcessHeap(), 0, pWndArray );
1285 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1289 /***********************************************************************
1290 * DestroyWindow (USER32.@)
1292 BOOL WINAPI DestroyWindow( HWND hwnd )
1296 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1298 SetLastError( ERROR_ACCESS_DENIED );
1302 TRACE("(%p)\n", hwnd);
1306 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1308 if (MENU_IsMenuActive() == hwnd)
1311 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1315 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1316 send_parent_notify( hwnd, WM_DESTROY );
1318 else if (!GetWindow( hwnd, GW_OWNER ))
1320 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1321 /* FIXME: clean up palette - see "Internals" p.352 */
1324 if (!IsWindow(hwnd)) return TRUE;
1326 /* Hide the window */
1327 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1329 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1331 ShowWindow( hwnd, SW_HIDE );
1333 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1334 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1337 if (!IsWindow(hwnd)) return TRUE;
1339 /* Recursively destroy owned windows */
1346 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1349 for (i = 0; list[i]; i++)
1351 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1352 if (WIN_IsCurrentThread( list[i] ))
1354 DestroyWindow( list[i] );
1358 WIN_SetOwner( list[i], 0 );
1360 HeapFree( GetProcessHeap(), 0, list );
1362 if (!got_one) break;
1366 /* Send destroy messages */
1368 WIN_SendDestroyMsg( hwnd );
1369 if (!IsWindow( hwnd )) return TRUE;
1371 if (GetClipboardOwner() == hwnd)
1372 CLIPBOARD_ReleaseOwner();
1374 /* Destroy the window storage */
1376 WIN_DestroyWindow( hwnd );
1381 /***********************************************************************
1382 * CloseWindow (USER32.@)
1384 BOOL WINAPI CloseWindow( HWND hwnd )
1386 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1387 ShowWindow( hwnd, SW_MINIMIZE );
1392 /***********************************************************************
1393 * OpenIcon (USER32.@)
1395 BOOL WINAPI OpenIcon( HWND hwnd )
1397 if (!IsIconic( hwnd )) return FALSE;
1398 ShowWindow( hwnd, SW_SHOWNORMAL );
1403 /***********************************************************************
1404 * FindWindowExW (USER32.@)
1406 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1411 WCHAR *buffer = NULL;
1413 if (!parent) parent = GetDesktopWindow();
1416 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1417 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1420 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1424 child = WIN_GetFullHandle( child );
1425 while (list[i] && list[i] != child) i++;
1426 if (!list[i]) goto done;
1427 i++; /* start from next window */
1434 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1441 HeapFree( GetProcessHeap(), 0, list );
1442 HeapFree( GetProcessHeap(), 0, buffer );
1448 /***********************************************************************
1449 * FindWindowA (USER32.@)
1451 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1453 HWND ret = FindWindowExA( 0, 0, className, title );
1454 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1459 /***********************************************************************
1460 * FindWindowExA (USER32.@)
1462 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1464 LPWSTR titleW = NULL;
1469 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1470 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1471 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1474 if (!IS_INTRESOURCE(className))
1477 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1478 hwnd = FindWindowExW( parent, child, classW, titleW );
1482 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1485 HeapFree( GetProcessHeap(), 0, titleW );
1490 /***********************************************************************
1491 * FindWindowW (USER32.@)
1493 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1495 return FindWindowExW( 0, 0, className, title );
1499 /**********************************************************************
1500 * GetDesktopWindow (USER32.@)
1502 HWND WINAPI GetDesktopWindow(void)
1504 struct user_thread_info *thread_info = get_user_thread_info();
1506 if (thread_info->desktop) return thread_info->desktop;
1508 SERVER_START_REQ( get_desktop_window )
1511 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1515 if (!thread_info->desktop)
1517 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1519 PROCESS_INFORMATION pi;
1520 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1522 memset( &si, 0, sizeof(si) );
1524 si.dwFlags = STARTF_USESTDHANDLES;
1527 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1529 GetSystemDirectoryW( cmdline, MAX_PATH );
1530 lstrcatW( cmdline, command_line );
1531 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1532 NULL, NULL, &si, &pi ))
1534 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1535 WaitForInputIdle( pi.hProcess, 10000 );
1536 CloseHandle( pi.hThread );
1537 CloseHandle( pi.hProcess );
1540 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1542 SERVER_START_REQ( get_desktop_window )
1545 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1550 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1551 ERR( "failed to create desktop window\n" );
1553 return thread_info->desktop;
1557 /*******************************************************************
1558 * EnableWindow (USER32.@)
1560 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1565 if (is_broadcast(hwnd))
1567 SetLastError( ERROR_INVALID_PARAMETER );
1571 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1572 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1576 TRACE("( %p, %d )\n", hwnd, enable);
1578 retvalue = !IsWindowEnabled( hwnd );
1580 if (enable && retvalue)
1582 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1583 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1585 else if (!enable && !retvalue)
1589 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1591 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1593 if (hwnd == GetFocus())
1594 SetFocus( 0 ); /* A disabled window can't have the focus */
1596 capture_wnd = GetCapture();
1597 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1598 ReleaseCapture(); /* A disabled window can't capture the mouse */
1600 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1606 /***********************************************************************
1607 * IsWindowEnabled (USER32.@)
1609 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1611 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1615 /***********************************************************************
1616 * IsWindowUnicode (USER32.@)
1618 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1621 BOOL retvalue = FALSE;
1623 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1625 if (wndPtr == WND_DESKTOP) return TRUE;
1627 if (wndPtr != WND_OTHER_PROCESS)
1629 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1630 WIN_ReleasePtr( wndPtr );
1634 SERVER_START_REQ( get_window_info )
1637 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1645 /**********************************************************************
1648 * Helper function for GetWindowLong().
1650 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1652 LONG_PTR retvalue = 0;
1655 if (offset == GWLP_HWNDPARENT)
1657 HWND parent = GetAncestor( hwnd, GA_PARENT );
1658 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1659 return (ULONG_PTR)parent;
1662 if (!(wndPtr = WIN_GetPtr( hwnd )))
1664 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1668 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1670 if (offset == GWLP_WNDPROC)
1672 SetLastError( ERROR_ACCESS_DENIED );
1675 SERVER_START_REQ( set_window_info )
1678 req->flags = 0; /* don't set anything, just retrieve */
1679 req->extra_offset = (offset >= 0) ? offset : -1;
1680 req->extra_size = (offset >= 0) ? size : 0;
1681 if (!wine_server_call_err( req ))
1685 case GWL_STYLE: retvalue = reply->old_style; break;
1686 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1687 case GWLP_ID: retvalue = reply->old_id; break;
1688 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1689 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1691 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1692 else SetLastError( ERROR_INVALID_INDEX );
1701 /* now we have a valid wndPtr */
1705 if (offset > (int)(wndPtr->cbWndExtra - size))
1707 WARN("Invalid offset %d\n", offset );
1708 WIN_ReleasePtr( wndPtr );
1709 SetLastError( ERROR_INVALID_INDEX );
1712 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1714 /* Special case for dialog window procedure */
1715 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1716 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1717 WIN_ReleasePtr( wndPtr );
1723 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1724 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1725 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1726 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
1727 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1729 /* This looks like a hack only for the edit control (see tests). This makes these controls
1730 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1731 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1733 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1734 retvalue = (ULONG_PTR)wndPtr->winproc;
1736 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1739 WARN("Unknown offset %d\n", offset );
1740 SetLastError( ERROR_INVALID_INDEX );
1743 WIN_ReleasePtr(wndPtr);
1748 /**********************************************************************
1751 * Helper function for SetWindowLong().
1753 * 0 is the failure code. However, in the case of failure SetLastError
1754 * must be set to distinguish between a 0 return value and a failure.
1756 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1760 LONG_PTR retval = 0;
1763 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1765 if (is_broadcast(hwnd))
1767 SetLastError( ERROR_INVALID_PARAMETER );
1771 if (!(wndPtr = WIN_GetPtr( hwnd )))
1773 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1776 if (wndPtr == WND_DESKTOP)
1778 /* can't change anything on the desktop window */
1779 SetLastError( ERROR_ACCESS_DENIED );
1782 if (wndPtr == WND_OTHER_PROCESS)
1784 if (offset == GWLP_WNDPROC)
1786 SetLastError( ERROR_ACCESS_DENIED );
1789 if (offset > 32767 || offset < -32767)
1791 SetLastError( ERROR_INVALID_INDEX );
1794 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1797 /* first some special cases */
1803 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1804 style.styleNew = newval;
1805 WIN_ReleasePtr( wndPtr );
1806 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1807 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1808 newval = style.styleNew;
1810 case GWLP_HWNDPARENT:
1811 if (wndPtr->parent == GetDesktopWindow())
1813 WIN_ReleasePtr( wndPtr );
1814 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1818 WIN_ReleasePtr( wndPtr );
1819 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1824 UINT old_flags = wndPtr->flags;
1825 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
1826 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1827 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1828 if (proc) wndPtr->winproc = proc;
1829 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1830 else wndPtr->flags &= ~WIN_ISUNICODE;
1831 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1833 WIN_ReleasePtr( wndPtr );
1836 /* update is_unicode flag on the server side */
1840 case GWLP_HINSTANCE:
1844 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1845 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1847 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1848 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1849 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1850 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1851 WIN_ReleasePtr( wndPtr );
1856 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1858 WARN("Invalid offset %d\n", offset );
1859 WIN_ReleasePtr( wndPtr );
1860 SetLastError( ERROR_INVALID_INDEX );
1863 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1865 /* already set to the same value */
1866 WIN_ReleasePtr( wndPtr );
1872 SERVER_START_REQ( set_window_info )
1875 req->extra_offset = -1;
1879 req->flags = SET_WIN_STYLE;
1880 req->style = newval;
1883 req->flags = SET_WIN_EXSTYLE;
1884 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
1885 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
1886 req->ex_style = newval;
1889 req->flags = SET_WIN_ID;
1892 case GWLP_HINSTANCE:
1893 req->flags = SET_WIN_INSTANCE;
1894 req->instance = (void *)newval;
1897 req->flags = SET_WIN_UNICODE;
1898 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1901 req->flags = SET_WIN_USERDATA;
1902 req->user_data = newval;
1905 req->flags = SET_WIN_EXTRA;
1906 req->extra_offset = offset;
1907 req->extra_size = size;
1908 set_win_data( &req->extra_value, newval, size );
1910 if ((ok = !wine_server_call_err( req )))
1915 wndPtr->dwStyle = newval;
1916 retval = reply->old_style;
1919 wndPtr->dwExStyle = newval;
1920 retval = reply->old_ex_style;
1923 wndPtr->wIDmenu = newval;
1924 retval = reply->old_id;
1926 case GWLP_HINSTANCE:
1927 wndPtr->hInstance = (HINSTANCE)newval;
1928 retval = (ULONG_PTR)reply->old_instance;
1933 wndPtr->userdata = newval;
1934 retval = reply->old_user_data;
1937 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
1938 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
1944 WIN_ReleasePtr( wndPtr );
1948 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
1950 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
1951 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
1957 /**********************************************************************
1958 * GetWindowLong (USER.135)
1960 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1964 BOOL is_winproc = (offset == GWLP_WNDPROC);
1968 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
1970 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1973 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
1975 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1978 * Some programs try to access last element from 16 bit
1979 * code using illegal offset value. Hopefully this is
1980 * what those programs really expect.
1982 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
1984 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1985 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
1990 WARN("Invalid offset %d\n", offset );
1991 WIN_ReleasePtr( wndPtr );
1992 SetLastError( ERROR_INVALID_INDEX );
1996 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
1997 WIN_ReleasePtr( wndPtr );
2000 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2001 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2006 /**********************************************************************
2007 * GetWindowWord (USER32.@)
2009 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2014 case GWLP_HINSTANCE:
2015 case GWLP_HWNDPARENT:
2020 WARN("Invalid offset %d\n", offset );
2021 SetLastError( ERROR_INVALID_INDEX );
2026 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2030 /**********************************************************************
2031 * GetWindowLongA (USER32.@)
2033 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2035 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2039 /**********************************************************************
2040 * GetWindowLongW (USER32.@)
2042 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2044 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2048 /**********************************************************************
2049 * SetWindowLong (USER.136)
2051 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2054 BOOL is_winproc = (offset == GWLP_WNDPROC);
2056 if (offset == DWLP_DLGPROC)
2058 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2060 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2063 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2065 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2066 (wndPtr->flags & WIN_ISDIALOG));
2067 WIN_ReleasePtr( wndPtr );
2073 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2074 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2075 return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2077 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2081 /**********************************************************************
2082 * SetWindowWord (USER32.@)
2084 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2089 case GWLP_HINSTANCE:
2090 case GWLP_HWNDPARENT:
2095 WARN("Invalid offset %d\n", offset );
2096 SetLastError( ERROR_INVALID_INDEX );
2101 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2105 /**********************************************************************
2106 * SetWindowLongA (USER32.@)
2108 * See SetWindowLongW.
2110 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2112 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2116 /**********************************************************************
2117 * SetWindowLongW (USER32.@) Set window attribute
2119 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2120 * value in a window's extra memory.
2122 * The _hwnd_ parameter specifies the window. is the handle to a
2123 * window that has extra memory. The _newval_ parameter contains the
2124 * new attribute or extra memory value. If positive, the _offset_
2125 * parameter is the byte-addressed location in the window's extra
2126 * memory to set. If negative, _offset_ specifies the window
2127 * attribute to set, and should be one of the following values:
2129 * GWL_EXSTYLE The window's extended window style
2131 * GWL_STYLE The window's window style.
2133 * GWLP_WNDPROC Pointer to the window's window procedure.
2135 * GWLP_HINSTANCE The window's pplication instance handle.
2137 * GWLP_ID The window's identifier.
2139 * GWLP_USERDATA The window's user-specified data.
2141 * If the window is a dialog box, the _offset_ parameter can be one of
2142 * the following values:
2144 * DWLP_DLGPROC The address of the window's dialog box procedure.
2146 * DWLP_MSGRESULT The return value of a message
2147 * that the dialog box procedure processed.
2149 * DWLP_USER Application specific information.
2153 * If successful, returns the previous value located at _offset_. Otherwise,
2158 * Extra memory for a window class is specified by a nonzero cbWndExtra
2159 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2160 * time of class creation.
2162 * Using GWL_WNDPROC to set a new window procedure effectively creates
2163 * a window subclass. Use CallWindowProc() in the new windows procedure
2164 * to pass messages to the superclass's window procedure.
2166 * The user data is reserved for use by the application which created
2169 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2170 * instead, call the EnableWindow() function to change the window's
2173 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2174 * SetParent() instead.
2177 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2178 * it sends WM_STYLECHANGING before changing the settings
2179 * and WM_STYLECHANGED afterwards.
2180 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2182 LONG WINAPI SetWindowLongW(
2183 HWND hwnd, /* [in] window to alter */
2184 INT offset, /* [in] offset, in bytes, of location to alter */
2185 LONG newval /* [in] new value of location */
2187 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2191 /*******************************************************************
2192 * GetWindowTextA (USER32.@)
2194 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2198 if (!lpString) return 0;
2200 if (WIN_IsCurrentProcess( hwnd ))
2201 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2203 /* when window belongs to other process, don't send a message */
2204 if (nMaxCount <= 0) return 0;
2205 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2206 get_server_window_text( hwnd, buffer, nMaxCount );
2207 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2208 lpString[nMaxCount-1] = 0;
2209 HeapFree( GetProcessHeap(), 0, buffer );
2210 return strlen(lpString);
2214 /*******************************************************************
2215 * InternalGetWindowText (USER32.@)
2217 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2221 if (nMaxCount <= 0) return 0;
2222 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2223 if (win == WND_DESKTOP) lpString[0] = 0;
2224 else if (win != WND_OTHER_PROCESS)
2226 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2227 else lpString[0] = 0;
2228 WIN_ReleasePtr( win );
2232 get_server_window_text( hwnd, lpString, nMaxCount );
2234 return strlenW(lpString);
2238 /*******************************************************************
2239 * GetWindowTextW (USER32.@)
2241 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2243 if (!lpString) return 0;
2245 if (WIN_IsCurrentProcess( hwnd ))
2246 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2248 /* when window belongs to other process, don't send a message */
2249 if (nMaxCount <= 0) return 0;
2250 get_server_window_text( hwnd, lpString, nMaxCount );
2251 return strlenW(lpString);
2255 /*******************************************************************
2256 * SetWindowTextA (USER32.@)
2257 * SetWindowText (USER32.@)
2259 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2261 if (is_broadcast(hwnd))
2263 SetLastError( ERROR_INVALID_PARAMETER );
2266 if (!WIN_IsCurrentProcess( hwnd ))
2267 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2268 debugstr_a(lpString), hwnd );
2269 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2273 /*******************************************************************
2274 * SetWindowTextW (USER32.@)
2276 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR 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_w(lpString), hwnd );
2286 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2290 /*******************************************************************
2291 * GetWindowTextLengthA (USER32.@)
2293 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2295 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2298 /*******************************************************************
2299 * GetWindowTextLengthW (USER32.@)
2301 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2303 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2307 /*******************************************************************
2308 * IsWindow (USER32.@)
2310 BOOL WINAPI IsWindow( HWND hwnd )
2315 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2316 if (ptr == WND_DESKTOP) return TRUE;
2318 if (ptr != WND_OTHER_PROCESS)
2320 WIN_ReleasePtr( ptr );
2324 /* check other processes */
2325 SERVER_START_REQ( get_window_info )
2328 ret = !wine_server_call_err( req );
2335 /***********************************************************************
2336 * GetWindowThreadProcessId (USER32.@)
2338 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2343 if (!(ptr = WIN_GetPtr( hwnd )))
2345 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2349 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2351 /* got a valid window */
2353 if (process) *process = GetCurrentProcessId();
2354 WIN_ReleasePtr( ptr );
2358 /* check other processes */
2359 SERVER_START_REQ( get_window_info )
2362 if (!wine_server_call_err( req ))
2364 tid = (DWORD)reply->tid;
2365 if (process) *process = (DWORD)reply->pid;
2373 /*****************************************************************
2374 * GetParent (USER32.@)
2376 HWND WINAPI GetParent( HWND hwnd )
2381 if (!(wndPtr = WIN_GetPtr( hwnd )))
2383 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2386 if (wndPtr == WND_DESKTOP) return 0;
2387 if (wndPtr == WND_OTHER_PROCESS)
2389 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2390 if (style & (WS_POPUP | WS_CHILD))
2392 SERVER_START_REQ( get_window_tree )
2395 if (!wine_server_call_err( req ))
2397 if (style & WS_POPUP) retvalue = reply->owner;
2398 else if (style & WS_CHILD) retvalue = reply->parent;
2406 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2407 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2408 WIN_ReleasePtr( wndPtr );
2414 /*****************************************************************
2415 * GetAncestor (USER32.@)
2417 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2420 HWND *list, ret = 0;
2425 if (!(win = WIN_GetPtr( hwnd )))
2427 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2430 if (win == WND_DESKTOP) return 0;
2431 if (win != WND_OTHER_PROCESS)
2434 WIN_ReleasePtr( win );
2436 else /* need to query the server */
2438 SERVER_START_REQ( get_window_tree )
2441 if (!wine_server_call_err( req )) ret = reply->parent;
2448 if (!(list = list_window_parents( hwnd ))) return 0;
2450 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2454 while (list[count]) count++;
2455 ret = list[count - 2]; /* get the one before the desktop */
2457 HeapFree( GetProcessHeap(), 0, list );
2461 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2464 HWND parent = GetParent( ret );
2474 /*****************************************************************
2475 * SetParent (USER32.@)
2477 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2480 HWND old_parent = 0;
2485 if (is_broadcast(hwnd) || is_broadcast(parent))
2487 SetLastError(ERROR_INVALID_PARAMETER);
2491 if (!parent) parent = GetDesktopWindow();
2492 else parent = WIN_GetFullHandle( parent );
2494 if (!IsWindow( parent ))
2496 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2500 /* Some applications try to set a child as a parent */
2501 if (IsChild(hwnd, parent))
2503 SetLastError( ERROR_INVALID_PARAMETER );
2507 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2508 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2510 /* Windows hides the window first, then shows it again
2511 * including the WM_SHOWWINDOW messages and all */
2512 was_visible = ShowWindow( hwnd, SW_HIDE );
2514 wndPtr = WIN_GetPtr( hwnd );
2515 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2517 SERVER_START_REQ( set_parent )
2520 req->parent = parent;
2521 if ((ret = !wine_server_call( req )))
2523 old_parent = reply->old_parent;
2524 wndPtr->parent = parent = reply->full_parent;
2529 WIN_ReleasePtr( wndPtr );
2532 USER_Driver->pSetParent( full_handle, parent, old_parent );
2534 /* SetParent additionally needs to make hwnd the topmost window
2535 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2536 WM_WINDOWPOSCHANGED notification messages.
2538 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2539 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2540 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2541 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2547 /*******************************************************************
2548 * IsChild (USER32.@)
2550 BOOL WINAPI IsChild( HWND parent, HWND child )
2552 HWND *list = list_window_parents( child );
2556 if (!list) return FALSE;
2557 parent = WIN_GetFullHandle( parent );
2558 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2559 ret = list[i] && list[i+1];
2560 HeapFree( GetProcessHeap(), 0, list );
2565 /***********************************************************************
2566 * IsWindowVisible (USER32.@)
2568 BOOL WINAPI IsWindowVisible( HWND hwnd )
2574 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2575 if (!(list = list_window_parents( hwnd ))) return TRUE;
2576 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2578 for (i = 0; list[i+1]; i++)
2579 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2580 retval = !list[i+1];
2582 HeapFree( GetProcessHeap(), 0, list );
2587 /***********************************************************************
2588 * WIN_IsWindowDrawable
2590 * hwnd is drawable when it is visible, all parents are not
2591 * minimized, and it is itself not minimized unless we are
2592 * trying to draw its default class icon.
2594 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2599 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2601 if (!(style & WS_VISIBLE)) return FALSE;
2602 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2604 if (!(list = list_window_parents( hwnd ))) return TRUE;
2605 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2607 for (i = 0; list[i+1]; i++)
2608 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2610 retval = !list[i+1];
2612 HeapFree( GetProcessHeap(), 0, list );
2617 /*******************************************************************
2618 * GetTopWindow (USER32.@)
2620 HWND WINAPI GetTopWindow( HWND hwnd )
2622 if (!hwnd) hwnd = GetDesktopWindow();
2623 return GetWindow( hwnd, GW_CHILD );
2627 /*******************************************************************
2628 * GetWindow (USER32.@)
2630 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2634 if (rel == GW_OWNER) /* this one may be available locally */
2636 WND *wndPtr = WIN_GetPtr( hwnd );
2639 SetLastError( ERROR_INVALID_HANDLE );
2642 if (wndPtr == WND_DESKTOP) return 0;
2643 if (wndPtr != WND_OTHER_PROCESS)
2645 retval = wndPtr->owner;
2646 WIN_ReleasePtr( wndPtr );
2649 /* else fall through to server call */
2652 SERVER_START_REQ( get_window_tree )
2655 if (!wine_server_call_err( req ))
2660 retval = reply->first_sibling;
2663 retval = reply->last_sibling;
2666 retval = reply->next_sibling;
2669 retval = reply->prev_sibling;
2672 retval = reply->owner;
2675 retval = reply->first_child;
2685 /*******************************************************************
2686 * ShowOwnedPopups (USER32.@)
2688 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2692 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2694 if (!win_array) return TRUE;
2696 while (win_array[count]) count++;
2697 while (--count >= 0)
2699 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2700 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2701 if (pWnd == WND_OTHER_PROCESS) continue;
2704 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2706 WIN_ReleasePtr( pWnd );
2707 /* In Windows, ShowOwnedPopups(TRUE) generates
2708 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2709 * regardless of the state of the owner
2711 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2717 if (pWnd->dwStyle & WS_VISIBLE)
2719 WIN_ReleasePtr( pWnd );
2720 /* In Windows, ShowOwnedPopups(FALSE) generates
2721 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2722 * regardless of the state of the owner
2724 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2728 WIN_ReleasePtr( pWnd );
2730 HeapFree( GetProcessHeap(), 0, win_array );
2735 /*******************************************************************
2736 * GetLastActivePopup (USER32.@)
2738 HWND WINAPI GetLastActivePopup( HWND hwnd )
2742 SERVER_START_REQ( get_window_info )
2745 if (!wine_server_call_err( req )) retval = reply->last_active;
2752 /*******************************************************************
2755 * Build an array of the children of a given window. The array must be
2756 * freed with HeapFree. Returns NULL when no windows are found.
2758 HWND *WIN_ListChildren( HWND hwnd )
2760 return list_window_children( hwnd, NULL, 0 );
2764 /*******************************************************************
2765 * EnumWindows (USER32.@)
2767 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2773 USER_CheckNotLock();
2775 /* We have to build a list of all windows first, to avoid */
2776 /* unpleasant side-effects, for instance if the callback */
2777 /* function changes the Z-order of the windows. */
2779 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2781 /* Now call the callback function for every window */
2783 for (i = 0; list[i]; i++)
2785 /* Make sure that the window still exists */
2786 if (!IsWindow( list[i] )) continue;
2787 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2789 HeapFree( GetProcessHeap(), 0, list );
2794 /**********************************************************************
2795 * EnumThreadWindows (USER32.@)
2797 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2802 USER_CheckNotLock();
2804 if (!(list = list_window_children( GetDesktopWindow(), NULL, id ))) return TRUE;
2806 /* Now call the callback function for every window */
2808 for (i = 0; list[i]; i++)
2809 if (!func( list[i], lParam )) break;
2810 HeapFree( GetProcessHeap(), 0, list );
2815 /**********************************************************************
2816 * WIN_EnumChildWindows
2818 * Helper function for EnumChildWindows().
2820 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2825 for ( ; *list; list++)
2827 /* Make sure that the window still exists */
2828 if (!IsWindow( *list )) continue;
2829 /* Build children list first */
2830 childList = WIN_ListChildren( *list );
2832 ret = func( *list, lParam );
2836 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2837 HeapFree( GetProcessHeap(), 0, childList );
2839 if (!ret) return FALSE;
2845 /**********************************************************************
2846 * EnumChildWindows (USER32.@)
2848 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2853 USER_CheckNotLock();
2855 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2856 ret = WIN_EnumChildWindows( list, func, lParam );
2857 HeapFree( GetProcessHeap(), 0, list );
2862 /*******************************************************************
2863 * AnyPopup (USER.52)
2865 BOOL16 WINAPI AnyPopup16(void)
2871 /*******************************************************************
2872 * AnyPopup (USER32.@)
2874 BOOL WINAPI AnyPopup(void)
2878 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2880 if (!list) return FALSE;
2881 for (i = 0; list[i]; i++)
2883 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2885 retvalue = (list[i] != 0);
2886 HeapFree( GetProcessHeap(), 0, list );
2891 /*******************************************************************
2892 * FlashWindow (USER32.@)
2894 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2898 TRACE("%p\n", hWnd);
2900 if (IsIconic( hWnd ))
2902 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2904 wndPtr = WIN_GetPtr(hWnd);
2905 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2906 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2908 wndPtr->flags |= WIN_NCACTIVATED;
2912 wndPtr->flags &= ~WIN_NCACTIVATED;
2914 WIN_ReleasePtr( wndPtr );
2921 wndPtr = WIN_GetPtr(hWnd);
2922 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2923 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2925 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2926 else wparam = (hWnd == GetForegroundWindow());
2928 WIN_ReleasePtr( wndPtr );
2929 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2934 /*******************************************************************
2935 * FlashWindowEx (USER32.@)
2937 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
2939 FIXME("%p\n", pfwi);
2943 /*******************************************************************
2944 * GetWindowContextHelpId (USER32.@)
2946 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2949 WND *wnd = WIN_GetPtr( hwnd );
2950 if (!wnd || wnd == WND_DESKTOP) return 0;
2951 if (wnd == WND_OTHER_PROCESS)
2953 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2956 retval = wnd->helpContext;
2957 WIN_ReleasePtr( wnd );
2962 /*******************************************************************
2963 * SetWindowContextHelpId (USER32.@)
2965 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2967 WND *wnd = WIN_GetPtr( hwnd );
2968 if (!wnd || wnd == WND_DESKTOP) return FALSE;
2969 if (wnd == WND_OTHER_PROCESS)
2971 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2974 wnd->helpContext = id;
2975 WIN_ReleasePtr( wnd );
2980 /*******************************************************************
2981 * DragDetect (USER32.@)
2983 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2987 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
2988 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
2990 rect.left = pt.x - wDragWidth;
2991 rect.right = pt.x + wDragWidth;
2993 rect.top = pt.y - wDragHeight;
2994 rect.bottom = pt.y + wDragHeight;
3000 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3002 if( msg.message == WM_LBUTTONUP )
3007 if( msg.message == WM_MOUSEMOVE )
3010 tmp.x = (short)LOWORD(msg.lParam);
3011 tmp.y = (short)HIWORD(msg.lParam);
3012 if( !PtInRect( &rect, tmp ))
3024 /******************************************************************************
3025 * GetWindowModuleFileNameA (USER32.@)
3027 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3029 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3030 hwnd, lpszFileName, cchFileNameMax);
3034 /******************************************************************************
3035 * GetWindowModuleFileNameW (USER32.@)
3037 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3039 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3040 hwnd, lpszFileName, cchFileNameMax);
3044 /******************************************************************************
3045 * GetWindowInfo (USER32.@)
3047 * Note: tests show that Windows doesn't check cbSize of the structure.
3049 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3051 if (!pwi) return FALSE;
3052 if (!IsWindow(hwnd)) return FALSE;
3054 GetWindowRect(hwnd, &pwi->rcWindow);
3055 GetClientRect(hwnd, &pwi->rcClient);
3056 /* translate to screen coordinates */
3057 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3059 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3060 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3061 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3063 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3064 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3066 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3067 pwi->wCreatorVersion = 0x0400;
3072 /******************************************************************************
3073 * SwitchDesktop (USER32.@)
3075 * NOTES: Sets the current input or interactive desktop.
3077 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3079 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3083 /*****************************************************************************
3084 * SetLayeredWindowAttributes (USER32.@)
3086 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3087 BYTE bAlpha, DWORD dwFlags )
3089 FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3093 /*****************************************************************************
3094 * GetLayeredWindowAttributes (USER32.@)
3096 BOOL WINAPI GetLayeredWindowAttributes( HWND hWnd, COLORREF *prgbKey,
3097 BYTE *pbAlpha, DWORD *pdwFlags )
3099 FIXME("(%p,%p,%p,%p): stub!\n", hWnd, prgbKey, pbAlpha, pdwFlags);
3103 /*****************************************************************************
3104 * UpdateLayeredWindow (USER32.@)
3106 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3107 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3114 FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3115 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3120 /* 64bit versions */
3122 #ifdef GetWindowLongPtrW
3123 #undef GetWindowLongPtrW
3126 #ifdef GetWindowLongPtrA
3127 #undef GetWindowLongPtrA
3130 #ifdef SetWindowLongPtrW
3131 #undef SetWindowLongPtrW
3134 #ifdef SetWindowLongPtrA
3135 #undef SetWindowLongPtrA
3138 /*****************************************************************************
3139 * GetWindowLongPtrW (USER32.@)
3141 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3143 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3146 /*****************************************************************************
3147 * GetWindowLongPtrA (USER32.@)
3149 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3151 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3154 /*****************************************************************************
3155 * SetWindowLongPtrW (USER32.@)
3157 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3159 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3162 /*****************************************************************************
3163 * SetWindowLongPtrA (USER32.@)
3165 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3167 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );