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( HDESK desktop, HWND hwnd, LPCWSTR class, DWORD tid )
224 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
226 SERVER_START_REQ( get_window_children )
228 req->desktop = desktop;
231 if (!(req->atom = get_int_atom_value( class )) && class)
232 wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
233 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
234 if (!wine_server_call( req )) count = reply->count;
237 if (count && count < size)
242 HeapFree( GetProcessHeap(), 0, list );
244 size = count + 1; /* restart with a large enough buffer */
250 /*******************************************************************
251 * list_window_parents
253 * Build an array of all parents of a given window, starting with
254 * the immediate parent. The array must be freed with HeapFree.
256 static HWND *list_window_parents( HWND hwnd )
260 int pos = 0, size = 16, count = 0;
262 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
267 if (!(win = WIN_GetPtr( current ))) goto empty;
268 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
269 if (win == WND_DESKTOP)
271 if (!pos) goto empty;
275 list[pos] = current = win->parent;
276 WIN_ReleasePtr( win );
277 if (++pos == size - 1)
279 /* need to grow the list */
280 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
281 if (!new_list) goto empty;
287 /* at least one parent belongs to another process, have to query the server */
292 SERVER_START_REQ( get_window_parents )
295 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
296 if (!wine_server_call( req )) count = reply->count;
299 if (!count) goto empty;
305 HeapFree( GetProcessHeap(), 0, list );
307 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
311 HeapFree( GetProcessHeap(), 0, list );
316 /*******************************************************************
319 static void send_parent_notify( HWND hwnd, UINT msg )
321 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
322 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
324 HWND parent = GetParent(hwnd);
325 if (parent && parent != GetDesktopWindow())
326 SendMessageW( parent, WM_PARENTNOTIFY,
327 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
332 /*******************************************************************
333 * get_server_window_text
335 * Retrieve the window text from the server.
337 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
341 SERVER_START_REQ( get_window_text )
344 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
345 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
348 text[len / sizeof(WCHAR)] = 0;
352 /***********************************************************************
355 * Return a pointer to the WND structure if local to the process,
356 * or WND_OTHER_PROCESS if handle may be valid in other process.
357 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
359 WND *WIN_GetPtr( HWND hwnd )
362 WORD index = USER_HANDLE_TO_INDEX(hwnd);
364 if (index >= NB_USER_HANDLES) return NULL;
367 if ((ptr = user_handles[index]))
369 if (ptr->dwMagic == WND_MAGIC &&
370 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
374 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
376 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
379 else ptr = WND_OTHER_PROCESS;
385 /***********************************************************************
386 * WIN_IsCurrentProcess
388 * Check whether a given window belongs to the current process (and return the full handle).
390 HWND WIN_IsCurrentProcess( HWND hwnd )
395 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
397 WIN_ReleasePtr( ptr );
402 /***********************************************************************
403 * WIN_IsCurrentThread
405 * Check whether a given window belongs to the current thread (and return the full handle).
407 HWND WIN_IsCurrentThread( HWND hwnd )
412 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
413 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
414 WIN_ReleasePtr( ptr );
419 /***********************************************************************
422 * Convert a 16-bit window handle to a full 32-bit handle.
424 HWND WIN_Handle32( HWND16 hwnd16 )
427 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
429 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
430 /* do sign extension for -2 and -3 */
431 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
433 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
435 if (ptr == WND_DESKTOP) return GetDesktopWindow();
437 if (ptr != WND_OTHER_PROCESS)
439 hwnd = ptr->hwndSelf;
440 WIN_ReleasePtr( ptr );
442 else /* may belong to another process */
444 SERVER_START_REQ( get_window_info )
447 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
455 /***********************************************************************
458 * Change the owner of a window.
460 HWND WIN_SetOwner( HWND hwnd, HWND owner )
462 WND *win = WIN_GetPtr( hwnd );
465 if (!win || win == WND_DESKTOP) return 0;
466 if (win == WND_OTHER_PROCESS)
468 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
471 SERVER_START_REQ( set_window_owner )
475 if (!wine_server_call( req ))
477 win->owner = reply->full_owner;
478 ret = reply->prev_owner;
482 WIN_ReleasePtr( win );
487 /***********************************************************************
490 * Change the style of a window.
492 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
495 ULONG new_style, old_style = 0;
496 WND *win = WIN_GetPtr( hwnd );
498 if (!win || win == WND_DESKTOP) return 0;
499 if (win == WND_OTHER_PROCESS)
502 ERR( "cannot set style %x/%x on other process window %p\n",
503 set_bits, clear_bits, hwnd );
506 new_style = (win->dwStyle | set_bits) & ~clear_bits;
507 if (new_style == win->dwStyle)
509 WIN_ReleasePtr( win );
512 SERVER_START_REQ( set_window_info )
515 req->flags = SET_WIN_STYLE;
516 req->style = new_style;
517 req->extra_offset = -1;
518 if ((ok = !wine_server_call( req )))
520 old_style = reply->old_style;
521 win->dwStyle = new_style;
525 WIN_ReleasePtr( win );
528 USER_Driver->pSetWindowStyle( hwnd, old_style );
529 if ((old_style ^ new_style) & WS_VISIBLE) invalidate_dce( hwnd, NULL );
535 /***********************************************************************
538 * Get the window and client rectangles.
540 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
542 WND *win = WIN_GetPtr( hwnd );
545 if (!win) return FALSE;
546 if (win == WND_DESKTOP)
549 rect.left = rect.top = 0;
550 rect.right = GetSystemMetrics(SM_CXSCREEN);
551 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
552 if (rectWindow) *rectWindow = rect;
553 if (rectClient) *rectClient = rect;
555 else if (win == WND_OTHER_PROCESS)
557 SERVER_START_REQ( get_window_rectangles )
560 if ((ret = !wine_server_call( req )))
564 rectWindow->left = reply->window.left;
565 rectWindow->top = reply->window.top;
566 rectWindow->right = reply->window.right;
567 rectWindow->bottom = reply->window.bottom;
571 rectClient->left = reply->client.left;
572 rectClient->top = reply->client.top;
573 rectClient->right = reply->client.right;
574 rectClient->bottom = reply->client.bottom;
582 if (rectWindow) *rectWindow = win->rectWindow;
583 if (rectClient) *rectClient = win->rectClient;
584 WIN_ReleasePtr( win );
590 /***********************************************************************
593 * Destroy storage associated to a window. "Internals" p.358
595 LRESULT WIN_DestroyWindow( HWND hwnd )
599 HMENU menu = 0, sys_menu;
602 TRACE("%p\n", hwnd );
604 /* free child windows */
605 if ((list = WIN_ListChildren( hwnd )))
608 for (i = 0; list[i]; i++)
610 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
611 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
613 HeapFree( GetProcessHeap(), 0, list );
616 /* Unlink now so we won't bother with the children later on */
617 SERVER_START_REQ( set_parent )
621 wine_server_call( req );
626 * Send the WM_NCDESTROY to the window being destroyed.
628 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
630 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
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 icon_title = wndPtr->icon_title;
641 WIN_ReleasePtr( wndPtr );
643 if (icon_title) DestroyWindow( icon_title );
644 if (menu) DestroyMenu( menu );
645 if (sys_menu) DestroyMenu( sys_menu );
647 USER_Driver->pDestroyWindow( hwnd );
649 free_window_handle( hwnd );
653 /***********************************************************************
654 * WIN_DestroyThreadWindows
656 * Destroy all children of 'wnd' owned by the current thread.
658 void WIN_DestroyThreadWindows( HWND hwnd )
663 if (!(list = WIN_ListChildren( hwnd ))) return;
664 for (i = 0; list[i]; i++)
666 if (WIN_IsCurrentThread( list[i] ))
667 DestroyWindow( list[i] );
669 WIN_DestroyThreadWindows( list[i] );
671 HeapFree( GetProcessHeap(), 0, list );
675 /***********************************************************************
678 * Fix the coordinates - Helper for WIN_CreateWindowEx.
679 * returns default show mode in sw.
681 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
683 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
686 if (cs->dwExStyle & WS_EX_MDICHILD)
690 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
691 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
693 TRACE("MDI child id %04x\n", id);
696 if (cs->style & (WS_CHILD | WS_POPUP))
698 if (cs->dwExStyle & WS_EX_MDICHILD)
700 if (IS_DEFAULT(cs->x))
705 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
706 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
710 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
711 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
714 else /* overlapped window */
717 MONITORINFO mon_info;
720 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
722 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
723 mon_info.cbSize = sizeof(mon_info);
724 GetMonitorInfoW( monitor, &mon_info );
725 GetStartupInfoW( &info );
727 if (IS_DEFAULT(cs->x))
729 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
730 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
731 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
734 if (IS_DEFAULT(cs->cx))
736 if (info.dwFlags & STARTF_USESIZE)
738 cs->cx = info.dwXSize;
739 cs->cy = info.dwYSize;
743 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
744 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
747 /* neither x nor cx are default. Check the y values .
748 * In the trace we see Outlook and Outlook Express using
749 * cy set to CW_USEDEFAULT when opening the address book.
751 else if (IS_DEFAULT(cs->cy))
753 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
754 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
760 /***********************************************************************
763 static void dump_window_styles( DWORD style, DWORD exstyle )
766 if(style & WS_POPUP) TRACE(" WS_POPUP");
767 if(style & WS_CHILD) TRACE(" WS_CHILD");
768 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
769 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
770 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
771 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
772 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
773 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
774 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
777 if(style & WS_BORDER) TRACE(" WS_BORDER");
778 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
780 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
781 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
782 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
783 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
784 if (style & WS_CHILD)
786 if(style & WS_GROUP) TRACE(" WS_GROUP");
787 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
791 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
792 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
795 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
796 #define DUMPED_STYLES \
816 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
821 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
822 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
823 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
824 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
825 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
826 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
827 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
828 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
829 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
830 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
831 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
832 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
833 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
834 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
835 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
836 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
837 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
838 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
840 #define DUMPED_EX_STYLES \
841 (WS_EX_DLGMODALFRAME | \
843 WS_EX_NOPARENTNOTIFY | \
845 WS_EX_ACCEPTFILES | \
846 WS_EX_TRANSPARENT | \
851 WS_EX_CONTEXTHELP | \
854 WS_EX_LEFTSCROLLBAR | \
855 WS_EX_CONTROLPARENT | \
860 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
862 #undef DUMPED_EX_STYLES
866 /***********************************************************************
869 * Implementation of CreateWindowEx().
871 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
873 INT cx, cy, style, sw = SW_SHOW;
877 HWND hwnd, parent, owner, top_child = 0;
878 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
879 MDICREATESTRUCTA mdi_cs;
883 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
884 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
885 debugstr_w(className),
886 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
887 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
888 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
890 /* Fix the styles for MDI children */
891 if (cs->dwExStyle & WS_EX_MDICHILD)
895 wndPtr = WIN_GetPtr(cs->hwndParent);
896 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
898 flags = wndPtr->flags;
899 WIN_ReleasePtr(wndPtr);
902 if (!(flags & WIN_ISMDICLIENT))
904 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
908 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
909 * MDICREATESTRUCT members have the originally passed values.
911 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
912 * have the same layout.
914 mdi_cs.szClass = cs->lpszClass;
915 mdi_cs.szTitle = cs->lpszName;
916 mdi_cs.hOwner = cs->hInstance;
921 mdi_cs.style = cs->style;
922 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
924 cs->lpCreateParams = (LPVOID)&mdi_cs;
926 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
928 if (cs->style & WS_POPUP)
930 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
933 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
937 cs->style &= ~WS_POPUP;
938 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
939 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
942 top_child = GetWindow(cs->hwndParent, GW_CHILD);
946 /* Restore current maximized child */
947 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
949 TRACE("Restoring current maximized child %p\n", top_child);
950 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
951 ShowWindow( top_child, SW_SHOWNORMAL );
952 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
957 /* Find the parent window */
959 parent = cs->hwndParent;
962 if (cs->hwndParent == HWND_MESSAGE)
964 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
965 * message window (style: WS_POPUP|WS_DISABLED)
967 FIXME("Parent is HWND_MESSAGE\n");
968 parent = GetDesktopWindow();
970 else if (cs->hwndParent)
972 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
974 parent = GetDesktopWindow();
975 owner = cs->hwndParent;
980 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
982 WARN("No parent for child window\n" );
983 SetLastError(ERROR_TLW_WITH_WSCHILD);
984 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
986 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM) /* are we creating the desktop itself? */
987 parent = GetDesktopWindow();
990 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
992 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
993 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
994 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
995 cs->dwExStyle |= WS_EX_WINDOWEDGE;
997 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
999 /* Create the window structure */
1001 if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
1003 hwnd = wndPtr->hwndSelf;
1005 /* Fill the window structure */
1007 wndPtr->tid = GetCurrentThreadId();
1008 wndPtr->hInstance = cs->hInstance;
1009 wndPtr->text = NULL;
1010 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1011 wndPtr->dwExStyle = cs->dwExStyle;
1012 wndPtr->wIDmenu = 0;
1013 wndPtr->helpContext = 0;
1014 wndPtr->pVScroll = NULL;
1015 wndPtr->pHScroll = NULL;
1016 wndPtr->userdata = 0;
1018 wndPtr->hIconSmall = 0;
1019 wndPtr->hSysMenu = 0;
1020 wndPtr->flags |= (flags & WIN_ISWIN32);
1022 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1025 * Correct the window styles.
1027 * It affects only the style loaded into the WIN structure.
1030 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1032 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1033 if (!(wndPtr->dwStyle & WS_POPUP))
1034 wndPtr->dwStyle |= WS_CAPTION;
1038 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1039 * why does the user get to set it?
1042 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1043 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1044 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1046 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1048 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1049 wndPtr->flags |= WIN_NEED_SIZE;
1051 SERVER_START_REQ( set_window_info )
1054 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1055 req->style = wndPtr->dwStyle;
1056 req->ex_style = wndPtr->dwExStyle;
1057 req->instance = (void *)wndPtr->hInstance;
1058 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1059 req->extra_offset = -1;
1060 wine_server_call( req );
1064 /* Set the window menu */
1066 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1070 if (!MENU_SetMenu(hwnd, cs->hMenu))
1072 WIN_ReleasePtr( wndPtr );
1073 free_window_handle( hwnd );
1079 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1082 if (!cs->hInstance || HIWORD(cs->hInstance))
1083 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1085 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1087 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1091 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1093 /* call the WH_CBT hook */
1095 /* the window style passed to the hook must be the real window style,
1096 * rather than just the window style that the caller to CreateWindowEx
1097 * passed in, so we have to copy the original CREATESTRUCT and get the
1098 * the real style. */
1100 cbcs.style = wndPtr->dwStyle;
1102 cbtc.hwndInsertAfter = HWND_TOP;
1103 WIN_ReleasePtr( wndPtr );
1104 if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode )) goto failed;
1106 /* send the WM_GETMINMAXINFO message and fix the size if needed */
1110 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
1112 POINT maxSize, maxPos, minTrack, maxTrack;
1113 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
1114 if (maxTrack.x < cx) cx = maxTrack.x;
1115 if (maxTrack.y < cy) cy = maxTrack.y;
1120 SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy );
1121 if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
1123 /* send WM_NCCREATE */
1125 TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cx, cy );
1127 result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1129 result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1132 WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1136 /* send WM_NCCALCSIZE */
1138 if ((wndPtr = WIN_GetPtr(hwnd)))
1140 /* yes, even if the CBT hook was called with HWND_TOP */
1141 HWND insert_after = (wndPtr->dwStyle & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
1142 RECT window_rect = wndPtr->rectWindow;
1143 RECT client_rect = window_rect;
1144 WIN_ReleasePtr( wndPtr );
1145 SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
1146 set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &window_rect, &client_rect, NULL );
1150 /* send WM_CREATE */
1153 result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1155 result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
1156 if (result == -1) goto failed;
1158 /* call the driver */
1160 if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1162 NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1164 /* send the size messages */
1166 if (!(wndPtr = WIN_GetPtr(hwnd))) return 0;
1167 if (!(wndPtr->flags & WIN_NEED_SIZE))
1169 rect = wndPtr->rectClient;
1170 WIN_ReleasePtr( wndPtr );
1171 SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1172 MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1173 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1175 else WIN_ReleasePtr( wndPtr );
1177 /* Show the window, maximizing or minimizing if needed */
1179 style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
1180 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1183 UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1185 swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1186 swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
1187 if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
1188 SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right, newPos.bottom, swFlag );
1191 /* Notify the parent window only */
1193 send_parent_notify( hwnd, WM_CREATE );
1194 if (!IsWindow( hwnd )) return 0;
1196 if (cs->style & WS_VISIBLE)
1198 if (cs->style & WS_MAXIMIZE)
1200 else if (cs->style & WS_MINIMIZE)
1201 sw = SW_SHOWMINIMIZED;
1203 ShowWindow( hwnd, sw );
1204 if (cs->dwExStyle & WS_EX_MDICHILD)
1206 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1207 /* ShowWindow won't activate child windows */
1208 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1212 /* Call WH_SHELL hook */
1214 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1215 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1217 TRACE("created window %p\n", hwnd);
1221 WIN_DestroyWindow( hwnd );
1226 /***********************************************************************
1227 * CreateWindow (USER.41)
1229 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1230 DWORD style, INT16 x, INT16 y, INT16 width,
1231 INT16 height, HWND16 parent, HMENU16 menu,
1232 HINSTANCE16 instance, LPVOID data )
1234 return CreateWindowEx16( 0, className, windowName, style,
1235 x, y, width, height, parent, menu, instance, data );
1239 /***********************************************************************
1240 * CreateWindowEx (USER.452)
1242 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1243 LPCSTR windowName, DWORD style, INT16 x,
1244 INT16 y, INT16 width, INT16 height,
1245 HWND16 parent, HMENU16 menu,
1246 HINSTANCE16 instance, LPVOID data )
1251 /* Fix the coordinates */
1253 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1254 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1255 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1256 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1258 /* Create the window */
1260 cs.lpCreateParams = data;
1261 cs.hInstance = HINSTANCE_32(instance);
1262 cs.hMenu = HMENU_32(menu);
1263 cs.hwndParent = WIN_Handle32( parent );
1265 cs.lpszName = windowName;
1266 cs.lpszClass = className;
1267 cs.dwExStyle = exStyle;
1269 if (!IS_INTRESOURCE(className))
1273 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1275 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1279 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1281 ERR( "bad atom %x\n", LOWORD(className));
1284 cs.lpszClass = buffer;
1285 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1290 /***********************************************************************
1291 * CreateWindowExA (USER32.@)
1293 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1294 LPCSTR windowName, DWORD style, INT x,
1295 INT y, INT width, INT height,
1296 HWND parent, HMENU menu,
1297 HINSTANCE instance, LPVOID data )
1301 cs.lpCreateParams = data;
1302 cs.hInstance = instance;
1304 cs.hwndParent = parent;
1310 cs.lpszName = windowName;
1311 cs.lpszClass = className;
1312 cs.dwExStyle = exStyle;
1314 if (!IS_INTRESOURCE(className))
1317 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1319 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1321 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1325 /***********************************************************************
1326 * CreateWindowExW (USER32.@)
1328 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1329 LPCWSTR windowName, DWORD style, INT x,
1330 INT y, INT width, INT height,
1331 HWND parent, HMENU menu,
1332 HINSTANCE instance, LPVOID data )
1336 cs.lpCreateParams = data;
1337 cs.hInstance = instance;
1339 cs.hwndParent = parent;
1345 cs.lpszName = windowName;
1346 cs.lpszClass = className;
1347 cs.dwExStyle = exStyle;
1349 /* Note: we rely on the fact that CREATESTRUCTA and */
1350 /* CREATESTRUCTW have the same layout. */
1351 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1355 /***********************************************************************
1356 * WIN_SendDestroyMsg
1358 static void WIN_SendDestroyMsg( HWND hwnd )
1362 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1364 if (hwnd == info.hwndCaret) DestroyCaret();
1365 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1369 * Send the WM_DESTROY to the window.
1371 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1374 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1375 * make sure that the window still exists when we come back.
1382 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1384 for (i = 0; pWndArray[i]; i++)
1386 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1388 HeapFree( GetProcessHeap(), 0, pWndArray );
1391 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1395 /***********************************************************************
1396 * DestroyWindow (USER32.@)
1398 BOOL WINAPI DestroyWindow( HWND hwnd )
1402 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1404 SetLastError( ERROR_ACCESS_DENIED );
1408 TRACE("(%p)\n", hwnd);
1412 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1414 if (MENU_IsMenuActive() == hwnd)
1417 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1421 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1422 send_parent_notify( hwnd, WM_DESTROY );
1424 else if (!GetWindow( hwnd, GW_OWNER ))
1426 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1427 /* FIXME: clean up palette - see "Internals" p.352 */
1430 if (!IsWindow(hwnd)) return TRUE;
1432 /* Hide the window */
1433 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1435 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1437 ShowWindow( hwnd, SW_HIDE );
1439 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1440 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1443 if (!IsWindow(hwnd)) return TRUE;
1445 /* Recursively destroy owned windows */
1452 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1455 for (i = 0; list[i]; i++)
1457 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1458 if (WIN_IsCurrentThread( list[i] ))
1460 DestroyWindow( list[i] );
1464 WIN_SetOwner( list[i], 0 );
1466 HeapFree( GetProcessHeap(), 0, list );
1468 if (!got_one) break;
1472 /* Send destroy messages */
1474 WIN_SendDestroyMsg( hwnd );
1475 if (!IsWindow( hwnd )) return TRUE;
1477 if (GetClipboardOwner() == hwnd)
1478 CLIPBOARD_ReleaseOwner();
1480 /* Destroy the window storage */
1482 WIN_DestroyWindow( hwnd );
1487 /***********************************************************************
1488 * CloseWindow (USER32.@)
1490 BOOL WINAPI CloseWindow( HWND hwnd )
1492 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1493 ShowWindow( hwnd, SW_MINIMIZE );
1498 /***********************************************************************
1499 * OpenIcon (USER32.@)
1501 BOOL WINAPI OpenIcon( HWND hwnd )
1503 if (!IsIconic( hwnd )) return FALSE;
1504 ShowWindow( hwnd, SW_SHOWNORMAL );
1509 /***********************************************************************
1510 * FindWindowExW (USER32.@)
1512 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1517 WCHAR *buffer = NULL;
1519 if (!parent) parent = GetDesktopWindow();
1522 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1523 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1526 if (!(list = list_window_children( 0, parent, className, 0 ))) goto done;
1530 child = WIN_GetFullHandle( child );
1531 while (list[i] && list[i] != child) i++;
1532 if (!list[i]) goto done;
1533 i++; /* start from next window */
1540 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1547 HeapFree( GetProcessHeap(), 0, list );
1548 HeapFree( GetProcessHeap(), 0, buffer );
1554 /***********************************************************************
1555 * FindWindowA (USER32.@)
1557 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1559 HWND ret = FindWindowExA( 0, 0, className, title );
1560 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1565 /***********************************************************************
1566 * FindWindowExA (USER32.@)
1568 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1570 LPWSTR titleW = NULL;
1575 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1576 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1577 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1580 if (!IS_INTRESOURCE(className))
1583 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1584 hwnd = FindWindowExW( parent, child, classW, titleW );
1588 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1591 HeapFree( GetProcessHeap(), 0, titleW );
1596 /***********************************************************************
1597 * FindWindowW (USER32.@)
1599 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1601 return FindWindowExW( 0, 0, className, title );
1605 /**********************************************************************
1606 * GetDesktopWindow (USER32.@)
1608 HWND WINAPI GetDesktopWindow(void)
1610 struct user_thread_info *thread_info = get_user_thread_info();
1612 if (thread_info->desktop) return thread_info->desktop;
1614 SERVER_START_REQ( get_desktop_window )
1617 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1621 if (!thread_info->desktop)
1623 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1625 PROCESS_INFORMATION pi;
1626 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1628 memset( &si, 0, sizeof(si) );
1630 si.dwFlags = STARTF_USESTDHANDLES;
1633 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1635 GetSystemDirectoryW( cmdline, MAX_PATH );
1636 lstrcatW( cmdline, command_line );
1637 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1638 NULL, NULL, &si, &pi ))
1640 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1641 WaitForInputIdle( pi.hProcess, 10000 );
1642 CloseHandle( pi.hThread );
1643 CloseHandle( pi.hProcess );
1646 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1648 SERVER_START_REQ( get_desktop_window )
1651 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1656 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1657 ERR( "failed to create desktop window\n" );
1659 return thread_info->desktop;
1663 /*******************************************************************
1664 * EnableWindow (USER32.@)
1666 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1671 if (is_broadcast(hwnd))
1673 SetLastError( ERROR_INVALID_PARAMETER );
1677 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1678 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1682 TRACE("( %p, %d )\n", hwnd, enable);
1684 retvalue = !IsWindowEnabled( hwnd );
1686 if (enable && retvalue)
1688 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1689 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1691 else if (!enable && !retvalue)
1695 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1697 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1699 if (hwnd == GetFocus())
1700 SetFocus( 0 ); /* A disabled window can't have the focus */
1702 capture_wnd = GetCapture();
1703 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1704 ReleaseCapture(); /* A disabled window can't capture the mouse */
1706 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1712 /***********************************************************************
1713 * IsWindowEnabled (USER32.@)
1715 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1717 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1721 /***********************************************************************
1722 * IsWindowUnicode (USER32.@)
1724 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1727 BOOL retvalue = FALSE;
1729 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1731 if (wndPtr == WND_DESKTOP) return TRUE;
1733 if (wndPtr != WND_OTHER_PROCESS)
1735 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1736 WIN_ReleasePtr( wndPtr );
1740 SERVER_START_REQ( get_window_info )
1743 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1751 /**********************************************************************
1754 * Helper function for GetWindowLong().
1756 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1758 LONG_PTR retvalue = 0;
1761 if (offset == GWLP_HWNDPARENT)
1763 HWND parent = GetAncestor( hwnd, GA_PARENT );
1764 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1765 return (ULONG_PTR)parent;
1768 if (!(wndPtr = WIN_GetPtr( hwnd )))
1770 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1774 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1776 if (offset == GWLP_WNDPROC)
1778 SetLastError( ERROR_ACCESS_DENIED );
1781 SERVER_START_REQ( set_window_info )
1784 req->flags = 0; /* don't set anything, just retrieve */
1785 req->extra_offset = (offset >= 0) ? offset : -1;
1786 req->extra_size = (offset >= 0) ? size : 0;
1787 if (!wine_server_call_err( req ))
1791 case GWL_STYLE: retvalue = reply->old_style; break;
1792 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1793 case GWLP_ID: retvalue = reply->old_id; break;
1794 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1795 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1797 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1798 else SetLastError( ERROR_INVALID_INDEX );
1807 /* now we have a valid wndPtr */
1811 if (offset > (int)(wndPtr->cbWndExtra - size))
1813 WARN("Invalid offset %d\n", offset );
1814 WIN_ReleasePtr( wndPtr );
1815 SetLastError( ERROR_INVALID_INDEX );
1818 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1820 /* Special case for dialog window procedure */
1821 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1822 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1823 WIN_ReleasePtr( wndPtr );
1829 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1830 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1831 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1832 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
1833 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1835 /* This looks like a hack only for the edit control (see tests). This makes these controls
1836 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1837 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1839 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1840 retvalue = (ULONG_PTR)wndPtr->winproc;
1842 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1845 WARN("Unknown offset %d\n", offset );
1846 SetLastError( ERROR_INVALID_INDEX );
1849 WIN_ReleasePtr(wndPtr);
1854 /**********************************************************************
1857 * Helper function for SetWindowLong().
1859 * 0 is the failure code. However, in the case of failure SetLastError
1860 * must be set to distinguish between a 0 return value and a failure.
1862 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1866 LONG_PTR retval = 0;
1869 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1871 if (is_broadcast(hwnd))
1873 SetLastError( ERROR_INVALID_PARAMETER );
1877 if (!(wndPtr = WIN_GetPtr( hwnd )))
1879 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1882 if (wndPtr == WND_DESKTOP)
1884 /* can't change anything on the desktop window */
1885 SetLastError( ERROR_ACCESS_DENIED );
1888 if (wndPtr == WND_OTHER_PROCESS)
1890 if (offset == GWLP_WNDPROC)
1892 SetLastError( ERROR_ACCESS_DENIED );
1895 if (offset > 32767 || offset < -32767)
1897 SetLastError( ERROR_INVALID_INDEX );
1900 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1903 /* first some special cases */
1909 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1910 style.styleNew = newval;
1911 WIN_ReleasePtr( wndPtr );
1912 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1913 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1914 newval = style.styleNew;
1916 case GWLP_HWNDPARENT:
1917 if (wndPtr->parent == GetDesktopWindow())
1919 WIN_ReleasePtr( wndPtr );
1920 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1924 WIN_ReleasePtr( wndPtr );
1925 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1930 UINT old_flags = wndPtr->flags;
1931 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
1932 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1933 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1934 if (proc) wndPtr->winproc = proc;
1935 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1936 else wndPtr->flags &= ~WIN_ISUNICODE;
1937 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1939 WIN_ReleasePtr( wndPtr );
1942 /* update is_unicode flag on the server side */
1946 case GWLP_HINSTANCE:
1950 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1951 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1953 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1954 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1955 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1956 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1957 WIN_ReleasePtr( wndPtr );
1962 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1964 WARN("Invalid offset %d\n", offset );
1965 WIN_ReleasePtr( wndPtr );
1966 SetLastError( ERROR_INVALID_INDEX );
1969 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1971 /* already set to the same value */
1972 WIN_ReleasePtr( wndPtr );
1978 SERVER_START_REQ( set_window_info )
1981 req->extra_offset = -1;
1985 req->flags = SET_WIN_STYLE;
1986 req->style = newval;
1989 req->flags = SET_WIN_EXSTYLE;
1990 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
1991 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
1992 req->ex_style = newval;
1995 req->flags = SET_WIN_ID;
1998 case GWLP_HINSTANCE:
1999 req->flags = SET_WIN_INSTANCE;
2000 req->instance = (void *)newval;
2003 req->flags = SET_WIN_UNICODE;
2004 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2007 req->flags = SET_WIN_USERDATA;
2008 req->user_data = newval;
2011 req->flags = SET_WIN_EXTRA;
2012 req->extra_offset = offset;
2013 req->extra_size = size;
2014 set_win_data( &req->extra_value, newval, size );
2016 if ((ok = !wine_server_call_err( req )))
2021 wndPtr->dwStyle = newval;
2022 retval = reply->old_style;
2025 wndPtr->dwExStyle = newval;
2026 retval = reply->old_ex_style;
2029 wndPtr->wIDmenu = newval;
2030 retval = reply->old_id;
2032 case GWLP_HINSTANCE:
2033 wndPtr->hInstance = (HINSTANCE)newval;
2034 retval = (ULONG_PTR)reply->old_instance;
2039 wndPtr->userdata = newval;
2040 retval = reply->old_user_data;
2043 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2044 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2050 WIN_ReleasePtr( wndPtr );
2054 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2056 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2057 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2063 /**********************************************************************
2064 * GetWindowLong (USER.135)
2066 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2070 BOOL is_winproc = (offset == GWLP_WNDPROC);
2074 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2076 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2079 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2081 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2084 * Some programs try to access last element from 16 bit
2085 * code using illegal offset value. Hopefully this is
2086 * what those programs really expect.
2088 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2090 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2091 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2096 WARN("Invalid offset %d\n", offset );
2097 WIN_ReleasePtr( wndPtr );
2098 SetLastError( ERROR_INVALID_INDEX );
2102 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2103 WIN_ReleasePtr( wndPtr );
2106 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2107 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2112 /**********************************************************************
2113 * GetWindowWord (USER32.@)
2115 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2120 case GWLP_HINSTANCE:
2121 case GWLP_HWNDPARENT:
2126 WARN("Invalid offset %d\n", offset );
2127 SetLastError( ERROR_INVALID_INDEX );
2132 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2136 /**********************************************************************
2137 * GetWindowLongA (USER32.@)
2139 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2141 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2145 /**********************************************************************
2146 * GetWindowLongW (USER32.@)
2148 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2150 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2154 /**********************************************************************
2155 * SetWindowLong (USER.136)
2157 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2160 BOOL is_winproc = (offset == GWLP_WNDPROC);
2162 if (offset == DWLP_DLGPROC)
2164 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2166 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2169 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2171 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2172 (wndPtr->flags & WIN_ISDIALOG));
2173 WIN_ReleasePtr( wndPtr );
2179 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2180 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2181 return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2183 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2187 /**********************************************************************
2188 * SetWindowWord (USER32.@)
2190 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2195 case GWLP_HINSTANCE:
2196 case GWLP_HWNDPARENT:
2201 WARN("Invalid offset %d\n", offset );
2202 SetLastError( ERROR_INVALID_INDEX );
2207 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2211 /**********************************************************************
2212 * SetWindowLongA (USER32.@)
2214 * See SetWindowLongW.
2216 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2218 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2222 /**********************************************************************
2223 * SetWindowLongW (USER32.@) Set window attribute
2225 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2226 * value in a window's extra memory.
2228 * The _hwnd_ parameter specifies the window. is the handle to a
2229 * window that has extra memory. The _newval_ parameter contains the
2230 * new attribute or extra memory value. If positive, the _offset_
2231 * parameter is the byte-addressed location in the window's extra
2232 * memory to set. If negative, _offset_ specifies the window
2233 * attribute to set, and should be one of the following values:
2235 * GWL_EXSTYLE The window's extended window style
2237 * GWL_STYLE The window's window style.
2239 * GWLP_WNDPROC Pointer to the window's window procedure.
2241 * GWLP_HINSTANCE The window's pplication instance handle.
2243 * GWLP_ID The window's identifier.
2245 * GWLP_USERDATA The window's user-specified data.
2247 * If the window is a dialog box, the _offset_ parameter can be one of
2248 * the following values:
2250 * DWLP_DLGPROC The address of the window's dialog box procedure.
2252 * DWLP_MSGRESULT The return value of a message
2253 * that the dialog box procedure processed.
2255 * DWLP_USER Application specific information.
2259 * If successful, returns the previous value located at _offset_. Otherwise,
2264 * Extra memory for a window class is specified by a nonzero cbWndExtra
2265 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2266 * time of class creation.
2268 * Using GWL_WNDPROC to set a new window procedure effectively creates
2269 * a window subclass. Use CallWindowProc() in the new windows procedure
2270 * to pass messages to the superclass's window procedure.
2272 * The user data is reserved for use by the application which created
2275 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2276 * instead, call the EnableWindow() function to change the window's
2279 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2280 * SetParent() instead.
2283 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2284 * it sends WM_STYLECHANGING before changing the settings
2285 * and WM_STYLECHANGED afterwards.
2286 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2288 LONG WINAPI SetWindowLongW(
2289 HWND hwnd, /* [in] window to alter */
2290 INT offset, /* [in] offset, in bytes, of location to alter */
2291 LONG newval /* [in] new value of location */
2293 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2297 /*******************************************************************
2298 * GetWindowTextA (USER32.@)
2300 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2304 if (!lpString) return 0;
2306 if (WIN_IsCurrentProcess( hwnd ))
2307 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2309 /* when window belongs to other process, don't send a message */
2310 if (nMaxCount <= 0) return 0;
2311 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2312 get_server_window_text( hwnd, buffer, nMaxCount );
2313 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2314 lpString[nMaxCount-1] = 0;
2315 HeapFree( GetProcessHeap(), 0, buffer );
2316 return strlen(lpString);
2320 /*******************************************************************
2321 * InternalGetWindowText (USER32.@)
2323 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2327 if (nMaxCount <= 0) return 0;
2328 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2329 if (win == WND_DESKTOP) lpString[0] = 0;
2330 else if (win != WND_OTHER_PROCESS)
2332 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2333 else lpString[0] = 0;
2334 WIN_ReleasePtr( win );
2338 get_server_window_text( hwnd, lpString, nMaxCount );
2340 return strlenW(lpString);
2344 /*******************************************************************
2345 * GetWindowTextW (USER32.@)
2347 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2349 if (!lpString) return 0;
2351 if (WIN_IsCurrentProcess( hwnd ))
2352 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2354 /* when window belongs to other process, don't send a message */
2355 if (nMaxCount <= 0) return 0;
2356 get_server_window_text( hwnd, lpString, nMaxCount );
2357 return strlenW(lpString);
2361 /*******************************************************************
2362 * SetWindowTextA (USER32.@)
2363 * SetWindowText (USER32.@)
2365 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2367 if (is_broadcast(hwnd))
2369 SetLastError( ERROR_INVALID_PARAMETER );
2372 if (!WIN_IsCurrentProcess( hwnd ))
2373 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2374 debugstr_a(lpString), hwnd );
2375 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2379 /*******************************************************************
2380 * SetWindowTextW (USER32.@)
2382 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2384 if (is_broadcast(hwnd))
2386 SetLastError( ERROR_INVALID_PARAMETER );
2389 if (!WIN_IsCurrentProcess( hwnd ))
2390 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2391 debugstr_w(lpString), hwnd );
2392 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2396 /*******************************************************************
2397 * GetWindowTextLengthA (USER32.@)
2399 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2401 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2404 /*******************************************************************
2405 * GetWindowTextLengthW (USER32.@)
2407 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2409 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2413 /*******************************************************************
2414 * IsWindow (USER32.@)
2416 BOOL WINAPI IsWindow( HWND hwnd )
2421 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2422 if (ptr == WND_DESKTOP) return TRUE;
2424 if (ptr != WND_OTHER_PROCESS)
2426 WIN_ReleasePtr( ptr );
2430 /* check other processes */
2431 SERVER_START_REQ( get_window_info )
2434 ret = !wine_server_call_err( req );
2441 /***********************************************************************
2442 * GetWindowThreadProcessId (USER32.@)
2444 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2449 if (!(ptr = WIN_GetPtr( hwnd )))
2451 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2455 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2457 /* got a valid window */
2459 if (process) *process = GetCurrentProcessId();
2460 WIN_ReleasePtr( ptr );
2464 /* check other processes */
2465 SERVER_START_REQ( get_window_info )
2468 if (!wine_server_call_err( req ))
2470 tid = (DWORD)reply->tid;
2471 if (process) *process = (DWORD)reply->pid;
2479 /*****************************************************************
2480 * GetParent (USER32.@)
2482 HWND WINAPI GetParent( HWND hwnd )
2487 if (!(wndPtr = WIN_GetPtr( hwnd )))
2489 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2492 if (wndPtr == WND_DESKTOP) return 0;
2493 if (wndPtr == WND_OTHER_PROCESS)
2495 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2496 if (style & (WS_POPUP | WS_CHILD))
2498 SERVER_START_REQ( get_window_tree )
2501 if (!wine_server_call_err( req ))
2503 if (style & WS_POPUP) retvalue = reply->owner;
2504 else if (style & WS_CHILD) retvalue = reply->parent;
2512 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2513 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2514 WIN_ReleasePtr( wndPtr );
2520 /*****************************************************************
2521 * GetAncestor (USER32.@)
2523 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2526 HWND *list, ret = 0;
2531 if (!(win = WIN_GetPtr( hwnd )))
2533 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2536 if (win == WND_DESKTOP) return 0;
2537 if (win != WND_OTHER_PROCESS)
2540 WIN_ReleasePtr( win );
2542 else /* need to query the server */
2544 SERVER_START_REQ( get_window_tree )
2547 if (!wine_server_call_err( req )) ret = reply->parent;
2554 if (!(list = list_window_parents( hwnd ))) return 0;
2556 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2560 while (list[count]) count++;
2561 ret = list[count - 2]; /* get the one before the desktop */
2563 HeapFree( GetProcessHeap(), 0, list );
2567 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2570 HWND parent = GetParent( ret );
2580 /*****************************************************************
2581 * SetParent (USER32.@)
2583 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2586 HWND old_parent = 0;
2591 if (is_broadcast(hwnd) || is_broadcast(parent))
2593 SetLastError(ERROR_INVALID_PARAMETER);
2597 if (!parent) parent = GetDesktopWindow();
2598 else parent = WIN_GetFullHandle( parent );
2600 if (!IsWindow( parent ))
2602 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2606 /* Some applications try to set a child as a parent */
2607 if (IsChild(hwnd, parent))
2609 SetLastError( ERROR_INVALID_PARAMETER );
2613 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2614 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2616 /* Windows hides the window first, then shows it again
2617 * including the WM_SHOWWINDOW messages and all */
2618 was_visible = ShowWindow( hwnd, SW_HIDE );
2620 wndPtr = WIN_GetPtr( hwnd );
2621 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2623 SERVER_START_REQ( set_parent )
2626 req->parent = parent;
2627 if ((ret = !wine_server_call( req )))
2629 old_parent = reply->old_parent;
2630 wndPtr->parent = parent = reply->full_parent;
2635 WIN_ReleasePtr( wndPtr );
2638 USER_Driver->pSetParent( full_handle, parent, old_parent );
2640 /* SetParent additionally needs to make hwnd the topmost window
2641 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2642 WM_WINDOWPOSCHANGED notification messages.
2644 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2645 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2646 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2647 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2653 /*******************************************************************
2654 * IsChild (USER32.@)
2656 BOOL WINAPI IsChild( HWND parent, HWND child )
2658 HWND *list = list_window_parents( child );
2662 if (!list) return FALSE;
2663 parent = WIN_GetFullHandle( parent );
2664 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2665 ret = list[i] && list[i+1];
2666 HeapFree( GetProcessHeap(), 0, list );
2671 /***********************************************************************
2672 * IsWindowVisible (USER32.@)
2674 BOOL WINAPI IsWindowVisible( HWND hwnd )
2680 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2681 if (!(list = list_window_parents( hwnd ))) return TRUE;
2682 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2684 for (i = 0; list[i+1]; i++)
2685 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2686 retval = !list[i+1];
2688 HeapFree( GetProcessHeap(), 0, list );
2693 /***********************************************************************
2694 * WIN_IsWindowDrawable
2696 * hwnd is drawable when it is visible, all parents are not
2697 * minimized, and it is itself not minimized unless we are
2698 * trying to draw its default class icon.
2700 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2705 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2707 if (!(style & WS_VISIBLE)) return FALSE;
2708 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2710 if (!(list = list_window_parents( hwnd ))) return TRUE;
2711 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2713 for (i = 0; list[i+1]; i++)
2714 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2716 retval = !list[i+1];
2718 HeapFree( GetProcessHeap(), 0, list );
2723 /*******************************************************************
2724 * GetTopWindow (USER32.@)
2726 HWND WINAPI GetTopWindow( HWND hwnd )
2728 if (!hwnd) hwnd = GetDesktopWindow();
2729 return GetWindow( hwnd, GW_CHILD );
2733 /*******************************************************************
2734 * GetWindow (USER32.@)
2736 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2740 if (rel == GW_OWNER) /* this one may be available locally */
2742 WND *wndPtr = WIN_GetPtr( hwnd );
2745 SetLastError( ERROR_INVALID_HANDLE );
2748 if (wndPtr == WND_DESKTOP) return 0;
2749 if (wndPtr != WND_OTHER_PROCESS)
2751 retval = wndPtr->owner;
2752 WIN_ReleasePtr( wndPtr );
2755 /* else fall through to server call */
2758 SERVER_START_REQ( get_window_tree )
2761 if (!wine_server_call_err( req ))
2766 retval = reply->first_sibling;
2769 retval = reply->last_sibling;
2772 retval = reply->next_sibling;
2775 retval = reply->prev_sibling;
2778 retval = reply->owner;
2781 retval = reply->first_child;
2791 /*******************************************************************
2792 * ShowOwnedPopups (USER32.@)
2794 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2798 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2800 if (!win_array) return TRUE;
2802 while (win_array[count]) count++;
2803 while (--count >= 0)
2805 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2806 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2807 if (pWnd == WND_OTHER_PROCESS) continue;
2810 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2812 WIN_ReleasePtr( pWnd );
2813 /* In Windows, ShowOwnedPopups(TRUE) generates
2814 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2815 * regardless of the state of the owner
2817 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2823 if (pWnd->dwStyle & WS_VISIBLE)
2825 WIN_ReleasePtr( pWnd );
2826 /* In Windows, ShowOwnedPopups(FALSE) generates
2827 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2828 * regardless of the state of the owner
2830 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2834 WIN_ReleasePtr( pWnd );
2836 HeapFree( GetProcessHeap(), 0, win_array );
2841 /*******************************************************************
2842 * GetLastActivePopup (USER32.@)
2844 HWND WINAPI GetLastActivePopup( HWND hwnd )
2848 SERVER_START_REQ( get_window_info )
2851 if (!wine_server_call_err( req )) retval = reply->last_active;
2858 /*******************************************************************
2861 * Build an array of the children of a given window. The array must be
2862 * freed with HeapFree. Returns NULL when no windows are found.
2864 HWND *WIN_ListChildren( HWND hwnd )
2866 return list_window_children( 0, hwnd, NULL, 0 );
2870 /*******************************************************************
2871 * EnumWindows (USER32.@)
2873 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2879 USER_CheckNotLock();
2881 /* We have to build a list of all windows first, to avoid */
2882 /* unpleasant side-effects, for instance if the callback */
2883 /* function changes the Z-order of the windows. */
2885 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2887 /* Now call the callback function for every window */
2889 for (i = 0; list[i]; i++)
2891 /* Make sure that the window still exists */
2892 if (!IsWindow( list[i] )) continue;
2893 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2895 HeapFree( GetProcessHeap(), 0, list );
2900 /**********************************************************************
2901 * EnumThreadWindows (USER32.@)
2903 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2908 USER_CheckNotLock();
2910 if (!(list = list_window_children( 0, GetDesktopWindow(), NULL, id ))) return TRUE;
2912 /* Now call the callback function for every window */
2914 for (i = 0; list[i]; i++)
2915 if (!func( list[i], lParam )) break;
2916 HeapFree( GetProcessHeap(), 0, list );
2921 /***********************************************************************
2922 * EnumDesktopWindows (USER32.@)
2924 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
2929 USER_CheckNotLock();
2931 if (!(list = list_window_children( desktop, 0, NULL, 0 ))) return TRUE;
2933 for (i = 0; list[i]; i++)
2934 if (!func( list[i], lparam )) break;
2935 HeapFree( GetProcessHeap(), 0, list );
2940 /**********************************************************************
2941 * WIN_EnumChildWindows
2943 * Helper function for EnumChildWindows().
2945 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2950 for ( ; *list; list++)
2952 /* Make sure that the window still exists */
2953 if (!IsWindow( *list )) continue;
2954 /* Build children list first */
2955 childList = WIN_ListChildren( *list );
2957 ret = func( *list, lParam );
2961 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2962 HeapFree( GetProcessHeap(), 0, childList );
2964 if (!ret) return FALSE;
2970 /**********************************************************************
2971 * EnumChildWindows (USER32.@)
2973 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2978 USER_CheckNotLock();
2980 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2981 ret = WIN_EnumChildWindows( list, func, lParam );
2982 HeapFree( GetProcessHeap(), 0, list );
2987 /*******************************************************************
2988 * AnyPopup (USER.52)
2990 BOOL16 WINAPI AnyPopup16(void)
2996 /*******************************************************************
2997 * AnyPopup (USER32.@)
2999 BOOL WINAPI AnyPopup(void)
3003 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3005 if (!list) return FALSE;
3006 for (i = 0; list[i]; i++)
3008 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3010 retvalue = (list[i] != 0);
3011 HeapFree( GetProcessHeap(), 0, list );
3016 /*******************************************************************
3017 * FlashWindow (USER32.@)
3019 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3023 TRACE("%p\n", hWnd);
3025 if (IsIconic( hWnd ))
3027 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3029 wndPtr = WIN_GetPtr(hWnd);
3030 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3031 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3033 wndPtr->flags |= WIN_NCACTIVATED;
3037 wndPtr->flags &= ~WIN_NCACTIVATED;
3039 WIN_ReleasePtr( wndPtr );
3046 wndPtr = WIN_GetPtr(hWnd);
3047 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3048 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3050 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3051 else wparam = (hWnd == GetForegroundWindow());
3053 WIN_ReleasePtr( wndPtr );
3054 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3059 /*******************************************************************
3060 * FlashWindowEx (USER32.@)
3062 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3064 FIXME("%p\n", pfwi);
3068 /*******************************************************************
3069 * GetWindowContextHelpId (USER32.@)
3071 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3074 WND *wnd = WIN_GetPtr( hwnd );
3075 if (!wnd || wnd == WND_DESKTOP) return 0;
3076 if (wnd == WND_OTHER_PROCESS)
3078 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3081 retval = wnd->helpContext;
3082 WIN_ReleasePtr( wnd );
3087 /*******************************************************************
3088 * SetWindowContextHelpId (USER32.@)
3090 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3092 WND *wnd = WIN_GetPtr( hwnd );
3093 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3094 if (wnd == WND_OTHER_PROCESS)
3096 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3099 wnd->helpContext = id;
3100 WIN_ReleasePtr( wnd );
3105 /*******************************************************************
3106 * DragDetect (USER32.@)
3108 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3112 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3113 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3115 rect.left = pt.x - wDragWidth;
3116 rect.right = pt.x + wDragWidth;
3118 rect.top = pt.y - wDragHeight;
3119 rect.bottom = pt.y + wDragHeight;
3125 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3127 if( msg.message == WM_LBUTTONUP )
3132 if( msg.message == WM_MOUSEMOVE )
3135 tmp.x = (short)LOWORD(msg.lParam);
3136 tmp.y = (short)HIWORD(msg.lParam);
3137 if( !PtInRect( &rect, tmp ))
3149 /******************************************************************************
3150 * GetWindowModuleFileNameA (USER32.@)
3152 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3154 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3155 hwnd, lpszFileName, cchFileNameMax);
3159 /******************************************************************************
3160 * GetWindowModuleFileNameW (USER32.@)
3162 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3164 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3165 hwnd, lpszFileName, cchFileNameMax);
3169 /******************************************************************************
3170 * GetWindowInfo (USER32.@)
3172 * Note: tests show that Windows doesn't check cbSize of the structure.
3174 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3176 if (!pwi) return FALSE;
3177 if (!IsWindow(hwnd)) return FALSE;
3179 GetWindowRect(hwnd, &pwi->rcWindow);
3180 GetClientRect(hwnd, &pwi->rcClient);
3181 /* translate to screen coordinates */
3182 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3184 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3185 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3186 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3188 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3189 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3191 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3192 pwi->wCreatorVersion = 0x0400;
3197 /******************************************************************************
3198 * SwitchDesktop (USER32.@)
3200 * NOTES: Sets the current input or interactive desktop.
3202 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3204 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3208 /*****************************************************************************
3209 * SetLayeredWindowAttributes (USER32.@)
3211 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3212 BYTE bAlpha, DWORD dwFlags )
3214 FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3218 /*****************************************************************************
3219 * GetLayeredWindowAttributes (USER32.@)
3221 BOOL WINAPI GetLayeredWindowAttributes( HWND hWnd, COLORREF *prgbKey,
3222 BYTE *pbAlpha, DWORD *pdwFlags )
3224 FIXME("(%p,%p,%p,%p): stub!\n", hWnd, prgbKey, pbAlpha, pdwFlags);
3228 /*****************************************************************************
3229 * UpdateLayeredWindow (USER32.@)
3231 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3232 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3239 FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3240 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3245 /* 64bit versions */
3247 #ifdef GetWindowLongPtrW
3248 #undef GetWindowLongPtrW
3251 #ifdef GetWindowLongPtrA
3252 #undef GetWindowLongPtrA
3255 #ifdef SetWindowLongPtrW
3256 #undef SetWindowLongPtrW
3259 #ifdef SetWindowLongPtrA
3260 #undef SetWindowLongPtrA
3263 /*****************************************************************************
3264 * GetWindowLongPtrW (USER32.@)
3266 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3268 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3271 /*****************************************************************************
3272 * GetWindowLongPtrA (USER32.@)
3274 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3276 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3279 /*****************************************************************************
3280 * SetWindowLongPtrW (USER32.@)
3282 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3284 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3287 /*****************************************************************************
3288 * SetWindowLongPtrA (USER32.@)
3290 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3292 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );