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 );
1297 * Send the WM_DESTROY to the window.
1299 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1302 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1303 * make sure that the window still exists when we come back.
1310 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1312 for (i = 0; pWndArray[i]; i++)
1314 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1316 HeapFree( GetProcessHeap(), 0, pWndArray );
1319 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1323 /***********************************************************************
1324 * DestroyWindow (USER32.@)
1326 BOOL WINAPI DestroyWindow( HWND hwnd )
1330 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1332 SetLastError( ERROR_ACCESS_DENIED );
1336 TRACE("(%p)\n", hwnd);
1340 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1342 if (MENU_IsMenuActive() == hwnd)
1345 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1349 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1350 send_parent_notify( hwnd, WM_DESTROY );
1352 else if (!GetWindow( hwnd, GW_OWNER ))
1354 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1355 /* FIXME: clean up palette - see "Internals" p.352 */
1358 if (!IsWindow(hwnd)) return TRUE;
1360 /* Hide the window */
1361 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1363 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1365 ShowWindow( hwnd, SW_HIDE );
1367 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1368 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1371 if (!IsWindow(hwnd)) return TRUE;
1373 /* Recursively destroy owned windows */
1380 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1383 for (i = 0; list[i]; i++)
1385 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1386 if (WIN_IsCurrentThread( list[i] ))
1388 DestroyWindow( list[i] );
1392 WIN_SetOwner( list[i], 0 );
1394 HeapFree( GetProcessHeap(), 0, list );
1396 if (!got_one) break;
1400 /* Send destroy messages */
1402 WIN_SendDestroyMsg( hwnd );
1403 if (!IsWindow( hwnd )) return TRUE;
1405 if (GetClipboardOwner() == hwnd)
1406 CLIPBOARD_ReleaseOwner();
1408 /* Destroy the window storage */
1410 WIN_DestroyWindow( hwnd );
1415 /***********************************************************************
1416 * CloseWindow (USER32.@)
1418 BOOL WINAPI CloseWindow( HWND hwnd )
1420 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1421 ShowWindow( hwnd, SW_MINIMIZE );
1426 /***********************************************************************
1427 * OpenIcon (USER32.@)
1429 BOOL WINAPI OpenIcon( HWND hwnd )
1431 if (!IsIconic( hwnd )) return FALSE;
1432 ShowWindow( hwnd, SW_SHOWNORMAL );
1437 /***********************************************************************
1440 * Implementation of FindWindow() and FindWindowEx().
1442 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1447 WCHAR *buffer = NULL;
1449 if (!parent) parent = GetDesktopWindow();
1452 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1453 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1456 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1460 child = WIN_GetFullHandle( child );
1461 while (list[i] && list[i] != child) i++;
1462 if (!list[i]) goto done;
1463 i++; /* start from next window */
1470 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1477 HeapFree( GetProcessHeap(), 0, list );
1478 HeapFree( GetProcessHeap(), 0, buffer );
1484 /***********************************************************************
1485 * FindWindowA (USER32.@)
1487 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1489 HWND ret = FindWindowExA( 0, 0, className, title );
1490 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1495 /***********************************************************************
1496 * FindWindowExA (USER32.@)
1498 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1499 LPCSTR className, LPCSTR title )
1508 /* If the atom doesn't exist, then no class */
1509 /* with this name exists either. */
1510 if (!(atom = GlobalFindAtomA( className )))
1512 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1516 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1518 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1519 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1520 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1521 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1522 HeapFree( GetProcessHeap(), 0, buffer );
1527 /***********************************************************************
1528 * FindWindowExW (USER32.@)
1530 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1531 LPCWSTR className, LPCWSTR title )
1537 /* If the atom doesn't exist, then no class */
1538 /* with this name exists either. */
1539 if (!(atom = GlobalFindAtomW( className )))
1541 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1545 return WIN_FindWindow( parent, child, atom, title );
1549 /***********************************************************************
1550 * FindWindowW (USER32.@)
1552 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1554 return FindWindowExW( 0, 0, className, title );
1558 /**********************************************************************
1559 * GetDesktopWindow (USER32.@)
1561 HWND WINAPI GetDesktopWindow(void)
1563 struct user_thread_info *thread_info = get_user_thread_info();
1565 if (thread_info->desktop) return thread_info->desktop;
1567 SERVER_START_REQ( get_desktop_window )
1570 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1574 if (!thread_info->desktop)
1577 PROCESS_INFORMATION pi;
1578 WCHAR command_line[] = {'e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1580 memset( &si, 0, sizeof(si) );
1582 if (CreateProcessW( NULL, command_line, NULL, NULL, FALSE, DETACHED_PROCESS,
1583 NULL, NULL, &si, &pi ))
1585 TRACE( "started explorer pid %04lx tid %04lx\n", pi.dwProcessId, pi.dwThreadId );
1586 WaitForInputIdle( pi.hProcess, 10000 );
1587 CloseHandle( pi.hThread );
1588 CloseHandle( pi.hProcess );
1591 else WARN( "failed to start explorer, err %ld\n", GetLastError() );
1593 SERVER_START_REQ( get_desktop_window )
1596 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1601 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1602 ERR( "failed to create desktop window\n" );
1604 return thread_info->desktop;
1608 /*******************************************************************
1609 * EnableWindow (USER32.@)
1611 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1616 if (is_broadcast(hwnd))
1618 SetLastError( ERROR_INVALID_PARAMETER );
1622 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1623 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1627 TRACE("( %p, %d )\n", hwnd, enable);
1629 retvalue = !IsWindowEnabled( hwnd );
1631 if (enable && retvalue)
1633 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1634 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1636 else if (!enable && !retvalue)
1640 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1642 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1644 if (hwnd == GetFocus())
1645 SetFocus( 0 ); /* A disabled window can't have the focus */
1647 capture_wnd = GetCapture();
1648 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1649 ReleaseCapture(); /* A disabled window can't capture the mouse */
1651 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1657 /***********************************************************************
1658 * IsWindowEnabled (USER32.@)
1660 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1662 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1666 /***********************************************************************
1667 * IsWindowUnicode (USER32.@)
1669 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1672 BOOL retvalue = FALSE;
1674 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1676 if (wndPtr == WND_DESKTOP) return TRUE;
1678 if (wndPtr != WND_OTHER_PROCESS)
1680 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1681 WIN_ReleasePtr( wndPtr );
1685 SERVER_START_REQ( get_window_info )
1688 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1696 /**********************************************************************
1697 * GetWindowWord (USER32.@)
1699 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1704 WND *wndPtr = WIN_GetPtr( hwnd );
1707 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1710 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1712 SERVER_START_REQ( set_window_info )
1715 req->flags = 0; /* don't set anything, just retrieve */
1716 req->extra_offset = offset;
1717 req->extra_size = sizeof(retvalue);
1718 if (!wine_server_call_err( req ))
1719 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1724 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1726 WARN("Invalid offset %d\n", offset );
1727 SetLastError( ERROR_INVALID_INDEX );
1729 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1730 WIN_ReleasePtr( wndPtr );
1736 case GWLP_HWNDPARENT:
1737 return GetWindowLongPtrW( hwnd, offset );
1739 case GWLP_HINSTANCE:
1741 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1743 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1747 WARN("Invalid offset %d\n", offset );
1753 /**********************************************************************
1754 * SetWindowWord (USER32.@)
1756 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1764 case GWLP_HINSTANCE:
1765 case GWLP_HWNDPARENT:
1766 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1770 WARN("Invalid offset %d\n", offset );
1771 SetLastError( ERROR_INVALID_INDEX );
1776 wndPtr = WIN_GetPtr( hwnd );
1777 if (wndPtr == WND_DESKTOP)
1779 SetLastError( ERROR_ACCESS_DENIED );
1782 if (wndPtr == WND_OTHER_PROCESS)
1785 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1786 offset, newval, hwnd );
1791 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1795 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1797 WARN("Invalid offset %d\n", offset );
1798 WIN_ReleasePtr(wndPtr);
1799 SetLastError( ERROR_INVALID_INDEX );
1803 SERVER_START_REQ( set_window_info )
1806 req->flags = SET_WIN_EXTRA;
1807 req->extra_offset = offset;
1808 req->extra_size = sizeof(newval);
1809 memcpy( &req->extra_value, &newval, sizeof(newval) );
1810 if (!wine_server_call_err( req ))
1812 void *ptr = (char *)wndPtr->wExtra + offset;
1813 memcpy( &retval, ptr, sizeof(retval) );
1814 memcpy( ptr, &newval, sizeof(newval) );
1818 WIN_ReleasePtr( wndPtr );
1823 /**********************************************************************
1826 * Helper function for GetWindowLong().
1828 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, BOOL unicode )
1830 LONG_PTR retvalue = 0;
1833 if (offset == GWLP_HWNDPARENT)
1835 HWND parent = GetAncestor( hwnd, GA_PARENT );
1836 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1837 return (ULONG_PTR)parent;
1840 if (!(wndPtr = WIN_GetPtr( hwnd )))
1842 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1846 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1848 if (offset == GWLP_WNDPROC)
1850 SetLastError( ERROR_ACCESS_DENIED );
1853 SERVER_START_REQ( set_window_info )
1856 req->flags = 0; /* don't set anything, just retrieve */
1857 req->extra_offset = (offset >= 0) ? offset : -1;
1858 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1859 if (!wine_server_call_err( req ))
1863 case GWL_STYLE: retvalue = reply->old_style; break;
1864 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1865 case GWLP_ID: retvalue = reply->old_id; break;
1866 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1867 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1869 if (offset >= 0) retvalue = reply->old_extra_value;
1870 else SetLastError( ERROR_INVALID_INDEX );
1879 /* now we have a valid wndPtr */
1883 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1885 WARN("Invalid offset %d\n", offset );
1886 WIN_ReleasePtr( wndPtr );
1887 SetLastError( ERROR_INVALID_INDEX );
1890 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
1891 /* Special case for dialog window procedure */
1892 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1893 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1894 WIN_ReleasePtr( wndPtr );
1900 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1901 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1902 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1903 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1904 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode ); break;
1905 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1907 WARN("Unknown offset %d\n", offset );
1908 SetLastError( ERROR_INVALID_INDEX );
1911 WIN_ReleasePtr(wndPtr);
1916 /**********************************************************************
1919 * Helper function for SetWindowLong().
1921 * 0 is the failure code. However, in the case of failure SetLastError
1922 * must be set to distinguish between a 0 return value and a failure.
1924 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval, BOOL unicode )
1928 LONG_PTR retval = 0;
1931 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1933 if (is_broadcast(hwnd))
1935 SetLastError( ERROR_INVALID_PARAMETER );
1939 if (!(wndPtr = WIN_GetPtr( hwnd )))
1941 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1944 if (wndPtr == WND_DESKTOP)
1946 /* can't change anything on the desktop window */
1947 SetLastError( ERROR_ACCESS_DENIED );
1950 if (wndPtr == WND_OTHER_PROCESS)
1952 if (offset == GWLP_WNDPROC)
1954 SetLastError( ERROR_ACCESS_DENIED );
1957 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1960 /* first some special cases */
1966 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1967 style.styleNew = newval;
1968 WIN_ReleasePtr( wndPtr );
1969 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1970 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1971 newval = style.styleNew;
1973 case GWLP_HWNDPARENT:
1974 if (wndPtr->parent == GetDesktopWindow())
1976 WIN_ReleasePtr( wndPtr );
1977 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1981 WIN_ReleasePtr( wndPtr );
1982 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1986 UINT old_flags = wndPtr->flags;
1987 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1988 if (unicode) wndPtr->winproc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1989 else wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1990 if (WINPROC_IsUnicode( wndPtr->winproc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1991 else wndPtr->flags &= ~WIN_ISUNICODE;
1992 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1994 WIN_ReleasePtr( wndPtr );
1997 /* update is_unicode flag on the server side */
2001 case GWLP_HINSTANCE:
2005 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2007 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2008 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
2009 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2010 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2011 WIN_ReleasePtr( wndPtr );
2016 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
2018 WARN("Invalid offset %d\n", offset );
2019 WIN_ReleasePtr( wndPtr );
2020 SetLastError( ERROR_INVALID_INDEX );
2025 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2026 if (*ptr == newval) /* already set to the same value */
2028 WIN_ReleasePtr( wndPtr );
2035 SERVER_START_REQ( set_window_info )
2038 req->extra_offset = -1;
2042 req->flags = SET_WIN_STYLE;
2043 req->style = newval;
2046 req->flags = SET_WIN_EXSTYLE;
2047 req->ex_style = newval;
2050 req->flags = SET_WIN_ID;
2053 case GWLP_HINSTANCE:
2054 req->flags = SET_WIN_INSTANCE;
2055 req->instance = (void *)newval;
2058 req->flags = SET_WIN_UNICODE;
2059 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2062 req->flags = SET_WIN_USERDATA;
2063 req->user_data = (void *)newval;
2066 req->flags = SET_WIN_EXTRA;
2067 req->extra_offset = offset;
2068 req->extra_size = sizeof(newval);
2069 memcpy( &req->extra_value, &newval, sizeof(newval) );
2071 if ((ok = !wine_server_call_err( req )))
2076 wndPtr->dwStyle = newval;
2077 retval = reply->old_style;
2080 wndPtr->dwExStyle = newval;
2081 retval = reply->old_ex_style;
2084 wndPtr->wIDmenu = newval;
2085 retval = reply->old_id;
2087 case GWLP_HINSTANCE:
2088 wndPtr->hInstance = (HINSTANCE)newval;
2089 retval = (ULONG_PTR)reply->old_instance;
2094 wndPtr->userdata = newval;
2095 retval = (ULONG_PTR)reply->old_user_data;
2099 void *ptr = (char *)wndPtr->wExtra + offset;
2100 memcpy( &retval, ptr, sizeof(retval) );
2101 memcpy( ptr, &newval, sizeof(newval) );
2108 WIN_ReleasePtr( wndPtr );
2112 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2114 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2115 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2121 /**********************************************************************
2122 * GetWindowLong (USER.135)
2124 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2128 BOOL is_winproc = (offset == GWLP_WNDPROC);
2132 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2134 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2137 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2139 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2142 * Some programs try to access last element from 16 bit
2143 * code using illegal offset value. Hopefully this is
2144 * what those programs really expect.
2146 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2148 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2149 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2154 WARN("Invalid offset %d\n", offset );
2155 WIN_ReleasePtr( wndPtr );
2156 SetLastError( ERROR_INVALID_INDEX );
2160 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2161 WIN_ReleasePtr( wndPtr );
2164 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2165 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2170 /**********************************************************************
2171 * GetWindowLongA (USER32.@)
2173 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2175 return WIN_GetWindowLong( hwnd, offset, FALSE );
2179 /**********************************************************************
2180 * GetWindowLongW (USER32.@)
2182 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2184 return WIN_GetWindowLong( hwnd, offset, TRUE );
2188 /**********************************************************************
2189 * SetWindowLong (USER.136)
2191 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2194 BOOL is_winproc = (offset == GWLP_WNDPROC);
2196 if (offset == DWLP_DLGPROC)
2198 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2200 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2203 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2205 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2206 (wndPtr->flags & WIN_ISDIALOG));
2207 WIN_ReleasePtr( wndPtr );
2213 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2214 WNDPROC old_proc = (WNDPROC)SetWindowLongA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2215 return (LONG)WINPROC_GetProc16( (WNDPROC)old_proc, FALSE );
2217 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2221 /**********************************************************************
2222 * SetWindowLongA (USER32.@)
2224 * See SetWindowLongW.
2226 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2228 return WIN_SetWindowLong( hwnd, offset, newval, FALSE );
2232 /**********************************************************************
2233 * SetWindowLongW (USER32.@) Set window attribute
2235 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2236 * value in a window's extra memory.
2238 * The _hwnd_ parameter specifies the window. is the handle to a
2239 * window that has extra memory. The _newval_ parameter contains the
2240 * new attribute or extra memory value. If positive, the _offset_
2241 * parameter is the byte-addressed location in the window's extra
2242 * memory to set. If negative, _offset_ specifies the window
2243 * attribute to set, and should be one of the following values:
2245 * GWL_EXSTYLE The window's extended window style
2247 * GWL_STYLE The window's window style.
2249 * GWLP_WNDPROC Pointer to the window's window procedure.
2251 * GWLP_HINSTANCE The window's pplication instance handle.
2253 * GWLP_ID The window's identifier.
2255 * GWLP_USERDATA The window's user-specified data.
2257 * If the window is a dialog box, the _offset_ parameter can be one of
2258 * the following values:
2260 * DWLP_DLGPROC The address of the window's dialog box procedure.
2262 * DWLP_MSGRESULT The return value of a message
2263 * that the dialog box procedure processed.
2265 * DWLP_USER Application specific information.
2269 * If successful, returns the previous value located at _offset_. Otherwise,
2274 * Extra memory for a window class is specified by a nonzero cbWndExtra
2275 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2276 * time of class creation.
2278 * Using GWL_WNDPROC to set a new window procedure effectively creates
2279 * a window subclass. Use CallWindowProc() in the new windows procedure
2280 * to pass messages to the superclass's window procedure.
2282 * The user data is reserved for use by the application which created
2285 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2286 * instead, call the EnableWindow() function to change the window's
2289 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2290 * SetParent() instead.
2293 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2294 * it sends WM_STYLECHANGING before changing the settings
2295 * and WM_STYLECHANGED afterwards.
2296 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2298 LONG WINAPI SetWindowLongW(
2299 HWND hwnd, /* [in] window to alter */
2300 INT offset, /* [in] offset, in bytes, of location to alter */
2301 LONG newval /* [in] new value of location */
2303 return WIN_SetWindowLong( hwnd, offset, newval, TRUE );
2307 /*******************************************************************
2308 * GetWindowTextA (USER32.@)
2310 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2314 if (!lpString) return 0;
2316 if (WIN_IsCurrentProcess( hwnd ))
2317 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2319 /* when window belongs to other process, don't send a message */
2320 if (nMaxCount <= 0) return 0;
2321 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2322 get_server_window_text( hwnd, buffer, nMaxCount );
2323 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2324 lpString[nMaxCount-1] = 0;
2325 HeapFree( GetProcessHeap(), 0, buffer );
2326 return strlen(lpString);
2330 /*******************************************************************
2331 * InternalGetWindowText (USER32.@)
2333 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2337 if (nMaxCount <= 0) return 0;
2338 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2339 if (win == WND_DESKTOP) lpString[0] = 0;
2340 else if (win != WND_OTHER_PROCESS)
2342 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2343 else lpString[0] = 0;
2344 WIN_ReleasePtr( win );
2348 get_server_window_text( hwnd, lpString, nMaxCount );
2350 return strlenW(lpString);
2354 /*******************************************************************
2355 * GetWindowTextW (USER32.@)
2357 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2359 if (!lpString) return 0;
2361 if (WIN_IsCurrentProcess( hwnd ))
2362 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2364 /* when window belongs to other process, don't send a message */
2365 if (nMaxCount <= 0) return 0;
2366 get_server_window_text( hwnd, lpString, nMaxCount );
2367 return strlenW(lpString);
2371 /*******************************************************************
2372 * SetWindowTextA (USER32.@)
2373 * SetWindowText (USER32.@)
2375 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2377 if (is_broadcast(hwnd))
2379 SetLastError( ERROR_INVALID_PARAMETER );
2382 if (!WIN_IsCurrentProcess( hwnd ))
2383 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2384 debugstr_a(lpString), hwnd );
2385 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2389 /*******************************************************************
2390 * SetWindowTextW (USER32.@)
2392 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2394 if (is_broadcast(hwnd))
2396 SetLastError( ERROR_INVALID_PARAMETER );
2399 if (!WIN_IsCurrentProcess( hwnd ))
2400 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2401 debugstr_w(lpString), hwnd );
2402 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2406 /*******************************************************************
2407 * GetWindowTextLengthA (USER32.@)
2409 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2411 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2414 /*******************************************************************
2415 * GetWindowTextLengthW (USER32.@)
2417 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2419 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2423 /*******************************************************************
2424 * IsWindow (USER32.@)
2426 BOOL WINAPI IsWindow( HWND hwnd )
2431 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2432 if (ptr == WND_DESKTOP) return TRUE;
2434 if (ptr != WND_OTHER_PROCESS)
2436 WIN_ReleasePtr( ptr );
2440 /* check other processes */
2441 SERVER_START_REQ( get_window_info )
2444 ret = !wine_server_call_err( req );
2451 /***********************************************************************
2452 * GetWindowThreadProcessId (USER32.@)
2454 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2459 if (!(ptr = WIN_GetPtr( hwnd )))
2461 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2465 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2467 /* got a valid window */
2469 if (process) *process = GetCurrentProcessId();
2470 WIN_ReleasePtr( ptr );
2474 /* check other processes */
2475 SERVER_START_REQ( get_window_info )
2478 if (!wine_server_call_err( req ))
2480 tid = (DWORD)reply->tid;
2481 if (process) *process = (DWORD)reply->pid;
2489 /*****************************************************************
2490 * GetParent (USER32.@)
2492 HWND WINAPI GetParent( HWND hwnd )
2497 if (!(wndPtr = WIN_GetPtr( hwnd )))
2499 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2502 if (wndPtr == WND_DESKTOP) return 0;
2503 if (wndPtr == WND_OTHER_PROCESS)
2505 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2506 if (style & (WS_POPUP | WS_CHILD))
2508 SERVER_START_REQ( get_window_tree )
2511 if (!wine_server_call_err( req ))
2513 if (style & WS_POPUP) retvalue = reply->owner;
2514 else if (style & WS_CHILD) retvalue = reply->parent;
2522 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2523 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2524 WIN_ReleasePtr( wndPtr );
2530 /*****************************************************************
2531 * GetAncestor (USER32.@)
2533 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2536 HWND *list, ret = 0;
2541 if (!(win = WIN_GetPtr( hwnd )))
2543 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2546 if (win == WND_DESKTOP) return 0;
2547 if (win != WND_OTHER_PROCESS)
2550 WIN_ReleasePtr( win );
2552 else /* need to query the server */
2554 SERVER_START_REQ( get_window_tree )
2557 if (!wine_server_call_err( req )) ret = reply->parent;
2564 if (!(list = list_window_parents( hwnd ))) return 0;
2566 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2570 while (list[count]) count++;
2571 ret = list[count - 2]; /* get the one before the desktop */
2573 HeapFree( GetProcessHeap(), 0, list );
2577 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2580 HWND parent = GetParent( ret );
2590 /*****************************************************************
2591 * SetParent (USER32.@)
2593 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2597 if (is_broadcast(hwnd) || is_broadcast(parent))
2599 SetLastError(ERROR_INVALID_PARAMETER);
2603 if (!parent) parent = GetDesktopWindow();
2604 else parent = WIN_GetFullHandle( parent );
2606 if (!IsWindow( parent ))
2608 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2612 /* Some applications try to set a child as a parent */
2613 if (IsChild(hwnd, parent))
2615 SetLastError( ERROR_INVALID_PARAMETER );
2619 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2620 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2622 return USER_Driver->pSetParent( full_handle, parent );
2626 /*******************************************************************
2627 * IsChild (USER32.@)
2629 BOOL WINAPI IsChild( HWND parent, HWND child )
2631 HWND *list = list_window_parents( child );
2635 if (!list) return FALSE;
2636 parent = WIN_GetFullHandle( parent );
2637 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2638 ret = (list[i] != 0);
2639 HeapFree( GetProcessHeap(), 0, list );
2644 /***********************************************************************
2645 * IsWindowVisible (USER32.@)
2647 BOOL WINAPI IsWindowVisible( HWND hwnd )
2653 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2654 if (!(list = list_window_parents( hwnd ))) return TRUE;
2655 for (i = 0; list[i]; i++)
2656 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2658 HeapFree( GetProcessHeap(), 0, list );
2663 /***********************************************************************
2664 * WIN_IsWindowDrawable
2666 * hwnd is drawable when it is visible, all parents are not
2667 * minimized, and it is itself not minimized unless we are
2668 * trying to draw its default class icon.
2670 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2675 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2677 if (!(style & WS_VISIBLE)) return FALSE;
2678 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2680 if (!(list = list_window_parents( hwnd ))) return TRUE;
2681 for (i = 0; list[i]; i++)
2682 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2685 HeapFree( GetProcessHeap(), 0, list );
2690 /*******************************************************************
2691 * GetTopWindow (USER32.@)
2693 HWND WINAPI GetTopWindow( HWND hwnd )
2695 if (!hwnd) hwnd = GetDesktopWindow();
2696 return GetWindow( hwnd, GW_CHILD );
2700 /*******************************************************************
2701 * GetWindow (USER32.@)
2703 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2707 if (rel == GW_OWNER) /* this one may be available locally */
2709 WND *wndPtr = WIN_GetPtr( hwnd );
2712 SetLastError( ERROR_INVALID_HANDLE );
2715 if (wndPtr == WND_DESKTOP) return 0;
2716 if (wndPtr != WND_OTHER_PROCESS)
2718 retval = wndPtr->owner;
2719 WIN_ReleasePtr( wndPtr );
2722 /* else fall through to server call */
2725 SERVER_START_REQ( get_window_tree )
2728 if (!wine_server_call_err( req ))
2733 retval = reply->first_sibling;
2736 retval = reply->last_sibling;
2739 retval = reply->next_sibling;
2742 retval = reply->prev_sibling;
2745 retval = reply->owner;
2748 retval = reply->first_child;
2758 /*******************************************************************
2759 * ShowOwnedPopups (USER32.@)
2761 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2765 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2767 if (!win_array) return TRUE;
2769 while (win_array[count]) count++;
2770 while (--count >= 0)
2772 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2773 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2774 if (pWnd == WND_OTHER_PROCESS) continue;
2777 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2779 WIN_ReleasePtr( pWnd );
2780 /* In Windows, ShowOwnedPopups(TRUE) generates
2781 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2782 * regardless of the state of the owner
2784 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2790 if (pWnd->dwStyle & WS_VISIBLE)
2792 WIN_ReleasePtr( pWnd );
2793 /* In Windows, ShowOwnedPopups(FALSE) generates
2794 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2795 * regardless of the state of the owner
2797 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2801 WIN_ReleasePtr( pWnd );
2803 HeapFree( GetProcessHeap(), 0, win_array );
2808 /*******************************************************************
2809 * GetLastActivePopup (USER32.@)
2811 HWND WINAPI GetLastActivePopup( HWND hwnd )
2815 SERVER_START_REQ( get_window_info )
2818 if (!wine_server_call_err( req )) retval = reply->last_active;
2825 /*******************************************************************
2828 * Build an array of the children of a given window. The array must be
2829 * freed with HeapFree. Returns NULL when no windows are found.
2831 HWND *WIN_ListChildren( HWND hwnd )
2833 return list_window_children( hwnd, 0, 0 );
2837 /*******************************************************************
2838 * EnumWindows (USER32.@)
2840 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2846 USER_CheckNotLock();
2848 /* We have to build a list of all windows first, to avoid */
2849 /* unpleasant side-effects, for instance if the callback */
2850 /* function changes the Z-order of the windows. */
2852 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2854 /* Now call the callback function for every window */
2856 for (i = 0; list[i]; i++)
2858 /* Make sure that the window still exists */
2859 if (!IsWindow( list[i] )) continue;
2860 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2862 HeapFree( GetProcessHeap(), 0, list );
2867 /**********************************************************************
2868 * EnumThreadWindows (USER32.@)
2870 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2875 USER_CheckNotLock();
2877 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2879 /* Now call the callback function for every window */
2881 for (i = 0; list[i]; i++)
2882 if (!func( list[i], lParam )) break;
2883 HeapFree( GetProcessHeap(), 0, list );
2888 /**********************************************************************
2889 * WIN_EnumChildWindows
2891 * Helper function for EnumChildWindows().
2893 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2898 for ( ; *list; list++)
2900 /* Make sure that the window still exists */
2901 if (!IsWindow( *list )) continue;
2902 /* Build children list first */
2903 childList = WIN_ListChildren( *list );
2905 ret = func( *list, lParam );
2909 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2910 HeapFree( GetProcessHeap(), 0, childList );
2912 if (!ret) return FALSE;
2918 /**********************************************************************
2919 * EnumChildWindows (USER32.@)
2921 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2926 USER_CheckNotLock();
2928 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2929 ret = WIN_EnumChildWindows( list, func, lParam );
2930 HeapFree( GetProcessHeap(), 0, list );
2935 /*******************************************************************
2936 * AnyPopup (USER.52)
2938 BOOL16 WINAPI AnyPopup16(void)
2944 /*******************************************************************
2945 * AnyPopup (USER32.@)
2947 BOOL WINAPI AnyPopup(void)
2951 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2953 if (!list) return FALSE;
2954 for (i = 0; list[i]; i++)
2956 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2958 retvalue = (list[i] != 0);
2959 HeapFree( GetProcessHeap(), 0, list );
2964 /*******************************************************************
2965 * FlashWindow (USER32.@)
2967 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2971 TRACE("%p\n", hWnd);
2973 if (IsIconic( hWnd ))
2975 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2977 wndPtr = WIN_GetPtr(hWnd);
2978 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2979 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2981 wndPtr->flags |= WIN_NCACTIVATED;
2985 wndPtr->flags &= ~WIN_NCACTIVATED;
2987 WIN_ReleasePtr( wndPtr );
2994 wndPtr = WIN_GetPtr(hWnd);
2995 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2996 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2998 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2999 else wparam = (hWnd == GetForegroundWindow());
3001 WIN_ReleasePtr( wndPtr );
3002 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3007 /*******************************************************************
3008 * FlashWindowEx (USER32.@)
3010 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3012 FIXME("%p\n", pfwi);
3016 /*******************************************************************
3017 * GetWindowContextHelpId (USER32.@)
3019 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3022 WND *wnd = WIN_GetPtr( hwnd );
3023 if (!wnd || wnd == WND_DESKTOP) return 0;
3024 if (wnd == WND_OTHER_PROCESS)
3026 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3029 retval = wnd->helpContext;
3030 WIN_ReleasePtr( wnd );
3035 /*******************************************************************
3036 * SetWindowContextHelpId (USER32.@)
3038 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3040 WND *wnd = WIN_GetPtr( hwnd );
3041 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3042 if (wnd == WND_OTHER_PROCESS)
3044 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3047 wnd->helpContext = id;
3048 WIN_ReleasePtr( wnd );
3053 /*******************************************************************
3054 * DragDetect (USER32.@)
3056 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3060 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3061 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3063 rect.left = pt.x - wDragWidth;
3064 rect.right = pt.x + wDragWidth;
3066 rect.top = pt.y - wDragHeight;
3067 rect.bottom = pt.y + wDragHeight;
3073 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3075 if( msg.message == WM_LBUTTONUP )
3080 if( msg.message == WM_MOUSEMOVE )
3083 tmp.x = LOWORD(msg.lParam);
3084 tmp.y = HIWORD(msg.lParam);
3085 if( !PtInRect( &rect, tmp ))
3097 /******************************************************************************
3098 * GetWindowModuleFileNameA (USER32.@)
3100 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3102 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3103 hwnd, lpszFileName, cchFileNameMax);
3107 /******************************************************************************
3108 * GetWindowModuleFileNameW (USER32.@)
3110 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3112 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3113 hwnd, lpszFileName, cchFileNameMax);
3117 /******************************************************************************
3118 * GetWindowInfo (USER32.@)
3120 * Note: tests show that Windows doesn't check cbSize of the structure.
3122 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3124 if (!pwi) return FALSE;
3125 if (!IsWindow(hwnd)) return FALSE;
3127 GetWindowRect(hwnd, &pwi->rcWindow);
3128 GetClientRect(hwnd, &pwi->rcClient);
3129 /* translate to screen coordinates */
3130 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3132 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3133 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3134 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3136 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3137 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3139 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3140 pwi->wCreatorVersion = 0x0400;
3145 /******************************************************************************
3146 * SwitchDesktop (USER32.@)
3148 * NOTES: Sets the current input or interactive desktop.
3150 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3152 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3156 /*****************************************************************************
3157 * SetLayeredWindowAttributes (USER32.@)
3159 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3160 BYTE bAlpha, DWORD dwFlags )
3162 FIXME("(%p,0x%.8lx,%d,%ld): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3166 /*****************************************************************************
3167 * UpdateLayeredWindow (USER32.@)
3169 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3170 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3173 FIXME("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%ld): stub!\n",
3174 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3178 /* 64bit versions */
3180 #ifdef GetWindowLongPtrW
3181 #undef GetWindowLongPtrW
3184 #ifdef GetWindowLongPtrA
3185 #undef GetWindowLongPtrA
3188 #ifdef SetWindowLongPtrW
3189 #undef SetWindowLongPtrW
3192 #ifdef SetWindowLongPtrA
3193 #undef SetWindowLongPtrA
3196 /*****************************************************************************
3197 * GetWindowLongPtrW (USER32.@)
3199 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3205 /*****************************************************************************
3206 * GetWindowLongPtrA (USER32.@)
3208 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3214 /*****************************************************************************
3215 * SetWindowLongPtrW (USER32.@)
3217 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3223 /*****************************************************************************
3224 * SetWindowLongPtrA (USER32.@)
3226 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )