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"
37 #include "user_private.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(win);
44 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
45 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
47 /**********************************************************************/
49 /* helper for Get/SetWindowLong */
50 static inline LONG_PTR get_win_data( const void *ptr, UINT size )
52 if (size == sizeof(WORD))
55 memcpy( &ret, ptr, sizeof(ret) );
58 else if (size == sizeof(DWORD))
61 memcpy( &ret, ptr, sizeof(ret) );
67 memcpy( &ret, ptr, sizeof(ret) );
72 /* helper for Get/SetWindowLong */
73 static inline void set_win_data( void *ptr, LONG_PTR val, UINT size )
75 if (size == sizeof(WORD))
78 memcpy( ptr, &newval, sizeof(newval) );
80 else if (size == sizeof(DWORD))
83 memcpy( ptr, &newval, sizeof(newval) );
87 memcpy( ptr, &val, sizeof(val) );
92 static void *user_handles[NB_USER_HANDLES];
94 /***********************************************************************
95 * create_window_handle
97 * Create a window handle with the server.
99 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
100 HINSTANCE instance, BOOL unicode )
104 HWND full_parent = 0, full_owner = 0;
105 struct tagCLASS *class = NULL;
106 user_handle_t handle = 0;
109 /* if 16-bit instance, map to module handle */
110 if (instance && !HIWORD(instance))
111 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
113 SERVER_START_REQ( create_window )
115 req->parent = parent;
118 req->instance = instance;
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 %ld creating window\n", GetLastError() );
136 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
138 SERVER_START_REQ( destroy_window )
140 req->handle = handle;
141 wine_server_call( req );
144 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
148 if (!parent) /* if parent is 0 we don't have a desktop window yet */
150 struct user_thread_info *thread_info = get_user_thread_info();
152 assert( !thread_info->desktop );
153 thread_info->desktop = full_parent ? full_parent : handle;
154 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
155 ERR( "failed to create desktop window\n" );
160 index = USER_HANDLE_TO_INDEX(handle);
161 assert( index < NB_USER_HANDLES );
162 user_handles[index] = win;
163 win->hwndSelf = handle;
164 win->parent = full_parent;
165 win->owner = full_owner;
166 win->dwMagic = WND_MAGIC;
168 win->cbWndExtra = extra_bytes;
169 memset( win->wExtra, 0, extra_bytes );
170 CLASS_AddWindow( class, win, unicode );
175 /***********************************************************************
178 * Free a window handle.
180 static WND *free_window_handle( HWND hwnd )
183 WORD index = USER_HANDLE_TO_INDEX(hwnd);
185 if (index >= NB_USER_HANDLES) return NULL;
187 if ((ptr = user_handles[index]))
189 SERVER_START_REQ( destroy_window )
192 if (!wine_server_call_err( req ))
194 user_handles[index] = NULL;
203 HeapFree( GetProcessHeap(), 0, ptr );
208 /*******************************************************************
209 * list_window_children
211 * Build an array of the children of a given window. The array must be
212 * freed with HeapFree. Returns NULL when no windows are found.
214 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
223 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
225 SERVER_START_REQ( get_window_children )
230 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
231 if (!wine_server_call( req )) count = reply->count;
234 if (count && count < size)
239 HeapFree( GetProcessHeap(), 0, list );
241 size = count + 1; /* restart with a large enough buffer */
247 /*******************************************************************
248 * list_window_parents
250 * Build an array of all parents of a given window, starting with
251 * the immediate parent. The array must be freed with HeapFree.
253 static HWND *list_window_parents( HWND hwnd )
257 int pos = 0, size = 16, count = 0;
259 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
264 if (!(win = WIN_GetPtr( current ))) goto empty;
265 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
266 if (win == WND_DESKTOP)
268 if (!pos) goto empty;
272 list[pos] = current = win->parent;
273 WIN_ReleasePtr( win );
274 if (++pos == size - 1)
276 /* need to grow the list */
277 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
278 if (!new_list) goto empty;
284 /* at least one parent belongs to another process, have to query the server */
289 SERVER_START_REQ( get_window_parents )
292 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
293 if (!wine_server_call( req )) count = reply->count;
296 if (!count) goto empty;
302 HeapFree( GetProcessHeap(), 0, list );
304 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
308 HeapFree( GetProcessHeap(), 0, list );
313 /*******************************************************************
316 static void send_parent_notify( HWND hwnd, UINT msg )
318 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
319 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
321 HWND parent = GetParent(hwnd);
322 if (parent && parent != GetDesktopWindow())
323 SendMessageW( parent, WM_PARENTNOTIFY,
324 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
329 /*******************************************************************
330 * get_server_window_text
332 * Retrieve the window text from the server.
334 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
338 SERVER_START_REQ( get_window_text )
341 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
342 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
345 text[len / sizeof(WCHAR)] = 0;
349 /***********************************************************************
352 * Return a pointer to the WND structure if local to the process,
353 * or WND_OTHER_PROCESS if handle may be valid in other process.
354 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
356 WND *WIN_GetPtr( HWND hwnd )
359 WORD index = USER_HANDLE_TO_INDEX(hwnd);
361 if (index >= NB_USER_HANDLES) return NULL;
364 if ((ptr = user_handles[index]))
366 if (ptr->dwMagic == WND_MAGIC &&
367 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
371 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
373 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
376 else ptr = WND_OTHER_PROCESS;
382 /***********************************************************************
383 * WIN_IsCurrentProcess
385 * Check whether a given window belongs to the current process (and return the full handle).
387 HWND WIN_IsCurrentProcess( HWND hwnd )
392 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
394 WIN_ReleasePtr( ptr );
399 /***********************************************************************
400 * WIN_IsCurrentThread
402 * Check whether a given window belongs to the current thread (and return the full handle).
404 HWND WIN_IsCurrentThread( HWND hwnd )
409 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
410 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
411 WIN_ReleasePtr( ptr );
416 /***********************************************************************
419 * Convert a 16-bit window handle to a full 32-bit handle.
421 HWND WIN_Handle32( HWND16 hwnd16 )
424 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
426 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
427 /* do sign extension for -2 and -3 */
428 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
430 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
432 if (ptr == WND_DESKTOP) return GetDesktopWindow();
434 if (ptr != WND_OTHER_PROCESS)
436 hwnd = ptr->hwndSelf;
437 WIN_ReleasePtr( ptr );
439 else /* may belong to another process */
441 SERVER_START_REQ( get_window_info )
444 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
452 /***********************************************************************
455 * Change the owner of a window.
457 HWND WIN_SetOwner( HWND hwnd, HWND owner )
459 WND *win = WIN_GetPtr( hwnd );
462 if (!win || win == WND_DESKTOP) return 0;
463 if (win == WND_OTHER_PROCESS)
465 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
468 SERVER_START_REQ( set_window_owner )
472 if (!wine_server_call( req ))
474 win->owner = reply->full_owner;
475 ret = reply->prev_owner;
479 WIN_ReleasePtr( win );
484 /***********************************************************************
487 * Change the style of a window.
489 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
492 ULONG new_style, old_style = 0;
493 WND *win = WIN_GetPtr( hwnd );
495 if (!win || win == WND_DESKTOP) return 0;
496 if (win == WND_OTHER_PROCESS)
499 ERR( "cannot set style %lx/%lx on other process window %p\n",
500 set_bits, clear_bits, hwnd );
503 new_style = (win->dwStyle | set_bits) & ~clear_bits;
504 if (new_style == win->dwStyle)
506 WIN_ReleasePtr( win );
509 SERVER_START_REQ( set_window_info )
512 req->flags = SET_WIN_STYLE;
513 req->style = new_style;
514 req->extra_offset = -1;
515 if ((ok = !wine_server_call( req )))
517 old_style = reply->old_style;
518 win->dwStyle = new_style;
522 WIN_ReleasePtr( win );
523 if (ok) USER_Driver->pSetWindowStyle( hwnd, old_style );
528 /***********************************************************************
531 * Get the window and client rectangles.
533 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
535 WND *win = WIN_GetPtr( hwnd );
538 if (!win) return FALSE;
539 if (win == WND_DESKTOP)
542 rect.left = rect.top = 0;
543 rect.right = GetSystemMetrics(SM_CXSCREEN);
544 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
545 if (rectWindow) *rectWindow = rect;
546 if (rectClient) *rectClient = rect;
548 else if (win == WND_OTHER_PROCESS)
550 SERVER_START_REQ( get_window_rectangles )
553 if ((ret = !wine_server_call( req )))
557 rectWindow->left = reply->window.left;
558 rectWindow->top = reply->window.top;
559 rectWindow->right = reply->window.right;
560 rectWindow->bottom = reply->window.bottom;
564 rectClient->left = reply->client.left;
565 rectClient->top = reply->client.top;
566 rectClient->right = reply->client.right;
567 rectClient->bottom = reply->client.bottom;
575 if (rectWindow) *rectWindow = win->rectWindow;
576 if (rectClient) *rectClient = win->rectClient;
577 WIN_ReleasePtr( win );
583 /***********************************************************************
586 * Destroy storage associated to a window. "Internals" p.358
588 LRESULT WIN_DestroyWindow( HWND hwnd )
592 HMENU menu = 0, sys_menu;
594 TRACE("%p\n", hwnd );
596 /* free child windows */
597 if ((list = WIN_ListChildren( hwnd )))
600 for (i = 0; list[i]; i++)
602 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
603 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
605 HeapFree( GetProcessHeap(), 0, list );
608 /* Unlink now so we won't bother with the children later on */
609 SERVER_START_REQ( set_parent )
613 wine_server_call( req );
618 * Send the WM_NCDESTROY to the window being destroyed.
620 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
622 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
624 WINPOS_CheckInternalPos( hwnd );
626 /* free resources associated with the window */
628 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
629 if (!(wndPtr->dwStyle & WS_CHILD)) menu = (HMENU)wndPtr->wIDmenu;
630 sys_menu = wndPtr->hSysMenu;
631 WIN_ReleasePtr( wndPtr );
633 if (menu) DestroyMenu( menu );
634 if (sys_menu) DestroyMenu( sys_menu );
636 USER_Driver->pDestroyWindow( hwnd );
638 free_window_handle( hwnd );
642 /***********************************************************************
643 * WIN_DestroyThreadWindows
645 * Destroy all children of 'wnd' owned by the current thread.
646 * Return TRUE if something was done.
648 void WIN_DestroyThreadWindows( HWND hwnd )
653 if (!(list = WIN_ListChildren( hwnd ))) return;
654 for (i = 0; list[i]; i++)
656 if (WIN_IsCurrentThread( list[i] ))
657 DestroyWindow( list[i] );
659 WIN_DestroyThreadWindows( list[i] );
661 HeapFree( GetProcessHeap(), 0, list );
665 /***********************************************************************
668 * Fix the coordinates - Helper for WIN_CreateWindowEx.
669 * returns default show mode in sw.
670 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
672 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
676 if (cs->dwExStyle & WS_EX_MDICHILD)
680 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
681 if (!(cs->style & WS_POPUP)) cs->hMenu = (HMENU)id;
683 TRACE("MDI child id %04x\n", id);
686 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
687 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
689 if (cs->style & (WS_CHILD | WS_POPUP))
691 if (cs->dwExStyle & WS_EX_MDICHILD)
693 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
698 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
700 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
705 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
707 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
711 else /* overlapped window */
715 GetStartupInfoW( &info );
717 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
719 /* Never believe Microsoft's documentation... CreateWindowEx doc says
720 * that if an overlapped window is created with WS_VISIBLE style bit
721 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
722 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
725 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
726 * 2) it does not ignore the y parameter as the docs claim; instead, it
727 * uses it as second parameter to ShowWindow() unless y is either
728 * CW_USEDEFAULT or CW_USEDEFAULT16.
730 * The fact that we didn't do 2) caused bogus windows pop up when wine
731 * was running apps that were using this obscure feature. Example -
732 * calc.exe that comes with Win98 (only Win98, it's different from
733 * the one that comes with Win95 and NT)
735 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
736 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
737 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
740 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
742 if (info.dwFlags & STARTF_USESIZE)
744 cs->cx = info.dwXSize;
745 cs->cy = info.dwYSize;
747 else /* if no other hint from the app, pick 3/4 of the screen real estate */
750 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
751 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
752 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
755 /* Handle case where only the cy values is set to default */
756 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
759 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
760 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
766 /* neither x nor cx are default. Check the y values .
767 * In the trace we see Outlook and Outlook Express using
768 * cy set to CW_USEDEFAULT when opening the address book.
770 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
772 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
773 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
774 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
779 /***********************************************************************
782 static void dump_window_styles( DWORD style, DWORD exstyle )
785 if(style & WS_POPUP) TRACE(" WS_POPUP");
786 if(style & WS_CHILD) TRACE(" WS_CHILD");
787 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
788 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
789 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
790 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
791 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
792 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
793 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
796 if(style & WS_BORDER) TRACE(" WS_BORDER");
797 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
799 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
800 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
801 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
802 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
803 if (style & WS_CHILD)
805 if(style & WS_GROUP) TRACE(" WS_GROUP");
806 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
810 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
811 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
814 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
815 #define DUMPED_STYLES \
835 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
840 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
841 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
842 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
843 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
844 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
845 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
846 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
847 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
848 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
849 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
850 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
851 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
852 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
853 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
854 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
855 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
856 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
857 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
859 #define DUMPED_EX_STYLES \
860 (WS_EX_DLGMODALFRAME | \
862 WS_EX_NOPARENTNOTIFY | \
864 WS_EX_ACCEPTFILES | \
865 WS_EX_TRANSPARENT | \
870 WS_EX_CONTEXTHELP | \
873 WS_EX_LEFTSCROLLBAR | \
874 WS_EX_CONTROLPARENT | \
879 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
881 #undef DUMPED_EX_STYLES
885 /***********************************************************************
888 * Implementation of CreateWindowEx().
890 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, UINT flags )
894 HWND hwnd, parent, owner, top_child = 0;
895 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
896 MDICREATESTRUCTA mdi_cs;
898 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
899 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
900 unicode ? debugstr_w((LPCWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
901 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
902 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
903 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
905 /* Fix the styles for MDI children */
906 if (cs->dwExStyle & WS_EX_MDICHILD)
910 wndPtr = WIN_GetPtr(cs->hwndParent);
911 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
913 flags = wndPtr->flags;
914 WIN_ReleasePtr(wndPtr);
917 if (!(flags & WIN_ISMDICLIENT))
919 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
923 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
924 * MDICREATESTRUCT members have the originally passed values.
926 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
927 * have the same layout.
929 mdi_cs.szClass = cs->lpszClass;
930 mdi_cs.szTitle = cs->lpszName;
931 mdi_cs.hOwner = cs->hInstance;
936 mdi_cs.style = cs->style;
937 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
939 cs->lpCreateParams = (LPVOID)&mdi_cs;
941 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
943 if (cs->style & WS_POPUP)
945 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
948 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
952 cs->style &= ~WS_POPUP;
953 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
954 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
957 top_child = GetWindow(cs->hwndParent, GW_CHILD);
961 /* Restore current maximized child */
962 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
964 TRACE("Restoring current maximized child %p\n", top_child);
965 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
966 ShowWindow(top_child, SW_RESTORE);
967 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
972 /* Find the parent window */
974 parent = cs->hwndParent;
977 if (cs->hwndParent == HWND_MESSAGE)
979 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
980 * message window (style: WS_POPUP|WS_DISABLED)
982 FIXME("Parent is HWND_MESSAGE\n");
983 parent = GetDesktopWindow();
985 else if (cs->hwndParent)
987 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
989 parent = GetDesktopWindow();
990 owner = cs->hwndParent;
995 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
997 WARN("No parent for child window\n" );
998 SetLastError(ERROR_TLW_WITH_WSCHILD);
999 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1001 if (classAtom != LOWORD(DESKTOP_CLASS_ATOM)) /* are we creating the desktop itself? */
1002 parent = GetDesktopWindow();
1005 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1007 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1008 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1009 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1010 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1012 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1014 /* Create the window structure */
1016 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, unicode )))
1018 hwnd = wndPtr->hwndSelf;
1020 /* Fill the window structure */
1022 wndPtr->tid = GetCurrentThreadId();
1023 wndPtr->hInstance = cs->hInstance;
1024 wndPtr->text = NULL;
1025 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1026 wndPtr->dwExStyle = cs->dwExStyle;
1027 wndPtr->wIDmenu = 0;
1028 wndPtr->helpContext = 0;
1029 wndPtr->pVScroll = NULL;
1030 wndPtr->pHScroll = NULL;
1031 wndPtr->userdata = 0;
1033 wndPtr->hIconSmall = 0;
1034 wndPtr->hSysMenu = 0;
1035 wndPtr->flags |= (flags & WIN_ISWIN32);
1037 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1040 * Correct the window styles.
1042 * It affects only the style loaded into the WIN structure.
1045 if (!(wndPtr->dwStyle & WS_CHILD))
1047 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1048 if (!(wndPtr->dwStyle & WS_POPUP))
1049 wndPtr->dwStyle |= WS_CAPTION;
1053 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1054 * why does the user get to set it?
1057 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1058 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1059 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1061 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1063 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1064 wndPtr->flags |= WIN_NEED_SIZE;
1066 SERVER_START_REQ( set_window_info )
1069 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1070 req->style = wndPtr->dwStyle;
1071 req->ex_style = wndPtr->dwExStyle;
1072 req->instance = (void *)wndPtr->hInstance;
1073 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1074 req->extra_offset = -1;
1075 wine_server_call( req );
1079 /* Set the window menu */
1081 if (!(wndPtr->dwStyle & WS_CHILD))
1085 if (!MENU_SetMenu(hwnd, cs->hMenu))
1087 WIN_ReleasePtr( wndPtr );
1088 free_window_handle( hwnd );
1094 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1097 if (!cs->hInstance || HIWORD(cs->hInstance))
1098 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1100 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1102 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1106 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1107 WIN_ReleasePtr( wndPtr );
1109 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1111 WIN_DestroyWindow( hwnd );
1115 /* Notify the parent window only */
1117 send_parent_notify( hwnd, WM_CREATE );
1118 if (!IsWindow( hwnd )) return 0;
1120 if (cs->style & WS_VISIBLE)
1122 if (cs->style & WS_MAXIMIZE)
1124 else if (cs->style & WS_MINIMIZE)
1125 sw = SW_SHOWMINIMIZED;
1127 ShowWindow( hwnd, sw );
1128 if (cs->dwExStyle & WS_EX_MDICHILD)
1130 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1131 /* ShowWindow won't activate child windows */
1132 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1136 /* Call WH_SHELL hook */
1138 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1139 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1141 TRACE("created window %p\n", hwnd);
1146 /***********************************************************************
1147 * CreateWindow (USER.41)
1149 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1150 DWORD style, INT16 x, INT16 y, INT16 width,
1151 INT16 height, HWND16 parent, HMENU16 menu,
1152 HINSTANCE16 instance, LPVOID data )
1154 return CreateWindowEx16( 0, className, windowName, style,
1155 x, y, width, height, parent, menu, instance, data );
1159 /***********************************************************************
1160 * CreateWindowEx (USER.452)
1162 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1163 LPCSTR windowName, DWORD style, INT16 x,
1164 INT16 y, INT16 width, INT16 height,
1165 HWND16 parent, HMENU16 menu,
1166 HINSTANCE16 instance, LPVOID data )
1172 /* Find the class atom */
1174 if (HIWORD(className))
1176 if (!(classAtom = GlobalFindAtomA( className )))
1178 ERR( "bad class name %s\n", debugstr_a(className) );
1184 classAtom = LOWORD(className);
1185 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1187 ERR( "bad atom %x\n", classAtom);
1193 /* Fix the coordinates */
1195 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1196 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1197 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1198 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1200 /* Create the window */
1202 cs.lpCreateParams = data;
1203 cs.hInstance = HINSTANCE_32(instance);
1204 cs.hMenu = HMENU_32(menu);
1205 cs.hwndParent = WIN_Handle32( parent );
1207 cs.lpszName = windowName;
1208 cs.lpszClass = className;
1209 cs.dwExStyle = exStyle;
1211 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, 0 ));
1215 /***********************************************************************
1216 * CreateWindowExA (USER32.@)
1218 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1219 LPCSTR windowName, DWORD style, INT x,
1220 INT y, INT width, INT height,
1221 HWND parent, HMENU menu,
1222 HINSTANCE instance, LPVOID data )
1228 /* Find the class atom */
1230 if (HIWORD(className))
1232 if (!(classAtom = GlobalFindAtomA( className )))
1234 ERR( "bad class name %s\n", debugstr_a(className) );
1240 classAtom = LOWORD(className);
1241 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1243 ERR( "bad atom %x\n", classAtom);
1249 /* Create the window */
1251 cs.lpCreateParams = data;
1252 cs.hInstance = instance;
1254 cs.hwndParent = parent;
1260 cs.lpszName = windowName;
1261 cs.lpszClass = className;
1262 cs.dwExStyle = exStyle;
1264 return WIN_CreateWindowEx( &cs, classAtom, WIN_ISWIN32 );
1268 /***********************************************************************
1269 * CreateWindowExW (USER32.@)
1271 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1272 LPCWSTR windowName, DWORD style, INT x,
1273 INT y, INT width, INT height,
1274 HWND parent, HMENU menu,
1275 HINSTANCE instance, LPVOID data )
1281 /* Find the class atom */
1283 if (HIWORD(className))
1285 if (!(classAtom = GlobalFindAtomW( className )))
1287 ERR( "bad class name %s\n", debugstr_w(className) );
1293 classAtom = LOWORD(className);
1294 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1296 ERR( "bad atom %x\n", classAtom);
1302 /* Create the window */
1304 cs.lpCreateParams = data;
1305 cs.hInstance = instance;
1307 cs.hwndParent = parent;
1313 cs.lpszName = windowName;
1314 cs.lpszClass = className;
1315 cs.dwExStyle = exStyle;
1317 /* Note: we rely on the fact that CREATESTRUCTA and */
1318 /* CREATESTRUCTW have the same layout. */
1319 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_ISWIN32 | WIN_ISUNICODE );
1323 /***********************************************************************
1324 * WIN_SendDestroyMsg
1326 static void WIN_SendDestroyMsg( HWND hwnd )
1330 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1332 if (hwnd == info.hwndCaret) DestroyCaret();
1333 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1337 * Send the WM_DESTROY to the window.
1339 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1342 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1343 * make sure that the window still exists when we come back.
1350 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1352 for (i = 0; pWndArray[i]; i++)
1354 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1356 HeapFree( GetProcessHeap(), 0, pWndArray );
1359 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1363 /***********************************************************************
1364 * DestroyWindow (USER32.@)
1366 BOOL WINAPI DestroyWindow( HWND hwnd )
1370 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1372 SetLastError( ERROR_ACCESS_DENIED );
1376 TRACE("(%p)\n", hwnd);
1380 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1382 if (MENU_IsMenuActive() == hwnd)
1385 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1389 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1390 send_parent_notify( hwnd, WM_DESTROY );
1392 else if (!GetWindow( hwnd, GW_OWNER ))
1394 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1395 /* FIXME: clean up palette - see "Internals" p.352 */
1398 if (!IsWindow(hwnd)) return TRUE;
1400 /* Hide the window */
1401 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1403 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1405 ShowWindow( hwnd, SW_HIDE );
1407 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1408 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1411 if (!IsWindow(hwnd)) return TRUE;
1413 /* Recursively destroy owned windows */
1420 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1423 for (i = 0; list[i]; i++)
1425 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1426 if (WIN_IsCurrentThread( list[i] ))
1428 DestroyWindow( list[i] );
1432 WIN_SetOwner( list[i], 0 );
1434 HeapFree( GetProcessHeap(), 0, list );
1436 if (!got_one) break;
1440 /* Send destroy messages */
1442 WIN_SendDestroyMsg( hwnd );
1443 if (!IsWindow( hwnd )) return TRUE;
1445 if (GetClipboardOwner() == hwnd)
1446 CLIPBOARD_ReleaseOwner();
1448 /* Destroy the window storage */
1450 WIN_DestroyWindow( hwnd );
1455 /***********************************************************************
1456 * CloseWindow (USER32.@)
1458 BOOL WINAPI CloseWindow( HWND hwnd )
1460 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1461 ShowWindow( hwnd, SW_MINIMIZE );
1466 /***********************************************************************
1467 * OpenIcon (USER32.@)
1469 BOOL WINAPI OpenIcon( HWND hwnd )
1471 if (!IsIconic( hwnd )) return FALSE;
1472 ShowWindow( hwnd, SW_SHOWNORMAL );
1477 /***********************************************************************
1480 * Implementation of FindWindow() and FindWindowEx().
1482 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1487 WCHAR *buffer = NULL;
1489 if (!parent) parent = GetDesktopWindow();
1492 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1493 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1496 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1500 child = WIN_GetFullHandle( child );
1501 while (list[i] && list[i] != child) i++;
1502 if (!list[i]) goto done;
1503 i++; /* start from next window */
1510 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1517 HeapFree( GetProcessHeap(), 0, list );
1518 HeapFree( GetProcessHeap(), 0, buffer );
1524 /***********************************************************************
1525 * FindWindowA (USER32.@)
1527 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1529 HWND ret = FindWindowExA( 0, 0, className, title );
1530 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1535 /***********************************************************************
1536 * FindWindowExA (USER32.@)
1538 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1539 LPCSTR className, LPCSTR title )
1548 /* If the atom doesn't exist, then no class */
1549 /* with this name exists either. */
1550 if (!(atom = GlobalFindAtomA( className )))
1552 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1556 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1558 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1559 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1560 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1561 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1562 HeapFree( GetProcessHeap(), 0, buffer );
1567 /***********************************************************************
1568 * FindWindowExW (USER32.@)
1570 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1571 LPCWSTR className, LPCWSTR title )
1577 /* If the atom doesn't exist, then no class */
1578 /* with this name exists either. */
1579 if (!(atom = GlobalFindAtomW( className )))
1581 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1585 return WIN_FindWindow( parent, child, atom, title );
1589 /***********************************************************************
1590 * FindWindowW (USER32.@)
1592 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1594 return FindWindowExW( 0, 0, className, title );
1598 /**********************************************************************
1599 * GetDesktopWindow (USER32.@)
1601 HWND WINAPI GetDesktopWindow(void)
1603 struct user_thread_info *thread_info = get_user_thread_info();
1605 if (thread_info->desktop) return thread_info->desktop;
1607 SERVER_START_REQ( get_desktop_window )
1610 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1614 if (!thread_info->desktop)
1617 PROCESS_INFORMATION pi;
1618 WCHAR command_line[] = {'e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1620 memset( &si, 0, sizeof(si) );
1622 if (CreateProcessW( NULL, command_line, NULL, NULL, FALSE, DETACHED_PROCESS,
1623 NULL, NULL, &si, &pi ))
1625 TRACE( "started explorer pid %04lx tid %04lx\n", pi.dwProcessId, pi.dwThreadId );
1626 WaitForInputIdle( pi.hProcess, 10000 );
1627 CloseHandle( pi.hThread );
1628 CloseHandle( pi.hProcess );
1631 else WARN( "failed to start explorer, err %ld\n", GetLastError() );
1633 SERVER_START_REQ( get_desktop_window )
1636 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1641 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1642 ERR( "failed to create desktop window\n" );
1644 return thread_info->desktop;
1648 /*******************************************************************
1649 * EnableWindow (USER32.@)
1651 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1656 if (is_broadcast(hwnd))
1658 SetLastError( ERROR_INVALID_PARAMETER );
1662 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1663 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1667 TRACE("( %p, %d )\n", hwnd, enable);
1669 retvalue = !IsWindowEnabled( hwnd );
1671 if (enable && retvalue)
1673 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1674 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1676 else if (!enable && !retvalue)
1680 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1682 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1684 if (hwnd == GetFocus())
1685 SetFocus( 0 ); /* A disabled window can't have the focus */
1687 capture_wnd = GetCapture();
1688 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1689 ReleaseCapture(); /* A disabled window can't capture the mouse */
1691 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1697 /***********************************************************************
1698 * IsWindowEnabled (USER32.@)
1700 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1702 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1706 /***********************************************************************
1707 * IsWindowUnicode (USER32.@)
1709 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1712 BOOL retvalue = FALSE;
1714 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1716 if (wndPtr == WND_DESKTOP) return TRUE;
1718 if (wndPtr != WND_OTHER_PROCESS)
1720 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1721 WIN_ReleasePtr( wndPtr );
1725 SERVER_START_REQ( get_window_info )
1728 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1736 /**********************************************************************
1739 * Helper function for GetWindowLong().
1741 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1743 LONG_PTR retvalue = 0;
1746 if (offset == GWLP_HWNDPARENT)
1748 HWND parent = GetAncestor( hwnd, GA_PARENT );
1749 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1750 return (ULONG_PTR)parent;
1753 if (!(wndPtr = WIN_GetPtr( hwnd )))
1755 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1759 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1761 if (offset == GWLP_WNDPROC)
1763 SetLastError( ERROR_ACCESS_DENIED );
1766 SERVER_START_REQ( set_window_info )
1769 req->flags = 0; /* don't set anything, just retrieve */
1770 req->extra_offset = (offset >= 0) ? offset : -1;
1771 req->extra_size = (offset >= 0) ? size : 0;
1772 if (!wine_server_call_err( req ))
1776 case GWL_STYLE: retvalue = reply->old_style; break;
1777 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1778 case GWLP_ID: retvalue = reply->old_id; break;
1779 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1780 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1782 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1783 else SetLastError( ERROR_INVALID_INDEX );
1792 /* now we have a valid wndPtr */
1796 if (offset > (int)(wndPtr->cbWndExtra - size))
1798 WARN("Invalid offset %d\n", offset );
1799 WIN_ReleasePtr( wndPtr );
1800 SetLastError( ERROR_INVALID_INDEX );
1803 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1805 /* Special case for dialog window procedure */
1806 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1807 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1808 WIN_ReleasePtr( wndPtr );
1814 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1815 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1816 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1817 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1818 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode ); break;
1819 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1821 WARN("Unknown offset %d\n", offset );
1822 SetLastError( ERROR_INVALID_INDEX );
1825 WIN_ReleasePtr(wndPtr);
1830 /**********************************************************************
1833 * Helper function for SetWindowLong().
1835 * 0 is the failure code. However, in the case of failure SetLastError
1836 * must be set to distinguish between a 0 return value and a failure.
1838 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1842 LONG_PTR retval = 0;
1845 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1847 if (is_broadcast(hwnd))
1849 SetLastError( ERROR_INVALID_PARAMETER );
1853 if (!(wndPtr = WIN_GetPtr( hwnd )))
1855 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1858 if (wndPtr == WND_DESKTOP)
1860 /* can't change anything on the desktop window */
1861 SetLastError( ERROR_ACCESS_DENIED );
1864 if (wndPtr == WND_OTHER_PROCESS)
1866 if (offset == GWLP_WNDPROC)
1868 SetLastError( ERROR_ACCESS_DENIED );
1871 if (offset > 32767 || offset < -32767)
1873 SetLastError( ERROR_INVALID_INDEX );
1876 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1879 /* first some special cases */
1885 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1886 style.styleNew = newval;
1887 WIN_ReleasePtr( wndPtr );
1888 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1889 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1890 newval = style.styleNew;
1892 case GWLP_HWNDPARENT:
1893 if (wndPtr->parent == GetDesktopWindow())
1895 WIN_ReleasePtr( wndPtr );
1896 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1900 WIN_ReleasePtr( wndPtr );
1901 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1906 UINT old_flags = wndPtr->flags;
1907 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1908 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1909 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1910 if (proc) wndPtr->winproc = proc;
1911 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1912 else wndPtr->flags &= ~WIN_ISUNICODE;
1913 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1915 WIN_ReleasePtr( wndPtr );
1918 /* update is_unicode flag on the server side */
1922 case GWLP_HINSTANCE:
1926 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1927 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1929 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1930 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1931 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1932 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1933 WIN_ReleasePtr( wndPtr );
1938 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1940 WARN("Invalid offset %d\n", offset );
1941 WIN_ReleasePtr( wndPtr );
1942 SetLastError( ERROR_INVALID_INDEX );
1945 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1947 /* already set to the same value */
1948 WIN_ReleasePtr( wndPtr );
1954 SERVER_START_REQ( set_window_info )
1957 req->extra_offset = -1;
1961 req->flags = SET_WIN_STYLE;
1962 req->style = newval;
1965 req->flags = SET_WIN_EXSTYLE;
1966 req->ex_style = newval;
1969 req->flags = SET_WIN_ID;
1972 case GWLP_HINSTANCE:
1973 req->flags = SET_WIN_INSTANCE;
1974 req->instance = (void *)newval;
1977 req->flags = SET_WIN_UNICODE;
1978 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1981 req->flags = SET_WIN_USERDATA;
1982 req->user_data = (void *)newval;
1985 req->flags = SET_WIN_EXTRA;
1986 req->extra_offset = offset;
1987 req->extra_size = size;
1988 set_win_data( &req->extra_value, newval, size );
1990 if ((ok = !wine_server_call_err( req )))
1995 wndPtr->dwStyle = newval;
1996 retval = reply->old_style;
1999 wndPtr->dwExStyle = newval;
2000 retval = reply->old_ex_style;
2003 wndPtr->wIDmenu = newval;
2004 retval = reply->old_id;
2006 case GWLP_HINSTANCE:
2007 wndPtr->hInstance = (HINSTANCE)newval;
2008 retval = (ULONG_PTR)reply->old_instance;
2013 wndPtr->userdata = newval;
2014 retval = (ULONG_PTR)reply->old_user_data;
2017 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2018 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2024 WIN_ReleasePtr( wndPtr );
2028 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2030 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2031 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2037 /**********************************************************************
2038 * GetWindowLong (USER.135)
2040 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2044 BOOL is_winproc = (offset == GWLP_WNDPROC);
2048 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2050 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2053 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2055 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2058 * Some programs try to access last element from 16 bit
2059 * code using illegal offset value. Hopefully this is
2060 * what those programs really expect.
2062 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2064 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2065 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2070 WARN("Invalid offset %d\n", offset );
2071 WIN_ReleasePtr( wndPtr );
2072 SetLastError( ERROR_INVALID_INDEX );
2076 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2077 WIN_ReleasePtr( wndPtr );
2080 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2081 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2086 /**********************************************************************
2087 * GetWindowWord (USER32.@)
2089 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2094 case GWLP_HINSTANCE:
2095 case GWLP_HWNDPARENT:
2100 WARN("Invalid offset %d\n", offset );
2101 SetLastError( ERROR_INVALID_INDEX );
2106 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2110 /**********************************************************************
2111 * GetWindowLongA (USER32.@)
2113 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2115 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2119 /**********************************************************************
2120 * GetWindowLongW (USER32.@)
2122 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2124 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2128 /**********************************************************************
2129 * SetWindowLong (USER.136)
2131 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2134 BOOL is_winproc = (offset == GWLP_WNDPROC);
2136 if (offset == DWLP_DLGPROC)
2138 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2140 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2143 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2145 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2146 (wndPtr->flags & WIN_ISDIALOG));
2147 WIN_ReleasePtr( wndPtr );
2153 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2154 WNDPROC old_proc = (WNDPROC)SetWindowLongA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2155 return (LONG)WINPROC_GetProc16( (WNDPROC)old_proc, FALSE );
2157 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2161 /**********************************************************************
2162 * SetWindowWord (USER32.@)
2164 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2169 case GWLP_HINSTANCE:
2170 case GWLP_HWNDPARENT:
2175 WARN("Invalid offset %d\n", offset );
2176 SetLastError( ERROR_INVALID_INDEX );
2181 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2185 /**********************************************************************
2186 * SetWindowLongA (USER32.@)
2188 * See SetWindowLongW.
2190 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2192 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2196 /**********************************************************************
2197 * SetWindowLongW (USER32.@) Set window attribute
2199 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2200 * value in a window's extra memory.
2202 * The _hwnd_ parameter specifies the window. is the handle to a
2203 * window that has extra memory. The _newval_ parameter contains the
2204 * new attribute or extra memory value. If positive, the _offset_
2205 * parameter is the byte-addressed location in the window's extra
2206 * memory to set. If negative, _offset_ specifies the window
2207 * attribute to set, and should be one of the following values:
2209 * GWL_EXSTYLE The window's extended window style
2211 * GWL_STYLE The window's window style.
2213 * GWLP_WNDPROC Pointer to the window's window procedure.
2215 * GWLP_HINSTANCE The window's pplication instance handle.
2217 * GWLP_ID The window's identifier.
2219 * GWLP_USERDATA The window's user-specified data.
2221 * If the window is a dialog box, the _offset_ parameter can be one of
2222 * the following values:
2224 * DWLP_DLGPROC The address of the window's dialog box procedure.
2226 * DWLP_MSGRESULT The return value of a message
2227 * that the dialog box procedure processed.
2229 * DWLP_USER Application specific information.
2233 * If successful, returns the previous value located at _offset_. Otherwise,
2238 * Extra memory for a window class is specified by a nonzero cbWndExtra
2239 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2240 * time of class creation.
2242 * Using GWL_WNDPROC to set a new window procedure effectively creates
2243 * a window subclass. Use CallWindowProc() in the new windows procedure
2244 * to pass messages to the superclass's window procedure.
2246 * The user data is reserved for use by the application which created
2249 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2250 * instead, call the EnableWindow() function to change the window's
2253 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2254 * SetParent() instead.
2257 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2258 * it sends WM_STYLECHANGING before changing the settings
2259 * and WM_STYLECHANGED afterwards.
2260 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2262 LONG WINAPI SetWindowLongW(
2263 HWND hwnd, /* [in] window to alter */
2264 INT offset, /* [in] offset, in bytes, of location to alter */
2265 LONG newval /* [in] new value of location */
2267 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2271 /*******************************************************************
2272 * GetWindowTextA (USER32.@)
2274 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2278 if (!lpString) return 0;
2280 if (WIN_IsCurrentProcess( hwnd ))
2281 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2283 /* when window belongs to other process, don't send a message */
2284 if (nMaxCount <= 0) return 0;
2285 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2286 get_server_window_text( hwnd, buffer, nMaxCount );
2287 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2288 lpString[nMaxCount-1] = 0;
2289 HeapFree( GetProcessHeap(), 0, buffer );
2290 return strlen(lpString);
2294 /*******************************************************************
2295 * InternalGetWindowText (USER32.@)
2297 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2301 if (nMaxCount <= 0) return 0;
2302 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2303 if (win == WND_DESKTOP) lpString[0] = 0;
2304 else if (win != WND_OTHER_PROCESS)
2306 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2307 else lpString[0] = 0;
2308 WIN_ReleasePtr( win );
2312 get_server_window_text( hwnd, lpString, nMaxCount );
2314 return strlenW(lpString);
2318 /*******************************************************************
2319 * GetWindowTextW (USER32.@)
2321 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2323 if (!lpString) return 0;
2325 if (WIN_IsCurrentProcess( hwnd ))
2326 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2328 /* when window belongs to other process, don't send a message */
2329 if (nMaxCount <= 0) return 0;
2330 get_server_window_text( hwnd, lpString, nMaxCount );
2331 return strlenW(lpString);
2335 /*******************************************************************
2336 * SetWindowTextA (USER32.@)
2337 * SetWindowText (USER32.@)
2339 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2341 if (is_broadcast(hwnd))
2343 SetLastError( ERROR_INVALID_PARAMETER );
2346 if (!WIN_IsCurrentProcess( hwnd ))
2347 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2348 debugstr_a(lpString), hwnd );
2349 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2353 /*******************************************************************
2354 * SetWindowTextW (USER32.@)
2356 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2358 if (is_broadcast(hwnd))
2360 SetLastError( ERROR_INVALID_PARAMETER );
2363 if (!WIN_IsCurrentProcess( hwnd ))
2364 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2365 debugstr_w(lpString), hwnd );
2366 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2370 /*******************************************************************
2371 * GetWindowTextLengthA (USER32.@)
2373 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2375 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2378 /*******************************************************************
2379 * GetWindowTextLengthW (USER32.@)
2381 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2383 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2387 /*******************************************************************
2388 * IsWindow (USER32.@)
2390 BOOL WINAPI IsWindow( HWND hwnd )
2395 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2396 if (ptr == WND_DESKTOP) return TRUE;
2398 if (ptr != WND_OTHER_PROCESS)
2400 WIN_ReleasePtr( ptr );
2404 /* check other processes */
2405 SERVER_START_REQ( get_window_info )
2408 ret = !wine_server_call_err( req );
2415 /***********************************************************************
2416 * GetWindowThreadProcessId (USER32.@)
2418 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2423 if (!(ptr = WIN_GetPtr( hwnd )))
2425 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2429 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2431 /* got a valid window */
2433 if (process) *process = GetCurrentProcessId();
2434 WIN_ReleasePtr( ptr );
2438 /* check other processes */
2439 SERVER_START_REQ( get_window_info )
2442 if (!wine_server_call_err( req ))
2444 tid = (DWORD)reply->tid;
2445 if (process) *process = (DWORD)reply->pid;
2453 /*****************************************************************
2454 * GetParent (USER32.@)
2456 HWND WINAPI GetParent( HWND hwnd )
2461 if (!(wndPtr = WIN_GetPtr( hwnd )))
2463 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2466 if (wndPtr == WND_DESKTOP) return 0;
2467 if (wndPtr == WND_OTHER_PROCESS)
2469 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2470 if (style & (WS_POPUP | WS_CHILD))
2472 SERVER_START_REQ( get_window_tree )
2475 if (!wine_server_call_err( req ))
2477 if (style & WS_POPUP) retvalue = reply->owner;
2478 else if (style & WS_CHILD) retvalue = reply->parent;
2486 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2487 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2488 WIN_ReleasePtr( wndPtr );
2494 /*****************************************************************
2495 * GetAncestor (USER32.@)
2497 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2500 HWND *list, ret = 0;
2505 if (!(win = WIN_GetPtr( hwnd )))
2507 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2510 if (win == WND_DESKTOP) return 0;
2511 if (win != WND_OTHER_PROCESS)
2514 WIN_ReleasePtr( win );
2516 else /* need to query the server */
2518 SERVER_START_REQ( get_window_tree )
2521 if (!wine_server_call_err( req )) ret = reply->parent;
2528 if (!(list = list_window_parents( hwnd ))) return 0;
2530 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2534 while (list[count]) count++;
2535 ret = list[count - 2]; /* get the one before the desktop */
2537 HeapFree( GetProcessHeap(), 0, list );
2541 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2544 HWND parent = GetParent( ret );
2554 /*****************************************************************
2555 * SetParent (USER32.@)
2557 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2561 if (is_broadcast(hwnd) || is_broadcast(parent))
2563 SetLastError(ERROR_INVALID_PARAMETER);
2567 if (!parent) parent = GetDesktopWindow();
2568 else parent = WIN_GetFullHandle( parent );
2570 if (!IsWindow( parent ))
2572 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2576 /* Some applications try to set a child as a parent */
2577 if (IsChild(hwnd, parent))
2579 SetLastError( ERROR_INVALID_PARAMETER );
2583 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2584 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2586 return USER_Driver->pSetParent( full_handle, parent );
2590 /*******************************************************************
2591 * IsChild (USER32.@)
2593 BOOL WINAPI IsChild( HWND parent, HWND child )
2595 HWND *list = list_window_parents( child );
2599 if (!list) return FALSE;
2600 parent = WIN_GetFullHandle( parent );
2601 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2602 ret = (list[i] != 0);
2603 HeapFree( GetProcessHeap(), 0, list );
2608 /***********************************************************************
2609 * IsWindowVisible (USER32.@)
2611 BOOL WINAPI IsWindowVisible( HWND hwnd )
2617 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2618 if (!(list = list_window_parents( hwnd ))) return TRUE;
2619 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2621 for (i = 0; list[i+1]; i++)
2622 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2623 retval = !list[i+1];
2625 HeapFree( GetProcessHeap(), 0, list );
2630 /***********************************************************************
2631 * WIN_IsWindowDrawable
2633 * hwnd is drawable when it is visible, all parents are not
2634 * minimized, and it is itself not minimized unless we are
2635 * trying to draw its default class icon.
2637 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2642 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2644 if (!(style & WS_VISIBLE)) return FALSE;
2645 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2647 if (!(list = list_window_parents( hwnd ))) return TRUE;
2648 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2650 for (i = 0; list[i+1]; i++)
2651 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2653 retval = !list[i+1];
2655 HeapFree( GetProcessHeap(), 0, list );
2660 /*******************************************************************
2661 * GetTopWindow (USER32.@)
2663 HWND WINAPI GetTopWindow( HWND hwnd )
2665 if (!hwnd) hwnd = GetDesktopWindow();
2666 return GetWindow( hwnd, GW_CHILD );
2670 /*******************************************************************
2671 * GetWindow (USER32.@)
2673 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2677 if (rel == GW_OWNER) /* this one may be available locally */
2679 WND *wndPtr = WIN_GetPtr( hwnd );
2682 SetLastError( ERROR_INVALID_HANDLE );
2685 if (wndPtr == WND_DESKTOP) return 0;
2686 if (wndPtr != WND_OTHER_PROCESS)
2688 retval = wndPtr->owner;
2689 WIN_ReleasePtr( wndPtr );
2692 /* else fall through to server call */
2695 SERVER_START_REQ( get_window_tree )
2698 if (!wine_server_call_err( req ))
2703 retval = reply->first_sibling;
2706 retval = reply->last_sibling;
2709 retval = reply->next_sibling;
2712 retval = reply->prev_sibling;
2715 retval = reply->owner;
2718 retval = reply->first_child;
2728 /*******************************************************************
2729 * ShowOwnedPopups (USER32.@)
2731 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2735 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2737 if (!win_array) return TRUE;
2739 while (win_array[count]) count++;
2740 while (--count >= 0)
2742 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2743 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2744 if (pWnd == WND_OTHER_PROCESS) continue;
2747 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2749 WIN_ReleasePtr( pWnd );
2750 /* In Windows, ShowOwnedPopups(TRUE) generates
2751 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2752 * regardless of the state of the owner
2754 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2760 if (pWnd->dwStyle & WS_VISIBLE)
2762 WIN_ReleasePtr( pWnd );
2763 /* In Windows, ShowOwnedPopups(FALSE) generates
2764 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2765 * regardless of the state of the owner
2767 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2771 WIN_ReleasePtr( pWnd );
2773 HeapFree( GetProcessHeap(), 0, win_array );
2778 /*******************************************************************
2779 * GetLastActivePopup (USER32.@)
2781 HWND WINAPI GetLastActivePopup( HWND hwnd )
2785 SERVER_START_REQ( get_window_info )
2788 if (!wine_server_call_err( req )) retval = reply->last_active;
2795 /*******************************************************************
2798 * Build an array of the children of a given window. The array must be
2799 * freed with HeapFree. Returns NULL when no windows are found.
2801 HWND *WIN_ListChildren( HWND hwnd )
2803 return list_window_children( hwnd, 0, 0 );
2807 /*******************************************************************
2808 * EnumWindows (USER32.@)
2810 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2816 USER_CheckNotLock();
2818 /* We have to build a list of all windows first, to avoid */
2819 /* unpleasant side-effects, for instance if the callback */
2820 /* function changes the Z-order of the windows. */
2822 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2824 /* Now call the callback function for every window */
2826 for (i = 0; list[i]; i++)
2828 /* Make sure that the window still exists */
2829 if (!IsWindow( list[i] )) continue;
2830 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2832 HeapFree( GetProcessHeap(), 0, list );
2837 /**********************************************************************
2838 * EnumThreadWindows (USER32.@)
2840 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2845 USER_CheckNotLock();
2847 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2849 /* Now call the callback function for every window */
2851 for (i = 0; list[i]; i++)
2852 if (!func( list[i], lParam )) break;
2853 HeapFree( GetProcessHeap(), 0, list );
2858 /**********************************************************************
2859 * WIN_EnumChildWindows
2861 * Helper function for EnumChildWindows().
2863 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2868 for ( ; *list; list++)
2870 /* Make sure that the window still exists */
2871 if (!IsWindow( *list )) continue;
2872 /* Build children list first */
2873 childList = WIN_ListChildren( *list );
2875 ret = func( *list, lParam );
2879 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2880 HeapFree( GetProcessHeap(), 0, childList );
2882 if (!ret) return FALSE;
2888 /**********************************************************************
2889 * EnumChildWindows (USER32.@)
2891 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2896 USER_CheckNotLock();
2898 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2899 ret = WIN_EnumChildWindows( list, func, lParam );
2900 HeapFree( GetProcessHeap(), 0, list );
2905 /*******************************************************************
2906 * AnyPopup (USER.52)
2908 BOOL16 WINAPI AnyPopup16(void)
2914 /*******************************************************************
2915 * AnyPopup (USER32.@)
2917 BOOL WINAPI AnyPopup(void)
2921 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2923 if (!list) return FALSE;
2924 for (i = 0; list[i]; i++)
2926 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2928 retvalue = (list[i] != 0);
2929 HeapFree( GetProcessHeap(), 0, list );
2934 /*******************************************************************
2935 * FlashWindow (USER32.@)
2937 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2941 TRACE("%p\n", hWnd);
2943 if (IsIconic( hWnd ))
2945 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2947 wndPtr = WIN_GetPtr(hWnd);
2948 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2949 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2951 wndPtr->flags |= WIN_NCACTIVATED;
2955 wndPtr->flags &= ~WIN_NCACTIVATED;
2957 WIN_ReleasePtr( wndPtr );
2964 wndPtr = WIN_GetPtr(hWnd);
2965 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2966 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2968 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2969 else wparam = (hWnd == GetForegroundWindow());
2971 WIN_ReleasePtr( wndPtr );
2972 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2977 /*******************************************************************
2978 * FlashWindowEx (USER32.@)
2980 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
2982 FIXME("%p\n", pfwi);
2986 /*******************************************************************
2987 * GetWindowContextHelpId (USER32.@)
2989 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2992 WND *wnd = WIN_GetPtr( hwnd );
2993 if (!wnd || wnd == WND_DESKTOP) return 0;
2994 if (wnd == WND_OTHER_PROCESS)
2996 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2999 retval = wnd->helpContext;
3000 WIN_ReleasePtr( wnd );
3005 /*******************************************************************
3006 * SetWindowContextHelpId (USER32.@)
3008 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3010 WND *wnd = WIN_GetPtr( hwnd );
3011 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3012 if (wnd == WND_OTHER_PROCESS)
3014 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3017 wnd->helpContext = id;
3018 WIN_ReleasePtr( wnd );
3023 /*******************************************************************
3024 * DragDetect (USER32.@)
3026 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3030 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3031 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3033 rect.left = pt.x - wDragWidth;
3034 rect.right = pt.x + wDragWidth;
3036 rect.top = pt.y - wDragHeight;
3037 rect.bottom = pt.y + wDragHeight;
3043 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3045 if( msg.message == WM_LBUTTONUP )
3050 if( msg.message == WM_MOUSEMOVE )
3053 tmp.x = LOWORD(msg.lParam);
3054 tmp.y = HIWORD(msg.lParam);
3055 if( !PtInRect( &rect, tmp ))
3067 /******************************************************************************
3068 * GetWindowModuleFileNameA (USER32.@)
3070 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3072 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3073 hwnd, lpszFileName, cchFileNameMax);
3077 /******************************************************************************
3078 * GetWindowModuleFileNameW (USER32.@)
3080 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3082 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3083 hwnd, lpszFileName, cchFileNameMax);
3087 /******************************************************************************
3088 * GetWindowInfo (USER32.@)
3090 * Note: tests show that Windows doesn't check cbSize of the structure.
3092 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3094 if (!pwi) return FALSE;
3095 if (!IsWindow(hwnd)) return FALSE;
3097 GetWindowRect(hwnd, &pwi->rcWindow);
3098 GetClientRect(hwnd, &pwi->rcClient);
3099 /* translate to screen coordinates */
3100 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3102 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3103 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3104 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3106 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3107 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3109 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3110 pwi->wCreatorVersion = 0x0400;
3115 /******************************************************************************
3116 * SwitchDesktop (USER32.@)
3118 * NOTES: Sets the current input or interactive desktop.
3120 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3122 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3126 /*****************************************************************************
3127 * SetLayeredWindowAttributes (USER32.@)
3129 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3130 BYTE bAlpha, DWORD dwFlags )
3132 FIXME("(%p,0x%.8lx,%d,%ld): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3136 /*****************************************************************************
3137 * UpdateLayeredWindow (USER32.@)
3139 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3140 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3143 FIXME("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%ld): stub!\n",
3144 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3148 /* 64bit versions */
3150 #ifdef GetWindowLongPtrW
3151 #undef GetWindowLongPtrW
3154 #ifdef GetWindowLongPtrA
3155 #undef GetWindowLongPtrA
3158 #ifdef SetWindowLongPtrW
3159 #undef SetWindowLongPtrW
3162 #ifdef SetWindowLongPtrA
3163 #undef SetWindowLongPtrA
3166 /*****************************************************************************
3167 * GetWindowLongPtrW (USER32.@)
3169 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3171 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3174 /*****************************************************************************
3175 * GetWindowLongPtrA (USER32.@)
3177 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3179 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3182 /*****************************************************************************
3183 * SetWindowLongPtrW (USER32.@)
3185 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3187 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3190 /*****************************************************************************
3191 * SetWindowLongPtrA (USER32.@)
3193 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3195 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );