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(), HEAP_ZERO_MEMORY,
137 sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
139 SERVER_START_REQ( destroy_window )
141 req->handle = handle;
142 wine_server_call( req );
145 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
149 if (!parent) /* if parent is 0 we don't have a desktop window yet */
151 struct user_thread_info *thread_info = get_user_thread_info();
153 if (!thread_info->desktop) thread_info->desktop = full_parent ? full_parent : handle;
154 else assert( full_parent == thread_info->desktop );
155 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
156 ERR( "failed to create desktop window\n" );
161 index = USER_HANDLE_TO_INDEX(handle);
162 assert( index < NB_USER_HANDLES );
163 user_handles[index] = win;
164 win->hwndSelf = handle;
165 win->parent = full_parent;
166 win->owner = full_owner;
168 win->winproc = get_class_winproc( class );
169 win->dwMagic = WND_MAGIC;
170 win->cbWndExtra = extra_bytes;
171 if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
176 /***********************************************************************
179 * Free a window handle.
181 static WND *free_window_handle( HWND hwnd )
184 WORD index = USER_HANDLE_TO_INDEX(hwnd);
186 if (index >= NB_USER_HANDLES) return NULL;
188 if ((ptr = user_handles[index]))
190 SERVER_START_REQ( destroy_window )
193 if (!wine_server_call_err( req ))
195 user_handles[index] = NULL;
204 HeapFree( GetProcessHeap(), 0, ptr );
209 /*******************************************************************
210 * list_window_children
212 * Build an array of the children of a given window. The array must be
213 * freed with HeapFree. Returns NULL when no windows are found.
215 static HWND *list_window_children( HWND hwnd, LPCWSTR class, DWORD tid )
224 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
226 SERVER_START_REQ( get_window_children )
230 if (!(req->atom = get_int_atom_value( class )) && class)
231 wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
232 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
233 if (!wine_server_call( req )) count = reply->count;
236 if (count && count < size)
241 HeapFree( GetProcessHeap(), 0, list );
243 size = count + 1; /* restart with a large enough buffer */
249 /*******************************************************************
250 * list_window_parents
252 * Build an array of all parents of a given window, starting with
253 * the immediate parent. The array must be freed with HeapFree.
255 static HWND *list_window_parents( HWND hwnd )
259 int pos = 0, size = 16, count = 0;
261 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
266 if (!(win = WIN_GetPtr( current ))) goto empty;
267 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
268 if (win == WND_DESKTOP)
270 if (!pos) goto empty;
274 list[pos] = current = win->parent;
275 WIN_ReleasePtr( win );
276 if (++pos == size - 1)
278 /* need to grow the list */
279 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
280 if (!new_list) goto empty;
286 /* at least one parent belongs to another process, have to query the server */
291 SERVER_START_REQ( get_window_parents )
294 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
295 if (!wine_server_call( req )) count = reply->count;
298 if (!count) goto empty;
304 HeapFree( GetProcessHeap(), 0, list );
306 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
310 HeapFree( GetProcessHeap(), 0, list );
315 /*******************************************************************
318 static void send_parent_notify( HWND hwnd, UINT msg )
320 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
321 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
323 HWND parent = GetParent(hwnd);
324 if (parent && parent != GetDesktopWindow())
325 SendMessageW( parent, WM_PARENTNOTIFY,
326 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
331 /*******************************************************************
332 * get_server_window_text
334 * Retrieve the window text from the server.
336 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
340 SERVER_START_REQ( get_window_text )
343 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
344 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
347 text[len / sizeof(WCHAR)] = 0;
351 /***********************************************************************
354 * Return a pointer to the WND structure if local to the process,
355 * or WND_OTHER_PROCESS if handle may be valid in other process.
356 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
358 WND *WIN_GetPtr( HWND hwnd )
361 WORD index = USER_HANDLE_TO_INDEX(hwnd);
363 if (index >= NB_USER_HANDLES) return NULL;
366 if ((ptr = user_handles[index]))
368 if (ptr->dwMagic == WND_MAGIC &&
369 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
373 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
375 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
378 else ptr = WND_OTHER_PROCESS;
384 /***********************************************************************
385 * WIN_IsCurrentProcess
387 * Check whether a given window belongs to the current process (and return the full handle).
389 HWND WIN_IsCurrentProcess( HWND hwnd )
394 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
396 WIN_ReleasePtr( ptr );
401 /***********************************************************************
402 * WIN_IsCurrentThread
404 * Check whether a given window belongs to the current thread (and return the full handle).
406 HWND WIN_IsCurrentThread( HWND hwnd )
411 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
412 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
413 WIN_ReleasePtr( ptr );
418 /***********************************************************************
421 * Convert a 16-bit window handle to a full 32-bit handle.
423 HWND WIN_Handle32( HWND16 hwnd16 )
426 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
428 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
429 /* do sign extension for -2 and -3 */
430 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
432 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
434 if (ptr == WND_DESKTOP) return GetDesktopWindow();
436 if (ptr != WND_OTHER_PROCESS)
438 hwnd = ptr->hwndSelf;
439 WIN_ReleasePtr( ptr );
441 else /* may belong to another process */
443 SERVER_START_REQ( get_window_info )
446 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
454 /***********************************************************************
457 * Change the owner of a window.
459 HWND WIN_SetOwner( HWND hwnd, HWND owner )
461 WND *win = WIN_GetPtr( hwnd );
464 if (!win || win == WND_DESKTOP) return 0;
465 if (win == WND_OTHER_PROCESS)
467 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
470 SERVER_START_REQ( set_window_owner )
474 if (!wine_server_call( req ))
476 win->owner = reply->full_owner;
477 ret = reply->prev_owner;
481 WIN_ReleasePtr( win );
486 /***********************************************************************
489 * Change the style of a window.
491 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
494 ULONG new_style, old_style = 0;
495 WND *win = WIN_GetPtr( hwnd );
497 if (!win || win == WND_DESKTOP) return 0;
498 if (win == WND_OTHER_PROCESS)
501 ERR( "cannot set style %x/%x on other process window %p\n",
502 set_bits, clear_bits, hwnd );
505 new_style = (win->dwStyle | set_bits) & ~clear_bits;
506 if (new_style == win->dwStyle)
508 WIN_ReleasePtr( win );
511 SERVER_START_REQ( set_window_info )
514 req->flags = SET_WIN_STYLE;
515 req->style = new_style;
516 req->extra_offset = -1;
517 if ((ok = !wine_server_call( req )))
519 old_style = reply->old_style;
520 win->dwStyle = new_style;
524 WIN_ReleasePtr( win );
527 USER_Driver->pSetWindowStyle( hwnd, old_style );
528 if ((old_style ^ new_style) & WS_VISIBLE) invalidate_dce( hwnd, NULL );
534 /***********************************************************************
537 * Get the window and client rectangles.
539 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
541 WND *win = WIN_GetPtr( hwnd );
544 if (!win) return FALSE;
545 if (win == WND_DESKTOP)
548 rect.left = rect.top = 0;
549 rect.right = GetSystemMetrics(SM_CXSCREEN);
550 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
551 if (rectWindow) *rectWindow = rect;
552 if (rectClient) *rectClient = rect;
554 else if (win == WND_OTHER_PROCESS)
556 SERVER_START_REQ( get_window_rectangles )
559 if ((ret = !wine_server_call( req )))
563 rectWindow->left = reply->window.left;
564 rectWindow->top = reply->window.top;
565 rectWindow->right = reply->window.right;
566 rectWindow->bottom = reply->window.bottom;
570 rectClient->left = reply->client.left;
571 rectClient->top = reply->client.top;
572 rectClient->right = reply->client.right;
573 rectClient->bottom = reply->client.bottom;
581 if (rectWindow) *rectWindow = win->rectWindow;
582 if (rectClient) *rectClient = win->rectClient;
583 WIN_ReleasePtr( win );
589 /***********************************************************************
592 * Destroy storage associated to a window. "Internals" p.358
594 LRESULT WIN_DestroyWindow( HWND hwnd )
598 HMENU menu = 0, sys_menu;
600 TRACE("%p\n", hwnd );
602 /* free child windows */
603 if ((list = WIN_ListChildren( hwnd )))
606 for (i = 0; list[i]; i++)
608 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
609 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
611 HeapFree( GetProcessHeap(), 0, list );
614 /* Unlink now so we won't bother with the children later on */
615 SERVER_START_REQ( set_parent )
619 wine_server_call( req );
624 * Send the WM_NCDESTROY to the window being destroyed.
626 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
628 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
630 WINPOS_CheckInternalPos( hwnd );
632 /* free resources associated with the window */
634 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
635 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
636 menu = (HMENU)wndPtr->wIDmenu;
637 sys_menu = wndPtr->hSysMenu;
638 free_dce( wndPtr->dce, hwnd );
640 WIN_ReleasePtr( wndPtr );
642 if (menu) DestroyMenu( menu );
643 if (sys_menu) DestroyMenu( sys_menu );
645 USER_Driver->pDestroyWindow( hwnd );
647 free_window_handle( hwnd );
651 /***********************************************************************
652 * WIN_DestroyThreadWindows
654 * Destroy all children of 'wnd' owned by the current thread.
656 void WIN_DestroyThreadWindows( HWND hwnd )
661 if (!(list = WIN_ListChildren( hwnd ))) return;
662 for (i = 0; list[i]; i++)
664 if (WIN_IsCurrentThread( list[i] ))
665 DestroyWindow( list[i] );
667 WIN_DestroyThreadWindows( list[i] );
669 HeapFree( GetProcessHeap(), 0, list );
673 /***********************************************************************
676 * Fix the coordinates - Helper for WIN_CreateWindowEx.
677 * returns default show mode in sw.
679 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
681 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
684 if (cs->dwExStyle & WS_EX_MDICHILD)
688 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
689 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
691 TRACE("MDI child id %04x\n", id);
694 if (cs->style & (WS_CHILD | WS_POPUP))
696 if (cs->dwExStyle & WS_EX_MDICHILD)
698 if (IS_DEFAULT(cs->x))
703 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
704 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
708 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
709 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
712 else /* overlapped window */
715 MONITORINFO mon_info;
718 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
720 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
721 mon_info.cbSize = sizeof(mon_info);
722 GetMonitorInfoW( monitor, &mon_info );
723 GetStartupInfoW( &info );
725 if (IS_DEFAULT(cs->x))
727 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
728 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
729 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
732 if (IS_DEFAULT(cs->cx))
734 if (info.dwFlags & STARTF_USESIZE)
736 cs->cx = info.dwXSize;
737 cs->cy = info.dwYSize;
741 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
742 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
745 /* neither x nor cx are default. Check the y values .
746 * In the trace we see Outlook and Outlook Express using
747 * cy set to CW_USEDEFAULT when opening the address book.
749 else if (IS_DEFAULT(cs->cy))
751 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
752 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
758 /***********************************************************************
761 static void dump_window_styles( DWORD style, DWORD exstyle )
764 if(style & WS_POPUP) TRACE(" WS_POPUP");
765 if(style & WS_CHILD) TRACE(" WS_CHILD");
766 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
767 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
768 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
769 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
770 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
771 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
772 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
775 if(style & WS_BORDER) TRACE(" WS_BORDER");
776 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
778 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
779 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
780 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
781 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
782 if (style & WS_CHILD)
784 if(style & WS_GROUP) TRACE(" WS_GROUP");
785 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
789 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
790 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
793 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
794 #define DUMPED_STYLES \
814 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
819 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
820 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
821 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
822 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
823 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
824 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
825 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
826 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
827 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
828 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
829 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
830 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
831 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
832 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
833 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
834 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
835 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
836 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
838 #define DUMPED_EX_STYLES \
839 (WS_EX_DLGMODALFRAME | \
841 WS_EX_NOPARENTNOTIFY | \
843 WS_EX_ACCEPTFILES | \
844 WS_EX_TRANSPARENT | \
849 WS_EX_CONTEXTHELP | \
852 WS_EX_LEFTSCROLLBAR | \
853 WS_EX_CONTROLPARENT | \
858 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
860 #undef DUMPED_EX_STYLES
864 /***********************************************************************
867 * Implementation of CreateWindowEx().
869 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
871 INT cx, cy, sw = SW_SHOW;
875 HWND hwnd, parent, owner, top_child = 0;
876 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
877 MDICREATESTRUCTA mdi_cs;
881 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
882 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
883 debugstr_w(className),
884 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
885 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
886 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
888 /* Fix the styles for MDI children */
889 if (cs->dwExStyle & WS_EX_MDICHILD)
893 wndPtr = WIN_GetPtr(cs->hwndParent);
894 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
896 flags = wndPtr->flags;
897 WIN_ReleasePtr(wndPtr);
900 if (!(flags & WIN_ISMDICLIENT))
902 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
906 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
907 * MDICREATESTRUCT members have the originally passed values.
909 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
910 * have the same layout.
912 mdi_cs.szClass = cs->lpszClass;
913 mdi_cs.szTitle = cs->lpszName;
914 mdi_cs.hOwner = cs->hInstance;
919 mdi_cs.style = cs->style;
920 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
922 cs->lpCreateParams = (LPVOID)&mdi_cs;
924 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
926 if (cs->style & WS_POPUP)
928 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
931 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
935 cs->style &= ~WS_POPUP;
936 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
937 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
940 top_child = GetWindow(cs->hwndParent, GW_CHILD);
944 /* Restore current maximized child */
945 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
947 TRACE("Restoring current maximized child %p\n", top_child);
948 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
949 ShowWindow( top_child, SW_SHOWNORMAL );
950 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
955 /* Find the parent window */
957 parent = cs->hwndParent;
960 if (cs->hwndParent == HWND_MESSAGE)
962 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
963 * message window (style: WS_POPUP|WS_DISABLED)
965 FIXME("Parent is HWND_MESSAGE\n");
966 parent = GetDesktopWindow();
968 else if (cs->hwndParent)
970 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
972 parent = GetDesktopWindow();
973 owner = cs->hwndParent;
978 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
980 WARN("No parent for child window\n" );
981 SetLastError(ERROR_TLW_WITH_WSCHILD);
982 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
984 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM) /* are we creating the desktop itself? */
985 parent = GetDesktopWindow();
988 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
990 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
991 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
992 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
993 cs->dwExStyle |= WS_EX_WINDOWEDGE;
995 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
997 /* Create the window structure */
999 if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
1001 hwnd = wndPtr->hwndSelf;
1003 /* Fill the window structure */
1005 wndPtr->tid = GetCurrentThreadId();
1006 wndPtr->hInstance = cs->hInstance;
1007 wndPtr->text = NULL;
1008 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1009 wndPtr->dwExStyle = cs->dwExStyle;
1010 wndPtr->wIDmenu = 0;
1011 wndPtr->helpContext = 0;
1012 wndPtr->pVScroll = NULL;
1013 wndPtr->pHScroll = NULL;
1014 wndPtr->userdata = 0;
1016 wndPtr->hIconSmall = 0;
1017 wndPtr->hSysMenu = 0;
1018 wndPtr->flags |= (flags & WIN_ISWIN32);
1020 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1023 * Correct the window styles.
1025 * It affects only the style loaded into the WIN structure.
1028 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1030 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1031 if (!(wndPtr->dwStyle & WS_POPUP))
1032 wndPtr->dwStyle |= WS_CAPTION;
1036 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1037 * why does the user get to set it?
1040 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1041 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1042 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1044 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1046 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1047 wndPtr->flags |= WIN_NEED_SIZE;
1049 SERVER_START_REQ( set_window_info )
1052 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1053 req->style = wndPtr->dwStyle;
1054 req->ex_style = wndPtr->dwExStyle;
1055 req->instance = (void *)wndPtr->hInstance;
1056 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1057 req->extra_offset = -1;
1058 wine_server_call( req );
1062 /* Set the window menu */
1064 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1068 if (!MENU_SetMenu(hwnd, cs->hMenu))
1070 WIN_ReleasePtr( wndPtr );
1071 free_window_handle( hwnd );
1077 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1080 if (!cs->hInstance || HIWORD(cs->hInstance))
1081 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1083 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1085 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1089 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1091 /* call the WH_CBT hook */
1093 /* the window style passed to the hook must be the real window style,
1094 * rather than just the window style that the caller to CreateWindowEx
1095 * passed in, so we have to copy the original CREATESTRUCT and get the
1096 * the real style. */
1098 cbcs.style = wndPtr->dwStyle;
1100 cbtc.hwndInsertAfter = HWND_TOP;
1101 WIN_ReleasePtr( wndPtr );
1102 if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode )) goto failed;
1104 /* send the WM_GETMINMAXINFO message and fix the size if needed */
1108 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
1110 POINT maxSize, maxPos, minTrack, maxTrack;
1111 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
1112 if (maxTrack.x < cx) cx = maxTrack.x;
1113 if (maxTrack.y < cy) cy = maxTrack.y;
1118 SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy );
1119 if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
1121 /* send WM_NCCREATE */
1123 TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cx, cy );
1125 result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1127 result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1130 WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1134 /* send WM_NCCALCSIZE */
1136 if ((wndPtr = WIN_GetPtr(hwnd)))
1138 /* yes, even if the CBT hook was called with HWND_TOP */
1139 HWND insert_after = (wndPtr->dwStyle & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
1140 RECT window_rect = wndPtr->rectWindow;
1141 RECT client_rect = window_rect;
1142 WIN_ReleasePtr( wndPtr );
1143 SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
1144 set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &window_rect, &client_rect, NULL );
1148 /* send WM_CREATE */
1151 result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1153 result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
1154 if (result == -1) goto failed;
1156 NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1158 /* send the size messages */
1160 if (!(wndPtr = WIN_GetPtr(hwnd))) return 0;
1161 if (!(wndPtr->flags & WIN_NEED_SIZE))
1163 rect = wndPtr->rectClient;
1164 WIN_ReleasePtr( wndPtr );
1165 SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1166 MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1167 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1169 else WIN_ReleasePtr( wndPtr );
1171 /* call the driver */
1173 if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1175 /* Notify the parent window only */
1177 send_parent_notify( hwnd, WM_CREATE );
1178 if (!IsWindow( hwnd )) return 0;
1180 if (cs->style & WS_VISIBLE)
1182 if (cs->style & WS_MAXIMIZE)
1184 else if (cs->style & WS_MINIMIZE)
1185 sw = SW_SHOWMINIMIZED;
1187 ShowWindow( hwnd, sw );
1188 if (cs->dwExStyle & WS_EX_MDICHILD)
1190 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1191 /* ShowWindow won't activate child windows */
1192 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1196 /* Call WH_SHELL hook */
1198 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1199 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1201 TRACE("created window %p\n", hwnd);
1205 WIN_DestroyWindow( hwnd );
1210 /***********************************************************************
1211 * CreateWindow (USER.41)
1213 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1214 DWORD style, INT16 x, INT16 y, INT16 width,
1215 INT16 height, HWND16 parent, HMENU16 menu,
1216 HINSTANCE16 instance, LPVOID data )
1218 return CreateWindowEx16( 0, className, windowName, style,
1219 x, y, width, height, parent, menu, instance, data );
1223 /***********************************************************************
1224 * CreateWindowEx (USER.452)
1226 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1227 LPCSTR windowName, DWORD style, INT16 x,
1228 INT16 y, INT16 width, INT16 height,
1229 HWND16 parent, HMENU16 menu,
1230 HINSTANCE16 instance, LPVOID data )
1235 /* Fix the coordinates */
1237 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1238 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1239 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1240 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1242 /* Create the window */
1244 cs.lpCreateParams = data;
1245 cs.hInstance = HINSTANCE_32(instance);
1246 cs.hMenu = HMENU_32(menu);
1247 cs.hwndParent = WIN_Handle32( parent );
1249 cs.lpszName = windowName;
1250 cs.lpszClass = className;
1251 cs.dwExStyle = exStyle;
1253 if (!IS_INTRESOURCE(className))
1257 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1259 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1263 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1265 ERR( "bad atom %x\n", LOWORD(className));
1268 cs.lpszClass = buffer;
1269 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1274 /***********************************************************************
1275 * CreateWindowExA (USER32.@)
1277 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1278 LPCSTR windowName, DWORD style, INT x,
1279 INT y, INT width, INT height,
1280 HWND parent, HMENU menu,
1281 HINSTANCE instance, LPVOID data )
1285 cs.lpCreateParams = data;
1286 cs.hInstance = instance;
1288 cs.hwndParent = parent;
1294 cs.lpszName = windowName;
1295 cs.lpszClass = className;
1296 cs.dwExStyle = exStyle;
1298 if (!IS_INTRESOURCE(className))
1301 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1303 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1305 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1309 /***********************************************************************
1310 * CreateWindowExW (USER32.@)
1312 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1313 LPCWSTR windowName, DWORD style, INT x,
1314 INT y, INT width, INT height,
1315 HWND parent, HMENU menu,
1316 HINSTANCE instance, LPVOID data )
1320 cs.lpCreateParams = data;
1321 cs.hInstance = instance;
1323 cs.hwndParent = parent;
1329 cs.lpszName = windowName;
1330 cs.lpszClass = className;
1331 cs.dwExStyle = exStyle;
1333 /* Note: we rely on the fact that CREATESTRUCTA and */
1334 /* CREATESTRUCTW have the same layout. */
1335 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1339 /***********************************************************************
1340 * WIN_SendDestroyMsg
1342 static void WIN_SendDestroyMsg( HWND hwnd )
1346 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1348 if (hwnd == info.hwndCaret) DestroyCaret();
1349 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1353 * Send the WM_DESTROY to the window.
1355 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1358 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1359 * make sure that the window still exists when we come back.
1366 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1368 for (i = 0; pWndArray[i]; i++)
1370 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1372 HeapFree( GetProcessHeap(), 0, pWndArray );
1375 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1379 /***********************************************************************
1380 * DestroyWindow (USER32.@)
1382 BOOL WINAPI DestroyWindow( HWND hwnd )
1386 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1388 SetLastError( ERROR_ACCESS_DENIED );
1392 TRACE("(%p)\n", hwnd);
1396 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1398 if (MENU_IsMenuActive() == hwnd)
1401 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1405 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1406 send_parent_notify( hwnd, WM_DESTROY );
1408 else if (!GetWindow( hwnd, GW_OWNER ))
1410 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1411 /* FIXME: clean up palette - see "Internals" p.352 */
1414 if (!IsWindow(hwnd)) return TRUE;
1416 /* Hide the window */
1417 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1419 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1421 ShowWindow( hwnd, SW_HIDE );
1423 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1424 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1427 if (!IsWindow(hwnd)) return TRUE;
1429 /* Recursively destroy owned windows */
1436 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1439 for (i = 0; list[i]; i++)
1441 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1442 if (WIN_IsCurrentThread( list[i] ))
1444 DestroyWindow( list[i] );
1448 WIN_SetOwner( list[i], 0 );
1450 HeapFree( GetProcessHeap(), 0, list );
1452 if (!got_one) break;
1456 /* Send destroy messages */
1458 WIN_SendDestroyMsg( hwnd );
1459 if (!IsWindow( hwnd )) return TRUE;
1461 if (GetClipboardOwner() == hwnd)
1462 CLIPBOARD_ReleaseOwner();
1464 /* Destroy the window storage */
1466 WIN_DestroyWindow( hwnd );
1471 /***********************************************************************
1472 * CloseWindow (USER32.@)
1474 BOOL WINAPI CloseWindow( HWND hwnd )
1476 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1477 ShowWindow( hwnd, SW_MINIMIZE );
1482 /***********************************************************************
1483 * OpenIcon (USER32.@)
1485 BOOL WINAPI OpenIcon( HWND hwnd )
1487 if (!IsIconic( hwnd )) return FALSE;
1488 ShowWindow( hwnd, SW_SHOWNORMAL );
1493 /***********************************************************************
1494 * FindWindowExW (USER32.@)
1496 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1501 WCHAR *buffer = NULL;
1503 if (!parent) parent = GetDesktopWindow();
1506 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1507 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1510 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1514 child = WIN_GetFullHandle( child );
1515 while (list[i] && list[i] != child) i++;
1516 if (!list[i]) goto done;
1517 i++; /* start from next window */
1524 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1531 HeapFree( GetProcessHeap(), 0, list );
1532 HeapFree( GetProcessHeap(), 0, buffer );
1538 /***********************************************************************
1539 * FindWindowA (USER32.@)
1541 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1543 HWND ret = FindWindowExA( 0, 0, className, title );
1544 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1549 /***********************************************************************
1550 * FindWindowExA (USER32.@)
1552 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1554 LPWSTR titleW = NULL;
1559 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1560 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1561 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1564 if (!IS_INTRESOURCE(className))
1567 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1568 hwnd = FindWindowExW( parent, child, classW, titleW );
1572 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1575 HeapFree( GetProcessHeap(), 0, titleW );
1580 /***********************************************************************
1581 * FindWindowW (USER32.@)
1583 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1585 return FindWindowExW( 0, 0, className, title );
1589 /**********************************************************************
1590 * GetDesktopWindow (USER32.@)
1592 HWND WINAPI GetDesktopWindow(void)
1594 struct user_thread_info *thread_info = get_user_thread_info();
1596 if (thread_info->desktop) return thread_info->desktop;
1598 SERVER_START_REQ( get_desktop_window )
1601 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1605 if (!thread_info->desktop)
1607 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1609 PROCESS_INFORMATION pi;
1610 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1612 memset( &si, 0, sizeof(si) );
1614 si.dwFlags = STARTF_USESTDHANDLES;
1617 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1619 GetSystemDirectoryW( cmdline, MAX_PATH );
1620 lstrcatW( cmdline, command_line );
1621 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1622 NULL, NULL, &si, &pi ))
1624 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1625 WaitForInputIdle( pi.hProcess, 10000 );
1626 CloseHandle( pi.hThread );
1627 CloseHandle( pi.hProcess );
1630 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1632 SERVER_START_REQ( get_desktop_window )
1635 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1640 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1641 ERR( "failed to create desktop window\n" );
1643 return thread_info->desktop;
1647 /*******************************************************************
1648 * EnableWindow (USER32.@)
1650 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1655 if (is_broadcast(hwnd))
1657 SetLastError( ERROR_INVALID_PARAMETER );
1661 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1662 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1666 TRACE("( %p, %d )\n", hwnd, enable);
1668 retvalue = !IsWindowEnabled( hwnd );
1670 if (enable && retvalue)
1672 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1673 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1675 else if (!enable && !retvalue)
1679 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1681 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1683 if (hwnd == GetFocus())
1684 SetFocus( 0 ); /* A disabled window can't have the focus */
1686 capture_wnd = GetCapture();
1687 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1688 ReleaseCapture(); /* A disabled window can't capture the mouse */
1690 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1696 /***********************************************************************
1697 * IsWindowEnabled (USER32.@)
1699 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1701 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1705 /***********************************************************************
1706 * IsWindowUnicode (USER32.@)
1708 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1711 BOOL retvalue = FALSE;
1713 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1715 if (wndPtr == WND_DESKTOP) return TRUE;
1717 if (wndPtr != WND_OTHER_PROCESS)
1719 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1720 WIN_ReleasePtr( wndPtr );
1724 SERVER_START_REQ( get_window_info )
1727 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1735 /**********************************************************************
1738 * Helper function for GetWindowLong().
1740 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1742 LONG_PTR retvalue = 0;
1745 if (offset == GWLP_HWNDPARENT)
1747 HWND parent = GetAncestor( hwnd, GA_PARENT );
1748 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1749 return (ULONG_PTR)parent;
1752 if (!(wndPtr = WIN_GetPtr( hwnd )))
1754 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1758 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1760 if (offset == GWLP_WNDPROC)
1762 SetLastError( ERROR_ACCESS_DENIED );
1765 SERVER_START_REQ( set_window_info )
1768 req->flags = 0; /* don't set anything, just retrieve */
1769 req->extra_offset = (offset >= 0) ? offset : -1;
1770 req->extra_size = (offset >= 0) ? size : 0;
1771 if (!wine_server_call_err( req ))
1775 case GWL_STYLE: retvalue = reply->old_style; break;
1776 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1777 case GWLP_ID: retvalue = reply->old_id; break;
1778 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1779 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1781 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1782 else SetLastError( ERROR_INVALID_INDEX );
1791 /* now we have a valid wndPtr */
1795 if (offset > (int)(wndPtr->cbWndExtra - size))
1797 WARN("Invalid offset %d\n", offset );
1798 WIN_ReleasePtr( wndPtr );
1799 SetLastError( ERROR_INVALID_INDEX );
1802 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1804 /* Special case for dialog window procedure */
1805 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1806 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1807 WIN_ReleasePtr( wndPtr );
1813 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1814 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1815 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1816 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
1817 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1819 /* This looks like a hack only for the edit control (see tests). This makes these controls
1820 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1821 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1823 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1824 retvalue = (ULONG_PTR)wndPtr->winproc;
1826 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1829 WARN("Unknown offset %d\n", offset );
1830 SetLastError( ERROR_INVALID_INDEX );
1833 WIN_ReleasePtr(wndPtr);
1838 /**********************************************************************
1841 * Helper function for SetWindowLong().
1843 * 0 is the failure code. However, in the case of failure SetLastError
1844 * must be set to distinguish between a 0 return value and a failure.
1846 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1850 LONG_PTR retval = 0;
1853 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1855 if (is_broadcast(hwnd))
1857 SetLastError( ERROR_INVALID_PARAMETER );
1861 if (!(wndPtr = WIN_GetPtr( hwnd )))
1863 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1866 if (wndPtr == WND_DESKTOP)
1868 /* can't change anything on the desktop window */
1869 SetLastError( ERROR_ACCESS_DENIED );
1872 if (wndPtr == WND_OTHER_PROCESS)
1874 if (offset == GWLP_WNDPROC)
1876 SetLastError( ERROR_ACCESS_DENIED );
1879 if (offset > 32767 || offset < -32767)
1881 SetLastError( ERROR_INVALID_INDEX );
1884 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1887 /* first some special cases */
1893 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1894 style.styleNew = newval;
1895 WIN_ReleasePtr( wndPtr );
1896 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1897 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1898 newval = style.styleNew;
1900 case GWLP_HWNDPARENT:
1901 if (wndPtr->parent == GetDesktopWindow())
1903 WIN_ReleasePtr( wndPtr );
1904 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1908 WIN_ReleasePtr( wndPtr );
1909 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1914 UINT old_flags = wndPtr->flags;
1915 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
1916 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1917 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1918 if (proc) wndPtr->winproc = proc;
1919 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1920 else wndPtr->flags &= ~WIN_ISUNICODE;
1921 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1923 WIN_ReleasePtr( wndPtr );
1926 /* update is_unicode flag on the server side */
1930 case GWLP_HINSTANCE:
1934 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1935 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1937 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1938 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1939 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1940 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1941 WIN_ReleasePtr( wndPtr );
1946 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1948 WARN("Invalid offset %d\n", offset );
1949 WIN_ReleasePtr( wndPtr );
1950 SetLastError( ERROR_INVALID_INDEX );
1953 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1955 /* already set to the same value */
1956 WIN_ReleasePtr( wndPtr );
1962 SERVER_START_REQ( set_window_info )
1965 req->extra_offset = -1;
1969 req->flags = SET_WIN_STYLE;
1970 req->style = newval;
1973 req->flags = SET_WIN_EXSTYLE;
1974 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
1975 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
1976 req->ex_style = newval;
1979 req->flags = SET_WIN_ID;
1982 case GWLP_HINSTANCE:
1983 req->flags = SET_WIN_INSTANCE;
1984 req->instance = (void *)newval;
1987 req->flags = SET_WIN_UNICODE;
1988 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1991 req->flags = SET_WIN_USERDATA;
1992 req->user_data = newval;
1995 req->flags = SET_WIN_EXTRA;
1996 req->extra_offset = offset;
1997 req->extra_size = size;
1998 set_win_data( &req->extra_value, newval, size );
2000 if ((ok = !wine_server_call_err( req )))
2005 wndPtr->dwStyle = newval;
2006 retval = reply->old_style;
2009 wndPtr->dwExStyle = newval;
2010 retval = reply->old_ex_style;
2013 wndPtr->wIDmenu = newval;
2014 retval = reply->old_id;
2016 case GWLP_HINSTANCE:
2017 wndPtr->hInstance = (HINSTANCE)newval;
2018 retval = (ULONG_PTR)reply->old_instance;
2023 wndPtr->userdata = newval;
2024 retval = reply->old_user_data;
2027 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2028 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2034 WIN_ReleasePtr( wndPtr );
2038 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2040 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2041 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2047 /**********************************************************************
2048 * GetWindowLong (USER.135)
2050 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2054 BOOL is_winproc = (offset == GWLP_WNDPROC);
2058 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2060 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2063 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2065 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2068 * Some programs try to access last element from 16 bit
2069 * code using illegal offset value. Hopefully this is
2070 * what those programs really expect.
2072 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2074 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2075 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2080 WARN("Invalid offset %d\n", offset );
2081 WIN_ReleasePtr( wndPtr );
2082 SetLastError( ERROR_INVALID_INDEX );
2086 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2087 WIN_ReleasePtr( wndPtr );
2090 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2091 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2096 /**********************************************************************
2097 * GetWindowWord (USER32.@)
2099 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2104 case GWLP_HINSTANCE:
2105 case GWLP_HWNDPARENT:
2110 WARN("Invalid offset %d\n", offset );
2111 SetLastError( ERROR_INVALID_INDEX );
2116 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2120 /**********************************************************************
2121 * GetWindowLongA (USER32.@)
2123 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2125 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2129 /**********************************************************************
2130 * GetWindowLongW (USER32.@)
2132 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2134 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2138 /**********************************************************************
2139 * SetWindowLong (USER.136)
2141 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2144 BOOL is_winproc = (offset == GWLP_WNDPROC);
2146 if (offset == DWLP_DLGPROC)
2148 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2150 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2153 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2155 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2156 (wndPtr->flags & WIN_ISDIALOG));
2157 WIN_ReleasePtr( wndPtr );
2163 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2164 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2165 return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2167 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2171 /**********************************************************************
2172 * SetWindowWord (USER32.@)
2174 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2179 case GWLP_HINSTANCE:
2180 case GWLP_HWNDPARENT:
2185 WARN("Invalid offset %d\n", offset );
2186 SetLastError( ERROR_INVALID_INDEX );
2191 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2195 /**********************************************************************
2196 * SetWindowLongA (USER32.@)
2198 * See SetWindowLongW.
2200 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2202 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2206 /**********************************************************************
2207 * SetWindowLongW (USER32.@) Set window attribute
2209 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2210 * value in a window's extra memory.
2212 * The _hwnd_ parameter specifies the window. is the handle to a
2213 * window that has extra memory. The _newval_ parameter contains the
2214 * new attribute or extra memory value. If positive, the _offset_
2215 * parameter is the byte-addressed location in the window's extra
2216 * memory to set. If negative, _offset_ specifies the window
2217 * attribute to set, and should be one of the following values:
2219 * GWL_EXSTYLE The window's extended window style
2221 * GWL_STYLE The window's window style.
2223 * GWLP_WNDPROC Pointer to the window's window procedure.
2225 * GWLP_HINSTANCE The window's pplication instance handle.
2227 * GWLP_ID The window's identifier.
2229 * GWLP_USERDATA The window's user-specified data.
2231 * If the window is a dialog box, the _offset_ parameter can be one of
2232 * the following values:
2234 * DWLP_DLGPROC The address of the window's dialog box procedure.
2236 * DWLP_MSGRESULT The return value of a message
2237 * that the dialog box procedure processed.
2239 * DWLP_USER Application specific information.
2243 * If successful, returns the previous value located at _offset_. Otherwise,
2248 * Extra memory for a window class is specified by a nonzero cbWndExtra
2249 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2250 * time of class creation.
2252 * Using GWL_WNDPROC to set a new window procedure effectively creates
2253 * a window subclass. Use CallWindowProc() in the new windows procedure
2254 * to pass messages to the superclass's window procedure.
2256 * The user data is reserved for use by the application which created
2259 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2260 * instead, call the EnableWindow() function to change the window's
2263 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2264 * SetParent() instead.
2267 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2268 * it sends WM_STYLECHANGING before changing the settings
2269 * and WM_STYLECHANGED afterwards.
2270 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2272 LONG WINAPI SetWindowLongW(
2273 HWND hwnd, /* [in] window to alter */
2274 INT offset, /* [in] offset, in bytes, of location to alter */
2275 LONG newval /* [in] new value of location */
2277 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2281 /*******************************************************************
2282 * GetWindowTextA (USER32.@)
2284 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2288 if (!lpString) return 0;
2290 if (WIN_IsCurrentProcess( hwnd ))
2291 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2293 /* when window belongs to other process, don't send a message */
2294 if (nMaxCount <= 0) return 0;
2295 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2296 get_server_window_text( hwnd, buffer, nMaxCount );
2297 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2298 lpString[nMaxCount-1] = 0;
2299 HeapFree( GetProcessHeap(), 0, buffer );
2300 return strlen(lpString);
2304 /*******************************************************************
2305 * InternalGetWindowText (USER32.@)
2307 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2311 if (nMaxCount <= 0) return 0;
2312 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2313 if (win == WND_DESKTOP) lpString[0] = 0;
2314 else if (win != WND_OTHER_PROCESS)
2316 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2317 else lpString[0] = 0;
2318 WIN_ReleasePtr( win );
2322 get_server_window_text( hwnd, lpString, nMaxCount );
2324 return strlenW(lpString);
2328 /*******************************************************************
2329 * GetWindowTextW (USER32.@)
2331 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2333 if (!lpString) return 0;
2335 if (WIN_IsCurrentProcess( hwnd ))
2336 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2338 /* when window belongs to other process, don't send a message */
2339 if (nMaxCount <= 0) return 0;
2340 get_server_window_text( hwnd, lpString, nMaxCount );
2341 return strlenW(lpString);
2345 /*******************************************************************
2346 * SetWindowTextA (USER32.@)
2347 * SetWindowText (USER32.@)
2349 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2351 if (is_broadcast(hwnd))
2353 SetLastError( ERROR_INVALID_PARAMETER );
2356 if (!WIN_IsCurrentProcess( hwnd ))
2357 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2358 debugstr_a(lpString), hwnd );
2359 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2363 /*******************************************************************
2364 * SetWindowTextW (USER32.@)
2366 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2368 if (is_broadcast(hwnd))
2370 SetLastError( ERROR_INVALID_PARAMETER );
2373 if (!WIN_IsCurrentProcess( hwnd ))
2374 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2375 debugstr_w(lpString), hwnd );
2376 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2380 /*******************************************************************
2381 * GetWindowTextLengthA (USER32.@)
2383 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2385 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2388 /*******************************************************************
2389 * GetWindowTextLengthW (USER32.@)
2391 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2393 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2397 /*******************************************************************
2398 * IsWindow (USER32.@)
2400 BOOL WINAPI IsWindow( HWND hwnd )
2405 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2406 if (ptr == WND_DESKTOP) return TRUE;
2408 if (ptr != WND_OTHER_PROCESS)
2410 WIN_ReleasePtr( ptr );
2414 /* check other processes */
2415 SERVER_START_REQ( get_window_info )
2418 ret = !wine_server_call_err( req );
2425 /***********************************************************************
2426 * GetWindowThreadProcessId (USER32.@)
2428 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2433 if (!(ptr = WIN_GetPtr( hwnd )))
2435 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2439 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2441 /* got a valid window */
2443 if (process) *process = GetCurrentProcessId();
2444 WIN_ReleasePtr( ptr );
2448 /* check other processes */
2449 SERVER_START_REQ( get_window_info )
2452 if (!wine_server_call_err( req ))
2454 tid = (DWORD)reply->tid;
2455 if (process) *process = (DWORD)reply->pid;
2463 /*****************************************************************
2464 * GetParent (USER32.@)
2466 HWND WINAPI GetParent( HWND hwnd )
2471 if (!(wndPtr = WIN_GetPtr( hwnd )))
2473 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2476 if (wndPtr == WND_DESKTOP) return 0;
2477 if (wndPtr == WND_OTHER_PROCESS)
2479 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2480 if (style & (WS_POPUP | WS_CHILD))
2482 SERVER_START_REQ( get_window_tree )
2485 if (!wine_server_call_err( req ))
2487 if (style & WS_POPUP) retvalue = reply->owner;
2488 else if (style & WS_CHILD) retvalue = reply->parent;
2496 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2497 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2498 WIN_ReleasePtr( wndPtr );
2504 /*****************************************************************
2505 * GetAncestor (USER32.@)
2507 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2510 HWND *list, ret = 0;
2515 if (!(win = WIN_GetPtr( hwnd )))
2517 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2520 if (win == WND_DESKTOP) return 0;
2521 if (win != WND_OTHER_PROCESS)
2524 WIN_ReleasePtr( win );
2526 else /* need to query the server */
2528 SERVER_START_REQ( get_window_tree )
2531 if (!wine_server_call_err( req )) ret = reply->parent;
2538 if (!(list = list_window_parents( hwnd ))) return 0;
2540 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2544 while (list[count]) count++;
2545 ret = list[count - 2]; /* get the one before the desktop */
2547 HeapFree( GetProcessHeap(), 0, list );
2551 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2554 HWND parent = GetParent( ret );
2564 /*****************************************************************
2565 * SetParent (USER32.@)
2567 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2570 HWND old_parent = 0;
2575 if (is_broadcast(hwnd) || is_broadcast(parent))
2577 SetLastError(ERROR_INVALID_PARAMETER);
2581 if (!parent) parent = GetDesktopWindow();
2582 else parent = WIN_GetFullHandle( parent );
2584 if (!IsWindow( parent ))
2586 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2590 /* Some applications try to set a child as a parent */
2591 if (IsChild(hwnd, parent))
2593 SetLastError( ERROR_INVALID_PARAMETER );
2597 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2598 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2600 /* Windows hides the window first, then shows it again
2601 * including the WM_SHOWWINDOW messages and all */
2602 was_visible = ShowWindow( hwnd, SW_HIDE );
2604 wndPtr = WIN_GetPtr( hwnd );
2605 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2607 SERVER_START_REQ( set_parent )
2610 req->parent = parent;
2611 if ((ret = !wine_server_call( req )))
2613 old_parent = reply->old_parent;
2614 wndPtr->parent = parent = reply->full_parent;
2619 WIN_ReleasePtr( wndPtr );
2622 USER_Driver->pSetParent( full_handle, parent, old_parent );
2624 /* SetParent additionally needs to make hwnd the topmost window
2625 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2626 WM_WINDOWPOSCHANGED notification messages.
2628 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2629 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2630 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2631 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2637 /*******************************************************************
2638 * IsChild (USER32.@)
2640 BOOL WINAPI IsChild( HWND parent, HWND child )
2642 HWND *list = list_window_parents( child );
2646 if (!list) return FALSE;
2647 parent = WIN_GetFullHandle( parent );
2648 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2649 ret = list[i] && list[i+1];
2650 HeapFree( GetProcessHeap(), 0, list );
2655 /***********************************************************************
2656 * IsWindowVisible (USER32.@)
2658 BOOL WINAPI IsWindowVisible( HWND hwnd )
2664 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2665 if (!(list = list_window_parents( hwnd ))) return TRUE;
2666 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2668 for (i = 0; list[i+1]; i++)
2669 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2670 retval = !list[i+1];
2672 HeapFree( GetProcessHeap(), 0, list );
2677 /***********************************************************************
2678 * WIN_IsWindowDrawable
2680 * hwnd is drawable when it is visible, all parents are not
2681 * minimized, and it is itself not minimized unless we are
2682 * trying to draw its default class icon.
2684 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2689 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2691 if (!(style & WS_VISIBLE)) return FALSE;
2692 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2694 if (!(list = list_window_parents( hwnd ))) return TRUE;
2695 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2697 for (i = 0; list[i+1]; i++)
2698 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2700 retval = !list[i+1];
2702 HeapFree( GetProcessHeap(), 0, list );
2707 /*******************************************************************
2708 * GetTopWindow (USER32.@)
2710 HWND WINAPI GetTopWindow( HWND hwnd )
2712 if (!hwnd) hwnd = GetDesktopWindow();
2713 return GetWindow( hwnd, GW_CHILD );
2717 /*******************************************************************
2718 * GetWindow (USER32.@)
2720 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2724 if (rel == GW_OWNER) /* this one may be available locally */
2726 WND *wndPtr = WIN_GetPtr( hwnd );
2729 SetLastError( ERROR_INVALID_HANDLE );
2732 if (wndPtr == WND_DESKTOP) return 0;
2733 if (wndPtr != WND_OTHER_PROCESS)
2735 retval = wndPtr->owner;
2736 WIN_ReleasePtr( wndPtr );
2739 /* else fall through to server call */
2742 SERVER_START_REQ( get_window_tree )
2745 if (!wine_server_call_err( req ))
2750 retval = reply->first_sibling;
2753 retval = reply->last_sibling;
2756 retval = reply->next_sibling;
2759 retval = reply->prev_sibling;
2762 retval = reply->owner;
2765 retval = reply->first_child;
2775 /*******************************************************************
2776 * ShowOwnedPopups (USER32.@)
2778 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2782 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2784 if (!win_array) return TRUE;
2786 while (win_array[count]) count++;
2787 while (--count >= 0)
2789 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2790 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2791 if (pWnd == WND_OTHER_PROCESS) continue;
2794 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2796 WIN_ReleasePtr( pWnd );
2797 /* In Windows, ShowOwnedPopups(TRUE) generates
2798 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2799 * regardless of the state of the owner
2801 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2807 if (pWnd->dwStyle & WS_VISIBLE)
2809 WIN_ReleasePtr( pWnd );
2810 /* In Windows, ShowOwnedPopups(FALSE) generates
2811 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2812 * regardless of the state of the owner
2814 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2818 WIN_ReleasePtr( pWnd );
2820 HeapFree( GetProcessHeap(), 0, win_array );
2825 /*******************************************************************
2826 * GetLastActivePopup (USER32.@)
2828 HWND WINAPI GetLastActivePopup( HWND hwnd )
2832 SERVER_START_REQ( get_window_info )
2835 if (!wine_server_call_err( req )) retval = reply->last_active;
2842 /*******************************************************************
2845 * Build an array of the children of a given window. The array must be
2846 * freed with HeapFree. Returns NULL when no windows are found.
2848 HWND *WIN_ListChildren( HWND hwnd )
2850 return list_window_children( hwnd, NULL, 0 );
2854 /*******************************************************************
2855 * EnumWindows (USER32.@)
2857 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2863 USER_CheckNotLock();
2865 /* We have to build a list of all windows first, to avoid */
2866 /* unpleasant side-effects, for instance if the callback */
2867 /* function changes the Z-order of the windows. */
2869 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2871 /* Now call the callback function for every window */
2873 for (i = 0; list[i]; i++)
2875 /* Make sure that the window still exists */
2876 if (!IsWindow( list[i] )) continue;
2877 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2879 HeapFree( GetProcessHeap(), 0, list );
2884 /**********************************************************************
2885 * EnumThreadWindows (USER32.@)
2887 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2892 USER_CheckNotLock();
2894 if (!(list = list_window_children( GetDesktopWindow(), NULL, id ))) return TRUE;
2896 /* Now call the callback function for every window */
2898 for (i = 0; list[i]; i++)
2899 if (!func( list[i], lParam )) break;
2900 HeapFree( GetProcessHeap(), 0, list );
2905 /**********************************************************************
2906 * WIN_EnumChildWindows
2908 * Helper function for EnumChildWindows().
2910 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2915 for ( ; *list; list++)
2917 /* Make sure that the window still exists */
2918 if (!IsWindow( *list )) continue;
2919 /* Build children list first */
2920 childList = WIN_ListChildren( *list );
2922 ret = func( *list, lParam );
2926 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2927 HeapFree( GetProcessHeap(), 0, childList );
2929 if (!ret) return FALSE;
2935 /**********************************************************************
2936 * EnumChildWindows (USER32.@)
2938 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2943 USER_CheckNotLock();
2945 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2946 ret = WIN_EnumChildWindows( list, func, lParam );
2947 HeapFree( GetProcessHeap(), 0, list );
2952 /*******************************************************************
2953 * AnyPopup (USER.52)
2955 BOOL16 WINAPI AnyPopup16(void)
2961 /*******************************************************************
2962 * AnyPopup (USER32.@)
2964 BOOL WINAPI AnyPopup(void)
2968 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2970 if (!list) return FALSE;
2971 for (i = 0; list[i]; i++)
2973 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2975 retvalue = (list[i] != 0);
2976 HeapFree( GetProcessHeap(), 0, list );
2981 /*******************************************************************
2982 * FlashWindow (USER32.@)
2984 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2988 TRACE("%p\n", hWnd);
2990 if (IsIconic( hWnd ))
2992 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2994 wndPtr = WIN_GetPtr(hWnd);
2995 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2996 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2998 wndPtr->flags |= WIN_NCACTIVATED;
3002 wndPtr->flags &= ~WIN_NCACTIVATED;
3004 WIN_ReleasePtr( wndPtr );
3011 wndPtr = WIN_GetPtr(hWnd);
3012 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3013 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3015 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3016 else wparam = (hWnd == GetForegroundWindow());
3018 WIN_ReleasePtr( wndPtr );
3019 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3024 /*******************************************************************
3025 * FlashWindowEx (USER32.@)
3027 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3029 FIXME("%p\n", pfwi);
3033 /*******************************************************************
3034 * GetWindowContextHelpId (USER32.@)
3036 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3039 WND *wnd = WIN_GetPtr( hwnd );
3040 if (!wnd || wnd == WND_DESKTOP) return 0;
3041 if (wnd == WND_OTHER_PROCESS)
3043 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3046 retval = wnd->helpContext;
3047 WIN_ReleasePtr( wnd );
3052 /*******************************************************************
3053 * SetWindowContextHelpId (USER32.@)
3055 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3057 WND *wnd = WIN_GetPtr( hwnd );
3058 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3059 if (wnd == WND_OTHER_PROCESS)
3061 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3064 wnd->helpContext = id;
3065 WIN_ReleasePtr( wnd );
3070 /*******************************************************************
3071 * DragDetect (USER32.@)
3073 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3077 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3078 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3080 rect.left = pt.x - wDragWidth;
3081 rect.right = pt.x + wDragWidth;
3083 rect.top = pt.y - wDragHeight;
3084 rect.bottom = pt.y + wDragHeight;
3090 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3092 if( msg.message == WM_LBUTTONUP )
3097 if( msg.message == WM_MOUSEMOVE )
3100 tmp.x = (short)LOWORD(msg.lParam);
3101 tmp.y = (short)HIWORD(msg.lParam);
3102 if( !PtInRect( &rect, tmp ))
3114 /******************************************************************************
3115 * GetWindowModuleFileNameA (USER32.@)
3117 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3119 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3120 hwnd, lpszFileName, cchFileNameMax);
3124 /******************************************************************************
3125 * GetWindowModuleFileNameW (USER32.@)
3127 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3129 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3130 hwnd, lpszFileName, cchFileNameMax);
3134 /******************************************************************************
3135 * GetWindowInfo (USER32.@)
3137 * Note: tests show that Windows doesn't check cbSize of the structure.
3139 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3141 if (!pwi) return FALSE;
3142 if (!IsWindow(hwnd)) return FALSE;
3144 GetWindowRect(hwnd, &pwi->rcWindow);
3145 GetClientRect(hwnd, &pwi->rcClient);
3146 /* translate to screen coordinates */
3147 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3149 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3150 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3151 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3153 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3154 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3156 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3157 pwi->wCreatorVersion = 0x0400;
3162 /******************************************************************************
3163 * SwitchDesktop (USER32.@)
3165 * NOTES: Sets the current input or interactive desktop.
3167 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3169 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3173 /*****************************************************************************
3174 * SetLayeredWindowAttributes (USER32.@)
3176 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3177 BYTE bAlpha, DWORD dwFlags )
3179 FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3183 /*****************************************************************************
3184 * GetLayeredWindowAttributes (USER32.@)
3186 BOOL WINAPI GetLayeredWindowAttributes( HWND hWnd, COLORREF *prgbKey,
3187 BYTE *pbAlpha, DWORD *pdwFlags )
3189 FIXME("(%p,%p,%p,%p): stub!\n", hWnd, prgbKey, pbAlpha, pdwFlags);
3193 /*****************************************************************************
3194 * UpdateLayeredWindow (USER32.@)
3196 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3197 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3204 FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3205 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3210 /* 64bit versions */
3212 #ifdef GetWindowLongPtrW
3213 #undef GetWindowLongPtrW
3216 #ifdef GetWindowLongPtrA
3217 #undef GetWindowLongPtrA
3220 #ifdef SetWindowLongPtrW
3221 #undef SetWindowLongPtrW
3224 #ifdef SetWindowLongPtrA
3225 #undef SetWindowLongPtrA
3228 /*****************************************************************************
3229 * GetWindowLongPtrW (USER32.@)
3231 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3233 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3236 /*****************************************************************************
3237 * GetWindowLongPtrA (USER32.@)
3239 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3241 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3244 /*****************************************************************************
3245 * SetWindowLongPtrW (USER32.@)
3247 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3249 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3252 /*****************************************************************************
3253 * SetWindowLongPtrA (USER32.@)
3255 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3257 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );