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"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(win);
45 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
46 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
48 /**********************************************************************/
51 static void *user_handles[NB_USER_HANDLES];
53 /***********************************************************************
54 * create_window_handle
56 * Create a window handle with the server.
58 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
59 HINSTANCE instance, BOOL unicode )
63 HWND full_parent = 0, full_owner = 0;
64 struct tagCLASS *class = NULL;
65 user_handle_t handle = 0;
68 /* if 16-bit instance, map to module handle */
69 if (instance && !HIWORD(instance))
70 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
72 SERVER_START_REQ( create_window )
77 req->instance = instance;
78 if (!wine_server_call_err( req ))
80 handle = reply->handle;
81 full_parent = reply->parent;
82 full_owner = reply->owner;
83 extra_bytes = reply->extra;
84 class = reply->class_ptr;
91 WARN( "error %ld creating window\n", GetLastError() );
95 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
97 SERVER_START_REQ( destroy_window )
100 wine_server_call( req );
103 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
107 if (!parent) /* if parent is 0 we don't have a desktop window yet */
109 struct user_thread_info *thread_info = get_user_thread_info();
111 assert( !thread_info->desktop );
112 thread_info->desktop = full_parent ? full_parent : handle;
113 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
114 ERR( "failed to create desktop window\n" );
119 index = USER_HANDLE_TO_INDEX(handle);
120 assert( index < NB_USER_HANDLES );
121 user_handles[index] = win;
122 win->hwndSelf = handle;
123 win->parent = full_parent;
124 win->owner = full_owner;
125 win->dwMagic = WND_MAGIC;
127 win->cbWndExtra = extra_bytes;
128 memset( win->wExtra, 0, extra_bytes );
129 CLASS_AddWindow( class, win, unicode );
134 /***********************************************************************
137 * Free a window handle.
139 static WND *free_window_handle( HWND hwnd )
142 WORD index = USER_HANDLE_TO_INDEX(hwnd);
144 if (index >= NB_USER_HANDLES) return NULL;
146 if ((ptr = user_handles[index]))
148 SERVER_START_REQ( destroy_window )
151 if (!wine_server_call_err( req ))
153 user_handles[index] = NULL;
162 HeapFree( GetProcessHeap(), 0, ptr );
167 /*******************************************************************
168 * list_window_children
170 * Build an array of the children of a given window. The array must be
171 * freed with HeapFree. Returns NULL when no windows are found.
173 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
182 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
184 SERVER_START_REQ( get_window_children )
189 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
190 if (!wine_server_call( req )) count = reply->count;
193 if (count && count < size)
198 HeapFree( GetProcessHeap(), 0, list );
200 size = count + 1; /* restart with a large enough buffer */
206 /*******************************************************************
207 * list_window_parents
209 * Build an array of all parents of a given window, starting with
210 * the immediate parent. The array must be freed with HeapFree.
211 * Returns NULL if window is a top-level window.
213 static HWND *list_window_parents( HWND hwnd )
217 int pos = 0, size = 16, count = 0;
219 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
224 if (!(win = WIN_GetPtr( current ))) goto empty;
225 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
226 if (win == WND_DESKTOP)
228 if (!pos) goto empty;
232 list[pos] = current = win->parent;
233 WIN_ReleasePtr( win );
234 if (++pos == size - 1)
236 /* need to grow the list */
237 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
238 if (!new_list) goto empty;
244 /* at least one parent belongs to another process, have to query the server */
249 SERVER_START_REQ( get_window_parents )
252 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
253 if (!wine_server_call( req )) count = reply->count;
256 if (!count) goto empty;
262 HeapFree( GetProcessHeap(), 0, list );
264 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
268 HeapFree( GetProcessHeap(), 0, list );
273 /*******************************************************************
276 static void send_parent_notify( HWND hwnd, UINT msg )
278 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
279 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
281 HWND parent = GetParent(hwnd);
282 if (parent && parent != GetDesktopWindow())
283 SendMessageW( parent, WM_PARENTNOTIFY,
284 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
289 /*******************************************************************
290 * get_server_window_text
292 * Retrieve the window text from the server.
294 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
298 SERVER_START_REQ( get_window_text )
301 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
302 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
305 text[len / sizeof(WCHAR)] = 0;
309 /***********************************************************************
312 * Return a pointer to the WND structure if local to the process,
313 * or WND_OTHER_PROCESS if handle may be valid in other process.
314 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
316 WND *WIN_GetPtr( HWND hwnd )
319 WORD index = USER_HANDLE_TO_INDEX(hwnd);
321 if (index >= NB_USER_HANDLES) return NULL;
324 if ((ptr = user_handles[index]))
326 if (ptr->dwMagic == WND_MAGIC &&
327 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
331 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
333 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
336 else ptr = WND_OTHER_PROCESS;
342 /***********************************************************************
343 * WIN_IsCurrentProcess
345 * Check whether a given window belongs to the current process (and return the full handle).
347 HWND WIN_IsCurrentProcess( HWND hwnd )
352 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
354 WIN_ReleasePtr( ptr );
359 /***********************************************************************
360 * WIN_IsCurrentThread
362 * Check whether a given window belongs to the current thread (and return the full handle).
364 HWND WIN_IsCurrentThread( HWND hwnd )
369 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
370 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
371 WIN_ReleasePtr( ptr );
376 /***********************************************************************
379 * Convert a 16-bit window handle to a full 32-bit handle.
381 HWND WIN_Handle32( HWND16 hwnd16 )
384 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
386 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
387 /* do sign extension for -2 and -3 */
388 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
390 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
392 if (ptr == WND_DESKTOP) return GetDesktopWindow();
394 if (ptr != WND_OTHER_PROCESS)
396 hwnd = ptr->hwndSelf;
397 WIN_ReleasePtr( ptr );
399 else /* may belong to another process */
401 SERVER_START_REQ( get_window_info )
404 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
412 /***********************************************************************
415 * Change the owner of a window.
417 HWND WIN_SetOwner( HWND hwnd, HWND owner )
419 WND *win = WIN_GetPtr( hwnd );
422 if (!win || win == WND_DESKTOP) return 0;
423 if (win == WND_OTHER_PROCESS)
425 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
428 SERVER_START_REQ( set_window_owner )
432 if (!wine_server_call( req ))
434 win->owner = reply->full_owner;
435 ret = reply->prev_owner;
439 WIN_ReleasePtr( win );
444 /***********************************************************************
447 * Change the style of a window.
449 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
452 ULONG new_style, old_style = 0;
453 WND *win = WIN_GetPtr( hwnd );
455 if (!win || win == WND_DESKTOP) return 0;
456 if (win == WND_OTHER_PROCESS)
459 ERR( "cannot set style %lx/%lx on other process window %p\n",
460 set_bits, clear_bits, hwnd );
463 new_style = (win->dwStyle | set_bits) & ~clear_bits;
464 if (new_style == win->dwStyle)
466 WIN_ReleasePtr( win );
469 SERVER_START_REQ( set_window_info )
472 req->flags = SET_WIN_STYLE;
473 req->style = new_style;
474 req->extra_offset = -1;
475 if ((ok = !wine_server_call( req )))
477 old_style = reply->old_style;
478 win->dwStyle = new_style;
482 WIN_ReleasePtr( win );
483 if (ok) USER_Driver->pSetWindowStyle( hwnd, old_style );
488 /***********************************************************************
491 * Get the window and client rectangles.
493 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
495 WND *win = WIN_GetPtr( hwnd );
498 if (!win) return FALSE;
499 if (win == WND_DESKTOP)
502 rect.left = rect.top = 0;
503 rect.right = GetSystemMetrics(SM_CXSCREEN);
504 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
505 if (rectWindow) *rectWindow = rect;
506 if (rectClient) *rectClient = rect;
508 else if (win == WND_OTHER_PROCESS)
510 SERVER_START_REQ( get_window_rectangles )
513 if ((ret = !wine_server_call( req )))
517 rectWindow->left = reply->window.left;
518 rectWindow->top = reply->window.top;
519 rectWindow->right = reply->window.right;
520 rectWindow->bottom = reply->window.bottom;
524 rectClient->left = reply->client.left;
525 rectClient->top = reply->client.top;
526 rectClient->right = reply->client.right;
527 rectClient->bottom = reply->client.bottom;
535 if (rectWindow) *rectWindow = win->rectWindow;
536 if (rectClient) *rectClient = win->rectClient;
537 WIN_ReleasePtr( win );
543 /***********************************************************************
546 * Destroy storage associated to a window. "Internals" p.358
548 LRESULT WIN_DestroyWindow( HWND hwnd )
552 HMENU menu = 0, sys_menu;
554 TRACE("%p\n", hwnd );
556 /* free child windows */
557 if ((list = WIN_ListChildren( hwnd )))
560 for (i = 0; list[i]; i++)
562 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
563 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
565 HeapFree( GetProcessHeap(), 0, list );
568 /* Unlink now so we won't bother with the children later on */
569 SERVER_START_REQ( set_parent )
573 wine_server_call( req );
578 * Send the WM_NCDESTROY to the window being destroyed.
580 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
582 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
584 WINPOS_CheckInternalPos( hwnd );
586 /* free resources associated with the window */
588 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
589 if (!(wndPtr->dwStyle & WS_CHILD)) menu = (HMENU)wndPtr->wIDmenu;
590 sys_menu = wndPtr->hSysMenu;
591 WIN_ReleasePtr( wndPtr );
593 if (menu) DestroyMenu( menu );
594 if (sys_menu) DestroyMenu( sys_menu );
596 USER_Driver->pDestroyWindow( hwnd );
598 free_window_handle( hwnd );
602 /***********************************************************************
603 * WIN_DestroyThreadWindows
605 * Destroy all children of 'wnd' owned by the current thread.
606 * Return TRUE if something was done.
608 void WIN_DestroyThreadWindows( HWND hwnd )
613 if (!(list = WIN_ListChildren( hwnd ))) return;
614 for (i = 0; list[i]; i++)
616 if (WIN_IsCurrentThread( list[i] ))
617 DestroyWindow( list[i] );
619 WIN_DestroyThreadWindows( list[i] );
621 HeapFree( GetProcessHeap(), 0, list );
625 /***********************************************************************
628 * Fix the coordinates - Helper for WIN_CreateWindowEx.
629 * returns default show mode in sw.
630 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
632 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
636 if (cs->dwExStyle & WS_EX_MDICHILD)
640 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
641 if (!(cs->style & WS_POPUP)) cs->hMenu = (HMENU)id;
643 TRACE("MDI child id %04x\n", id);
646 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
647 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
649 if (cs->style & (WS_CHILD | WS_POPUP))
651 if (cs->dwExStyle & WS_EX_MDICHILD)
653 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
658 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
660 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
665 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
667 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
671 else /* overlapped window */
675 GetStartupInfoW( &info );
677 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
679 /* Never believe Microsoft's documentation... CreateWindowEx doc says
680 * that if an overlapped window is created with WS_VISIBLE style bit
681 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
682 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
685 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
686 * 2) it does not ignore the y parameter as the docs claim; instead, it
687 * uses it as second parameter to ShowWindow() unless y is either
688 * CW_USEDEFAULT or CW_USEDEFAULT16.
690 * The fact that we didn't do 2) caused bogus windows pop up when wine
691 * was running apps that were using this obscure feature. Example -
692 * calc.exe that comes with Win98 (only Win98, it's different from
693 * the one that comes with Win95 and NT)
695 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
696 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
697 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
700 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
702 if (info.dwFlags & STARTF_USESIZE)
704 cs->cx = info.dwXSize;
705 cs->cy = info.dwYSize;
707 else /* if no other hint from the app, pick 3/4 of the screen real estate */
710 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
711 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
712 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
715 /* Handle case where only the cy values is set to default */
716 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
719 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
720 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
726 /* neither x nor cx are default. Check the y values .
727 * In the trace we see Outlook and Outlook Express using
728 * cy set to CW_USEDEFAULT when opening the address book.
730 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
732 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
733 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
734 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
739 /***********************************************************************
742 static void dump_window_styles( DWORD style, DWORD exstyle )
745 if(style & WS_POPUP) TRACE(" WS_POPUP");
746 if(style & WS_CHILD) TRACE(" WS_CHILD");
747 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
748 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
749 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
750 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
751 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
752 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
753 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
756 if(style & WS_BORDER) TRACE(" WS_BORDER");
757 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
759 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
760 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
761 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
762 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
763 if (style & WS_CHILD)
765 if(style & WS_GROUP) TRACE(" WS_GROUP");
766 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
770 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
771 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
774 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
775 #define DUMPED_STYLES \
795 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
800 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
801 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
802 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
803 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
804 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
805 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
806 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
807 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
808 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
809 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
810 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
811 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
812 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
813 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
814 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
815 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
816 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
817 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
819 #define DUMPED_EX_STYLES \
820 (WS_EX_DLGMODALFRAME | \
822 WS_EX_NOPARENTNOTIFY | \
824 WS_EX_ACCEPTFILES | \
825 WS_EX_TRANSPARENT | \
830 WS_EX_CONTEXTHELP | \
833 WS_EX_LEFTSCROLLBAR | \
834 WS_EX_CONTROLPARENT | \
839 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
841 #undef DUMPED_EX_STYLES
845 /***********************************************************************
848 * Implementation of CreateWindowEx().
850 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, UINT flags )
854 HWND hwnd, parent, owner, top_child = 0;
855 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
856 MDICREATESTRUCTA mdi_cs;
858 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
859 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
860 unicode ? debugstr_w((LPCWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
861 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
862 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
863 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
865 /* Fix the styles for MDI children */
866 if (cs->dwExStyle & WS_EX_MDICHILD)
870 wndPtr = WIN_GetPtr(cs->hwndParent);
871 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
873 flags = wndPtr->flags;
874 WIN_ReleasePtr(wndPtr);
877 if (!(flags & WIN_ISMDICLIENT))
879 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
883 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
884 * MDICREATESTRUCT members have the originally passed values.
886 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
887 * have the same layout.
889 mdi_cs.szClass = cs->lpszClass;
890 mdi_cs.szTitle = cs->lpszName;
891 mdi_cs.hOwner = cs->hInstance;
896 mdi_cs.style = cs->style;
897 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
899 cs->lpCreateParams = (LPVOID)&mdi_cs;
901 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
903 if (cs->style & WS_POPUP)
905 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
908 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
912 cs->style &= ~WS_POPUP;
913 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
914 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
917 top_child = GetWindow(cs->hwndParent, GW_CHILD);
921 /* Restore current maximized child */
922 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
924 TRACE("Restoring current maximized child %p\n", top_child);
925 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
926 ShowWindow(top_child, SW_RESTORE);
927 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
932 /* Find the parent window */
934 parent = cs->hwndParent;
937 if (cs->hwndParent == HWND_MESSAGE)
939 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
940 * message window (style: WS_POPUP|WS_DISABLED)
942 FIXME("Parent is HWND_MESSAGE\n");
943 parent = GetDesktopWindow();
945 else if (cs->hwndParent)
947 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
949 parent = GetDesktopWindow();
950 owner = cs->hwndParent;
955 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
957 WARN("No parent for child window\n" );
958 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
960 if (classAtom != LOWORD(DESKTOP_CLASS_ATOM)) /* are we creating the desktop itself? */
961 parent = GetDesktopWindow();
964 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
966 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
967 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
968 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
969 cs->dwExStyle |= WS_EX_WINDOWEDGE;
971 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
973 /* Create the window structure */
975 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, unicode )))
977 hwnd = wndPtr->hwndSelf;
979 /* Fill the window structure */
981 wndPtr->tid = GetCurrentThreadId();
982 wndPtr->hInstance = cs->hInstance;
984 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
985 wndPtr->dwExStyle = cs->dwExStyle;
987 wndPtr->helpContext = 0;
988 wndPtr->pVScroll = NULL;
989 wndPtr->pHScroll = NULL;
990 wndPtr->userdata = 0;
992 wndPtr->hIconSmall = 0;
993 wndPtr->hSysMenu = 0;
994 wndPtr->flags |= (flags & WIN_ISWIN32);
996 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
999 * Correct the window styles.
1001 * It affects only the style loaded into the WIN structure.
1004 if (!(wndPtr->dwStyle & WS_CHILD))
1006 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1007 if (!(wndPtr->dwStyle & WS_POPUP))
1008 wndPtr->dwStyle |= WS_CAPTION;
1012 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1013 * why does the user get to set it?
1016 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1017 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1018 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1020 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1022 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1023 wndPtr->flags |= WIN_NEED_SIZE;
1025 SERVER_START_REQ( set_window_info )
1028 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1029 req->style = wndPtr->dwStyle;
1030 req->ex_style = wndPtr->dwExStyle;
1031 req->instance = (void *)wndPtr->hInstance;
1032 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1033 req->extra_offset = -1;
1034 wine_server_call( req );
1038 /* Set the window menu */
1040 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1041 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1045 if (!MENU_SetMenu(hwnd, cs->hMenu))
1047 WIN_ReleasePtr( wndPtr );
1048 free_window_handle( hwnd );
1054 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1057 if (!cs->hInstance || HIWORD(cs->hInstance))
1058 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1060 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1062 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1066 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1067 WIN_ReleasePtr( wndPtr );
1069 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1071 WIN_DestroyWindow( hwnd );
1075 /* Notify the parent window only */
1077 send_parent_notify( hwnd, WM_CREATE );
1078 if (!IsWindow( hwnd )) return 0;
1080 if (cs->style & WS_VISIBLE)
1082 if (cs->style & WS_MAXIMIZE)
1084 else if (cs->style & WS_MINIMIZE)
1085 sw = SW_SHOWMINIMIZED;
1087 ShowWindow( hwnd, sw );
1088 if (cs->dwExStyle & WS_EX_MDICHILD)
1090 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1091 /* ShowWindow won't activate child windows */
1092 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1096 /* Call WH_SHELL hook */
1098 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1099 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1101 TRACE("created window %p\n", hwnd);
1106 /***********************************************************************
1107 * CreateWindow (USER.41)
1109 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1110 DWORD style, INT16 x, INT16 y, INT16 width,
1111 INT16 height, HWND16 parent, HMENU16 menu,
1112 HINSTANCE16 instance, LPVOID data )
1114 return CreateWindowEx16( 0, className, windowName, style,
1115 x, y, width, height, parent, menu, instance, data );
1119 /***********************************************************************
1120 * CreateWindowEx (USER.452)
1122 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1123 LPCSTR windowName, DWORD style, INT16 x,
1124 INT16 y, INT16 width, INT16 height,
1125 HWND16 parent, HMENU16 menu,
1126 HINSTANCE16 instance, LPVOID data )
1132 /* Find the class atom */
1134 if (HIWORD(className))
1136 if (!(classAtom = GlobalFindAtomA( className )))
1138 ERR( "bad class name %s\n", debugstr_a(className) );
1144 classAtom = LOWORD(className);
1145 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1147 ERR( "bad atom %x\n", classAtom);
1153 /* Fix the coordinates */
1155 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1156 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1157 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1158 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1160 /* Create the window */
1162 cs.lpCreateParams = data;
1163 cs.hInstance = HINSTANCE_32(instance);
1164 cs.hMenu = HMENU_32(menu);
1165 cs.hwndParent = WIN_Handle32( parent );
1167 cs.lpszName = windowName;
1168 cs.lpszClass = className;
1169 cs.dwExStyle = exStyle;
1171 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, 0 ));
1175 /***********************************************************************
1176 * CreateWindowExA (USER32.@)
1178 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1179 LPCSTR windowName, DWORD style, INT x,
1180 INT y, INT width, INT height,
1181 HWND parent, HMENU menu,
1182 HINSTANCE instance, LPVOID data )
1188 /* Find the class atom */
1190 if (HIWORD(className))
1192 if (!(classAtom = GlobalFindAtomA( className )))
1194 ERR( "bad class name %s\n", debugstr_a(className) );
1200 classAtom = LOWORD(className);
1201 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1203 ERR( "bad atom %x\n", classAtom);
1209 /* Create the window */
1211 cs.lpCreateParams = data;
1212 cs.hInstance = instance;
1214 cs.hwndParent = parent;
1220 cs.lpszName = windowName;
1221 cs.lpszClass = className;
1222 cs.dwExStyle = exStyle;
1224 return WIN_CreateWindowEx( &cs, classAtom, WIN_ISWIN32 );
1228 /***********************************************************************
1229 * CreateWindowExW (USER32.@)
1231 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1232 LPCWSTR windowName, DWORD style, INT x,
1233 INT y, INT width, INT height,
1234 HWND parent, HMENU menu,
1235 HINSTANCE instance, LPVOID data )
1241 /* Find the class atom */
1243 if (HIWORD(className))
1245 if (!(classAtom = GlobalFindAtomW( className )))
1247 ERR( "bad class name %s\n", debugstr_w(className) );
1253 classAtom = LOWORD(className);
1254 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1256 ERR( "bad atom %x\n", classAtom);
1262 /* Create the window */
1264 cs.lpCreateParams = data;
1265 cs.hInstance = instance;
1267 cs.hwndParent = parent;
1273 cs.lpszName = windowName;
1274 cs.lpszClass = className;
1275 cs.dwExStyle = exStyle;
1277 /* Note: we rely on the fact that CREATESTRUCTA and */
1278 /* CREATESTRUCTW have the same layout. */
1279 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_ISWIN32 | WIN_ISUNICODE );
1283 /***********************************************************************
1284 * WIN_SendDestroyMsg
1286 static void WIN_SendDestroyMsg( HWND hwnd )
1290 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1292 if (hwnd == info.hwndCaret) DestroyCaret();
1293 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1295 USER_Driver->pResetSelectionOwner( hwnd, TRUE );
1298 * Send the WM_DESTROY to the window.
1300 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1303 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1304 * make sure that the window still exists when we come back.
1311 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1313 for (i = 0; pWndArray[i]; i++)
1315 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1317 HeapFree( GetProcessHeap(), 0, pWndArray );
1320 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1324 /***********************************************************************
1325 * DestroyWindow (USER32.@)
1327 BOOL WINAPI DestroyWindow( HWND hwnd )
1331 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1333 SetLastError( ERROR_ACCESS_DENIED );
1337 TRACE("(%p)\n", hwnd);
1341 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1343 if (MENU_IsMenuActive() == hwnd)
1346 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1350 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1351 send_parent_notify( hwnd, WM_DESTROY );
1353 else if (!GetWindow( hwnd, GW_OWNER ))
1355 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1356 /* FIXME: clean up palette - see "Internals" p.352 */
1359 if (!IsWindow(hwnd)) return TRUE;
1361 USER_Driver->pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1363 /* Hide the window */
1364 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1366 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1368 ShowWindow( hwnd, SW_HIDE );
1370 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1371 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1374 if (!IsWindow(hwnd)) return TRUE;
1376 /* Recursively destroy owned windows */
1383 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1386 for (i = 0; list[i]; i++)
1388 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1389 if (WIN_IsCurrentThread( list[i] ))
1391 DestroyWindow( list[i] );
1395 WIN_SetOwner( list[i], 0 );
1397 HeapFree( GetProcessHeap(), 0, list );
1399 if (!got_one) break;
1403 /* Send destroy messages */
1405 WIN_SendDestroyMsg( hwnd );
1406 if (!IsWindow( hwnd )) return TRUE;
1408 if (GetClipboardOwner() == hwnd)
1409 CLIPBOARD_ReleaseOwner();
1411 /* Destroy the window storage */
1413 WIN_DestroyWindow( hwnd );
1418 /***********************************************************************
1419 * CloseWindow (USER32.@)
1421 BOOL WINAPI CloseWindow( HWND hwnd )
1423 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1424 ShowWindow( hwnd, SW_MINIMIZE );
1429 /***********************************************************************
1430 * OpenIcon (USER32.@)
1432 BOOL WINAPI OpenIcon( HWND hwnd )
1434 if (!IsIconic( hwnd )) return FALSE;
1435 ShowWindow( hwnd, SW_SHOWNORMAL );
1440 /***********************************************************************
1443 * Implementation of FindWindow() and FindWindowEx().
1445 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1450 WCHAR *buffer = NULL;
1452 if (!parent) parent = GetDesktopWindow();
1455 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1456 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1459 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1463 child = WIN_GetFullHandle( child );
1464 while (list[i] && list[i] != child) i++;
1465 if (!list[i]) goto done;
1466 i++; /* start from next window */
1473 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1480 HeapFree( GetProcessHeap(), 0, list );
1481 HeapFree( GetProcessHeap(), 0, buffer );
1487 /***********************************************************************
1488 * FindWindowA (USER32.@)
1490 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1492 HWND ret = FindWindowExA( 0, 0, className, title );
1493 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1498 /***********************************************************************
1499 * FindWindowExA (USER32.@)
1501 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1502 LPCSTR className, LPCSTR title )
1511 /* If the atom doesn't exist, then no class */
1512 /* with this name exists either. */
1513 if (!(atom = GlobalFindAtomA( className )))
1515 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1519 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1521 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1522 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1523 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1524 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1525 HeapFree( GetProcessHeap(), 0, buffer );
1530 /***********************************************************************
1531 * FindWindowExW (USER32.@)
1533 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1534 LPCWSTR className, LPCWSTR title )
1540 /* If the atom doesn't exist, then no class */
1541 /* with this name exists either. */
1542 if (!(atom = GlobalFindAtomW( className )))
1544 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1548 return WIN_FindWindow( parent, child, atom, title );
1552 /***********************************************************************
1553 * FindWindowW (USER32.@)
1555 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1557 return FindWindowExW( 0, 0, className, title );
1561 /**********************************************************************
1562 * GetDesktopWindow (USER32.@)
1564 HWND WINAPI GetDesktopWindow(void)
1566 struct user_thread_info *thread_info = get_user_thread_info();
1568 if (thread_info->desktop) return thread_info->desktop;
1570 SERVER_START_REQ( get_desktop_window )
1573 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1577 if (!thread_info->desktop)
1580 PROCESS_INFORMATION pi;
1581 WCHAR command_line[] = {'e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1583 memset( &si, 0, sizeof(si) );
1585 if (CreateProcessW( NULL, command_line, NULL, NULL, FALSE, DETACHED_PROCESS,
1586 NULL, NULL, &si, &pi ))
1588 TRACE( "started explorer pid %04lx tid %04lx\n", pi.dwProcessId, pi.dwThreadId );
1589 WaitForInputIdle( pi.hProcess, 10000 );
1590 CloseHandle( pi.hThread );
1591 CloseHandle( pi.hProcess );
1594 else WARN( "failed to start explorer, err %ld\n", GetLastError() );
1596 SERVER_START_REQ( get_desktop_window )
1599 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1604 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1605 ERR( "failed to create desktop window\n" );
1607 return thread_info->desktop;
1611 /*******************************************************************
1612 * EnableWindow (USER32.@)
1614 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1619 if (is_broadcast(hwnd))
1621 SetLastError( ERROR_INVALID_PARAMETER );
1625 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1626 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1630 TRACE("( %p, %d )\n", hwnd, enable);
1632 retvalue = !IsWindowEnabled( hwnd );
1634 if (enable && retvalue)
1636 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1637 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1639 else if (!enable && !retvalue)
1643 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1645 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1647 if (hwnd == GetFocus())
1648 SetFocus( 0 ); /* A disabled window can't have the focus */
1650 capture_wnd = GetCapture();
1651 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1652 ReleaseCapture(); /* A disabled window can't capture the mouse */
1654 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1660 /***********************************************************************
1661 * IsWindowEnabled (USER32.@)
1663 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1665 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1669 /***********************************************************************
1670 * IsWindowUnicode (USER32.@)
1672 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1675 BOOL retvalue = FALSE;
1677 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1679 if (wndPtr == WND_DESKTOP) return TRUE;
1681 if (wndPtr != WND_OTHER_PROCESS)
1683 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1684 WIN_ReleasePtr( wndPtr );
1688 SERVER_START_REQ( get_window_info )
1691 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1699 /**********************************************************************
1700 * GetWindowWord (USER32.@)
1702 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1707 WND *wndPtr = WIN_GetPtr( hwnd );
1710 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1713 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1715 SERVER_START_REQ( set_window_info )
1718 req->flags = 0; /* don't set anything, just retrieve */
1719 req->extra_offset = offset;
1720 req->extra_size = sizeof(retvalue);
1721 if (!wine_server_call_err( req ))
1722 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1727 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1729 WARN("Invalid offset %d\n", offset );
1730 SetLastError( ERROR_INVALID_INDEX );
1732 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1733 WIN_ReleasePtr( wndPtr );
1739 case GWLP_HWNDPARENT:
1740 return GetWindowLongPtrW( hwnd, offset );
1742 case GWLP_HINSTANCE:
1744 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1746 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1750 WARN("Invalid offset %d\n", offset );
1756 /**********************************************************************
1757 * SetWindowWord (USER32.@)
1759 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1767 case GWLP_HINSTANCE:
1768 case GWLP_HWNDPARENT:
1769 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1773 WARN("Invalid offset %d\n", offset );
1774 SetLastError( ERROR_INVALID_INDEX );
1779 wndPtr = WIN_GetPtr( hwnd );
1780 if (wndPtr == WND_DESKTOP)
1782 SetLastError( ERROR_ACCESS_DENIED );
1785 if (wndPtr == WND_OTHER_PROCESS)
1788 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1789 offset, newval, hwnd );
1794 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1798 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1800 WARN("Invalid offset %d\n", offset );
1801 WIN_ReleasePtr(wndPtr);
1802 SetLastError( ERROR_INVALID_INDEX );
1806 SERVER_START_REQ( set_window_info )
1809 req->flags = SET_WIN_EXTRA;
1810 req->extra_offset = offset;
1811 req->extra_size = sizeof(newval);
1812 memcpy( &req->extra_value, &newval, sizeof(newval) );
1813 if (!wine_server_call_err( req ))
1815 void *ptr = (char *)wndPtr->wExtra + offset;
1816 memcpy( &retval, ptr, sizeof(retval) );
1817 memcpy( ptr, &newval, sizeof(newval) );
1821 WIN_ReleasePtr( wndPtr );
1826 /**********************************************************************
1829 * Helper function for GetWindowLong().
1831 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, BOOL unicode )
1833 LONG_PTR retvalue = 0;
1836 if (offset == GWLP_HWNDPARENT)
1838 HWND parent = GetAncestor( hwnd, GA_PARENT );
1839 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1840 return (ULONG_PTR)parent;
1843 if (!(wndPtr = WIN_GetPtr( hwnd )))
1845 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1849 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1851 if (offset == GWLP_WNDPROC)
1853 SetLastError( ERROR_ACCESS_DENIED );
1856 SERVER_START_REQ( set_window_info )
1859 req->flags = 0; /* don't set anything, just retrieve */
1860 req->extra_offset = (offset >= 0) ? offset : -1;
1861 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1862 if (!wine_server_call_err( req ))
1866 case GWL_STYLE: retvalue = reply->old_style; break;
1867 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1868 case GWLP_ID: retvalue = reply->old_id; break;
1869 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1870 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1872 if (offset >= 0) retvalue = reply->old_extra_value;
1873 else SetLastError( ERROR_INVALID_INDEX );
1882 /* now we have a valid wndPtr */
1886 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1888 WARN("Invalid offset %d\n", offset );
1889 WIN_ReleasePtr( wndPtr );
1890 SetLastError( ERROR_INVALID_INDEX );
1893 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
1894 /* Special case for dialog window procedure */
1895 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1896 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1897 WIN_ReleasePtr( wndPtr );
1903 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1904 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1905 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1906 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1907 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode ); break;
1908 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1910 WARN("Unknown offset %d\n", offset );
1911 SetLastError( ERROR_INVALID_INDEX );
1914 WIN_ReleasePtr(wndPtr);
1919 /**********************************************************************
1922 * Helper function for SetWindowLong().
1924 * 0 is the failure code. However, in the case of failure SetLastError
1925 * must be set to distinguish between a 0 return value and a failure.
1927 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval, BOOL unicode )
1931 LONG_PTR retval = 0;
1934 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1936 if (is_broadcast(hwnd))
1938 SetLastError( ERROR_INVALID_PARAMETER );
1942 if (!(wndPtr = WIN_GetPtr( hwnd )))
1944 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1947 if (wndPtr == WND_DESKTOP)
1949 /* can't change anything on the desktop window */
1950 SetLastError( ERROR_ACCESS_DENIED );
1953 if (wndPtr == WND_OTHER_PROCESS)
1955 if (offset == GWLP_WNDPROC)
1957 SetLastError( ERROR_ACCESS_DENIED );
1960 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1963 /* first some special cases */
1969 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1970 style.styleNew = newval;
1971 WIN_ReleasePtr( wndPtr );
1972 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1973 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1974 newval = style.styleNew;
1976 case GWLP_HWNDPARENT:
1977 if (wndPtr->parent == GetDesktopWindow())
1979 WIN_ReleasePtr( wndPtr );
1980 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1984 WIN_ReleasePtr( wndPtr );
1985 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1989 UINT old_flags = wndPtr->flags;
1990 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1991 if (unicode) wndPtr->winproc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1992 else wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1993 if (WINPROC_IsUnicode( wndPtr->winproc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1994 else wndPtr->flags &= ~WIN_ISUNICODE;
1995 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1997 WIN_ReleasePtr( wndPtr );
2000 /* update is_unicode flag on the server side */
2004 case GWLP_HINSTANCE:
2008 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2010 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2011 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
2012 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2013 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2014 WIN_ReleasePtr( wndPtr );
2019 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
2021 WARN("Invalid offset %d\n", offset );
2022 WIN_ReleasePtr( wndPtr );
2023 SetLastError( ERROR_INVALID_INDEX );
2028 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2029 if (*ptr == newval) /* already set to the same value */
2031 WIN_ReleasePtr( wndPtr );
2038 SERVER_START_REQ( set_window_info )
2041 req->extra_offset = -1;
2045 req->flags = SET_WIN_STYLE;
2046 req->style = newval;
2049 req->flags = SET_WIN_EXSTYLE;
2050 req->ex_style = newval;
2053 req->flags = SET_WIN_ID;
2056 case GWLP_HINSTANCE:
2057 req->flags = SET_WIN_INSTANCE;
2058 req->instance = (void *)newval;
2061 req->flags = SET_WIN_UNICODE;
2062 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2065 req->flags = SET_WIN_USERDATA;
2066 req->user_data = (void *)newval;
2069 req->flags = SET_WIN_EXTRA;
2070 req->extra_offset = offset;
2071 req->extra_size = sizeof(newval);
2072 memcpy( &req->extra_value, &newval, sizeof(newval) );
2074 if ((ok = !wine_server_call_err( req )))
2079 wndPtr->dwStyle = newval;
2080 retval = reply->old_style;
2083 wndPtr->dwExStyle = newval;
2084 retval = reply->old_ex_style;
2087 wndPtr->wIDmenu = newval;
2088 retval = reply->old_id;
2090 case GWLP_HINSTANCE:
2091 wndPtr->hInstance = (HINSTANCE)newval;
2092 retval = (ULONG_PTR)reply->old_instance;
2097 wndPtr->userdata = newval;
2098 retval = (ULONG_PTR)reply->old_user_data;
2102 void *ptr = (char *)wndPtr->wExtra + offset;
2103 memcpy( &retval, ptr, sizeof(retval) );
2104 memcpy( ptr, &newval, sizeof(newval) );
2111 WIN_ReleasePtr( wndPtr );
2115 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2117 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2118 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2124 /**********************************************************************
2125 * GetWindowLong (USER.135)
2127 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2131 BOOL is_winproc = (offset == GWLP_WNDPROC);
2135 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2137 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2140 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2142 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2145 * Some programs try to access last element from 16 bit
2146 * code using illegal offset value. Hopefully this is
2147 * what those programs really expect.
2149 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2151 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2152 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2157 WARN("Invalid offset %d\n", offset );
2158 WIN_ReleasePtr( wndPtr );
2159 SetLastError( ERROR_INVALID_INDEX );
2163 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2164 WIN_ReleasePtr( wndPtr );
2167 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2168 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2173 /**********************************************************************
2174 * GetWindowLongA (USER32.@)
2176 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2178 return WIN_GetWindowLong( hwnd, offset, FALSE );
2182 /**********************************************************************
2183 * GetWindowLongW (USER32.@)
2185 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2187 return WIN_GetWindowLong( hwnd, offset, TRUE );
2191 /**********************************************************************
2192 * SetWindowLong (USER.136)
2194 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2197 BOOL is_winproc = (offset == GWLP_WNDPROC);
2199 if (offset == DWLP_DLGPROC)
2201 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2203 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2206 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2208 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2209 (wndPtr->flags & WIN_ISDIALOG));
2210 WIN_ReleasePtr( wndPtr );
2216 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2217 WNDPROC old_proc = (WNDPROC)SetWindowLongA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2218 return (LONG)WINPROC_GetProc16( (WNDPROC)old_proc, FALSE );
2220 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2224 /**********************************************************************
2225 * SetWindowLongA (USER32.@)
2227 * See SetWindowLongW.
2229 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2231 return WIN_SetWindowLong( hwnd, offset, newval, FALSE );
2235 /**********************************************************************
2236 * SetWindowLongW (USER32.@) Set window attribute
2238 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2239 * value in a window's extra memory.
2241 * The _hwnd_ parameter specifies the window. is the handle to a
2242 * window that has extra memory. The _newval_ parameter contains the
2243 * new attribute or extra memory value. If positive, the _offset_
2244 * parameter is the byte-addressed location in the window's extra
2245 * memory to set. If negative, _offset_ specifies the window
2246 * attribute to set, and should be one of the following values:
2248 * GWL_EXSTYLE The window's extended window style
2250 * GWL_STYLE The window's window style.
2252 * GWLP_WNDPROC Pointer to the window's window procedure.
2254 * GWLP_HINSTANCE The window's pplication instance handle.
2256 * GWLP_ID The window's identifier.
2258 * GWLP_USERDATA The window's user-specified data.
2260 * If the window is a dialog box, the _offset_ parameter can be one of
2261 * the following values:
2263 * DWLP_DLGPROC The address of the window's dialog box procedure.
2265 * DWLP_MSGRESULT The return value of a message
2266 * that the dialog box procedure processed.
2268 * DWLP_USER Application specific information.
2272 * If successful, returns the previous value located at _offset_. Otherwise,
2277 * Extra memory for a window class is specified by a nonzero cbWndExtra
2278 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2279 * time of class creation.
2281 * Using GWL_WNDPROC to set a new window procedure effectively creates
2282 * a window subclass. Use CallWindowProc() in the new windows procedure
2283 * to pass messages to the superclass's window procedure.
2285 * The user data is reserved for use by the application which created
2288 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2289 * instead, call the EnableWindow() function to change the window's
2292 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2293 * SetParent() instead.
2296 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2297 * it sends WM_STYLECHANGING before changing the settings
2298 * and WM_STYLECHANGED afterwards.
2299 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2301 LONG WINAPI SetWindowLongW(
2302 HWND hwnd, /* [in] window to alter */
2303 INT offset, /* [in] offset, in bytes, of location to alter */
2304 LONG newval /* [in] new value of location */
2306 return WIN_SetWindowLong( hwnd, offset, newval, TRUE );
2310 /*******************************************************************
2311 * GetWindowTextA (USER32.@)
2313 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2317 if (!lpString) return 0;
2319 if (WIN_IsCurrentProcess( hwnd ))
2320 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2322 /* when window belongs to other process, don't send a message */
2323 if (nMaxCount <= 0) return 0;
2324 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2325 get_server_window_text( hwnd, buffer, nMaxCount );
2326 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2327 lpString[nMaxCount-1] = 0;
2328 HeapFree( GetProcessHeap(), 0, buffer );
2329 return strlen(lpString);
2333 /*******************************************************************
2334 * InternalGetWindowText (USER32.@)
2336 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2340 if (nMaxCount <= 0) return 0;
2341 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2342 if (win == WND_DESKTOP) lpString[0] = 0;
2343 else if (win != WND_OTHER_PROCESS)
2345 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2346 else lpString[0] = 0;
2347 WIN_ReleasePtr( win );
2351 get_server_window_text( hwnd, lpString, nMaxCount );
2353 return strlenW(lpString);
2357 /*******************************************************************
2358 * GetWindowTextW (USER32.@)
2360 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2362 if (!lpString) return 0;
2364 if (WIN_IsCurrentProcess( hwnd ))
2365 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2367 /* when window belongs to other process, don't send a message */
2368 if (nMaxCount <= 0) return 0;
2369 get_server_window_text( hwnd, lpString, nMaxCount );
2370 return strlenW(lpString);
2374 /*******************************************************************
2375 * SetWindowTextA (USER32.@)
2376 * SetWindowText (USER32.@)
2378 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2380 if (is_broadcast(hwnd))
2382 SetLastError( ERROR_INVALID_PARAMETER );
2385 if (!WIN_IsCurrentProcess( hwnd ))
2386 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2387 debugstr_a(lpString), hwnd );
2388 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2392 /*******************************************************************
2393 * SetWindowTextW (USER32.@)
2395 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2397 if (is_broadcast(hwnd))
2399 SetLastError( ERROR_INVALID_PARAMETER );
2402 if (!WIN_IsCurrentProcess( hwnd ))
2403 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2404 debugstr_w(lpString), hwnd );
2405 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2409 /*******************************************************************
2410 * GetWindowTextLengthA (USER32.@)
2412 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2414 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2417 /*******************************************************************
2418 * GetWindowTextLengthW (USER32.@)
2420 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2422 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2426 /*******************************************************************
2427 * IsWindow (USER32.@)
2429 BOOL WINAPI IsWindow( HWND hwnd )
2434 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2435 if (ptr == WND_DESKTOP) return TRUE;
2437 if (ptr != WND_OTHER_PROCESS)
2439 WIN_ReleasePtr( ptr );
2443 /* check other processes */
2444 SERVER_START_REQ( get_window_info )
2447 ret = !wine_server_call_err( req );
2454 /***********************************************************************
2455 * GetWindowThreadProcessId (USER32.@)
2457 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2462 if (!(ptr = WIN_GetPtr( hwnd )))
2464 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2468 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2470 /* got a valid window */
2472 if (process) *process = GetCurrentProcessId();
2473 WIN_ReleasePtr( ptr );
2477 /* check other processes */
2478 SERVER_START_REQ( get_window_info )
2481 if (!wine_server_call_err( req ))
2483 tid = (DWORD)reply->tid;
2484 if (process) *process = (DWORD)reply->pid;
2492 /*****************************************************************
2493 * GetParent (USER32.@)
2495 HWND WINAPI GetParent( HWND hwnd )
2500 if (!(wndPtr = WIN_GetPtr( hwnd )))
2502 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2505 if (wndPtr == WND_DESKTOP) return 0;
2506 if (wndPtr == WND_OTHER_PROCESS)
2508 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2509 if (style & (WS_POPUP | WS_CHILD))
2511 SERVER_START_REQ( get_window_tree )
2514 if (!wine_server_call_err( req ))
2516 if (style & WS_POPUP) retvalue = reply->owner;
2517 else if (style & WS_CHILD) retvalue = reply->parent;
2525 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2526 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2527 WIN_ReleasePtr( wndPtr );
2533 /*****************************************************************
2534 * GetAncestor (USER32.@)
2536 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2539 HWND *list, ret = 0;
2544 if (!(win = WIN_GetPtr( hwnd )))
2546 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2549 if (win == WND_DESKTOP) return 0;
2550 if (win != WND_OTHER_PROCESS)
2553 WIN_ReleasePtr( win );
2555 else /* need to query the server */
2557 SERVER_START_REQ( get_window_tree )
2560 if (!wine_server_call_err( req )) ret = reply->parent;
2567 if (!(list = list_window_parents( hwnd ))) return 0;
2569 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2573 while (list[count]) count++;
2574 ret = list[count - 2]; /* get the one before the desktop */
2576 HeapFree( GetProcessHeap(), 0, list );
2580 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2583 HWND parent = GetParent( ret );
2593 /*****************************************************************
2594 * SetParent (USER32.@)
2596 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2600 if (is_broadcast(hwnd) || is_broadcast(parent))
2602 SetLastError(ERROR_INVALID_PARAMETER);
2606 if (!parent) parent = GetDesktopWindow();
2607 else parent = WIN_GetFullHandle( parent );
2609 if (!IsWindow( parent ))
2611 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2615 /* Some applications try to set a child as a parent */
2616 if (IsChild(hwnd, parent))
2618 SetLastError( ERROR_INVALID_PARAMETER );
2622 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2623 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2625 return USER_Driver->pSetParent( full_handle, parent );
2629 /*******************************************************************
2630 * IsChild (USER32.@)
2632 BOOL WINAPI IsChild( HWND parent, HWND child )
2634 HWND *list = list_window_parents( child );
2638 if (!list) return FALSE;
2639 parent = WIN_GetFullHandle( parent );
2640 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2641 ret = (list[i] != 0);
2642 HeapFree( GetProcessHeap(), 0, list );
2647 /***********************************************************************
2648 * IsWindowVisible (USER32.@)
2650 BOOL WINAPI IsWindowVisible( HWND hwnd )
2656 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2657 if (!(list = list_window_parents( hwnd ))) return TRUE;
2658 for (i = 0; list[i]; i++)
2659 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2661 HeapFree( GetProcessHeap(), 0, list );
2666 /***********************************************************************
2667 * WIN_IsWindowDrawable
2669 * hwnd is drawable when it is visible, all parents are not
2670 * minimized, and it is itself not minimized unless we are
2671 * trying to draw its default class icon.
2673 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2678 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2680 if (!(style & WS_VISIBLE)) return FALSE;
2681 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2683 if (!(list = list_window_parents( hwnd ))) return TRUE;
2684 for (i = 0; list[i]; i++)
2685 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2688 HeapFree( GetProcessHeap(), 0, list );
2693 /*******************************************************************
2694 * GetTopWindow (USER32.@)
2696 HWND WINAPI GetTopWindow( HWND hwnd )
2698 if (!hwnd) hwnd = GetDesktopWindow();
2699 return GetWindow( hwnd, GW_CHILD );
2703 /*******************************************************************
2704 * GetWindow (USER32.@)
2706 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2710 if (rel == GW_OWNER) /* this one may be available locally */
2712 WND *wndPtr = WIN_GetPtr( hwnd );
2715 SetLastError( ERROR_INVALID_HANDLE );
2718 if (wndPtr == WND_DESKTOP) return 0;
2719 if (wndPtr != WND_OTHER_PROCESS)
2721 retval = wndPtr->owner;
2722 WIN_ReleasePtr( wndPtr );
2725 /* else fall through to server call */
2728 SERVER_START_REQ( get_window_tree )
2731 if (!wine_server_call_err( req ))
2736 retval = reply->first_sibling;
2739 retval = reply->last_sibling;
2742 retval = reply->next_sibling;
2745 retval = reply->prev_sibling;
2748 retval = reply->owner;
2751 retval = reply->first_child;
2761 /*******************************************************************
2762 * ShowOwnedPopups (USER32.@)
2764 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2768 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2770 if (!win_array) return TRUE;
2772 while (win_array[count]) count++;
2773 while (--count >= 0)
2775 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2776 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2777 if (pWnd == WND_OTHER_PROCESS) continue;
2780 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2782 WIN_ReleasePtr( pWnd );
2783 /* In Windows, ShowOwnedPopups(TRUE) generates
2784 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2785 * regardless of the state of the owner
2787 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2793 if (pWnd->dwStyle & WS_VISIBLE)
2795 WIN_ReleasePtr( pWnd );
2796 /* In Windows, ShowOwnedPopups(FALSE) generates
2797 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2798 * regardless of the state of the owner
2800 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2804 WIN_ReleasePtr( pWnd );
2806 HeapFree( GetProcessHeap(), 0, win_array );
2811 /*******************************************************************
2812 * GetLastActivePopup (USER32.@)
2814 HWND WINAPI GetLastActivePopup( HWND hwnd )
2818 SERVER_START_REQ( get_window_info )
2821 if (!wine_server_call_err( req )) retval = reply->last_active;
2828 /*******************************************************************
2831 * Build an array of the children of a given window. The array must be
2832 * freed with HeapFree. Returns NULL when no windows are found.
2834 HWND *WIN_ListChildren( HWND hwnd )
2836 return list_window_children( hwnd, 0, 0 );
2840 /*******************************************************************
2841 * EnumWindows (USER32.@)
2843 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2849 USER_CheckNotLock();
2851 /* We have to build a list of all windows first, to avoid */
2852 /* unpleasant side-effects, for instance if the callback */
2853 /* function changes the Z-order of the windows. */
2855 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2857 /* Now call the callback function for every window */
2859 for (i = 0; list[i]; i++)
2861 /* Make sure that the window still exists */
2862 if (!IsWindow( list[i] )) continue;
2863 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2865 HeapFree( GetProcessHeap(), 0, list );
2870 /**********************************************************************
2871 * EnumThreadWindows (USER32.@)
2873 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2878 USER_CheckNotLock();
2880 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2882 /* Now call the callback function for every window */
2884 for (i = 0; list[i]; i++)
2885 if (!func( list[i], lParam )) break;
2886 HeapFree( GetProcessHeap(), 0, list );
2891 /**********************************************************************
2892 * WIN_EnumChildWindows
2894 * Helper function for EnumChildWindows().
2896 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2901 for ( ; *list; list++)
2903 /* Make sure that the window still exists */
2904 if (!IsWindow( *list )) continue;
2905 /* Build children list first */
2906 childList = WIN_ListChildren( *list );
2908 ret = func( *list, lParam );
2912 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2913 HeapFree( GetProcessHeap(), 0, childList );
2915 if (!ret) return FALSE;
2921 /**********************************************************************
2922 * EnumChildWindows (USER32.@)
2924 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2929 USER_CheckNotLock();
2931 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2932 ret = WIN_EnumChildWindows( list, func, lParam );
2933 HeapFree( GetProcessHeap(), 0, list );
2938 /*******************************************************************
2939 * AnyPopup (USER.52)
2941 BOOL16 WINAPI AnyPopup16(void)
2947 /*******************************************************************
2948 * AnyPopup (USER32.@)
2950 BOOL WINAPI AnyPopup(void)
2954 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2956 if (!list) return FALSE;
2957 for (i = 0; list[i]; i++)
2959 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2961 retvalue = (list[i] != 0);
2962 HeapFree( GetProcessHeap(), 0, list );
2967 /*******************************************************************
2968 * FlashWindow (USER32.@)
2970 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2974 TRACE("%p\n", hWnd);
2976 if (IsIconic( hWnd ))
2978 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2980 wndPtr = WIN_GetPtr(hWnd);
2981 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2982 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2984 wndPtr->flags |= WIN_NCACTIVATED;
2988 wndPtr->flags &= ~WIN_NCACTIVATED;
2990 WIN_ReleasePtr( wndPtr );
2997 wndPtr = WIN_GetPtr(hWnd);
2998 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2999 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3001 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3002 else wparam = (hWnd == GetForegroundWindow());
3004 WIN_ReleasePtr( wndPtr );
3005 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3010 /*******************************************************************
3011 * FlashWindowEx (USER32.@)
3013 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3015 FIXME("%p\n", pfwi);
3019 /*******************************************************************
3020 * GetWindowContextHelpId (USER32.@)
3022 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3025 WND *wnd = WIN_GetPtr( hwnd );
3026 if (!wnd || wnd == WND_DESKTOP) return 0;
3027 if (wnd == WND_OTHER_PROCESS)
3029 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3032 retval = wnd->helpContext;
3033 WIN_ReleasePtr( wnd );
3038 /*******************************************************************
3039 * SetWindowContextHelpId (USER32.@)
3041 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3043 WND *wnd = WIN_GetPtr( hwnd );
3044 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3045 if (wnd == WND_OTHER_PROCESS)
3047 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3050 wnd->helpContext = id;
3051 WIN_ReleasePtr( wnd );
3056 /*******************************************************************
3057 * DragDetect (USER32.@)
3059 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3063 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3064 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3066 rect.left = pt.x - wDragWidth;
3067 rect.right = pt.x + wDragWidth;
3069 rect.top = pt.y - wDragHeight;
3070 rect.bottom = pt.y + wDragHeight;
3076 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3078 if( msg.message == WM_LBUTTONUP )
3083 if( msg.message == WM_MOUSEMOVE )
3086 tmp.x = LOWORD(msg.lParam);
3087 tmp.y = HIWORD(msg.lParam);
3088 if( !PtInRect( &rect, tmp ))
3100 /******************************************************************************
3101 * GetWindowModuleFileNameA (USER32.@)
3103 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3105 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3106 hwnd, lpszFileName, cchFileNameMax);
3110 /******************************************************************************
3111 * GetWindowModuleFileNameW (USER32.@)
3113 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3115 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3116 hwnd, lpszFileName, cchFileNameMax);
3120 /******************************************************************************
3121 * GetWindowInfo (USER32.@)
3123 * Note: tests show that Windows doesn't check cbSize of the structure.
3125 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3127 if (!pwi) return FALSE;
3128 if (!IsWindow(hwnd)) return FALSE;
3130 GetWindowRect(hwnd, &pwi->rcWindow);
3131 GetClientRect(hwnd, &pwi->rcClient);
3132 /* translate to screen coordinates */
3133 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3135 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3136 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3137 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3139 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3140 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3142 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3143 pwi->wCreatorVersion = 0x0400;
3148 /******************************************************************************
3149 * SwitchDesktop (USER32.@)
3151 * NOTES: Sets the current input or interactive desktop.
3153 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3155 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3159 /*****************************************************************************
3160 * SetLayeredWindowAttributes (USER32.@)
3162 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3163 BYTE bAlpha, DWORD dwFlags )
3165 FIXME("(%p,0x%.8lx,%d,%ld): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3169 /*****************************************************************************
3170 * UpdateLayeredWindow (USER32.@)
3172 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3173 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3176 FIXME("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%ld): stub!\n",
3177 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);