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, style, 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 /* call the driver */
1158 if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1160 NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1162 /* send the size messages */
1164 if (!(wndPtr = WIN_GetPtr(hwnd))) return 0;
1165 if (!(wndPtr->flags & WIN_NEED_SIZE))
1167 rect = wndPtr->rectClient;
1168 WIN_ReleasePtr( wndPtr );
1169 SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1170 MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1171 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1173 else WIN_ReleasePtr( wndPtr );
1175 /* Show the window, maximizing or minimizing if needed */
1177 style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
1178 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1181 UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1183 swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1184 swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
1185 if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
1186 SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right, newPos.bottom, swFlag );
1189 /* Notify the parent window only */
1191 send_parent_notify( hwnd, WM_CREATE );
1192 if (!IsWindow( hwnd )) return 0;
1194 if (cs->style & WS_VISIBLE)
1196 if (cs->style & WS_MAXIMIZE)
1198 else if (cs->style & WS_MINIMIZE)
1199 sw = SW_SHOWMINIMIZED;
1201 ShowWindow( hwnd, sw );
1202 if (cs->dwExStyle & WS_EX_MDICHILD)
1204 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1205 /* ShowWindow won't activate child windows */
1206 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1210 /* Call WH_SHELL hook */
1212 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1213 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1215 TRACE("created window %p\n", hwnd);
1219 WIN_DestroyWindow( hwnd );
1224 /***********************************************************************
1225 * CreateWindow (USER.41)
1227 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1228 DWORD style, INT16 x, INT16 y, INT16 width,
1229 INT16 height, HWND16 parent, HMENU16 menu,
1230 HINSTANCE16 instance, LPVOID data )
1232 return CreateWindowEx16( 0, className, windowName, style,
1233 x, y, width, height, parent, menu, instance, data );
1237 /***********************************************************************
1238 * CreateWindowEx (USER.452)
1240 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1241 LPCSTR windowName, DWORD style, INT16 x,
1242 INT16 y, INT16 width, INT16 height,
1243 HWND16 parent, HMENU16 menu,
1244 HINSTANCE16 instance, LPVOID data )
1249 /* Fix the coordinates */
1251 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1252 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1253 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1254 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1256 /* Create the window */
1258 cs.lpCreateParams = data;
1259 cs.hInstance = HINSTANCE_32(instance);
1260 cs.hMenu = HMENU_32(menu);
1261 cs.hwndParent = WIN_Handle32( parent );
1263 cs.lpszName = windowName;
1264 cs.lpszClass = className;
1265 cs.dwExStyle = exStyle;
1267 if (!IS_INTRESOURCE(className))
1271 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1273 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1277 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1279 ERR( "bad atom %x\n", LOWORD(className));
1282 cs.lpszClass = buffer;
1283 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1288 /***********************************************************************
1289 * CreateWindowExA (USER32.@)
1291 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1292 LPCSTR windowName, DWORD style, INT x,
1293 INT y, INT width, INT height,
1294 HWND parent, HMENU menu,
1295 HINSTANCE instance, LPVOID data )
1299 cs.lpCreateParams = data;
1300 cs.hInstance = instance;
1302 cs.hwndParent = parent;
1308 cs.lpszName = windowName;
1309 cs.lpszClass = className;
1310 cs.dwExStyle = exStyle;
1312 if (!IS_INTRESOURCE(className))
1315 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1317 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1319 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1323 /***********************************************************************
1324 * CreateWindowExW (USER32.@)
1326 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1327 LPCWSTR windowName, DWORD style, INT x,
1328 INT y, INT width, INT height,
1329 HWND parent, HMENU menu,
1330 HINSTANCE instance, LPVOID data )
1334 cs.lpCreateParams = data;
1335 cs.hInstance = instance;
1337 cs.hwndParent = parent;
1343 cs.lpszName = windowName;
1344 cs.lpszClass = className;
1345 cs.dwExStyle = exStyle;
1347 /* Note: we rely on the fact that CREATESTRUCTA and */
1348 /* CREATESTRUCTW have the same layout. */
1349 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1353 /***********************************************************************
1354 * WIN_SendDestroyMsg
1356 static void WIN_SendDestroyMsg( HWND hwnd )
1360 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1362 if (hwnd == info.hwndCaret) DestroyCaret();
1363 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1367 * Send the WM_DESTROY to the window.
1369 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1372 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1373 * make sure that the window still exists when we come back.
1380 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1382 for (i = 0; pWndArray[i]; i++)
1384 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1386 HeapFree( GetProcessHeap(), 0, pWndArray );
1389 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1393 /***********************************************************************
1394 * DestroyWindow (USER32.@)
1396 BOOL WINAPI DestroyWindow( HWND hwnd )
1400 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1402 SetLastError( ERROR_ACCESS_DENIED );
1406 TRACE("(%p)\n", hwnd);
1410 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1412 if (MENU_IsMenuActive() == hwnd)
1415 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1419 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1420 send_parent_notify( hwnd, WM_DESTROY );
1422 else if (!GetWindow( hwnd, GW_OWNER ))
1424 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1425 /* FIXME: clean up palette - see "Internals" p.352 */
1428 if (!IsWindow(hwnd)) return TRUE;
1430 /* Hide the window */
1431 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1433 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1435 ShowWindow( hwnd, SW_HIDE );
1437 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1438 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1441 if (!IsWindow(hwnd)) return TRUE;
1443 /* Recursively destroy owned windows */
1450 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1453 for (i = 0; list[i]; i++)
1455 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1456 if (WIN_IsCurrentThread( list[i] ))
1458 DestroyWindow( list[i] );
1462 WIN_SetOwner( list[i], 0 );
1464 HeapFree( GetProcessHeap(), 0, list );
1466 if (!got_one) break;
1470 /* Send destroy messages */
1472 WIN_SendDestroyMsg( hwnd );
1473 if (!IsWindow( hwnd )) return TRUE;
1475 if (GetClipboardOwner() == hwnd)
1476 CLIPBOARD_ReleaseOwner();
1478 /* Destroy the window storage */
1480 WIN_DestroyWindow( hwnd );
1485 /***********************************************************************
1486 * CloseWindow (USER32.@)
1488 BOOL WINAPI CloseWindow( HWND hwnd )
1490 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1491 ShowWindow( hwnd, SW_MINIMIZE );
1496 /***********************************************************************
1497 * OpenIcon (USER32.@)
1499 BOOL WINAPI OpenIcon( HWND hwnd )
1501 if (!IsIconic( hwnd )) return FALSE;
1502 ShowWindow( hwnd, SW_SHOWNORMAL );
1507 /***********************************************************************
1508 * FindWindowExW (USER32.@)
1510 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1515 WCHAR *buffer = NULL;
1517 if (!parent) parent = GetDesktopWindow();
1520 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1521 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1524 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1528 child = WIN_GetFullHandle( child );
1529 while (list[i] && list[i] != child) i++;
1530 if (!list[i]) goto done;
1531 i++; /* start from next window */
1538 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1545 HeapFree( GetProcessHeap(), 0, list );
1546 HeapFree( GetProcessHeap(), 0, buffer );
1552 /***********************************************************************
1553 * FindWindowA (USER32.@)
1555 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1557 HWND ret = FindWindowExA( 0, 0, className, title );
1558 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1563 /***********************************************************************
1564 * FindWindowExA (USER32.@)
1566 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1568 LPWSTR titleW = NULL;
1573 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1574 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1575 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1578 if (!IS_INTRESOURCE(className))
1581 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1582 hwnd = FindWindowExW( parent, child, classW, titleW );
1586 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1589 HeapFree( GetProcessHeap(), 0, titleW );
1594 /***********************************************************************
1595 * FindWindowW (USER32.@)
1597 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1599 return FindWindowExW( 0, 0, className, title );
1603 /**********************************************************************
1604 * GetDesktopWindow (USER32.@)
1606 HWND WINAPI GetDesktopWindow(void)
1608 struct user_thread_info *thread_info = get_user_thread_info();
1610 if (thread_info->desktop) return thread_info->desktop;
1612 SERVER_START_REQ( get_desktop_window )
1615 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1619 if (!thread_info->desktop)
1621 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1623 PROCESS_INFORMATION pi;
1624 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1626 memset( &si, 0, sizeof(si) );
1628 si.dwFlags = STARTF_USESTDHANDLES;
1631 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1633 GetSystemDirectoryW( cmdline, MAX_PATH );
1634 lstrcatW( cmdline, command_line );
1635 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1636 NULL, NULL, &si, &pi ))
1638 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1639 WaitForInputIdle( pi.hProcess, 10000 );
1640 CloseHandle( pi.hThread );
1641 CloseHandle( pi.hProcess );
1644 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1646 SERVER_START_REQ( get_desktop_window )
1649 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1654 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1655 ERR( "failed to create desktop window\n" );
1657 return thread_info->desktop;
1661 /*******************************************************************
1662 * EnableWindow (USER32.@)
1664 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1669 if (is_broadcast(hwnd))
1671 SetLastError( ERROR_INVALID_PARAMETER );
1675 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1676 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1680 TRACE("( %p, %d )\n", hwnd, enable);
1682 retvalue = !IsWindowEnabled( hwnd );
1684 if (enable && retvalue)
1686 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1687 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1689 else if (!enable && !retvalue)
1693 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1695 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1697 if (hwnd == GetFocus())
1698 SetFocus( 0 ); /* A disabled window can't have the focus */
1700 capture_wnd = GetCapture();
1701 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1702 ReleaseCapture(); /* A disabled window can't capture the mouse */
1704 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1710 /***********************************************************************
1711 * IsWindowEnabled (USER32.@)
1713 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1715 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1719 /***********************************************************************
1720 * IsWindowUnicode (USER32.@)
1722 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1725 BOOL retvalue = FALSE;
1727 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1729 if (wndPtr == WND_DESKTOP) return TRUE;
1731 if (wndPtr != WND_OTHER_PROCESS)
1733 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1734 WIN_ReleasePtr( wndPtr );
1738 SERVER_START_REQ( get_window_info )
1741 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1749 /**********************************************************************
1752 * Helper function for GetWindowLong().
1754 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1756 LONG_PTR retvalue = 0;
1759 if (offset == GWLP_HWNDPARENT)
1761 HWND parent = GetAncestor( hwnd, GA_PARENT );
1762 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1763 return (ULONG_PTR)parent;
1766 if (!(wndPtr = WIN_GetPtr( hwnd )))
1768 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1772 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1774 if (offset == GWLP_WNDPROC)
1776 SetLastError( ERROR_ACCESS_DENIED );
1779 SERVER_START_REQ( set_window_info )
1782 req->flags = 0; /* don't set anything, just retrieve */
1783 req->extra_offset = (offset >= 0) ? offset : -1;
1784 req->extra_size = (offset >= 0) ? size : 0;
1785 if (!wine_server_call_err( req ))
1789 case GWL_STYLE: retvalue = reply->old_style; break;
1790 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1791 case GWLP_ID: retvalue = reply->old_id; break;
1792 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1793 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1795 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1796 else SetLastError( ERROR_INVALID_INDEX );
1805 /* now we have a valid wndPtr */
1809 if (offset > (int)(wndPtr->cbWndExtra - size))
1811 WARN("Invalid offset %d\n", offset );
1812 WIN_ReleasePtr( wndPtr );
1813 SetLastError( ERROR_INVALID_INDEX );
1816 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1818 /* Special case for dialog window procedure */
1819 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1820 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1821 WIN_ReleasePtr( wndPtr );
1827 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1828 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1829 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1830 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
1831 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1833 /* This looks like a hack only for the edit control (see tests). This makes these controls
1834 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1835 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1837 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1838 retvalue = (ULONG_PTR)wndPtr->winproc;
1840 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1843 WARN("Unknown offset %d\n", offset );
1844 SetLastError( ERROR_INVALID_INDEX );
1847 WIN_ReleasePtr(wndPtr);
1852 /**********************************************************************
1855 * Helper function for SetWindowLong().
1857 * 0 is the failure code. However, in the case of failure SetLastError
1858 * must be set to distinguish between a 0 return value and a failure.
1860 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1864 LONG_PTR retval = 0;
1867 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1869 if (is_broadcast(hwnd))
1871 SetLastError( ERROR_INVALID_PARAMETER );
1875 if (!(wndPtr = WIN_GetPtr( hwnd )))
1877 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1880 if (wndPtr == WND_DESKTOP)
1882 /* can't change anything on the desktop window */
1883 SetLastError( ERROR_ACCESS_DENIED );
1886 if (wndPtr == WND_OTHER_PROCESS)
1888 if (offset == GWLP_WNDPROC)
1890 SetLastError( ERROR_ACCESS_DENIED );
1893 if (offset > 32767 || offset < -32767)
1895 SetLastError( ERROR_INVALID_INDEX );
1898 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1901 /* first some special cases */
1907 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1908 style.styleNew = newval;
1909 WIN_ReleasePtr( wndPtr );
1910 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1911 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1912 newval = style.styleNew;
1914 case GWLP_HWNDPARENT:
1915 if (wndPtr->parent == GetDesktopWindow())
1917 WIN_ReleasePtr( wndPtr );
1918 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1922 WIN_ReleasePtr( wndPtr );
1923 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1928 UINT old_flags = wndPtr->flags;
1929 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
1930 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1931 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1932 if (proc) wndPtr->winproc = proc;
1933 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1934 else wndPtr->flags &= ~WIN_ISUNICODE;
1935 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1937 WIN_ReleasePtr( wndPtr );
1940 /* update is_unicode flag on the server side */
1944 case GWLP_HINSTANCE:
1948 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1949 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1951 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1952 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1953 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1954 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1955 WIN_ReleasePtr( wndPtr );
1960 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1962 WARN("Invalid offset %d\n", offset );
1963 WIN_ReleasePtr( wndPtr );
1964 SetLastError( ERROR_INVALID_INDEX );
1967 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1969 /* already set to the same value */
1970 WIN_ReleasePtr( wndPtr );
1976 SERVER_START_REQ( set_window_info )
1979 req->extra_offset = -1;
1983 req->flags = SET_WIN_STYLE;
1984 req->style = newval;
1987 req->flags = SET_WIN_EXSTYLE;
1988 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
1989 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
1990 req->ex_style = newval;
1993 req->flags = SET_WIN_ID;
1996 case GWLP_HINSTANCE:
1997 req->flags = SET_WIN_INSTANCE;
1998 req->instance = (void *)newval;
2001 req->flags = SET_WIN_UNICODE;
2002 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2005 req->flags = SET_WIN_USERDATA;
2006 req->user_data = newval;
2009 req->flags = SET_WIN_EXTRA;
2010 req->extra_offset = offset;
2011 req->extra_size = size;
2012 set_win_data( &req->extra_value, newval, size );
2014 if ((ok = !wine_server_call_err( req )))
2019 wndPtr->dwStyle = newval;
2020 retval = reply->old_style;
2023 wndPtr->dwExStyle = newval;
2024 retval = reply->old_ex_style;
2027 wndPtr->wIDmenu = newval;
2028 retval = reply->old_id;
2030 case GWLP_HINSTANCE:
2031 wndPtr->hInstance = (HINSTANCE)newval;
2032 retval = (ULONG_PTR)reply->old_instance;
2037 wndPtr->userdata = newval;
2038 retval = reply->old_user_data;
2041 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2042 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2048 WIN_ReleasePtr( wndPtr );
2052 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2054 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2055 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2061 /**********************************************************************
2062 * GetWindowLong (USER.135)
2064 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2068 BOOL is_winproc = (offset == GWLP_WNDPROC);
2072 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2074 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2077 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2079 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2082 * Some programs try to access last element from 16 bit
2083 * code using illegal offset value. Hopefully this is
2084 * what those programs really expect.
2086 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2088 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2089 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2094 WARN("Invalid offset %d\n", offset );
2095 WIN_ReleasePtr( wndPtr );
2096 SetLastError( ERROR_INVALID_INDEX );
2100 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2101 WIN_ReleasePtr( wndPtr );
2104 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2105 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2110 /**********************************************************************
2111 * GetWindowWord (USER32.@)
2113 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2118 case GWLP_HINSTANCE:
2119 case GWLP_HWNDPARENT:
2124 WARN("Invalid offset %d\n", offset );
2125 SetLastError( ERROR_INVALID_INDEX );
2130 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2134 /**********************************************************************
2135 * GetWindowLongA (USER32.@)
2137 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2139 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2143 /**********************************************************************
2144 * GetWindowLongW (USER32.@)
2146 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2148 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2152 /**********************************************************************
2153 * SetWindowLong (USER.136)
2155 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2158 BOOL is_winproc = (offset == GWLP_WNDPROC);
2160 if (offset == DWLP_DLGPROC)
2162 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2164 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2167 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2169 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2170 (wndPtr->flags & WIN_ISDIALOG));
2171 WIN_ReleasePtr( wndPtr );
2177 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2178 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2179 return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2181 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2185 /**********************************************************************
2186 * SetWindowWord (USER32.@)
2188 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2193 case GWLP_HINSTANCE:
2194 case GWLP_HWNDPARENT:
2199 WARN("Invalid offset %d\n", offset );
2200 SetLastError( ERROR_INVALID_INDEX );
2205 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2209 /**********************************************************************
2210 * SetWindowLongA (USER32.@)
2212 * See SetWindowLongW.
2214 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2216 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2220 /**********************************************************************
2221 * SetWindowLongW (USER32.@) Set window attribute
2223 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2224 * value in a window's extra memory.
2226 * The _hwnd_ parameter specifies the window. is the handle to a
2227 * window that has extra memory. The _newval_ parameter contains the
2228 * new attribute or extra memory value. If positive, the _offset_
2229 * parameter is the byte-addressed location in the window's extra
2230 * memory to set. If negative, _offset_ specifies the window
2231 * attribute to set, and should be one of the following values:
2233 * GWL_EXSTYLE The window's extended window style
2235 * GWL_STYLE The window's window style.
2237 * GWLP_WNDPROC Pointer to the window's window procedure.
2239 * GWLP_HINSTANCE The window's pplication instance handle.
2241 * GWLP_ID The window's identifier.
2243 * GWLP_USERDATA The window's user-specified data.
2245 * If the window is a dialog box, the _offset_ parameter can be one of
2246 * the following values:
2248 * DWLP_DLGPROC The address of the window's dialog box procedure.
2250 * DWLP_MSGRESULT The return value of a message
2251 * that the dialog box procedure processed.
2253 * DWLP_USER Application specific information.
2257 * If successful, returns the previous value located at _offset_. Otherwise,
2262 * Extra memory for a window class is specified by a nonzero cbWndExtra
2263 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2264 * time of class creation.
2266 * Using GWL_WNDPROC to set a new window procedure effectively creates
2267 * a window subclass. Use CallWindowProc() in the new windows procedure
2268 * to pass messages to the superclass's window procedure.
2270 * The user data is reserved for use by the application which created
2273 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2274 * instead, call the EnableWindow() function to change the window's
2277 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2278 * SetParent() instead.
2281 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2282 * it sends WM_STYLECHANGING before changing the settings
2283 * and WM_STYLECHANGED afterwards.
2284 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2286 LONG WINAPI SetWindowLongW(
2287 HWND hwnd, /* [in] window to alter */
2288 INT offset, /* [in] offset, in bytes, of location to alter */
2289 LONG newval /* [in] new value of location */
2291 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2295 /*******************************************************************
2296 * GetWindowTextA (USER32.@)
2298 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2302 if (!lpString) return 0;
2304 if (WIN_IsCurrentProcess( hwnd ))
2305 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2307 /* when window belongs to other process, don't send a message */
2308 if (nMaxCount <= 0) return 0;
2309 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2310 get_server_window_text( hwnd, buffer, nMaxCount );
2311 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2312 lpString[nMaxCount-1] = 0;
2313 HeapFree( GetProcessHeap(), 0, buffer );
2314 return strlen(lpString);
2318 /*******************************************************************
2319 * InternalGetWindowText (USER32.@)
2321 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2325 if (nMaxCount <= 0) return 0;
2326 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2327 if (win == WND_DESKTOP) lpString[0] = 0;
2328 else if (win != WND_OTHER_PROCESS)
2330 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2331 else lpString[0] = 0;
2332 WIN_ReleasePtr( win );
2336 get_server_window_text( hwnd, lpString, nMaxCount );
2338 return strlenW(lpString);
2342 /*******************************************************************
2343 * GetWindowTextW (USER32.@)
2345 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2347 if (!lpString) return 0;
2349 if (WIN_IsCurrentProcess( hwnd ))
2350 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2352 /* when window belongs to other process, don't send a message */
2353 if (nMaxCount <= 0) return 0;
2354 get_server_window_text( hwnd, lpString, nMaxCount );
2355 return strlenW(lpString);
2359 /*******************************************************************
2360 * SetWindowTextA (USER32.@)
2361 * SetWindowText (USER32.@)
2363 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2365 if (is_broadcast(hwnd))
2367 SetLastError( ERROR_INVALID_PARAMETER );
2370 if (!WIN_IsCurrentProcess( hwnd ))
2371 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2372 debugstr_a(lpString), hwnd );
2373 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2377 /*******************************************************************
2378 * SetWindowTextW (USER32.@)
2380 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2382 if (is_broadcast(hwnd))
2384 SetLastError( ERROR_INVALID_PARAMETER );
2387 if (!WIN_IsCurrentProcess( hwnd ))
2388 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2389 debugstr_w(lpString), hwnd );
2390 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2394 /*******************************************************************
2395 * GetWindowTextLengthA (USER32.@)
2397 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2399 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2402 /*******************************************************************
2403 * GetWindowTextLengthW (USER32.@)
2405 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2407 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2411 /*******************************************************************
2412 * IsWindow (USER32.@)
2414 BOOL WINAPI IsWindow( HWND hwnd )
2419 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2420 if (ptr == WND_DESKTOP) return TRUE;
2422 if (ptr != WND_OTHER_PROCESS)
2424 WIN_ReleasePtr( ptr );
2428 /* check other processes */
2429 SERVER_START_REQ( get_window_info )
2432 ret = !wine_server_call_err( req );
2439 /***********************************************************************
2440 * GetWindowThreadProcessId (USER32.@)
2442 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2447 if (!(ptr = WIN_GetPtr( hwnd )))
2449 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2453 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2455 /* got a valid window */
2457 if (process) *process = GetCurrentProcessId();
2458 WIN_ReleasePtr( ptr );
2462 /* check other processes */
2463 SERVER_START_REQ( get_window_info )
2466 if (!wine_server_call_err( req ))
2468 tid = (DWORD)reply->tid;
2469 if (process) *process = (DWORD)reply->pid;
2477 /*****************************************************************
2478 * GetParent (USER32.@)
2480 HWND WINAPI GetParent( HWND hwnd )
2485 if (!(wndPtr = WIN_GetPtr( hwnd )))
2487 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2490 if (wndPtr == WND_DESKTOP) return 0;
2491 if (wndPtr == WND_OTHER_PROCESS)
2493 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2494 if (style & (WS_POPUP | WS_CHILD))
2496 SERVER_START_REQ( get_window_tree )
2499 if (!wine_server_call_err( req ))
2501 if (style & WS_POPUP) retvalue = reply->owner;
2502 else if (style & WS_CHILD) retvalue = reply->parent;
2510 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2511 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2512 WIN_ReleasePtr( wndPtr );
2518 /*****************************************************************
2519 * GetAncestor (USER32.@)
2521 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2524 HWND *list, ret = 0;
2529 if (!(win = WIN_GetPtr( hwnd )))
2531 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2534 if (win == WND_DESKTOP) return 0;
2535 if (win != WND_OTHER_PROCESS)
2538 WIN_ReleasePtr( win );
2540 else /* need to query the server */
2542 SERVER_START_REQ( get_window_tree )
2545 if (!wine_server_call_err( req )) ret = reply->parent;
2552 if (!(list = list_window_parents( hwnd ))) return 0;
2554 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2558 while (list[count]) count++;
2559 ret = list[count - 2]; /* get the one before the desktop */
2561 HeapFree( GetProcessHeap(), 0, list );
2565 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2568 HWND parent = GetParent( ret );
2578 /*****************************************************************
2579 * SetParent (USER32.@)
2581 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2584 HWND old_parent = 0;
2589 if (is_broadcast(hwnd) || is_broadcast(parent))
2591 SetLastError(ERROR_INVALID_PARAMETER);
2595 if (!parent) parent = GetDesktopWindow();
2596 else parent = WIN_GetFullHandle( parent );
2598 if (!IsWindow( parent ))
2600 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2604 /* Some applications try to set a child as a parent */
2605 if (IsChild(hwnd, parent))
2607 SetLastError( ERROR_INVALID_PARAMETER );
2611 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2612 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2614 /* Windows hides the window first, then shows it again
2615 * including the WM_SHOWWINDOW messages and all */
2616 was_visible = ShowWindow( hwnd, SW_HIDE );
2618 wndPtr = WIN_GetPtr( hwnd );
2619 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2621 SERVER_START_REQ( set_parent )
2624 req->parent = parent;
2625 if ((ret = !wine_server_call( req )))
2627 old_parent = reply->old_parent;
2628 wndPtr->parent = parent = reply->full_parent;
2633 WIN_ReleasePtr( wndPtr );
2636 USER_Driver->pSetParent( full_handle, parent, old_parent );
2638 /* SetParent additionally needs to make hwnd the topmost window
2639 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2640 WM_WINDOWPOSCHANGED notification messages.
2642 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2643 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2644 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2645 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2651 /*******************************************************************
2652 * IsChild (USER32.@)
2654 BOOL WINAPI IsChild( HWND parent, HWND child )
2656 HWND *list = list_window_parents( child );
2660 if (!list) return FALSE;
2661 parent = WIN_GetFullHandle( parent );
2662 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2663 ret = list[i] && list[i+1];
2664 HeapFree( GetProcessHeap(), 0, list );
2669 /***********************************************************************
2670 * IsWindowVisible (USER32.@)
2672 BOOL WINAPI IsWindowVisible( HWND hwnd )
2678 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2679 if (!(list = list_window_parents( hwnd ))) return TRUE;
2680 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2682 for (i = 0; list[i+1]; i++)
2683 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2684 retval = !list[i+1];
2686 HeapFree( GetProcessHeap(), 0, list );
2691 /***********************************************************************
2692 * WIN_IsWindowDrawable
2694 * hwnd is drawable when it is visible, all parents are not
2695 * minimized, and it is itself not minimized unless we are
2696 * trying to draw its default class icon.
2698 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2703 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2705 if (!(style & WS_VISIBLE)) return FALSE;
2706 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2708 if (!(list = list_window_parents( hwnd ))) return TRUE;
2709 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2711 for (i = 0; list[i+1]; i++)
2712 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2714 retval = !list[i+1];
2716 HeapFree( GetProcessHeap(), 0, list );
2721 /*******************************************************************
2722 * GetTopWindow (USER32.@)
2724 HWND WINAPI GetTopWindow( HWND hwnd )
2726 if (!hwnd) hwnd = GetDesktopWindow();
2727 return GetWindow( hwnd, GW_CHILD );
2731 /*******************************************************************
2732 * GetWindow (USER32.@)
2734 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2738 if (rel == GW_OWNER) /* this one may be available locally */
2740 WND *wndPtr = WIN_GetPtr( hwnd );
2743 SetLastError( ERROR_INVALID_HANDLE );
2746 if (wndPtr == WND_DESKTOP) return 0;
2747 if (wndPtr != WND_OTHER_PROCESS)
2749 retval = wndPtr->owner;
2750 WIN_ReleasePtr( wndPtr );
2753 /* else fall through to server call */
2756 SERVER_START_REQ( get_window_tree )
2759 if (!wine_server_call_err( req ))
2764 retval = reply->first_sibling;
2767 retval = reply->last_sibling;
2770 retval = reply->next_sibling;
2773 retval = reply->prev_sibling;
2776 retval = reply->owner;
2779 retval = reply->first_child;
2789 /*******************************************************************
2790 * ShowOwnedPopups (USER32.@)
2792 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2796 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2798 if (!win_array) return TRUE;
2800 while (win_array[count]) count++;
2801 while (--count >= 0)
2803 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2804 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2805 if (pWnd == WND_OTHER_PROCESS) continue;
2808 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2810 WIN_ReleasePtr( pWnd );
2811 /* In Windows, ShowOwnedPopups(TRUE) generates
2812 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2813 * regardless of the state of the owner
2815 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2821 if (pWnd->dwStyle & WS_VISIBLE)
2823 WIN_ReleasePtr( pWnd );
2824 /* In Windows, ShowOwnedPopups(FALSE) generates
2825 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2826 * regardless of the state of the owner
2828 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2832 WIN_ReleasePtr( pWnd );
2834 HeapFree( GetProcessHeap(), 0, win_array );
2839 /*******************************************************************
2840 * GetLastActivePopup (USER32.@)
2842 HWND WINAPI GetLastActivePopup( HWND hwnd )
2846 SERVER_START_REQ( get_window_info )
2849 if (!wine_server_call_err( req )) retval = reply->last_active;
2856 /*******************************************************************
2859 * Build an array of the children of a given window. The array must be
2860 * freed with HeapFree. Returns NULL when no windows are found.
2862 HWND *WIN_ListChildren( HWND hwnd )
2864 return list_window_children( hwnd, NULL, 0 );
2868 /*******************************************************************
2869 * EnumWindows (USER32.@)
2871 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2877 USER_CheckNotLock();
2879 /* We have to build a list of all windows first, to avoid */
2880 /* unpleasant side-effects, for instance if the callback */
2881 /* function changes the Z-order of the windows. */
2883 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2885 /* Now call the callback function for every window */
2887 for (i = 0; list[i]; i++)
2889 /* Make sure that the window still exists */
2890 if (!IsWindow( list[i] )) continue;
2891 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2893 HeapFree( GetProcessHeap(), 0, list );
2898 /**********************************************************************
2899 * EnumThreadWindows (USER32.@)
2901 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2906 USER_CheckNotLock();
2908 if (!(list = list_window_children( GetDesktopWindow(), NULL, id ))) return TRUE;
2910 /* Now call the callback function for every window */
2912 for (i = 0; list[i]; i++)
2913 if (!func( list[i], lParam )) break;
2914 HeapFree( GetProcessHeap(), 0, list );
2919 /**********************************************************************
2920 * WIN_EnumChildWindows
2922 * Helper function for EnumChildWindows().
2924 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2929 for ( ; *list; list++)
2931 /* Make sure that the window still exists */
2932 if (!IsWindow( *list )) continue;
2933 /* Build children list first */
2934 childList = WIN_ListChildren( *list );
2936 ret = func( *list, lParam );
2940 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2941 HeapFree( GetProcessHeap(), 0, childList );
2943 if (!ret) return FALSE;
2949 /**********************************************************************
2950 * EnumChildWindows (USER32.@)
2952 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2957 USER_CheckNotLock();
2959 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2960 ret = WIN_EnumChildWindows( list, func, lParam );
2961 HeapFree( GetProcessHeap(), 0, list );
2966 /*******************************************************************
2967 * AnyPopup (USER.52)
2969 BOOL16 WINAPI AnyPopup16(void)
2975 /*******************************************************************
2976 * AnyPopup (USER32.@)
2978 BOOL WINAPI AnyPopup(void)
2982 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2984 if (!list) return FALSE;
2985 for (i = 0; list[i]; i++)
2987 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2989 retvalue = (list[i] != 0);
2990 HeapFree( GetProcessHeap(), 0, list );
2995 /*******************************************************************
2996 * FlashWindow (USER32.@)
2998 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3002 TRACE("%p\n", hWnd);
3004 if (IsIconic( hWnd ))
3006 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3008 wndPtr = WIN_GetPtr(hWnd);
3009 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3010 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3012 wndPtr->flags |= WIN_NCACTIVATED;
3016 wndPtr->flags &= ~WIN_NCACTIVATED;
3018 WIN_ReleasePtr( wndPtr );
3025 wndPtr = WIN_GetPtr(hWnd);
3026 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3027 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3029 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3030 else wparam = (hWnd == GetForegroundWindow());
3032 WIN_ReleasePtr( wndPtr );
3033 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3038 /*******************************************************************
3039 * FlashWindowEx (USER32.@)
3041 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3043 FIXME("%p\n", pfwi);
3047 /*******************************************************************
3048 * GetWindowContextHelpId (USER32.@)
3050 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3053 WND *wnd = WIN_GetPtr( hwnd );
3054 if (!wnd || wnd == WND_DESKTOP) return 0;
3055 if (wnd == WND_OTHER_PROCESS)
3057 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3060 retval = wnd->helpContext;
3061 WIN_ReleasePtr( wnd );
3066 /*******************************************************************
3067 * SetWindowContextHelpId (USER32.@)
3069 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3071 WND *wnd = WIN_GetPtr( hwnd );
3072 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3073 if (wnd == WND_OTHER_PROCESS)
3075 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3078 wnd->helpContext = id;
3079 WIN_ReleasePtr( wnd );
3084 /*******************************************************************
3085 * DragDetect (USER32.@)
3087 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3091 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3092 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3094 rect.left = pt.x - wDragWidth;
3095 rect.right = pt.x + wDragWidth;
3097 rect.top = pt.y - wDragHeight;
3098 rect.bottom = pt.y + wDragHeight;
3104 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3106 if( msg.message == WM_LBUTTONUP )
3111 if( msg.message == WM_MOUSEMOVE )
3114 tmp.x = (short)LOWORD(msg.lParam);
3115 tmp.y = (short)HIWORD(msg.lParam);
3116 if( !PtInRect( &rect, tmp ))
3128 /******************************************************************************
3129 * GetWindowModuleFileNameA (USER32.@)
3131 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3133 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3134 hwnd, lpszFileName, cchFileNameMax);
3138 /******************************************************************************
3139 * GetWindowModuleFileNameW (USER32.@)
3141 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3143 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3144 hwnd, lpszFileName, cchFileNameMax);
3148 /******************************************************************************
3149 * GetWindowInfo (USER32.@)
3151 * Note: tests show that Windows doesn't check cbSize of the structure.
3153 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3155 if (!pwi) return FALSE;
3156 if (!IsWindow(hwnd)) return FALSE;
3158 GetWindowRect(hwnd, &pwi->rcWindow);
3159 GetClientRect(hwnd, &pwi->rcClient);
3160 /* translate to screen coordinates */
3161 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3163 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3164 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3165 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3167 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3168 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3170 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3171 pwi->wCreatorVersion = 0x0400;
3176 /******************************************************************************
3177 * SwitchDesktop (USER32.@)
3179 * NOTES: Sets the current input or interactive desktop.
3181 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3183 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3187 /*****************************************************************************
3188 * SetLayeredWindowAttributes (USER32.@)
3190 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3191 BYTE bAlpha, DWORD dwFlags )
3193 FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3197 /*****************************************************************************
3198 * GetLayeredWindowAttributes (USER32.@)
3200 BOOL WINAPI GetLayeredWindowAttributes( HWND hWnd, COLORREF *prgbKey,
3201 BYTE *pbAlpha, DWORD *pdwFlags )
3203 FIXME("(%p,%p,%p,%p): stub!\n", hWnd, prgbKey, pbAlpha, pdwFlags);
3207 /*****************************************************************************
3208 * UpdateLayeredWindow (USER32.@)
3210 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3211 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3218 FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3219 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3224 /* 64bit versions */
3226 #ifdef GetWindowLongPtrW
3227 #undef GetWindowLongPtrW
3230 #ifdef GetWindowLongPtrA
3231 #undef GetWindowLongPtrA
3234 #ifdef SetWindowLongPtrW
3235 #undef SetWindowLongPtrW
3238 #ifdef SetWindowLongPtrA
3239 #undef SetWindowLongPtrA
3242 /*****************************************************************************
3243 * GetWindowLongPtrW (USER32.@)
3245 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3247 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3250 /*****************************************************************************
3251 * GetWindowLongPtrA (USER32.@)
3253 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3255 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3258 /*****************************************************************************
3259 * SetWindowLongPtrW (USER32.@)
3261 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3263 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3266 /*****************************************************************************
3267 * SetWindowLongPtrA (USER32.@)
3269 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3271 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );