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_CHILD))
1044 if (!MENU_SetMenu(hwnd, cs->hMenu))
1046 WIN_ReleasePtr( wndPtr );
1047 free_window_handle( hwnd );
1053 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1056 if (!cs->hInstance || HIWORD(cs->hInstance))
1057 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1059 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1061 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1065 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1066 WIN_ReleasePtr( wndPtr );
1068 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1070 WIN_DestroyWindow( hwnd );
1074 /* Notify the parent window only */
1076 send_parent_notify( hwnd, WM_CREATE );
1077 if (!IsWindow( hwnd )) return 0;
1079 if (cs->style & WS_VISIBLE)
1081 if (cs->style & WS_MAXIMIZE)
1083 else if (cs->style & WS_MINIMIZE)
1084 sw = SW_SHOWMINIMIZED;
1086 ShowWindow( hwnd, sw );
1087 if (cs->dwExStyle & WS_EX_MDICHILD)
1089 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1090 /* ShowWindow won't activate child windows */
1091 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1095 /* Call WH_SHELL hook */
1097 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1098 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1100 TRACE("created window %p\n", hwnd);
1105 /***********************************************************************
1106 * CreateWindow (USER.41)
1108 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1109 DWORD style, INT16 x, INT16 y, INT16 width,
1110 INT16 height, HWND16 parent, HMENU16 menu,
1111 HINSTANCE16 instance, LPVOID data )
1113 return CreateWindowEx16( 0, className, windowName, style,
1114 x, y, width, height, parent, menu, instance, data );
1118 /***********************************************************************
1119 * CreateWindowEx (USER.452)
1121 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1122 LPCSTR windowName, DWORD style, INT16 x,
1123 INT16 y, INT16 width, INT16 height,
1124 HWND16 parent, HMENU16 menu,
1125 HINSTANCE16 instance, LPVOID data )
1131 /* Find the class atom */
1133 if (HIWORD(className))
1135 if (!(classAtom = GlobalFindAtomA( className )))
1137 ERR( "bad class name %s\n", debugstr_a(className) );
1143 classAtom = LOWORD(className);
1144 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1146 ERR( "bad atom %x\n", classAtom);
1152 /* Fix the coordinates */
1154 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1155 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1156 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1157 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1159 /* Create the window */
1161 cs.lpCreateParams = data;
1162 cs.hInstance = HINSTANCE_32(instance);
1163 cs.hMenu = HMENU_32(menu);
1164 cs.hwndParent = WIN_Handle32( parent );
1166 cs.lpszName = windowName;
1167 cs.lpszClass = className;
1168 cs.dwExStyle = exStyle;
1170 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, 0 ));
1174 /***********************************************************************
1175 * CreateWindowExA (USER32.@)
1177 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1178 LPCSTR windowName, DWORD style, INT x,
1179 INT y, INT width, INT height,
1180 HWND parent, HMENU menu,
1181 HINSTANCE instance, LPVOID data )
1187 /* Find the class atom */
1189 if (HIWORD(className))
1191 if (!(classAtom = GlobalFindAtomA( className )))
1193 ERR( "bad class name %s\n", debugstr_a(className) );
1199 classAtom = LOWORD(className);
1200 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1202 ERR( "bad atom %x\n", classAtom);
1208 /* Create the window */
1210 cs.lpCreateParams = data;
1211 cs.hInstance = instance;
1213 cs.hwndParent = parent;
1219 cs.lpszName = windowName;
1220 cs.lpszClass = className;
1221 cs.dwExStyle = exStyle;
1223 return WIN_CreateWindowEx( &cs, classAtom, WIN_ISWIN32 );
1227 /***********************************************************************
1228 * CreateWindowExW (USER32.@)
1230 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1231 LPCWSTR windowName, DWORD style, INT x,
1232 INT y, INT width, INT height,
1233 HWND parent, HMENU menu,
1234 HINSTANCE instance, LPVOID data )
1240 /* Find the class atom */
1242 if (HIWORD(className))
1244 if (!(classAtom = GlobalFindAtomW( className )))
1246 ERR( "bad class name %s\n", debugstr_w(className) );
1252 classAtom = LOWORD(className);
1253 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1255 ERR( "bad atom %x\n", classAtom);
1261 /* Create the window */
1263 cs.lpCreateParams = data;
1264 cs.hInstance = instance;
1266 cs.hwndParent = parent;
1272 cs.lpszName = windowName;
1273 cs.lpszClass = className;
1274 cs.dwExStyle = exStyle;
1276 /* Note: we rely on the fact that CREATESTRUCTA and */
1277 /* CREATESTRUCTW have the same layout. */
1278 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_ISWIN32 | WIN_ISUNICODE );
1282 /***********************************************************************
1283 * WIN_SendDestroyMsg
1285 static void WIN_SendDestroyMsg( HWND hwnd )
1289 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1291 if (hwnd == info.hwndCaret) DestroyCaret();
1292 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1296 * Send the WM_DESTROY to the window.
1298 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1301 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1302 * make sure that the window still exists when we come back.
1309 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1311 for (i = 0; pWndArray[i]; i++)
1313 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1315 HeapFree( GetProcessHeap(), 0, pWndArray );
1318 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1322 /***********************************************************************
1323 * DestroyWindow (USER32.@)
1325 BOOL WINAPI DestroyWindow( HWND hwnd )
1329 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1331 SetLastError( ERROR_ACCESS_DENIED );
1335 TRACE("(%p)\n", hwnd);
1339 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1341 if (MENU_IsMenuActive() == hwnd)
1344 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1348 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1349 send_parent_notify( hwnd, WM_DESTROY );
1351 else if (!GetWindow( hwnd, GW_OWNER ))
1353 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1354 /* FIXME: clean up palette - see "Internals" p.352 */
1357 if (!IsWindow(hwnd)) return TRUE;
1359 /* Hide the window */
1360 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1362 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1364 ShowWindow( hwnd, SW_HIDE );
1366 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1367 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1370 if (!IsWindow(hwnd)) return TRUE;
1372 /* Recursively destroy owned windows */
1379 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1382 for (i = 0; list[i]; i++)
1384 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1385 if (WIN_IsCurrentThread( list[i] ))
1387 DestroyWindow( list[i] );
1391 WIN_SetOwner( list[i], 0 );
1393 HeapFree( GetProcessHeap(), 0, list );
1395 if (!got_one) break;
1399 /* Send destroy messages */
1401 WIN_SendDestroyMsg( hwnd );
1402 if (!IsWindow( hwnd )) return TRUE;
1404 if (GetClipboardOwner() == hwnd)
1405 CLIPBOARD_ReleaseOwner();
1407 /* Destroy the window storage */
1409 WIN_DestroyWindow( hwnd );
1414 /***********************************************************************
1415 * CloseWindow (USER32.@)
1417 BOOL WINAPI CloseWindow( HWND hwnd )
1419 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1420 ShowWindow( hwnd, SW_MINIMIZE );
1425 /***********************************************************************
1426 * OpenIcon (USER32.@)
1428 BOOL WINAPI OpenIcon( HWND hwnd )
1430 if (!IsIconic( hwnd )) return FALSE;
1431 ShowWindow( hwnd, SW_SHOWNORMAL );
1436 /***********************************************************************
1439 * Implementation of FindWindow() and FindWindowEx().
1441 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1446 WCHAR *buffer = NULL;
1448 if (!parent) parent = GetDesktopWindow();
1451 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1452 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1455 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1459 child = WIN_GetFullHandle( child );
1460 while (list[i] && list[i] != child) i++;
1461 if (!list[i]) goto done;
1462 i++; /* start from next window */
1469 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1476 HeapFree( GetProcessHeap(), 0, list );
1477 HeapFree( GetProcessHeap(), 0, buffer );
1483 /***********************************************************************
1484 * FindWindowA (USER32.@)
1486 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1488 HWND ret = FindWindowExA( 0, 0, className, title );
1489 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1494 /***********************************************************************
1495 * FindWindowExA (USER32.@)
1497 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1498 LPCSTR className, LPCSTR title )
1507 /* If the atom doesn't exist, then no class */
1508 /* with this name exists either. */
1509 if (!(atom = GlobalFindAtomA( className )))
1511 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1515 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1517 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1518 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1519 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1520 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1521 HeapFree( GetProcessHeap(), 0, buffer );
1526 /***********************************************************************
1527 * FindWindowExW (USER32.@)
1529 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1530 LPCWSTR className, LPCWSTR title )
1536 /* If the atom doesn't exist, then no class */
1537 /* with this name exists either. */
1538 if (!(atom = GlobalFindAtomW( className )))
1540 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1544 return WIN_FindWindow( parent, child, atom, title );
1548 /***********************************************************************
1549 * FindWindowW (USER32.@)
1551 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1553 return FindWindowExW( 0, 0, className, title );
1557 /**********************************************************************
1558 * GetDesktopWindow (USER32.@)
1560 HWND WINAPI GetDesktopWindow(void)
1562 struct user_thread_info *thread_info = get_user_thread_info();
1564 if (thread_info->desktop) return thread_info->desktop;
1566 SERVER_START_REQ( get_desktop_window )
1569 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1573 if (!thread_info->desktop)
1576 PROCESS_INFORMATION pi;
1577 WCHAR command_line[] = {'e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1579 memset( &si, 0, sizeof(si) );
1581 if (CreateProcessW( NULL, command_line, NULL, NULL, FALSE, DETACHED_PROCESS,
1582 NULL, NULL, &si, &pi ))
1584 TRACE( "started explorer pid %04lx tid %04lx\n", pi.dwProcessId, pi.dwThreadId );
1585 WaitForInputIdle( pi.hProcess, 10000 );
1586 CloseHandle( pi.hThread );
1587 CloseHandle( pi.hProcess );
1590 else WARN( "failed to start explorer, err %ld\n", GetLastError() );
1592 SERVER_START_REQ( get_desktop_window )
1595 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1600 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1601 ERR( "failed to create desktop window\n" );
1603 return thread_info->desktop;
1607 /*******************************************************************
1608 * EnableWindow (USER32.@)
1610 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1615 if (is_broadcast(hwnd))
1617 SetLastError( ERROR_INVALID_PARAMETER );
1621 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1622 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1626 TRACE("( %p, %d )\n", hwnd, enable);
1628 retvalue = !IsWindowEnabled( hwnd );
1630 if (enable && retvalue)
1632 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1633 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1635 else if (!enable && !retvalue)
1639 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1641 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1643 if (hwnd == GetFocus())
1644 SetFocus( 0 ); /* A disabled window can't have the focus */
1646 capture_wnd = GetCapture();
1647 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1648 ReleaseCapture(); /* A disabled window can't capture the mouse */
1650 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1656 /***********************************************************************
1657 * IsWindowEnabled (USER32.@)
1659 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1661 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1665 /***********************************************************************
1666 * IsWindowUnicode (USER32.@)
1668 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1671 BOOL retvalue = FALSE;
1673 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1675 if (wndPtr == WND_DESKTOP) return TRUE;
1677 if (wndPtr != WND_OTHER_PROCESS)
1679 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1680 WIN_ReleasePtr( wndPtr );
1684 SERVER_START_REQ( get_window_info )
1687 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1695 /**********************************************************************
1696 * GetWindowWord (USER32.@)
1698 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1703 WND *wndPtr = WIN_GetPtr( hwnd );
1706 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1709 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1711 SERVER_START_REQ( set_window_info )
1714 req->flags = 0; /* don't set anything, just retrieve */
1715 req->extra_offset = offset;
1716 req->extra_size = sizeof(retvalue);
1717 if (!wine_server_call_err( req ))
1718 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1723 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1725 WARN("Invalid offset %d\n", offset );
1726 SetLastError( ERROR_INVALID_INDEX );
1728 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1729 WIN_ReleasePtr( wndPtr );
1735 case GWLP_HWNDPARENT:
1736 return GetWindowLongPtrW( hwnd, offset );
1738 case GWLP_HINSTANCE:
1740 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1742 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1746 WARN("Invalid offset %d\n", offset );
1752 /**********************************************************************
1753 * SetWindowWord (USER32.@)
1755 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1763 case GWLP_HINSTANCE:
1764 case GWLP_HWNDPARENT:
1765 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1769 WARN("Invalid offset %d\n", offset );
1770 SetLastError( ERROR_INVALID_INDEX );
1775 wndPtr = WIN_GetPtr( hwnd );
1776 if (wndPtr == WND_DESKTOP)
1778 SetLastError( ERROR_ACCESS_DENIED );
1781 if (wndPtr == WND_OTHER_PROCESS)
1784 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1785 offset, newval, hwnd );
1790 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1794 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1796 WARN("Invalid offset %d\n", offset );
1797 WIN_ReleasePtr(wndPtr);
1798 SetLastError( ERROR_INVALID_INDEX );
1802 SERVER_START_REQ( set_window_info )
1805 req->flags = SET_WIN_EXTRA;
1806 req->extra_offset = offset;
1807 req->extra_size = sizeof(newval);
1808 memcpy( &req->extra_value, &newval, sizeof(newval) );
1809 if (!wine_server_call_err( req ))
1811 void *ptr = (char *)wndPtr->wExtra + offset;
1812 memcpy( &retval, ptr, sizeof(retval) );
1813 memcpy( ptr, &newval, sizeof(newval) );
1817 WIN_ReleasePtr( wndPtr );
1822 /**********************************************************************
1825 * Helper function for GetWindowLong().
1827 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, BOOL unicode )
1829 LONG_PTR retvalue = 0;
1832 if (offset == GWLP_HWNDPARENT)
1834 HWND parent = GetAncestor( hwnd, GA_PARENT );
1835 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1836 return (ULONG_PTR)parent;
1839 if (!(wndPtr = WIN_GetPtr( hwnd )))
1841 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1845 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1847 if (offset == GWLP_WNDPROC)
1849 SetLastError( ERROR_ACCESS_DENIED );
1852 SERVER_START_REQ( set_window_info )
1855 req->flags = 0; /* don't set anything, just retrieve */
1856 req->extra_offset = (offset >= 0) ? offset : -1;
1857 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1858 if (!wine_server_call_err( req ))
1862 case GWL_STYLE: retvalue = reply->old_style; break;
1863 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1864 case GWLP_ID: retvalue = reply->old_id; break;
1865 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1866 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1868 if (offset >= 0) retvalue = reply->old_extra_value;
1869 else SetLastError( ERROR_INVALID_INDEX );
1878 /* now we have a valid wndPtr */
1882 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1884 WARN("Invalid offset %d\n", offset );
1885 WIN_ReleasePtr( wndPtr );
1886 SetLastError( ERROR_INVALID_INDEX );
1889 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
1890 /* Special case for dialog window procedure */
1891 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1892 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1893 WIN_ReleasePtr( wndPtr );
1899 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1900 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1901 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1902 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1903 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode ); break;
1904 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1906 WARN("Unknown offset %d\n", offset );
1907 SetLastError( ERROR_INVALID_INDEX );
1910 WIN_ReleasePtr(wndPtr);
1915 /**********************************************************************
1918 * Helper function for SetWindowLong().
1920 * 0 is the failure code. However, in the case of failure SetLastError
1921 * must be set to distinguish between a 0 return value and a failure.
1923 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval, BOOL unicode )
1927 LONG_PTR retval = 0;
1930 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1932 if (is_broadcast(hwnd))
1934 SetLastError( ERROR_INVALID_PARAMETER );
1938 if (!(wndPtr = WIN_GetPtr( hwnd )))
1940 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1943 if (wndPtr == WND_DESKTOP)
1945 /* can't change anything on the desktop window */
1946 SetLastError( ERROR_ACCESS_DENIED );
1949 if (wndPtr == WND_OTHER_PROCESS)
1951 if (offset == GWLP_WNDPROC)
1953 SetLastError( ERROR_ACCESS_DENIED );
1956 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1959 /* first some special cases */
1965 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1966 style.styleNew = newval;
1967 WIN_ReleasePtr( wndPtr );
1968 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1969 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1970 newval = style.styleNew;
1972 case GWLP_HWNDPARENT:
1973 if (wndPtr->parent == GetDesktopWindow())
1975 WIN_ReleasePtr( wndPtr );
1976 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1980 WIN_ReleasePtr( wndPtr );
1981 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1985 UINT old_flags = wndPtr->flags;
1986 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1987 if (unicode) wndPtr->winproc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1988 else wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1989 if (WINPROC_IsUnicode( wndPtr->winproc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1990 else wndPtr->flags &= ~WIN_ISUNICODE;
1991 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1993 WIN_ReleasePtr( wndPtr );
1996 /* update is_unicode flag on the server side */
2000 case GWLP_HINSTANCE:
2004 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2006 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2007 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
2008 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2009 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2010 WIN_ReleasePtr( wndPtr );
2015 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
2017 WARN("Invalid offset %d\n", offset );
2018 WIN_ReleasePtr( wndPtr );
2019 SetLastError( ERROR_INVALID_INDEX );
2024 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2025 if (*ptr == newval) /* already set to the same value */
2027 WIN_ReleasePtr( wndPtr );
2034 SERVER_START_REQ( set_window_info )
2037 req->extra_offset = -1;
2041 req->flags = SET_WIN_STYLE;
2042 req->style = newval;
2045 req->flags = SET_WIN_EXSTYLE;
2046 req->ex_style = newval;
2049 req->flags = SET_WIN_ID;
2052 case GWLP_HINSTANCE:
2053 req->flags = SET_WIN_INSTANCE;
2054 req->instance = (void *)newval;
2057 req->flags = SET_WIN_UNICODE;
2058 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2061 req->flags = SET_WIN_USERDATA;
2062 req->user_data = (void *)newval;
2065 req->flags = SET_WIN_EXTRA;
2066 req->extra_offset = offset;
2067 req->extra_size = sizeof(newval);
2068 memcpy( &req->extra_value, &newval, sizeof(newval) );
2070 if ((ok = !wine_server_call_err( req )))
2075 wndPtr->dwStyle = newval;
2076 retval = reply->old_style;
2079 wndPtr->dwExStyle = newval;
2080 retval = reply->old_ex_style;
2083 wndPtr->wIDmenu = newval;
2084 retval = reply->old_id;
2086 case GWLP_HINSTANCE:
2087 wndPtr->hInstance = (HINSTANCE)newval;
2088 retval = (ULONG_PTR)reply->old_instance;
2093 wndPtr->userdata = newval;
2094 retval = (ULONG_PTR)reply->old_user_data;
2098 void *ptr = (char *)wndPtr->wExtra + offset;
2099 memcpy( &retval, ptr, sizeof(retval) );
2100 memcpy( ptr, &newval, sizeof(newval) );
2107 WIN_ReleasePtr( wndPtr );
2111 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2113 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2114 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2120 /**********************************************************************
2121 * GetWindowLong (USER.135)
2123 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2127 BOOL is_winproc = (offset == GWLP_WNDPROC);
2131 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2133 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2136 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2138 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2141 * Some programs try to access last element from 16 bit
2142 * code using illegal offset value. Hopefully this is
2143 * what those programs really expect.
2145 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2147 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2148 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2153 WARN("Invalid offset %d\n", offset );
2154 WIN_ReleasePtr( wndPtr );
2155 SetLastError( ERROR_INVALID_INDEX );
2159 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2160 WIN_ReleasePtr( wndPtr );
2163 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2164 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2169 /**********************************************************************
2170 * GetWindowLongA (USER32.@)
2172 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2174 return WIN_GetWindowLong( hwnd, offset, FALSE );
2178 /**********************************************************************
2179 * GetWindowLongW (USER32.@)
2181 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2183 return WIN_GetWindowLong( hwnd, offset, TRUE );
2187 /**********************************************************************
2188 * SetWindowLong (USER.136)
2190 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2193 BOOL is_winproc = (offset == GWLP_WNDPROC);
2195 if (offset == DWLP_DLGPROC)
2197 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2199 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2202 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2204 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2205 (wndPtr->flags & WIN_ISDIALOG));
2206 WIN_ReleasePtr( wndPtr );
2212 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2213 WNDPROC old_proc = (WNDPROC)SetWindowLongA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2214 return (LONG)WINPROC_GetProc16( (WNDPROC)old_proc, FALSE );
2216 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2220 /**********************************************************************
2221 * SetWindowLongA (USER32.@)
2223 * See SetWindowLongW.
2225 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2227 return WIN_SetWindowLong( hwnd, offset, newval, FALSE );
2231 /**********************************************************************
2232 * SetWindowLongW (USER32.@) Set window attribute
2234 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2235 * value in a window's extra memory.
2237 * The _hwnd_ parameter specifies the window. is the handle to a
2238 * window that has extra memory. The _newval_ parameter contains the
2239 * new attribute or extra memory value. If positive, the _offset_
2240 * parameter is the byte-addressed location in the window's extra
2241 * memory to set. If negative, _offset_ specifies the window
2242 * attribute to set, and should be one of the following values:
2244 * GWL_EXSTYLE The window's extended window style
2246 * GWL_STYLE The window's window style.
2248 * GWLP_WNDPROC Pointer to the window's window procedure.
2250 * GWLP_HINSTANCE The window's pplication instance handle.
2252 * GWLP_ID The window's identifier.
2254 * GWLP_USERDATA The window's user-specified data.
2256 * If the window is a dialog box, the _offset_ parameter can be one of
2257 * the following values:
2259 * DWLP_DLGPROC The address of the window's dialog box procedure.
2261 * DWLP_MSGRESULT The return value of a message
2262 * that the dialog box procedure processed.
2264 * DWLP_USER Application specific information.
2268 * If successful, returns the previous value located at _offset_. Otherwise,
2273 * Extra memory for a window class is specified by a nonzero cbWndExtra
2274 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2275 * time of class creation.
2277 * Using GWL_WNDPROC to set a new window procedure effectively creates
2278 * a window subclass. Use CallWindowProc() in the new windows procedure
2279 * to pass messages to the superclass's window procedure.
2281 * The user data is reserved for use by the application which created
2284 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2285 * instead, call the EnableWindow() function to change the window's
2288 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2289 * SetParent() instead.
2292 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2293 * it sends WM_STYLECHANGING before changing the settings
2294 * and WM_STYLECHANGED afterwards.
2295 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2297 LONG WINAPI SetWindowLongW(
2298 HWND hwnd, /* [in] window to alter */
2299 INT offset, /* [in] offset, in bytes, of location to alter */
2300 LONG newval /* [in] new value of location */
2302 return WIN_SetWindowLong( hwnd, offset, newval, TRUE );
2306 /*******************************************************************
2307 * GetWindowTextA (USER32.@)
2309 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2313 if (!lpString) return 0;
2315 if (WIN_IsCurrentProcess( hwnd ))
2316 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2318 /* when window belongs to other process, don't send a message */
2319 if (nMaxCount <= 0) return 0;
2320 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2321 get_server_window_text( hwnd, buffer, nMaxCount );
2322 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2323 lpString[nMaxCount-1] = 0;
2324 HeapFree( GetProcessHeap(), 0, buffer );
2325 return strlen(lpString);
2329 /*******************************************************************
2330 * InternalGetWindowText (USER32.@)
2332 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2336 if (nMaxCount <= 0) return 0;
2337 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2338 if (win == WND_DESKTOP) lpString[0] = 0;
2339 else if (win != WND_OTHER_PROCESS)
2341 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2342 else lpString[0] = 0;
2343 WIN_ReleasePtr( win );
2347 get_server_window_text( hwnd, lpString, nMaxCount );
2349 return strlenW(lpString);
2353 /*******************************************************************
2354 * GetWindowTextW (USER32.@)
2356 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2358 if (!lpString) return 0;
2360 if (WIN_IsCurrentProcess( hwnd ))
2361 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2363 /* when window belongs to other process, don't send a message */
2364 if (nMaxCount <= 0) return 0;
2365 get_server_window_text( hwnd, lpString, nMaxCount );
2366 return strlenW(lpString);
2370 /*******************************************************************
2371 * SetWindowTextA (USER32.@)
2372 * SetWindowText (USER32.@)
2374 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2376 if (is_broadcast(hwnd))
2378 SetLastError( ERROR_INVALID_PARAMETER );
2381 if (!WIN_IsCurrentProcess( hwnd ))
2382 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2383 debugstr_a(lpString), hwnd );
2384 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2388 /*******************************************************************
2389 * SetWindowTextW (USER32.@)
2391 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2393 if (is_broadcast(hwnd))
2395 SetLastError( ERROR_INVALID_PARAMETER );
2398 if (!WIN_IsCurrentProcess( hwnd ))
2399 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2400 debugstr_w(lpString), hwnd );
2401 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2405 /*******************************************************************
2406 * GetWindowTextLengthA (USER32.@)
2408 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2410 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2413 /*******************************************************************
2414 * GetWindowTextLengthW (USER32.@)
2416 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2418 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2422 /*******************************************************************
2423 * IsWindow (USER32.@)
2425 BOOL WINAPI IsWindow( HWND hwnd )
2430 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2431 if (ptr == WND_DESKTOP) return TRUE;
2433 if (ptr != WND_OTHER_PROCESS)
2435 WIN_ReleasePtr( ptr );
2439 /* check other processes */
2440 SERVER_START_REQ( get_window_info )
2443 ret = !wine_server_call_err( req );
2450 /***********************************************************************
2451 * GetWindowThreadProcessId (USER32.@)
2453 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2458 if (!(ptr = WIN_GetPtr( hwnd )))
2460 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2464 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2466 /* got a valid window */
2468 if (process) *process = GetCurrentProcessId();
2469 WIN_ReleasePtr( ptr );
2473 /* check other processes */
2474 SERVER_START_REQ( get_window_info )
2477 if (!wine_server_call_err( req ))
2479 tid = (DWORD)reply->tid;
2480 if (process) *process = (DWORD)reply->pid;
2488 /*****************************************************************
2489 * GetParent (USER32.@)
2491 HWND WINAPI GetParent( HWND hwnd )
2496 if (!(wndPtr = WIN_GetPtr( hwnd )))
2498 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2501 if (wndPtr == WND_DESKTOP) return 0;
2502 if (wndPtr == WND_OTHER_PROCESS)
2504 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2505 if (style & (WS_POPUP | WS_CHILD))
2507 SERVER_START_REQ( get_window_tree )
2510 if (!wine_server_call_err( req ))
2512 if (style & WS_POPUP) retvalue = reply->owner;
2513 else if (style & WS_CHILD) retvalue = reply->parent;
2521 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2522 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2523 WIN_ReleasePtr( wndPtr );
2529 /*****************************************************************
2530 * GetAncestor (USER32.@)
2532 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2535 HWND *list, ret = 0;
2540 if (!(win = WIN_GetPtr( hwnd )))
2542 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2545 if (win == WND_DESKTOP) return 0;
2546 if (win != WND_OTHER_PROCESS)
2549 WIN_ReleasePtr( win );
2551 else /* need to query the server */
2553 SERVER_START_REQ( get_window_tree )
2556 if (!wine_server_call_err( req )) ret = reply->parent;
2563 if (!(list = list_window_parents( hwnd ))) return 0;
2565 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2569 while (list[count]) count++;
2570 ret = list[count - 2]; /* get the one before the desktop */
2572 HeapFree( GetProcessHeap(), 0, list );
2576 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2579 HWND parent = GetParent( ret );
2589 /*****************************************************************
2590 * SetParent (USER32.@)
2592 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2596 if (is_broadcast(hwnd) || is_broadcast(parent))
2598 SetLastError(ERROR_INVALID_PARAMETER);
2602 if (!parent) parent = GetDesktopWindow();
2603 else parent = WIN_GetFullHandle( parent );
2605 if (!IsWindow( parent ))
2607 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2611 /* Some applications try to set a child as a parent */
2612 if (IsChild(hwnd, parent))
2614 SetLastError( ERROR_INVALID_PARAMETER );
2618 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2619 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2621 return USER_Driver->pSetParent( full_handle, parent );
2625 /*******************************************************************
2626 * IsChild (USER32.@)
2628 BOOL WINAPI IsChild( HWND parent, HWND child )
2630 HWND *list = list_window_parents( child );
2634 if (!list) return FALSE;
2635 parent = WIN_GetFullHandle( parent );
2636 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2637 ret = (list[i] != 0);
2638 HeapFree( GetProcessHeap(), 0, list );
2643 /***********************************************************************
2644 * IsWindowVisible (USER32.@)
2646 BOOL WINAPI IsWindowVisible( HWND hwnd )
2652 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2653 if (!(list = list_window_parents( hwnd ))) return TRUE;
2654 for (i = 0; list[i]; i++)
2655 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2657 HeapFree( GetProcessHeap(), 0, list );
2662 /***********************************************************************
2663 * WIN_IsWindowDrawable
2665 * hwnd is drawable when it is visible, all parents are not
2666 * minimized, and it is itself not minimized unless we are
2667 * trying to draw its default class icon.
2669 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2674 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2676 if (!(style & WS_VISIBLE)) return FALSE;
2677 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2679 if (!(list = list_window_parents( hwnd ))) return TRUE;
2680 for (i = 0; list[i]; i++)
2681 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2684 HeapFree( GetProcessHeap(), 0, list );
2689 /*******************************************************************
2690 * GetTopWindow (USER32.@)
2692 HWND WINAPI GetTopWindow( HWND hwnd )
2694 if (!hwnd) hwnd = GetDesktopWindow();
2695 return GetWindow( hwnd, GW_CHILD );
2699 /*******************************************************************
2700 * GetWindow (USER32.@)
2702 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2706 if (rel == GW_OWNER) /* this one may be available locally */
2708 WND *wndPtr = WIN_GetPtr( hwnd );
2711 SetLastError( ERROR_INVALID_HANDLE );
2714 if (wndPtr == WND_DESKTOP) return 0;
2715 if (wndPtr != WND_OTHER_PROCESS)
2717 retval = wndPtr->owner;
2718 WIN_ReleasePtr( wndPtr );
2721 /* else fall through to server call */
2724 SERVER_START_REQ( get_window_tree )
2727 if (!wine_server_call_err( req ))
2732 retval = reply->first_sibling;
2735 retval = reply->last_sibling;
2738 retval = reply->next_sibling;
2741 retval = reply->prev_sibling;
2744 retval = reply->owner;
2747 retval = reply->first_child;
2757 /*******************************************************************
2758 * ShowOwnedPopups (USER32.@)
2760 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2764 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2766 if (!win_array) return TRUE;
2768 while (win_array[count]) count++;
2769 while (--count >= 0)
2771 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2772 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2773 if (pWnd == WND_OTHER_PROCESS) continue;
2776 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2778 WIN_ReleasePtr( pWnd );
2779 /* In Windows, ShowOwnedPopups(TRUE) generates
2780 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2781 * regardless of the state of the owner
2783 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2789 if (pWnd->dwStyle & WS_VISIBLE)
2791 WIN_ReleasePtr( pWnd );
2792 /* In Windows, ShowOwnedPopups(FALSE) generates
2793 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2794 * regardless of the state of the owner
2796 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2800 WIN_ReleasePtr( pWnd );
2802 HeapFree( GetProcessHeap(), 0, win_array );
2807 /*******************************************************************
2808 * GetLastActivePopup (USER32.@)
2810 HWND WINAPI GetLastActivePopup( HWND hwnd )
2814 SERVER_START_REQ( get_window_info )
2817 if (!wine_server_call_err( req )) retval = reply->last_active;
2824 /*******************************************************************
2827 * Build an array of the children of a given window. The array must be
2828 * freed with HeapFree. Returns NULL when no windows are found.
2830 HWND *WIN_ListChildren( HWND hwnd )
2832 return list_window_children( hwnd, 0, 0 );
2836 /*******************************************************************
2837 * EnumWindows (USER32.@)
2839 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2845 USER_CheckNotLock();
2847 /* We have to build a list of all windows first, to avoid */
2848 /* unpleasant side-effects, for instance if the callback */
2849 /* function changes the Z-order of the windows. */
2851 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2853 /* Now call the callback function for every window */
2855 for (i = 0; list[i]; i++)
2857 /* Make sure that the window still exists */
2858 if (!IsWindow( list[i] )) continue;
2859 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2861 HeapFree( GetProcessHeap(), 0, list );
2866 /**********************************************************************
2867 * EnumThreadWindows (USER32.@)
2869 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2874 USER_CheckNotLock();
2876 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2878 /* Now call the callback function for every window */
2880 for (i = 0; list[i]; i++)
2881 if (!func( list[i], lParam )) break;
2882 HeapFree( GetProcessHeap(), 0, list );
2887 /**********************************************************************
2888 * WIN_EnumChildWindows
2890 * Helper function for EnumChildWindows().
2892 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2897 for ( ; *list; list++)
2899 /* Make sure that the window still exists */
2900 if (!IsWindow( *list )) continue;
2901 /* Build children list first */
2902 childList = WIN_ListChildren( *list );
2904 ret = func( *list, lParam );
2908 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2909 HeapFree( GetProcessHeap(), 0, childList );
2911 if (!ret) return FALSE;
2917 /**********************************************************************
2918 * EnumChildWindows (USER32.@)
2920 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2925 USER_CheckNotLock();
2927 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2928 ret = WIN_EnumChildWindows( list, func, lParam );
2929 HeapFree( GetProcessHeap(), 0, list );
2934 /*******************************************************************
2935 * AnyPopup (USER.52)
2937 BOOL16 WINAPI AnyPopup16(void)
2943 /*******************************************************************
2944 * AnyPopup (USER32.@)
2946 BOOL WINAPI AnyPopup(void)
2950 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2952 if (!list) return FALSE;
2953 for (i = 0; list[i]; i++)
2955 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2957 retvalue = (list[i] != 0);
2958 HeapFree( GetProcessHeap(), 0, list );
2963 /*******************************************************************
2964 * FlashWindow (USER32.@)
2966 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2970 TRACE("%p\n", hWnd);
2972 if (IsIconic( hWnd ))
2974 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2976 wndPtr = WIN_GetPtr(hWnd);
2977 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2978 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2980 wndPtr->flags |= WIN_NCACTIVATED;
2984 wndPtr->flags &= ~WIN_NCACTIVATED;
2986 WIN_ReleasePtr( wndPtr );
2993 wndPtr = WIN_GetPtr(hWnd);
2994 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2995 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2997 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2998 else wparam = (hWnd == GetForegroundWindow());
3000 WIN_ReleasePtr( wndPtr );
3001 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3006 /*******************************************************************
3007 * FlashWindowEx (USER32.@)
3009 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3011 FIXME("%p\n", pfwi);
3015 /*******************************************************************
3016 * GetWindowContextHelpId (USER32.@)
3018 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3021 WND *wnd = WIN_GetPtr( hwnd );
3022 if (!wnd || wnd == WND_DESKTOP) return 0;
3023 if (wnd == WND_OTHER_PROCESS)
3025 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3028 retval = wnd->helpContext;
3029 WIN_ReleasePtr( wnd );
3034 /*******************************************************************
3035 * SetWindowContextHelpId (USER32.@)
3037 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3039 WND *wnd = WIN_GetPtr( hwnd );
3040 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3041 if (wnd == WND_OTHER_PROCESS)
3043 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3046 wnd->helpContext = id;
3047 WIN_ReleasePtr( wnd );
3052 /*******************************************************************
3053 * DragDetect (USER32.@)
3055 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3059 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3060 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3062 rect.left = pt.x - wDragWidth;
3063 rect.right = pt.x + wDragWidth;
3065 rect.top = pt.y - wDragHeight;
3066 rect.bottom = pt.y + wDragHeight;
3072 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3074 if( msg.message == WM_LBUTTONUP )
3079 if( msg.message == WM_MOUSEMOVE )
3082 tmp.x = LOWORD(msg.lParam);
3083 tmp.y = HIWORD(msg.lParam);
3084 if( !PtInRect( &rect, tmp ))
3096 /******************************************************************************
3097 * GetWindowModuleFileNameA (USER32.@)
3099 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3101 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3102 hwnd, lpszFileName, cchFileNameMax);
3106 /******************************************************************************
3107 * GetWindowModuleFileNameW (USER32.@)
3109 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3111 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3112 hwnd, lpszFileName, cchFileNameMax);
3116 /******************************************************************************
3117 * GetWindowInfo (USER32.@)
3119 * Note: tests show that Windows doesn't check cbSize of the structure.
3121 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3123 if (!pwi) return FALSE;
3124 if (!IsWindow(hwnd)) return FALSE;
3126 GetWindowRect(hwnd, &pwi->rcWindow);
3127 GetClientRect(hwnd, &pwi->rcClient);
3128 /* translate to screen coordinates */
3129 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3131 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3132 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3133 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3135 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3136 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3138 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3139 pwi->wCreatorVersion = 0x0400;
3144 /******************************************************************************
3145 * SwitchDesktop (USER32.@)
3147 * NOTES: Sets the current input or interactive desktop.
3149 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3151 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3155 /*****************************************************************************
3156 * SetLayeredWindowAttributes (USER32.@)
3158 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3159 BYTE bAlpha, DWORD dwFlags )
3161 FIXME("(%p,0x%.8lx,%d,%ld): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3165 /*****************************************************************************
3166 * UpdateLayeredWindow (USER32.@)
3168 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3169 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3172 FIXME("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%ld): stub!\n",
3173 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3177 /* 64bit versions */
3179 #ifdef GetWindowLongPtrW
3180 #undef GetWindowLongPtrW
3183 #ifdef GetWindowLongPtrA
3184 #undef GetWindowLongPtrA
3187 #ifdef SetWindowLongPtrW
3188 #undef SetWindowLongPtrW
3191 #ifdef SetWindowLongPtrA
3192 #undef SetWindowLongPtrA
3195 /*****************************************************************************
3196 * GetWindowLongPtrW (USER32.@)
3198 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3204 /*****************************************************************************
3205 * GetWindowLongPtrA (USER32.@)
3207 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3213 /*****************************************************************************
3214 * SetWindowLongPtrW (USER32.@)
3216 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3222 /*****************************************************************************
3223 * SetWindowLongPtrA (USER32.@)
3225 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )