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, LPCWSTR class, DWORD tid )
223 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
225 SERVER_START_REQ( get_window_children )
229 if (!(req->atom = get_int_atom_value( class )) && class)
230 wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
231 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
232 if (!wine_server_call( req )) count = reply->count;
235 if (count && count < size)
240 HeapFree( GetProcessHeap(), 0, list );
242 size = count + 1; /* restart with a large enough buffer */
248 /*******************************************************************
249 * list_window_parents
251 * Build an array of all parents of a given window, starting with
252 * the immediate parent. The array must be freed with HeapFree.
254 static HWND *list_window_parents( HWND hwnd )
258 int pos = 0, size = 16, count = 0;
260 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
265 if (!(win = WIN_GetPtr( current ))) goto empty;
266 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
267 if (win == WND_DESKTOP)
269 if (!pos) goto empty;
273 list[pos] = current = win->parent;
274 WIN_ReleasePtr( win );
275 if (++pos == size - 1)
277 /* need to grow the list */
278 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
279 if (!new_list) goto empty;
285 /* at least one parent belongs to another process, have to query the server */
290 SERVER_START_REQ( get_window_parents )
293 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
294 if (!wine_server_call( req )) count = reply->count;
297 if (!count) goto empty;
303 HeapFree( GetProcessHeap(), 0, list );
305 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
309 HeapFree( GetProcessHeap(), 0, list );
314 /*******************************************************************
317 static void send_parent_notify( HWND hwnd, UINT msg )
319 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
320 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
322 HWND parent = GetParent(hwnd);
323 if (parent && parent != GetDesktopWindow())
324 SendMessageW( parent, WM_PARENTNOTIFY,
325 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
330 /*******************************************************************
331 * get_server_window_text
333 * Retrieve the window text from the server.
335 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
339 SERVER_START_REQ( get_window_text )
342 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
343 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
346 text[len / sizeof(WCHAR)] = 0;
350 /***********************************************************************
353 * Return a pointer to the WND structure if local to the process,
354 * or WND_OTHER_PROCESS if handle may be valid in other process.
355 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
357 WND *WIN_GetPtr( HWND hwnd )
360 WORD index = USER_HANDLE_TO_INDEX(hwnd);
362 if (index >= NB_USER_HANDLES) return NULL;
365 if ((ptr = user_handles[index]))
367 if (ptr->dwMagic == WND_MAGIC &&
368 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
372 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
374 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
377 else ptr = WND_OTHER_PROCESS;
383 /***********************************************************************
384 * WIN_IsCurrentProcess
386 * Check whether a given window belongs to the current process (and return the full handle).
388 HWND WIN_IsCurrentProcess( HWND hwnd )
393 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
395 WIN_ReleasePtr( ptr );
400 /***********************************************************************
401 * WIN_IsCurrentThread
403 * Check whether a given window belongs to the current thread (and return the full handle).
405 HWND WIN_IsCurrentThread( HWND hwnd )
410 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
411 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
412 WIN_ReleasePtr( ptr );
417 /***********************************************************************
420 * Convert a 16-bit window handle to a full 32-bit handle.
422 HWND WIN_Handle32( HWND16 hwnd16 )
425 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
427 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
428 /* do sign extension for -2 and -3 */
429 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
431 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
433 if (ptr == WND_DESKTOP) return GetDesktopWindow();
435 if (ptr != WND_OTHER_PROCESS)
437 hwnd = ptr->hwndSelf;
438 WIN_ReleasePtr( ptr );
440 else /* may belong to another process */
442 SERVER_START_REQ( get_window_info )
445 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
453 /***********************************************************************
456 * Change the owner of a window.
458 HWND WIN_SetOwner( HWND hwnd, HWND owner )
460 WND *win = WIN_GetPtr( hwnd );
463 if (!win || win == WND_DESKTOP) return 0;
464 if (win == WND_OTHER_PROCESS)
466 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
469 SERVER_START_REQ( set_window_owner )
473 if (!wine_server_call( req ))
475 win->owner = reply->full_owner;
476 ret = reply->prev_owner;
480 WIN_ReleasePtr( win );
485 /***********************************************************************
488 * Change the style of a window.
490 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
493 ULONG new_style, old_style = 0;
494 WND *win = WIN_GetPtr( hwnd );
496 if (!win || win == WND_DESKTOP) return 0;
497 if (win == WND_OTHER_PROCESS)
500 ERR( "cannot set style %x/%x on other process window %p\n",
501 set_bits, clear_bits, hwnd );
504 new_style = (win->dwStyle | set_bits) & ~clear_bits;
505 if (new_style == win->dwStyle)
507 WIN_ReleasePtr( win );
510 SERVER_START_REQ( set_window_info )
513 req->flags = SET_WIN_STYLE;
514 req->style = new_style;
515 req->extra_offset = -1;
516 if ((ok = !wine_server_call( req )))
518 old_style = reply->old_style;
519 win->dwStyle = new_style;
523 WIN_ReleasePtr( win );
524 if (ok) USER_Driver->pSetWindowStyle( hwnd, old_style );
529 /***********************************************************************
532 * Get the window and client rectangles.
534 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
536 WND *win = WIN_GetPtr( hwnd );
539 if (!win) return FALSE;
540 if (win == WND_DESKTOP)
543 rect.left = rect.top = 0;
544 rect.right = GetSystemMetrics(SM_CXSCREEN);
545 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
546 if (rectWindow) *rectWindow = rect;
547 if (rectClient) *rectClient = rect;
549 else if (win == WND_OTHER_PROCESS)
551 SERVER_START_REQ( get_window_rectangles )
554 if ((ret = !wine_server_call( req )))
558 rectWindow->left = reply->window.left;
559 rectWindow->top = reply->window.top;
560 rectWindow->right = reply->window.right;
561 rectWindow->bottom = reply->window.bottom;
565 rectClient->left = reply->client.left;
566 rectClient->top = reply->client.top;
567 rectClient->right = reply->client.right;
568 rectClient->bottom = reply->client.bottom;
576 if (rectWindow) *rectWindow = win->rectWindow;
577 if (rectClient) *rectClient = win->rectClient;
578 WIN_ReleasePtr( win );
584 /***********************************************************************
587 * Destroy storage associated to a window. "Internals" p.358
589 LRESULT WIN_DestroyWindow( HWND hwnd )
593 HMENU menu = 0, sys_menu;
595 TRACE("%p\n", hwnd );
597 /* free child windows */
598 if ((list = WIN_ListChildren( hwnd )))
601 for (i = 0; list[i]; i++)
603 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
604 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
606 HeapFree( GetProcessHeap(), 0, list );
609 /* Unlink now so we won't bother with the children later on */
610 SERVER_START_REQ( set_parent )
614 wine_server_call( req );
619 * Send the WM_NCDESTROY to the window being destroyed.
621 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
623 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
625 WINPOS_CheckInternalPos( hwnd );
627 /* free resources associated with the window */
629 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
630 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
631 menu = (HMENU)wndPtr->wIDmenu;
632 sys_menu = wndPtr->hSysMenu;
633 WIN_ReleasePtr( wndPtr );
635 if (menu) DestroyMenu( menu );
636 if (sys_menu) DestroyMenu( sys_menu );
638 USER_Driver->pDestroyWindow( hwnd );
640 free_window_handle( hwnd );
644 /***********************************************************************
645 * WIN_DestroyThreadWindows
647 * Destroy all children of 'wnd' owned by the current thread.
649 void WIN_DestroyThreadWindows( HWND hwnd )
654 if (!(list = WIN_ListChildren( hwnd ))) return;
655 for (i = 0; list[i]; i++)
657 if (WIN_IsCurrentThread( list[i] ))
658 DestroyWindow( list[i] );
660 WIN_DestroyThreadWindows( list[i] );
662 HeapFree( GetProcessHeap(), 0, list );
666 /***********************************************************************
669 * Fix the coordinates - Helper for WIN_CreateWindowEx.
670 * returns default show mode in sw.
672 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
674 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
677 if (cs->dwExStyle & WS_EX_MDICHILD)
681 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
682 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
684 TRACE("MDI child id %04x\n", id);
687 if (cs->style & (WS_CHILD | WS_POPUP))
689 if (cs->dwExStyle & WS_EX_MDICHILD)
691 if (IS_DEFAULT(cs->x))
696 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
697 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
701 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
702 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
705 else /* overlapped window */
708 MONITORINFO mon_info;
711 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
713 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
714 mon_info.cbSize = sizeof(mon_info);
715 GetMonitorInfoW( monitor, &mon_info );
716 GetStartupInfoW( &info );
718 if (IS_DEFAULT(cs->x))
720 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
721 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
722 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
725 if (IS_DEFAULT(cs->cx))
727 if (info.dwFlags & STARTF_USESIZE)
729 cs->cx = info.dwXSize;
730 cs->cy = info.dwYSize;
734 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
735 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
738 /* neither x nor cx are default. Check the y values .
739 * In the trace we see Outlook and Outlook Express using
740 * cy set to CW_USEDEFAULT when opening the address book.
742 else if (IS_DEFAULT(cs->cy))
744 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
745 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
751 /***********************************************************************
754 static void dump_window_styles( DWORD style, DWORD exstyle )
757 if(style & WS_POPUP) TRACE(" WS_POPUP");
758 if(style & WS_CHILD) TRACE(" WS_CHILD");
759 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
760 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
761 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
762 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
763 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
764 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
765 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
768 if(style & WS_BORDER) TRACE(" WS_BORDER");
769 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
771 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
772 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
773 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
774 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
775 if (style & WS_CHILD)
777 if(style & WS_GROUP) TRACE(" WS_GROUP");
778 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
782 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
783 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
786 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
787 #define DUMPED_STYLES \
807 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
812 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
813 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
814 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
815 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
816 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
817 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
818 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
819 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
820 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
821 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
822 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
823 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
824 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
825 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
826 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
827 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
828 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
829 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
831 #define DUMPED_EX_STYLES \
832 (WS_EX_DLGMODALFRAME | \
834 WS_EX_NOPARENTNOTIFY | \
836 WS_EX_ACCEPTFILES | \
837 WS_EX_TRANSPARENT | \
842 WS_EX_CONTEXTHELP | \
845 WS_EX_LEFTSCROLLBAR | \
846 WS_EX_CONTROLPARENT | \
851 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
853 #undef DUMPED_EX_STYLES
857 /***********************************************************************
860 * Implementation of CreateWindowEx().
862 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
866 HWND hwnd, parent, owner, top_child = 0;
867 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
868 MDICREATESTRUCTA mdi_cs;
870 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
871 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
872 debugstr_w(className),
873 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
874 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
875 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
877 /* Fix the styles for MDI children */
878 if (cs->dwExStyle & WS_EX_MDICHILD)
882 wndPtr = WIN_GetPtr(cs->hwndParent);
883 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
885 flags = wndPtr->flags;
886 WIN_ReleasePtr(wndPtr);
889 if (!(flags & WIN_ISMDICLIENT))
891 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
895 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
896 * MDICREATESTRUCT members have the originally passed values.
898 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
899 * have the same layout.
901 mdi_cs.szClass = cs->lpszClass;
902 mdi_cs.szTitle = cs->lpszName;
903 mdi_cs.hOwner = cs->hInstance;
908 mdi_cs.style = cs->style;
909 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
911 cs->lpCreateParams = (LPVOID)&mdi_cs;
913 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
915 if (cs->style & WS_POPUP)
917 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
920 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
924 cs->style &= ~WS_POPUP;
925 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
926 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
929 top_child = GetWindow(cs->hwndParent, GW_CHILD);
933 /* Restore current maximized child */
934 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
936 TRACE("Restoring current maximized child %p\n", top_child);
937 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
938 ShowWindow( top_child, SW_SHOWNORMAL );
939 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
944 /* Find the parent window */
946 parent = cs->hwndParent;
949 if (cs->hwndParent == HWND_MESSAGE)
951 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
952 * message window (style: WS_POPUP|WS_DISABLED)
954 FIXME("Parent is HWND_MESSAGE\n");
955 parent = GetDesktopWindow();
957 else if (cs->hwndParent)
959 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
961 parent = GetDesktopWindow();
962 owner = cs->hwndParent;
967 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
969 WARN("No parent for child window\n" );
970 SetLastError(ERROR_TLW_WITH_WSCHILD);
971 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
973 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM) /* are we creating the desktop itself? */
974 parent = GetDesktopWindow();
977 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
979 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
980 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
981 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
982 cs->dwExStyle |= WS_EX_WINDOWEDGE;
984 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
986 /* Create the window structure */
988 if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
990 hwnd = wndPtr->hwndSelf;
992 /* Fill the window structure */
994 wndPtr->tid = GetCurrentThreadId();
995 wndPtr->hInstance = cs->hInstance;
997 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
998 wndPtr->dwExStyle = cs->dwExStyle;
1000 wndPtr->helpContext = 0;
1001 wndPtr->pVScroll = NULL;
1002 wndPtr->pHScroll = NULL;
1003 wndPtr->userdata = 0;
1005 wndPtr->hIconSmall = 0;
1006 wndPtr->hSysMenu = 0;
1007 wndPtr->flags |= (flags & WIN_ISWIN32);
1009 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1012 * Correct the window styles.
1014 * It affects only the style loaded into the WIN structure.
1017 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1019 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1020 if (!(wndPtr->dwStyle & WS_POPUP))
1021 wndPtr->dwStyle |= WS_CAPTION;
1025 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1026 * why does the user get to set it?
1029 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1030 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1031 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1033 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1035 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1036 wndPtr->flags |= WIN_NEED_SIZE;
1038 SERVER_START_REQ( set_window_info )
1041 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1042 req->style = wndPtr->dwStyle;
1043 req->ex_style = wndPtr->dwExStyle;
1044 req->instance = (void *)wndPtr->hInstance;
1045 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1046 req->extra_offset = -1;
1047 wine_server_call( req );
1051 /* Set the window menu */
1053 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1057 if (!MENU_SetMenu(hwnd, cs->hMenu))
1059 WIN_ReleasePtr( wndPtr );
1060 free_window_handle( hwnd );
1066 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1069 if (!cs->hInstance || HIWORD(cs->hInstance))
1070 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1072 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1074 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1078 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1079 WIN_ReleasePtr( wndPtr );
1081 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1083 WIN_DestroyWindow( hwnd );
1087 /* Notify the parent window only */
1089 send_parent_notify( hwnd, WM_CREATE );
1090 if (!IsWindow( hwnd )) return 0;
1092 if (cs->style & WS_VISIBLE)
1094 if (cs->style & WS_MAXIMIZE)
1096 else if (cs->style & WS_MINIMIZE)
1097 sw = SW_SHOWMINIMIZED;
1099 ShowWindow( hwnd, sw );
1100 if (cs->dwExStyle & WS_EX_MDICHILD)
1102 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1103 /* ShowWindow won't activate child windows */
1104 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1108 /* Call WH_SHELL hook */
1110 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1111 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1113 TRACE("created window %p\n", hwnd);
1118 /***********************************************************************
1119 * CreateWindow (USER.41)
1121 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1122 DWORD style, INT16 x, INT16 y, INT16 width,
1123 INT16 height, HWND16 parent, HMENU16 menu,
1124 HINSTANCE16 instance, LPVOID data )
1126 return CreateWindowEx16( 0, className, windowName, style,
1127 x, y, width, height, parent, menu, instance, data );
1131 /***********************************************************************
1132 * CreateWindowEx (USER.452)
1134 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1135 LPCSTR windowName, DWORD style, INT16 x,
1136 INT16 y, INT16 width, INT16 height,
1137 HWND16 parent, HMENU16 menu,
1138 HINSTANCE16 instance, LPVOID data )
1143 /* Fix the coordinates */
1145 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1146 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1147 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1148 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1150 /* Create the window */
1152 cs.lpCreateParams = data;
1153 cs.hInstance = HINSTANCE_32(instance);
1154 cs.hMenu = HMENU_32(menu);
1155 cs.hwndParent = WIN_Handle32( parent );
1157 cs.lpszName = windowName;
1158 cs.lpszClass = className;
1159 cs.dwExStyle = exStyle;
1161 if (!IS_INTRESOURCE(className))
1165 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1167 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1171 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1173 ERR( "bad atom %x\n", LOWORD(className));
1176 cs.lpszClass = buffer;
1177 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1182 /***********************************************************************
1183 * CreateWindowExA (USER32.@)
1185 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1186 LPCSTR windowName, DWORD style, INT x,
1187 INT y, INT width, INT height,
1188 HWND parent, HMENU menu,
1189 HINSTANCE instance, LPVOID data )
1193 cs.lpCreateParams = data;
1194 cs.hInstance = instance;
1196 cs.hwndParent = parent;
1202 cs.lpszName = windowName;
1203 cs.lpszClass = className;
1204 cs.dwExStyle = exStyle;
1206 if (!IS_INTRESOURCE(className))
1209 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1211 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1213 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1217 /***********************************************************************
1218 * CreateWindowExW (USER32.@)
1220 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1221 LPCWSTR windowName, DWORD style, INT x,
1222 INT y, INT width, INT height,
1223 HWND parent, HMENU menu,
1224 HINSTANCE instance, LPVOID data )
1228 cs.lpCreateParams = data;
1229 cs.hInstance = instance;
1231 cs.hwndParent = parent;
1237 cs.lpszName = windowName;
1238 cs.lpszClass = className;
1239 cs.dwExStyle = exStyle;
1241 /* Note: we rely on the fact that CREATESTRUCTA and */
1242 /* CREATESTRUCTW have the same layout. */
1243 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1247 /***********************************************************************
1248 * WIN_SendDestroyMsg
1250 static void WIN_SendDestroyMsg( HWND hwnd )
1254 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1256 if (hwnd == info.hwndCaret) DestroyCaret();
1257 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1261 * Send the WM_DESTROY to the window.
1263 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1266 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1267 * make sure that the window still exists when we come back.
1274 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1276 for (i = 0; pWndArray[i]; i++)
1278 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1280 HeapFree( GetProcessHeap(), 0, pWndArray );
1283 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1287 /***********************************************************************
1288 * DestroyWindow (USER32.@)
1290 BOOL WINAPI DestroyWindow( HWND hwnd )
1294 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1296 SetLastError( ERROR_ACCESS_DENIED );
1300 TRACE("(%p)\n", hwnd);
1304 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1306 if (MENU_IsMenuActive() == hwnd)
1309 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1313 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1314 send_parent_notify( hwnd, WM_DESTROY );
1316 else if (!GetWindow( hwnd, GW_OWNER ))
1318 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1319 /* FIXME: clean up palette - see "Internals" p.352 */
1322 if (!IsWindow(hwnd)) return TRUE;
1324 /* Hide the window */
1325 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1327 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1329 ShowWindow( hwnd, SW_HIDE );
1331 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1332 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1335 if (!IsWindow(hwnd)) return TRUE;
1337 /* Recursively destroy owned windows */
1344 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1347 for (i = 0; list[i]; i++)
1349 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1350 if (WIN_IsCurrentThread( list[i] ))
1352 DestroyWindow( list[i] );
1356 WIN_SetOwner( list[i], 0 );
1358 HeapFree( GetProcessHeap(), 0, list );
1360 if (!got_one) break;
1364 /* Send destroy messages */
1366 WIN_SendDestroyMsg( hwnd );
1367 if (!IsWindow( hwnd )) return TRUE;
1369 if (GetClipboardOwner() == hwnd)
1370 CLIPBOARD_ReleaseOwner();
1372 /* Destroy the window storage */
1374 WIN_DestroyWindow( hwnd );
1379 /***********************************************************************
1380 * CloseWindow (USER32.@)
1382 BOOL WINAPI CloseWindow( HWND hwnd )
1384 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1385 ShowWindow( hwnd, SW_MINIMIZE );
1390 /***********************************************************************
1391 * OpenIcon (USER32.@)
1393 BOOL WINAPI OpenIcon( HWND hwnd )
1395 if (!IsIconic( hwnd )) return FALSE;
1396 ShowWindow( hwnd, SW_SHOWNORMAL );
1401 /***********************************************************************
1402 * FindWindowExW (USER32.@)
1404 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1409 WCHAR *buffer = NULL;
1411 if (!parent) parent = GetDesktopWindow();
1414 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1415 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1418 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1422 child = WIN_GetFullHandle( child );
1423 while (list[i] && list[i] != child) i++;
1424 if (!list[i]) goto done;
1425 i++; /* start from next window */
1432 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1439 HeapFree( GetProcessHeap(), 0, list );
1440 HeapFree( GetProcessHeap(), 0, buffer );
1446 /***********************************************************************
1447 * FindWindowA (USER32.@)
1449 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1451 HWND ret = FindWindowExA( 0, 0, className, title );
1452 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1457 /***********************************************************************
1458 * FindWindowExA (USER32.@)
1460 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1462 LPWSTR titleW = NULL;
1467 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1468 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1469 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1472 if (!IS_INTRESOURCE(className))
1475 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1476 hwnd = FindWindowExW( parent, child, classW, titleW );
1480 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1483 HeapFree( GetProcessHeap(), 0, titleW );
1488 /***********************************************************************
1489 * FindWindowW (USER32.@)
1491 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1493 return FindWindowExW( 0, 0, className, title );
1497 /**********************************************************************
1498 * GetDesktopWindow (USER32.@)
1500 HWND WINAPI GetDesktopWindow(void)
1502 struct user_thread_info *thread_info = get_user_thread_info();
1504 if (thread_info->desktop) return thread_info->desktop;
1506 SERVER_START_REQ( get_desktop_window )
1509 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1513 if (!thread_info->desktop)
1515 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1517 PROCESS_INFORMATION pi;
1518 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1520 memset( &si, 0, sizeof(si) );
1522 GetSystemDirectoryW( cmdline, MAX_PATH );
1523 lstrcatW( cmdline, command_line );
1524 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1525 NULL, NULL, &si, &pi ))
1527 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1528 WaitForInputIdle( pi.hProcess, 10000 );
1529 CloseHandle( pi.hThread );
1530 CloseHandle( pi.hProcess );
1533 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1535 SERVER_START_REQ( get_desktop_window )
1538 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1543 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1544 ERR( "failed to create desktop window\n" );
1546 return thread_info->desktop;
1550 /*******************************************************************
1551 * EnableWindow (USER32.@)
1553 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1558 if (is_broadcast(hwnd))
1560 SetLastError( ERROR_INVALID_PARAMETER );
1564 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1565 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1569 TRACE("( %p, %d )\n", hwnd, enable);
1571 retvalue = !IsWindowEnabled( hwnd );
1573 if (enable && retvalue)
1575 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1576 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1578 else if (!enable && !retvalue)
1582 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1584 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1586 if (hwnd == GetFocus())
1587 SetFocus( 0 ); /* A disabled window can't have the focus */
1589 capture_wnd = GetCapture();
1590 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1591 ReleaseCapture(); /* A disabled window can't capture the mouse */
1593 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1599 /***********************************************************************
1600 * IsWindowEnabled (USER32.@)
1602 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1604 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1608 /***********************************************************************
1609 * IsWindowUnicode (USER32.@)
1611 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1614 BOOL retvalue = FALSE;
1616 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1618 if (wndPtr == WND_DESKTOP) return TRUE;
1620 if (wndPtr != WND_OTHER_PROCESS)
1622 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1623 WIN_ReleasePtr( wndPtr );
1627 SERVER_START_REQ( get_window_info )
1630 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1638 /**********************************************************************
1641 * Helper function for GetWindowLong().
1643 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1645 LONG_PTR retvalue = 0;
1648 if (offset == GWLP_HWNDPARENT)
1650 HWND parent = GetAncestor( hwnd, GA_PARENT );
1651 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1652 return (ULONG_PTR)parent;
1655 if (!(wndPtr = WIN_GetPtr( hwnd )))
1657 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1661 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1663 if (offset == GWLP_WNDPROC)
1665 SetLastError( ERROR_ACCESS_DENIED );
1668 SERVER_START_REQ( set_window_info )
1671 req->flags = 0; /* don't set anything, just retrieve */
1672 req->extra_offset = (offset >= 0) ? offset : -1;
1673 req->extra_size = (offset >= 0) ? size : 0;
1674 if (!wine_server_call_err( req ))
1678 case GWL_STYLE: retvalue = reply->old_style; break;
1679 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1680 case GWLP_ID: retvalue = reply->old_id; break;
1681 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1682 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1684 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1685 else SetLastError( ERROR_INVALID_INDEX );
1694 /* now we have a valid wndPtr */
1698 if (offset > (int)(wndPtr->cbWndExtra - size))
1700 WARN("Invalid offset %d\n", offset );
1701 WIN_ReleasePtr( wndPtr );
1702 SetLastError( ERROR_INVALID_INDEX );
1705 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1707 /* Special case for dialog window procedure */
1708 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1709 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1710 WIN_ReleasePtr( wndPtr );
1716 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1717 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1718 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1719 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1720 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1722 /* This looks like a hack only for the edit control (see tests). This makes these controls
1723 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1724 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1726 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1727 retvalue = (ULONG_PTR)wndPtr->winproc;
1729 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1732 WARN("Unknown offset %d\n", offset );
1733 SetLastError( ERROR_INVALID_INDEX );
1736 WIN_ReleasePtr(wndPtr);
1741 /**********************************************************************
1744 * Helper function for SetWindowLong().
1746 * 0 is the failure code. However, in the case of failure SetLastError
1747 * must be set to distinguish between a 0 return value and a failure.
1749 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1753 LONG_PTR retval = 0;
1756 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1758 if (is_broadcast(hwnd))
1760 SetLastError( ERROR_INVALID_PARAMETER );
1764 if (!(wndPtr = WIN_GetPtr( hwnd )))
1766 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1769 if (wndPtr == WND_DESKTOP)
1771 /* can't change anything on the desktop window */
1772 SetLastError( ERROR_ACCESS_DENIED );
1775 if (wndPtr == WND_OTHER_PROCESS)
1777 if (offset == GWLP_WNDPROC)
1779 SetLastError( ERROR_ACCESS_DENIED );
1782 if (offset > 32767 || offset < -32767)
1784 SetLastError( ERROR_INVALID_INDEX );
1787 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1790 /* first some special cases */
1796 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1797 style.styleNew = newval;
1798 WIN_ReleasePtr( wndPtr );
1799 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1800 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1801 newval = style.styleNew;
1803 case GWLP_HWNDPARENT:
1804 if (wndPtr->parent == GetDesktopWindow())
1806 WIN_ReleasePtr( wndPtr );
1807 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1811 WIN_ReleasePtr( wndPtr );
1812 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1817 UINT old_flags = wndPtr->flags;
1818 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
1819 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1820 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1821 if (proc) wndPtr->winproc = proc;
1822 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1823 else wndPtr->flags &= ~WIN_ISUNICODE;
1824 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1826 WIN_ReleasePtr( wndPtr );
1829 /* update is_unicode flag on the server side */
1833 case GWLP_HINSTANCE:
1837 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1838 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1840 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1841 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1842 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1843 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1844 WIN_ReleasePtr( wndPtr );
1849 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1851 WARN("Invalid offset %d\n", offset );
1852 WIN_ReleasePtr( wndPtr );
1853 SetLastError( ERROR_INVALID_INDEX );
1856 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1858 /* already set to the same value */
1859 WIN_ReleasePtr( wndPtr );
1865 SERVER_START_REQ( set_window_info )
1868 req->extra_offset = -1;
1872 req->flags = SET_WIN_STYLE;
1873 req->style = newval;
1876 req->flags = SET_WIN_EXSTYLE;
1877 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
1878 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
1879 req->ex_style = newval;
1882 req->flags = SET_WIN_ID;
1885 case GWLP_HINSTANCE:
1886 req->flags = SET_WIN_INSTANCE;
1887 req->instance = (void *)newval;
1890 req->flags = SET_WIN_UNICODE;
1891 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1894 req->flags = SET_WIN_USERDATA;
1895 req->user_data = newval;
1898 req->flags = SET_WIN_EXTRA;
1899 req->extra_offset = offset;
1900 req->extra_size = size;
1901 set_win_data( &req->extra_value, newval, size );
1903 if ((ok = !wine_server_call_err( req )))
1908 wndPtr->dwStyle = newval;
1909 retval = reply->old_style;
1912 wndPtr->dwExStyle = newval;
1913 retval = reply->old_ex_style;
1916 wndPtr->wIDmenu = newval;
1917 retval = reply->old_id;
1919 case GWLP_HINSTANCE:
1920 wndPtr->hInstance = (HINSTANCE)newval;
1921 retval = (ULONG_PTR)reply->old_instance;
1926 wndPtr->userdata = newval;
1927 retval = reply->old_user_data;
1930 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
1931 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
1937 WIN_ReleasePtr( wndPtr );
1941 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
1943 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
1944 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
1950 /**********************************************************************
1951 * GetWindowLong (USER.135)
1953 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1957 BOOL is_winproc = (offset == GWLP_WNDPROC);
1961 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
1963 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1966 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
1968 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1971 * Some programs try to access last element from 16 bit
1972 * code using illegal offset value. Hopefully this is
1973 * what those programs really expect.
1975 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
1977 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1978 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
1983 WARN("Invalid offset %d\n", offset );
1984 WIN_ReleasePtr( wndPtr );
1985 SetLastError( ERROR_INVALID_INDEX );
1989 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
1990 WIN_ReleasePtr( wndPtr );
1993 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
1994 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
1999 /**********************************************************************
2000 * GetWindowWord (USER32.@)
2002 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2007 case GWLP_HINSTANCE:
2008 case GWLP_HWNDPARENT:
2013 WARN("Invalid offset %d\n", offset );
2014 SetLastError( ERROR_INVALID_INDEX );
2019 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2023 /**********************************************************************
2024 * GetWindowLongA (USER32.@)
2026 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2028 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2032 /**********************************************************************
2033 * GetWindowLongW (USER32.@)
2035 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2037 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2041 /**********************************************************************
2042 * SetWindowLong (USER.136)
2044 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2047 BOOL is_winproc = (offset == GWLP_WNDPROC);
2049 if (offset == DWLP_DLGPROC)
2051 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2053 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2056 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2058 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2059 (wndPtr->flags & WIN_ISDIALOG));
2060 WIN_ReleasePtr( wndPtr );
2066 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2067 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2068 return (LONG)WINPROC_GetProc16( (WNDPROC)old_proc, FALSE );
2070 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2074 /**********************************************************************
2075 * SetWindowWord (USER32.@)
2077 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2082 case GWLP_HINSTANCE:
2083 case GWLP_HWNDPARENT:
2088 WARN("Invalid offset %d\n", offset );
2089 SetLastError( ERROR_INVALID_INDEX );
2094 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2098 /**********************************************************************
2099 * SetWindowLongA (USER32.@)
2101 * See SetWindowLongW.
2103 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2105 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2109 /**********************************************************************
2110 * SetWindowLongW (USER32.@) Set window attribute
2112 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2113 * value in a window's extra memory.
2115 * The _hwnd_ parameter specifies the window. is the handle to a
2116 * window that has extra memory. The _newval_ parameter contains the
2117 * new attribute or extra memory value. If positive, the _offset_
2118 * parameter is the byte-addressed location in the window's extra
2119 * memory to set. If negative, _offset_ specifies the window
2120 * attribute to set, and should be one of the following values:
2122 * GWL_EXSTYLE The window's extended window style
2124 * GWL_STYLE The window's window style.
2126 * GWLP_WNDPROC Pointer to the window's window procedure.
2128 * GWLP_HINSTANCE The window's pplication instance handle.
2130 * GWLP_ID The window's identifier.
2132 * GWLP_USERDATA The window's user-specified data.
2134 * If the window is a dialog box, the _offset_ parameter can be one of
2135 * the following values:
2137 * DWLP_DLGPROC The address of the window's dialog box procedure.
2139 * DWLP_MSGRESULT The return value of a message
2140 * that the dialog box procedure processed.
2142 * DWLP_USER Application specific information.
2146 * If successful, returns the previous value located at _offset_. Otherwise,
2151 * Extra memory for a window class is specified by a nonzero cbWndExtra
2152 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2153 * time of class creation.
2155 * Using GWL_WNDPROC to set a new window procedure effectively creates
2156 * a window subclass. Use CallWindowProc() in the new windows procedure
2157 * to pass messages to the superclass's window procedure.
2159 * The user data is reserved for use by the application which created
2162 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2163 * instead, call the EnableWindow() function to change the window's
2166 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2167 * SetParent() instead.
2170 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2171 * it sends WM_STYLECHANGING before changing the settings
2172 * and WM_STYLECHANGED afterwards.
2173 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2175 LONG WINAPI SetWindowLongW(
2176 HWND hwnd, /* [in] window to alter */
2177 INT offset, /* [in] offset, in bytes, of location to alter */
2178 LONG newval /* [in] new value of location */
2180 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2184 /*******************************************************************
2185 * GetWindowTextA (USER32.@)
2187 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2191 if (!lpString) return 0;
2193 if (WIN_IsCurrentProcess( hwnd ))
2194 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2196 /* when window belongs to other process, don't send a message */
2197 if (nMaxCount <= 0) return 0;
2198 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2199 get_server_window_text( hwnd, buffer, nMaxCount );
2200 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2201 lpString[nMaxCount-1] = 0;
2202 HeapFree( GetProcessHeap(), 0, buffer );
2203 return strlen(lpString);
2207 /*******************************************************************
2208 * InternalGetWindowText (USER32.@)
2210 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2214 if (nMaxCount <= 0) return 0;
2215 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2216 if (win == WND_DESKTOP) lpString[0] = 0;
2217 else if (win != WND_OTHER_PROCESS)
2219 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2220 else lpString[0] = 0;
2221 WIN_ReleasePtr( win );
2225 get_server_window_text( hwnd, lpString, nMaxCount );
2227 return strlenW(lpString);
2231 /*******************************************************************
2232 * GetWindowTextW (USER32.@)
2234 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2236 if (!lpString) return 0;
2238 if (WIN_IsCurrentProcess( hwnd ))
2239 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2241 /* when window belongs to other process, don't send a message */
2242 if (nMaxCount <= 0) return 0;
2243 get_server_window_text( hwnd, lpString, nMaxCount );
2244 return strlenW(lpString);
2248 /*******************************************************************
2249 * SetWindowTextA (USER32.@)
2250 * SetWindowText (USER32.@)
2252 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2254 if (is_broadcast(hwnd))
2256 SetLastError( ERROR_INVALID_PARAMETER );
2259 if (!WIN_IsCurrentProcess( hwnd ))
2260 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2261 debugstr_a(lpString), hwnd );
2262 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2266 /*******************************************************************
2267 * SetWindowTextW (USER32.@)
2269 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2271 if (is_broadcast(hwnd))
2273 SetLastError( ERROR_INVALID_PARAMETER );
2276 if (!WIN_IsCurrentProcess( hwnd ))
2277 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2278 debugstr_w(lpString), hwnd );
2279 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2283 /*******************************************************************
2284 * GetWindowTextLengthA (USER32.@)
2286 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2288 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2291 /*******************************************************************
2292 * GetWindowTextLengthW (USER32.@)
2294 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2296 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2300 /*******************************************************************
2301 * IsWindow (USER32.@)
2303 BOOL WINAPI IsWindow( HWND hwnd )
2308 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2309 if (ptr == WND_DESKTOP) return TRUE;
2311 if (ptr != WND_OTHER_PROCESS)
2313 WIN_ReleasePtr( ptr );
2317 /* check other processes */
2318 SERVER_START_REQ( get_window_info )
2321 ret = !wine_server_call_err( req );
2328 /***********************************************************************
2329 * GetWindowThreadProcessId (USER32.@)
2331 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2336 if (!(ptr = WIN_GetPtr( hwnd )))
2338 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2342 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2344 /* got a valid window */
2346 if (process) *process = GetCurrentProcessId();
2347 WIN_ReleasePtr( ptr );
2351 /* check other processes */
2352 SERVER_START_REQ( get_window_info )
2355 if (!wine_server_call_err( req ))
2357 tid = (DWORD)reply->tid;
2358 if (process) *process = (DWORD)reply->pid;
2366 /*****************************************************************
2367 * GetParent (USER32.@)
2369 HWND WINAPI GetParent( HWND hwnd )
2374 if (!(wndPtr = WIN_GetPtr( hwnd )))
2376 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2379 if (wndPtr == WND_DESKTOP) return 0;
2380 if (wndPtr == WND_OTHER_PROCESS)
2382 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2383 if (style & (WS_POPUP | WS_CHILD))
2385 SERVER_START_REQ( get_window_tree )
2388 if (!wine_server_call_err( req ))
2390 if (style & WS_POPUP) retvalue = reply->owner;
2391 else if (style & WS_CHILD) retvalue = reply->parent;
2399 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2400 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2401 WIN_ReleasePtr( wndPtr );
2407 /*****************************************************************
2408 * GetAncestor (USER32.@)
2410 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2413 HWND *list, ret = 0;
2418 if (!(win = WIN_GetPtr( hwnd )))
2420 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2423 if (win == WND_DESKTOP) return 0;
2424 if (win != WND_OTHER_PROCESS)
2427 WIN_ReleasePtr( win );
2429 else /* need to query the server */
2431 SERVER_START_REQ( get_window_tree )
2434 if (!wine_server_call_err( req )) ret = reply->parent;
2441 if (!(list = list_window_parents( hwnd ))) return 0;
2443 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2447 while (list[count]) count++;
2448 ret = list[count - 2]; /* get the one before the desktop */
2450 HeapFree( GetProcessHeap(), 0, list );
2454 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2457 HWND parent = GetParent( ret );
2467 /*****************************************************************
2468 * SetParent (USER32.@)
2470 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2473 HWND old_parent = 0;
2478 if (is_broadcast(hwnd) || is_broadcast(parent))
2480 SetLastError(ERROR_INVALID_PARAMETER);
2484 if (!parent) parent = GetDesktopWindow();
2485 else parent = WIN_GetFullHandle( parent );
2487 if (!IsWindow( parent ))
2489 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2493 /* Some applications try to set a child as a parent */
2494 if (IsChild(hwnd, parent))
2496 SetLastError( ERROR_INVALID_PARAMETER );
2500 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2501 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2503 /* Windows hides the window first, then shows it again
2504 * including the WM_SHOWWINDOW messages and all */
2505 was_visible = ShowWindow( hwnd, SW_HIDE );
2507 wndPtr = WIN_GetPtr( hwnd );
2508 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2510 SERVER_START_REQ( set_parent )
2513 req->parent = parent;
2514 if ((ret = !wine_server_call( req )))
2516 old_parent = reply->old_parent;
2517 wndPtr->parent = parent = reply->full_parent;
2522 WIN_ReleasePtr( wndPtr );
2525 USER_Driver->pSetParent( full_handle, parent, old_parent );
2527 /* SetParent additionally needs to make hwnd the topmost window
2528 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2529 WM_WINDOWPOSCHANGED notification messages.
2531 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2532 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2533 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2534 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2540 /*******************************************************************
2541 * IsChild (USER32.@)
2543 BOOL WINAPI IsChild( HWND parent, HWND child )
2545 HWND *list = list_window_parents( child );
2549 if (!list) return FALSE;
2550 parent = WIN_GetFullHandle( parent );
2551 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2552 ret = list[i] && list[i+1];
2553 HeapFree( GetProcessHeap(), 0, list );
2558 /***********************************************************************
2559 * IsWindowVisible (USER32.@)
2561 BOOL WINAPI IsWindowVisible( HWND hwnd )
2567 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2568 if (!(list = list_window_parents( hwnd ))) return TRUE;
2569 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2571 for (i = 0; list[i+1]; i++)
2572 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2573 retval = !list[i+1];
2575 HeapFree( GetProcessHeap(), 0, list );
2580 /***********************************************************************
2581 * WIN_IsWindowDrawable
2583 * hwnd is drawable when it is visible, all parents are not
2584 * minimized, and it is itself not minimized unless we are
2585 * trying to draw its default class icon.
2587 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2592 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2594 if (!(style & WS_VISIBLE)) return FALSE;
2595 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2597 if (!(list = list_window_parents( hwnd ))) return TRUE;
2598 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2600 for (i = 0; list[i+1]; i++)
2601 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2603 retval = !list[i+1];
2605 HeapFree( GetProcessHeap(), 0, list );
2610 /*******************************************************************
2611 * GetTopWindow (USER32.@)
2613 HWND WINAPI GetTopWindow( HWND hwnd )
2615 if (!hwnd) hwnd = GetDesktopWindow();
2616 return GetWindow( hwnd, GW_CHILD );
2620 /*******************************************************************
2621 * GetWindow (USER32.@)
2623 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2627 if (rel == GW_OWNER) /* this one may be available locally */
2629 WND *wndPtr = WIN_GetPtr( hwnd );
2632 SetLastError( ERROR_INVALID_HANDLE );
2635 if (wndPtr == WND_DESKTOP) return 0;
2636 if (wndPtr != WND_OTHER_PROCESS)
2638 retval = wndPtr->owner;
2639 WIN_ReleasePtr( wndPtr );
2642 /* else fall through to server call */
2645 SERVER_START_REQ( get_window_tree )
2648 if (!wine_server_call_err( req ))
2653 retval = reply->first_sibling;
2656 retval = reply->last_sibling;
2659 retval = reply->next_sibling;
2662 retval = reply->prev_sibling;
2665 retval = reply->owner;
2668 retval = reply->first_child;
2678 /*******************************************************************
2679 * ShowOwnedPopups (USER32.@)
2681 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2685 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2687 if (!win_array) return TRUE;
2689 while (win_array[count]) count++;
2690 while (--count >= 0)
2692 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2693 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2694 if (pWnd == WND_OTHER_PROCESS) continue;
2697 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2699 WIN_ReleasePtr( pWnd );
2700 /* In Windows, ShowOwnedPopups(TRUE) generates
2701 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2702 * regardless of the state of the owner
2704 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2710 if (pWnd->dwStyle & WS_VISIBLE)
2712 WIN_ReleasePtr( pWnd );
2713 /* In Windows, ShowOwnedPopups(FALSE) generates
2714 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2715 * regardless of the state of the owner
2717 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2721 WIN_ReleasePtr( pWnd );
2723 HeapFree( GetProcessHeap(), 0, win_array );
2728 /*******************************************************************
2729 * GetLastActivePopup (USER32.@)
2731 HWND WINAPI GetLastActivePopup( HWND hwnd )
2735 SERVER_START_REQ( get_window_info )
2738 if (!wine_server_call_err( req )) retval = reply->last_active;
2745 /*******************************************************************
2748 * Build an array of the children of a given window. The array must be
2749 * freed with HeapFree. Returns NULL when no windows are found.
2751 HWND *WIN_ListChildren( HWND hwnd )
2753 return list_window_children( hwnd, NULL, 0 );
2757 /*******************************************************************
2758 * EnumWindows (USER32.@)
2760 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2766 USER_CheckNotLock();
2768 /* We have to build a list of all windows first, to avoid */
2769 /* unpleasant side-effects, for instance if the callback */
2770 /* function changes the Z-order of the windows. */
2772 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2774 /* Now call the callback function for every window */
2776 for (i = 0; list[i]; i++)
2778 /* Make sure that the window still exists */
2779 if (!IsWindow( list[i] )) continue;
2780 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2782 HeapFree( GetProcessHeap(), 0, list );
2787 /**********************************************************************
2788 * EnumThreadWindows (USER32.@)
2790 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2795 USER_CheckNotLock();
2797 if (!(list = list_window_children( GetDesktopWindow(), NULL, id ))) return TRUE;
2799 /* Now call the callback function for every window */
2801 for (i = 0; list[i]; i++)
2802 if (!func( list[i], lParam )) break;
2803 HeapFree( GetProcessHeap(), 0, list );
2808 /**********************************************************************
2809 * WIN_EnumChildWindows
2811 * Helper function for EnumChildWindows().
2813 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2818 for ( ; *list; list++)
2820 /* Make sure that the window still exists */
2821 if (!IsWindow( *list )) continue;
2822 /* Build children list first */
2823 childList = WIN_ListChildren( *list );
2825 ret = func( *list, lParam );
2829 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2830 HeapFree( GetProcessHeap(), 0, childList );
2832 if (!ret) return FALSE;
2838 /**********************************************************************
2839 * EnumChildWindows (USER32.@)
2841 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2846 USER_CheckNotLock();
2848 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2849 ret = WIN_EnumChildWindows( list, func, lParam );
2850 HeapFree( GetProcessHeap(), 0, list );
2855 /*******************************************************************
2856 * AnyPopup (USER.52)
2858 BOOL16 WINAPI AnyPopup16(void)
2864 /*******************************************************************
2865 * AnyPopup (USER32.@)
2867 BOOL WINAPI AnyPopup(void)
2871 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2873 if (!list) return FALSE;
2874 for (i = 0; list[i]; i++)
2876 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2878 retvalue = (list[i] != 0);
2879 HeapFree( GetProcessHeap(), 0, list );
2884 /*******************************************************************
2885 * FlashWindow (USER32.@)
2887 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2891 TRACE("%p\n", hWnd);
2893 if (IsIconic( hWnd ))
2895 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2897 wndPtr = WIN_GetPtr(hWnd);
2898 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2899 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2901 wndPtr->flags |= WIN_NCACTIVATED;
2905 wndPtr->flags &= ~WIN_NCACTIVATED;
2907 WIN_ReleasePtr( wndPtr );
2914 wndPtr = WIN_GetPtr(hWnd);
2915 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2916 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2918 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2919 else wparam = (hWnd == GetForegroundWindow());
2921 WIN_ReleasePtr( wndPtr );
2922 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2927 /*******************************************************************
2928 * FlashWindowEx (USER32.@)
2930 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
2932 FIXME("%p\n", pfwi);
2936 /*******************************************************************
2937 * GetWindowContextHelpId (USER32.@)
2939 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2942 WND *wnd = WIN_GetPtr( hwnd );
2943 if (!wnd || wnd == WND_DESKTOP) return 0;
2944 if (wnd == WND_OTHER_PROCESS)
2946 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2949 retval = wnd->helpContext;
2950 WIN_ReleasePtr( wnd );
2955 /*******************************************************************
2956 * SetWindowContextHelpId (USER32.@)
2958 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2960 WND *wnd = WIN_GetPtr( hwnd );
2961 if (!wnd || wnd == WND_DESKTOP) return FALSE;
2962 if (wnd == WND_OTHER_PROCESS)
2964 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2967 wnd->helpContext = id;
2968 WIN_ReleasePtr( wnd );
2973 /*******************************************************************
2974 * DragDetect (USER32.@)
2976 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2980 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
2981 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
2983 rect.left = pt.x - wDragWidth;
2984 rect.right = pt.x + wDragWidth;
2986 rect.top = pt.y - wDragHeight;
2987 rect.bottom = pt.y + wDragHeight;
2993 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
2995 if( msg.message == WM_LBUTTONUP )
3000 if( msg.message == WM_MOUSEMOVE )
3003 tmp.x = (short)LOWORD(msg.lParam);
3004 tmp.y = (short)HIWORD(msg.lParam);
3005 if( !PtInRect( &rect, tmp ))
3017 /******************************************************************************
3018 * GetWindowModuleFileNameA (USER32.@)
3020 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3022 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3023 hwnd, lpszFileName, cchFileNameMax);
3027 /******************************************************************************
3028 * GetWindowModuleFileNameW (USER32.@)
3030 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3032 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3033 hwnd, lpszFileName, cchFileNameMax);
3037 /******************************************************************************
3038 * GetWindowInfo (USER32.@)
3040 * Note: tests show that Windows doesn't check cbSize of the structure.
3042 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3044 if (!pwi) return FALSE;
3045 if (!IsWindow(hwnd)) return FALSE;
3047 GetWindowRect(hwnd, &pwi->rcWindow);
3048 GetClientRect(hwnd, &pwi->rcClient);
3049 /* translate to screen coordinates */
3050 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3052 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3053 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3054 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3056 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3057 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3059 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3060 pwi->wCreatorVersion = 0x0400;
3065 /******************************************************************************
3066 * SwitchDesktop (USER32.@)
3068 * NOTES: Sets the current input or interactive desktop.
3070 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3072 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3076 /*****************************************************************************
3077 * SetLayeredWindowAttributes (USER32.@)
3079 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3080 BYTE bAlpha, DWORD dwFlags )
3082 FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3086 /*****************************************************************************
3087 * UpdateLayeredWindow (USER32.@)
3089 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3090 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3097 FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3098 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3103 /* 64bit versions */
3105 #ifdef GetWindowLongPtrW
3106 #undef GetWindowLongPtrW
3109 #ifdef GetWindowLongPtrA
3110 #undef GetWindowLongPtrA
3113 #ifdef SetWindowLongPtrW
3114 #undef SetWindowLongPtrW
3117 #ifdef SetWindowLongPtrA
3118 #undef SetWindowLongPtrA
3121 /*****************************************************************************
3122 * GetWindowLongPtrW (USER32.@)
3124 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3126 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3129 /*****************************************************************************
3130 * GetWindowLongPtrA (USER32.@)
3132 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3134 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3137 /*****************************************************************************
3138 * SetWindowLongPtrW (USER32.@)
3140 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3142 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3145 /*****************************************************************************
3146 * SetWindowLongPtrA (USER32.@)
3148 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3150 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );