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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
36 #include "user_private.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(win);
44 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
45 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
47 /**********************************************************************/
50 static void *user_handles[NB_USER_HANDLES];
52 /***********************************************************************
53 * create_window_handle
55 * Create a window handle with the server.
57 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
58 HINSTANCE instance, WINDOWPROCTYPE type )
62 HWND full_parent = 0, full_owner = 0;
63 struct tagCLASS *class = NULL;
64 user_handle_t handle = 0;
67 /* if 16-bit instance, map to module handle */
68 if (instance && !HIWORD(instance))
69 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
71 SERVER_START_REQ( create_window )
76 req->instance = instance;
77 if (!wine_server_call_err( req ))
79 handle = reply->handle;
80 full_parent = reply->parent;
81 full_owner = reply->owner;
82 extra_bytes = reply->extra;
83 class = reply->class_ptr;
90 WARN( "error %ld creating window\n", GetLastError() );
94 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
96 SERVER_START_REQ( destroy_window )
99 wine_server_call( req );
102 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
106 if (!parent) /* if parent is 0 we don't have a desktop window yet */
108 struct user_thread_info *thread_info = get_user_thread_info();
110 assert( !thread_info->desktop );
111 thread_info->desktop = full_parent ? full_parent : handle;
112 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
113 ERR( "failed to create desktop window\n" );
118 index = USER_HANDLE_TO_INDEX(handle);
119 assert( index < NB_USER_HANDLES );
120 user_handles[index] = win;
121 win->hwndSelf = handle;
122 win->parent = full_parent;
123 win->owner = full_owner;
124 win->dwMagic = WND_MAGIC;
125 win->cbWndExtra = extra_bytes;
126 memset( win->wExtra, 0, extra_bytes );
127 CLASS_AddWindow( class, win, type );
132 /***********************************************************************
135 * Free a window handle.
137 static WND *free_window_handle( HWND hwnd )
140 WORD index = USER_HANDLE_TO_INDEX(hwnd);
142 if (index >= NB_USER_HANDLES) return NULL;
144 if ((ptr = user_handles[index]))
146 SERVER_START_REQ( destroy_window )
149 if (!wine_server_call_err( req ))
151 user_handles[index] = NULL;
160 HeapFree( GetProcessHeap(), 0, ptr );
165 /*******************************************************************
166 * list_window_children
168 * Build an array of the children of a given window. The array must be
169 * freed with HeapFree. Returns NULL when no windows are found.
171 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
180 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
182 SERVER_START_REQ( get_window_children )
187 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
188 if (!wine_server_call( req )) count = reply->count;
191 if (count && count < size)
196 HeapFree( GetProcessHeap(), 0, list );
198 size = count + 1; /* restart with a large enough buffer */
204 /*******************************************************************
205 * list_window_parents
207 * Build an array of all parents of a given window, starting with
208 * the immediate parent. The array must be freed with HeapFree.
209 * Returns NULL if window is a top-level window.
211 static HWND *list_window_parents( HWND hwnd )
215 int pos = 0, size = 16, count = 0;
217 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
222 if (!(win = WIN_GetPtr( current ))) goto empty;
223 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
224 if (win == WND_DESKTOP)
226 if (!pos) goto empty;
230 list[pos] = current = win->parent;
231 WIN_ReleasePtr( win );
232 if (++pos == size - 1)
234 /* need to grow the list */
235 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
236 if (!new_list) goto empty;
242 /* at least one parent belongs to another process, have to query the server */
247 SERVER_START_REQ( get_window_parents )
250 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
251 if (!wine_server_call( req )) count = reply->count;
254 if (!count) goto empty;
260 HeapFree( GetProcessHeap(), 0, list );
262 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
266 HeapFree( GetProcessHeap(), 0, list );
271 /*******************************************************************
274 static void send_parent_notify( HWND hwnd, UINT msg )
276 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
277 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
278 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
279 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
283 /*******************************************************************
284 * get_server_window_text
286 * Retrieve the window text from the server.
288 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
292 SERVER_START_REQ( get_window_text )
295 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
296 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
299 text[len / sizeof(WCHAR)] = 0;
303 /***********************************************************************
306 * Return a pointer to the WND structure if local to the process,
307 * or WND_OTHER_PROCESS if handle may be valid in other process.
308 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
310 WND *WIN_GetPtr( HWND hwnd )
313 WORD index = USER_HANDLE_TO_INDEX(hwnd);
315 if (index >= NB_USER_HANDLES) return NULL;
318 if ((ptr = user_handles[index]))
320 if (ptr->dwMagic == WND_MAGIC &&
321 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
325 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
327 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
330 else ptr = WND_OTHER_PROCESS;
336 /***********************************************************************
337 * WIN_IsCurrentProcess
339 * Check whether a given window belongs to the current process (and return the full handle).
341 HWND WIN_IsCurrentProcess( HWND hwnd )
346 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
348 WIN_ReleasePtr( ptr );
353 /***********************************************************************
354 * WIN_IsCurrentThread
356 * Check whether a given window belongs to the current thread (and return the full handle).
358 HWND WIN_IsCurrentThread( HWND hwnd )
363 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
364 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
365 WIN_ReleasePtr( ptr );
370 /***********************************************************************
373 * Convert a 16-bit window handle to a full 32-bit handle.
375 HWND WIN_Handle32( HWND16 hwnd16 )
378 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
380 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
381 /* do sign extension for -2 and -3 */
382 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
384 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
386 if (ptr == WND_DESKTOP) return GetDesktopWindow();
388 if (ptr != WND_OTHER_PROCESS)
390 hwnd = ptr->hwndSelf;
391 WIN_ReleasePtr( ptr );
393 else /* may belong to another process */
395 SERVER_START_REQ( get_window_info )
398 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
406 /***********************************************************************
409 * Change the owner of a window.
411 HWND WIN_SetOwner( HWND hwnd, HWND owner )
413 WND *win = WIN_GetPtr( hwnd );
416 if (!win || win == WND_DESKTOP) return 0;
417 if (win == WND_OTHER_PROCESS)
419 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
422 SERVER_START_REQ( set_window_owner )
426 if (!wine_server_call( req ))
428 win->owner = reply->full_owner;
429 ret = reply->prev_owner;
433 WIN_ReleasePtr( win );
438 /***********************************************************************
441 * Change the style of a window.
443 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
446 ULONG new_style, old_style = 0;
447 WND *win = WIN_GetPtr( hwnd );
449 if (!win || win == WND_DESKTOP) return 0;
450 if (win == WND_OTHER_PROCESS)
453 ERR( "cannot set style %lx/%lx on other process window %p\n",
454 set_bits, clear_bits, hwnd );
457 new_style = (win->dwStyle | set_bits) & ~clear_bits;
458 if (new_style == win->dwStyle)
460 WIN_ReleasePtr( win );
463 SERVER_START_REQ( set_window_info )
466 req->flags = SET_WIN_STYLE;
467 req->style = new_style;
468 req->extra_offset = -1;
469 if ((ok = !wine_server_call( req )))
471 old_style = reply->old_style;
472 win->dwStyle = new_style;
476 WIN_ReleasePtr( win );
477 if (ok) USER_Driver->pSetWindowStyle( hwnd, old_style );
482 /***********************************************************************
485 * Get the window and client rectangles.
487 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
489 WND *win = WIN_GetPtr( hwnd );
492 if (!win) return FALSE;
493 if (win == WND_DESKTOP)
496 rect.left = rect.top = 0;
497 rect.right = GetSystemMetrics(SM_CXSCREEN);
498 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
499 if (rectWindow) *rectWindow = rect;
500 if (rectClient) *rectClient = rect;
502 else if (win == WND_OTHER_PROCESS)
504 SERVER_START_REQ( get_window_rectangles )
507 if ((ret = !wine_server_call( req )))
511 rectWindow->left = reply->window.left;
512 rectWindow->top = reply->window.top;
513 rectWindow->right = reply->window.right;
514 rectWindow->bottom = reply->window.bottom;
518 rectClient->left = reply->client.left;
519 rectClient->top = reply->client.top;
520 rectClient->right = reply->client.right;
521 rectClient->bottom = reply->client.bottom;
529 if (rectWindow) *rectWindow = win->rectWindow;
530 if (rectClient) *rectClient = win->rectClient;
531 WIN_ReleasePtr( win );
537 /***********************************************************************
540 * Destroy storage associated to a window. "Internals" p.358
542 LRESULT WIN_DestroyWindow( HWND hwnd )
546 HMENU menu = 0, sys_menu;
548 TRACE("%p\n", hwnd );
550 /* free child windows */
551 if ((list = WIN_ListChildren( hwnd )))
554 for (i = 0; list[i]; i++)
556 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
557 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
559 HeapFree( GetProcessHeap(), 0, list );
562 /* Unlink now so we won't bother with the children later on */
563 SERVER_START_REQ( set_parent )
567 wine_server_call( req );
572 * Send the WM_NCDESTROY to the window being destroyed.
574 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
576 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
578 WINPOS_CheckInternalPos( hwnd );
580 /* free resources associated with the window */
582 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
583 if (!(wndPtr->dwStyle & WS_CHILD)) menu = (HMENU)wndPtr->wIDmenu;
584 sys_menu = wndPtr->hSysMenu;
585 WIN_ReleasePtr( wndPtr );
587 if (menu) DestroyMenu( menu );
588 if (sys_menu) DestroyMenu( sys_menu );
590 USER_Driver->pDestroyWindow( hwnd );
592 free_window_handle( hwnd );
596 /***********************************************************************
597 * WIN_DestroyThreadWindows
599 * Destroy all children of 'wnd' owned by the current thread.
600 * Return TRUE if something was done.
602 void WIN_DestroyThreadWindows( HWND hwnd )
607 if (!(list = WIN_ListChildren( hwnd ))) return;
608 for (i = 0; list[i]; i++)
610 if (WIN_IsCurrentThread( list[i] ))
611 DestroyWindow( list[i] );
613 WIN_DestroyThreadWindows( list[i] );
615 HeapFree( GetProcessHeap(), 0, list );
619 /***********************************************************************
622 * Fix the coordinates - Helper for WIN_CreateWindowEx.
623 * returns default show mode in sw.
624 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
626 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
630 if (cs->dwExStyle & WS_EX_MDICHILD)
634 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
635 if (!(cs->style & WS_POPUP)) cs->hMenu = (HMENU)id;
637 TRACE("MDI child id %04x\n", id);
640 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
641 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
643 if (cs->style & (WS_CHILD | WS_POPUP))
645 if (cs->dwExStyle & WS_EX_MDICHILD)
647 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
652 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
654 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
659 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
661 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
665 else /* overlapped window */
669 GetStartupInfoW( &info );
671 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
673 /* Never believe Microsoft's documentation... CreateWindowEx doc says
674 * that if an overlapped window is created with WS_VISIBLE style bit
675 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
676 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
679 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
680 * 2) it does not ignore the y parameter as the docs claim; instead, it
681 * uses it as second parameter to ShowWindow() unless y is either
682 * CW_USEDEFAULT or CW_USEDEFAULT16.
684 * The fact that we didn't do 2) caused bogus windows pop up when wine
685 * was running apps that were using this obscure feature. Example -
686 * calc.exe that comes with Win98 (only Win98, it's different from
687 * the one that comes with Win95 and NT)
689 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
690 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
691 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
694 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
696 if (info.dwFlags & STARTF_USESIZE)
698 cs->cx = info.dwXSize;
699 cs->cy = info.dwYSize;
701 else /* if no other hint from the app, pick 3/4 of the screen real estate */
704 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
705 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
706 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
709 /* Handle case where only the cy values is set to default */
710 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
713 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
714 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
720 /* neither x nor cx are default. Check the y values .
721 * In the trace we see Outlook and Outlook Express using
722 * cy set to CW_USEDEFAULT when opening the address book.
724 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
726 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
727 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
728 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
733 /***********************************************************************
736 static void dump_window_styles( DWORD style, DWORD exstyle )
739 if(style & WS_POPUP) TRACE(" WS_POPUP");
740 if(style & WS_CHILD) TRACE(" WS_CHILD");
741 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
742 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
743 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
744 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
745 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
746 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
747 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
750 if(style & WS_BORDER) TRACE(" WS_BORDER");
751 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
753 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
754 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
755 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
756 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
757 if (style & WS_CHILD)
759 if(style & WS_GROUP) TRACE(" WS_GROUP");
760 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
764 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
765 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
768 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
769 #define DUMPED_STYLES \
789 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
794 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
795 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
796 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
797 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
798 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
799 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
800 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
801 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
802 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
803 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
804 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
805 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
806 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
807 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
808 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
809 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
810 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
811 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
813 #define DUMPED_EX_STYLES \
814 (WS_EX_DLGMODALFRAME | \
816 WS_EX_NOPARENTNOTIFY | \
818 WS_EX_ACCEPTFILES | \
819 WS_EX_TRANSPARENT | \
824 WS_EX_CONTEXTHELP | \
827 WS_EX_LEFTSCROLLBAR | \
828 WS_EX_CONTROLPARENT | \
833 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
835 #undef DUMPED_EX_STYLES
839 /***********************************************************************
842 * Implementation of CreateWindowEx().
844 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
845 WINDOWPROCTYPE type )
849 HWND hwnd, parent, owner, top_child = 0;
850 BOOL unicode = (type == WIN_PROC_32W);
851 MDICREATESTRUCTA mdi_cs;
853 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
854 (type == WIN_PROC_32W) ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
855 (type == WIN_PROC_32W) ? debugstr_w((LPCWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
856 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
857 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
859 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
861 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
862 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
864 /* Fix the styles for MDI children */
865 if (cs->dwExStyle & WS_EX_MDICHILD)
869 wndPtr = WIN_GetPtr(cs->hwndParent);
870 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
872 flags = wndPtr->flags;
873 WIN_ReleasePtr(wndPtr);
876 if (!(flags & WIN_ISMDICLIENT))
878 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
882 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
883 * MDICREATESTRUCT members have the originally passed values.
885 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
886 * have the same layout.
888 mdi_cs.szClass = cs->lpszClass;
889 mdi_cs.szTitle = cs->lpszName;
890 mdi_cs.hOwner = cs->hInstance;
895 mdi_cs.style = cs->style;
896 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
898 cs->lpCreateParams = (LPVOID)&mdi_cs;
900 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
902 if (cs->style & WS_POPUP)
904 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
907 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
911 cs->style &= ~WS_POPUP;
912 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
913 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
916 top_child = GetWindow(cs->hwndParent, GW_CHILD);
920 /* Restore current maximized child */
921 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
923 TRACE("Restoring current maximized child %p\n", top_child);
924 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
925 ShowWindow(top_child, SW_RESTORE);
926 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
931 /* Find the parent window */
933 parent = cs->hwndParent;
936 if (cs->hwndParent == HWND_MESSAGE)
938 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
939 * message window (style: WS_POPUP|WS_DISABLED)
941 FIXME("Parent is HWND_MESSAGE\n");
942 parent = GetDesktopWindow();
944 else if (cs->hwndParent)
946 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
948 parent = GetDesktopWindow();
949 owner = cs->hwndParent;
954 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
956 WARN("No parent for child window\n" );
957 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
959 if (classAtom != LOWORD(DESKTOP_CLASS_ATOM)) /* are we creating the desktop itself? */
960 parent = GetDesktopWindow();
963 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
965 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
966 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
967 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
968 cs->dwExStyle |= WS_EX_WINDOWEDGE;
970 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
972 /* Create the window structure */
974 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
976 hwnd = wndPtr->hwndSelf;
978 /* Fill the window structure */
980 wndPtr->tid = GetCurrentThreadId();
981 wndPtr->hInstance = cs->hInstance;
983 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
984 wndPtr->dwExStyle = cs->dwExStyle;
986 wndPtr->helpContext = 0;
987 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
988 wndPtr->pVScroll = NULL;
989 wndPtr->pHScroll = NULL;
990 wndPtr->userdata = 0;
992 wndPtr->hIconSmall = 0;
993 wndPtr->hSysMenu = 0;
995 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
998 * Correct the window styles.
1000 * It affects only the style loaded into the WIN structure.
1003 if (!(wndPtr->dwStyle & WS_CHILD))
1005 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1006 if (!(wndPtr->dwStyle & WS_POPUP))
1007 wndPtr->dwStyle |= WS_CAPTION;
1011 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1012 * why does the user get to set it?
1015 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1016 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1017 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1019 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1021 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1022 wndPtr->flags |= WIN_NEED_SIZE;
1024 SERVER_START_REQ( set_window_info )
1027 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1028 req->style = wndPtr->dwStyle;
1029 req->ex_style = wndPtr->dwExStyle;
1030 req->instance = (void *)wndPtr->hInstance;
1031 req->is_unicode = (type == WIN_PROC_32W);
1032 req->extra_offset = -1;
1033 wine_server_call( req );
1037 /* Set the window menu */
1039 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1040 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
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, WIN_PROC_16 ));
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_PROC_32A );
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_PROC_32W );
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 );
1294 USER_Driver->pResetSelectionOwner( hwnd, TRUE );
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 USER_Driver->pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1362 /* Hide the window */
1363 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1365 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1367 ShowWindow( hwnd, SW_HIDE );
1369 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1370 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1373 if (!IsWindow(hwnd)) return TRUE;
1375 /* Recursively destroy owned windows */
1382 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1385 for (i = 0; list[i]; i++)
1387 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1388 if (WIN_IsCurrentThread( list[i] ))
1390 DestroyWindow( list[i] );
1394 WIN_SetOwner( list[i], 0 );
1396 HeapFree( GetProcessHeap(), 0, list );
1398 if (!got_one) break;
1402 /* Send destroy messages */
1404 WIN_SendDestroyMsg( hwnd );
1405 if (!IsWindow( hwnd )) return TRUE;
1407 if (GetClipboardOwner() == hwnd)
1408 CLIPBOARD_ReleaseOwner();
1410 /* Destroy the window storage */
1412 WIN_DestroyWindow( hwnd );
1417 /***********************************************************************
1418 * CloseWindow (USER32.@)
1420 BOOL WINAPI CloseWindow( HWND hwnd )
1422 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1423 ShowWindow( hwnd, SW_MINIMIZE );
1428 /***********************************************************************
1429 * OpenIcon (USER32.@)
1431 BOOL WINAPI OpenIcon( HWND hwnd )
1433 if (!IsIconic( hwnd )) return FALSE;
1434 ShowWindow( hwnd, SW_SHOWNORMAL );
1439 /***********************************************************************
1442 * Implementation of FindWindow() and FindWindowEx().
1444 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1449 WCHAR *buffer = NULL;
1451 if (!parent) parent = GetDesktopWindow();
1454 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1455 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1458 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1462 child = WIN_GetFullHandle( child );
1463 while (list[i] && list[i] != child) i++;
1464 if (!list[i]) goto done;
1465 i++; /* start from next window */
1472 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1479 HeapFree( GetProcessHeap(), 0, list );
1480 HeapFree( GetProcessHeap(), 0, buffer );
1486 /***********************************************************************
1487 * FindWindowA (USER32.@)
1489 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1491 HWND ret = FindWindowExA( 0, 0, className, title );
1492 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1497 /***********************************************************************
1498 * FindWindowExA (USER32.@)
1500 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1501 LPCSTR className, LPCSTR title )
1510 /* If the atom doesn't exist, then no class */
1511 /* with this name exists either. */
1512 if (!(atom = GlobalFindAtomA( className )))
1514 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1518 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1520 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1521 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1522 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1523 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1524 HeapFree( GetProcessHeap(), 0, buffer );
1529 /***********************************************************************
1530 * FindWindowExW (USER32.@)
1532 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1533 LPCWSTR className, LPCWSTR title )
1539 /* If the atom doesn't exist, then no class */
1540 /* with this name exists either. */
1541 if (!(atom = GlobalFindAtomW( className )))
1543 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1547 return WIN_FindWindow( parent, child, atom, title );
1551 /***********************************************************************
1552 * FindWindowW (USER32.@)
1554 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1556 return FindWindowExW( 0, 0, className, title );
1560 /**********************************************************************
1561 * GetDesktopWindow (USER32.@)
1563 HWND WINAPI GetDesktopWindow(void)
1565 struct user_thread_info *thread_info = get_user_thread_info();
1567 if (thread_info->desktop) return thread_info->desktop;
1569 SERVER_START_REQ( get_desktop_window )
1572 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1576 if (!thread_info->desktop)
1579 PROCESS_INFORMATION pi;
1580 WCHAR command_line[] = {'e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1582 memset( &si, 0, sizeof(si) );
1584 if (CreateProcessW( NULL, command_line, NULL, NULL, FALSE, DETACHED_PROCESS,
1585 NULL, NULL, &si, &pi ))
1587 TRACE( "started explorer pid %04lx tid %04lx\n", pi.dwProcessId, pi.dwThreadId );
1588 WaitForInputIdle( pi.hProcess, 10000 );
1589 CloseHandle( pi.hThread );
1590 CloseHandle( pi.hProcess );
1593 else WARN( "failed to start explorer, err %ld\n", GetLastError() );
1595 SERVER_START_REQ( get_desktop_window )
1598 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1603 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1604 ERR( "failed to create desktop window\n" );
1606 return thread_info->desktop;
1610 /*******************************************************************
1611 * EnableWindow (USER32.@)
1613 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1618 if (is_broadcast(hwnd))
1620 SetLastError( ERROR_INVALID_PARAMETER );
1624 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1625 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1629 TRACE("( %p, %d )\n", hwnd, enable);
1631 retvalue = !IsWindowEnabled( hwnd );
1633 if (enable && retvalue)
1635 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1636 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1638 else if (!enable && !retvalue)
1642 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1644 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1646 if (hwnd == GetFocus())
1647 SetFocus( 0 ); /* A disabled window can't have the focus */
1649 capture_wnd = GetCapture();
1650 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1651 ReleaseCapture(); /* A disabled window can't capture the mouse */
1653 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1659 /***********************************************************************
1660 * IsWindowEnabled (USER32.@)
1662 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1664 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1668 /***********************************************************************
1669 * IsWindowUnicode (USER32.@)
1671 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1674 BOOL retvalue = FALSE;
1676 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1678 if (wndPtr == WND_DESKTOP) return TRUE;
1680 if (wndPtr != WND_OTHER_PROCESS)
1682 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1683 WIN_ReleasePtr( wndPtr );
1687 SERVER_START_REQ( get_window_info )
1690 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1698 /**********************************************************************
1699 * GetWindowWord (USER32.@)
1701 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1706 WND *wndPtr = WIN_GetPtr( hwnd );
1709 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1712 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1714 SERVER_START_REQ( set_window_info )
1717 req->flags = 0; /* don't set anything, just retrieve */
1718 req->extra_offset = offset;
1719 req->extra_size = sizeof(retvalue);
1720 if (!wine_server_call_err( req ))
1721 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1726 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1728 WARN("Invalid offset %d\n", offset );
1729 SetLastError( ERROR_INVALID_INDEX );
1731 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1732 WIN_ReleasePtr( wndPtr );
1738 case GWLP_HWNDPARENT:
1739 return GetWindowLongPtrW( hwnd, offset );
1741 case GWLP_HINSTANCE:
1743 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1745 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1749 WARN("Invalid offset %d\n", offset );
1755 /**********************************************************************
1756 * SetWindowWord (USER32.@)
1758 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1766 case GWLP_HINSTANCE:
1767 case GWLP_HWNDPARENT:
1768 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1772 WARN("Invalid offset %d\n", offset );
1773 SetLastError( ERROR_INVALID_INDEX );
1778 wndPtr = WIN_GetPtr( hwnd );
1779 if (wndPtr == WND_DESKTOP)
1781 SetLastError( ERROR_ACCESS_DENIED );
1784 if (wndPtr == WND_OTHER_PROCESS)
1787 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1788 offset, newval, hwnd );
1793 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1797 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1799 WARN("Invalid offset %d\n", offset );
1800 WIN_ReleasePtr(wndPtr);
1801 SetLastError( ERROR_INVALID_INDEX );
1805 SERVER_START_REQ( set_window_info )
1808 req->flags = SET_WIN_EXTRA;
1809 req->extra_offset = offset;
1810 req->extra_size = sizeof(newval);
1811 memcpy( &req->extra_value, &newval, sizeof(newval) );
1812 if (!wine_server_call_err( req ))
1814 void *ptr = (char *)wndPtr->wExtra + offset;
1815 memcpy( &retval, ptr, sizeof(retval) );
1816 memcpy( ptr, &newval, sizeof(newval) );
1820 WIN_ReleasePtr( wndPtr );
1825 /**********************************************************************
1828 * Helper function for GetWindowLong().
1830 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1832 LONG_PTR retvalue = 0;
1835 if (offset == GWLP_HWNDPARENT)
1837 HWND parent = GetAncestor( hwnd, GA_PARENT );
1838 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1839 return (ULONG_PTR)parent;
1842 if (!(wndPtr = WIN_GetPtr( hwnd )))
1844 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1848 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1850 if (offset == GWLP_WNDPROC)
1852 SetLastError( ERROR_ACCESS_DENIED );
1855 SERVER_START_REQ( set_window_info )
1858 req->flags = 0; /* don't set anything, just retrieve */
1859 req->extra_offset = (offset >= 0) ? offset : -1;
1860 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1861 if (!wine_server_call_err( req ))
1865 case GWL_STYLE: retvalue = reply->old_style; break;
1866 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1867 case GWLP_ID: retvalue = reply->old_id; break;
1868 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1869 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1871 if (offset >= 0) retvalue = reply->old_extra_value;
1872 else SetLastError( ERROR_INVALID_INDEX );
1881 /* now we have a valid wndPtr */
1885 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1888 * Some programs try to access last element from 16 bit
1889 * code using illegal offset value. Hopefully this is
1890 * what those programs really expect.
1892 if (type == WIN_PROC_16 &&
1893 wndPtr->cbWndExtra >= 4 &&
1894 offset == wndPtr->cbWndExtra - sizeof(WORD))
1896 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1898 ERR( "- replaced invalid offset %d with %d\n",
1901 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset2);
1902 WIN_ReleasePtr( wndPtr );
1905 WARN("Invalid offset %d\n", offset );
1906 WIN_ReleasePtr( wndPtr );
1907 SetLastError( ERROR_INVALID_INDEX );
1910 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
1911 /* Special case for dialog window procedure */
1912 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1913 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, type );
1914 WIN_ReleasePtr( wndPtr );
1920 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1921 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1922 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1923 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1924 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type ); break;
1925 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1927 WARN("Unknown offset %d\n", offset );
1928 SetLastError( ERROR_INVALID_INDEX );
1931 WIN_ReleasePtr(wndPtr);
1936 /**********************************************************************
1939 * Helper function for SetWindowLong().
1941 * 0 is the failure code. However, in the case of failure SetLastError
1942 * must be set to distinguish between a 0 return value and a failure.
1944 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval,
1945 WINDOWPROCTYPE type )
1949 LONG_PTR retval = 0;
1952 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1954 if (is_broadcast(hwnd))
1956 SetLastError( ERROR_INVALID_PARAMETER );
1960 if (!(wndPtr = WIN_GetPtr( hwnd )))
1962 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1965 if (wndPtr == WND_DESKTOP)
1967 /* can't change anything on the desktop window */
1968 SetLastError( ERROR_ACCESS_DENIED );
1971 if (wndPtr == WND_OTHER_PROCESS)
1973 if (offset == GWLP_WNDPROC)
1975 SetLastError( ERROR_ACCESS_DENIED );
1978 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1981 /* first some special cases */
1987 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1988 style.styleNew = newval;
1989 WIN_ReleasePtr( wndPtr );
1990 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1991 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1992 newval = style.styleNew;
1994 case GWLP_HWNDPARENT:
1995 if (wndPtr->parent == GetDesktopWindow())
1997 WIN_ReleasePtr( wndPtr );
1998 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2002 WIN_ReleasePtr( wndPtr );
2003 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2007 WINDOWPROCTYPE old_type = WINPROC_GetProcType( wndPtr->winproc );
2008 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type );
2009 wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, type );
2010 if (old_type == type)
2012 WIN_ReleasePtr( wndPtr );
2015 /* update is_unicode flag on the server side */
2019 case GWLP_HINSTANCE:
2023 if ((wndPtr->cbWndExtra + sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2025 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2026 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, type );
2027 *ptr = WINPROC_AllocProc( (WNDPROC)newval, type );
2028 WIN_ReleasePtr( wndPtr );
2033 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
2035 WARN("Invalid offset %d\n", offset );
2036 WIN_ReleasePtr( wndPtr );
2037 SetLastError( ERROR_INVALID_INDEX );
2042 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2043 if (*ptr == newval) /* already set to the same value */
2045 WIN_ReleasePtr( wndPtr );
2052 SERVER_START_REQ( set_window_info )
2055 req->extra_offset = -1;
2059 req->flags = SET_WIN_STYLE;
2060 req->style = newval;
2063 req->flags = SET_WIN_EXSTYLE;
2064 req->ex_style = newval;
2067 req->flags = SET_WIN_ID;
2070 case GWLP_HINSTANCE:
2071 req->flags = SET_WIN_INSTANCE;
2072 req->instance = (void *)newval;
2075 req->flags = SET_WIN_UNICODE;
2076 req->is_unicode = (type == WIN_PROC_32W);
2079 req->flags = SET_WIN_USERDATA;
2080 req->user_data = (void *)newval;
2083 req->flags = SET_WIN_EXTRA;
2084 req->extra_offset = offset;
2085 req->extra_size = sizeof(newval);
2086 memcpy( &req->extra_value, &newval, sizeof(newval) );
2088 if ((ok = !wine_server_call_err( req )))
2093 wndPtr->dwStyle = newval;
2094 retval = reply->old_style;
2097 wndPtr->dwExStyle = newval;
2098 retval = reply->old_ex_style;
2101 wndPtr->wIDmenu = newval;
2102 retval = reply->old_id;
2104 case GWLP_HINSTANCE:
2105 wndPtr->hInstance = (HINSTANCE)newval;
2106 retval = (ULONG_PTR)reply->old_instance;
2111 wndPtr->userdata = newval;
2112 retval = (ULONG_PTR)reply->old_user_data;
2116 void *ptr = (char *)wndPtr->wExtra + offset;
2117 memcpy( &retval, ptr, sizeof(retval) );
2118 memcpy( ptr, &newval, sizeof(newval) );
2125 WIN_ReleasePtr( wndPtr );
2129 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2131 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2132 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2138 /**********************************************************************
2139 * GetWindowLong (USER.135)
2141 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2143 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2147 /**********************************************************************
2148 * GetWindowLongA (USER32.@)
2150 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2152 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2156 /**********************************************************************
2157 * GetWindowLongW (USER32.@)
2159 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2161 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2165 /**********************************************************************
2166 * SetWindowLong (USER.136)
2168 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2170 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2174 /**********************************************************************
2175 * SetWindowLongA (USER32.@)
2177 * See SetWindowLongW.
2179 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2181 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2185 /**********************************************************************
2186 * SetWindowLongW (USER32.@) Set window attribute
2188 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2189 * value in a window's extra memory.
2191 * The _hwnd_ parameter specifies the window. is the handle to a
2192 * window that has extra memory. The _newval_ parameter contains the
2193 * new attribute or extra memory value. If positive, the _offset_
2194 * parameter is the byte-addressed location in the window's extra
2195 * memory to set. If negative, _offset_ specifies the window
2196 * attribute to set, and should be one of the following values:
2198 * GWL_EXSTYLE The window's extended window style
2200 * GWL_STYLE The window's window style.
2202 * GWLP_WNDPROC Pointer to the window's window procedure.
2204 * GWLP_HINSTANCE The window's pplication instance handle.
2206 * GWLP_ID The window's identifier.
2208 * GWLP_USERDATA The window's user-specified data.
2210 * If the window is a dialog box, the _offset_ parameter can be one of
2211 * the following values:
2213 * DWLP_DLGPROC The address of the window's dialog box procedure.
2215 * DWLP_MSGRESULT The return value of a message
2216 * that the dialog box procedure processed.
2218 * DWLP_USER Application specific information.
2222 * If successful, returns the previous value located at _offset_. Otherwise,
2227 * Extra memory for a window class is specified by a nonzero cbWndExtra
2228 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2229 * time of class creation.
2231 * Using GWL_WNDPROC to set a new window procedure effectively creates
2232 * a window subclass. Use CallWindowProc() in the new windows procedure
2233 * to pass messages to the superclass's window procedure.
2235 * The user data is reserved for use by the application which created
2238 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2239 * instead, call the EnableWindow() function to change the window's
2242 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2243 * SetParent() instead.
2246 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2247 * it sends WM_STYLECHANGING before changing the settings
2248 * and WM_STYLECHANGED afterwards.
2249 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2251 LONG WINAPI SetWindowLongW(
2252 HWND hwnd, /* [in] window to alter */
2253 INT offset, /* [in] offset, in bytes, of location to alter */
2254 LONG newval /* [in] new value of location */
2256 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2260 /*******************************************************************
2261 * GetWindowTextA (USER32.@)
2263 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2267 if (!lpString) return 0;
2269 if (WIN_IsCurrentProcess( hwnd ))
2270 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2272 /* when window belongs to other process, don't send a message */
2273 if (nMaxCount <= 0) return 0;
2274 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2275 get_server_window_text( hwnd, buffer, nMaxCount );
2276 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2277 lpString[nMaxCount-1] = 0;
2278 HeapFree( GetProcessHeap(), 0, buffer );
2279 return strlen(lpString);
2283 /*******************************************************************
2284 * InternalGetWindowText (USER32.@)
2286 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2290 if (nMaxCount <= 0) return 0;
2291 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2292 if (win == WND_DESKTOP) lpString[0] = 0;
2293 else if (win != WND_OTHER_PROCESS)
2295 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2296 else lpString[0] = 0;
2297 WIN_ReleasePtr( win );
2301 get_server_window_text( hwnd, lpString, nMaxCount );
2303 return strlenW(lpString);
2307 /*******************************************************************
2308 * GetWindowTextW (USER32.@)
2310 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2312 if (!lpString) return 0;
2314 if (WIN_IsCurrentProcess( hwnd ))
2315 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2317 /* when window belongs to other process, don't send a message */
2318 if (nMaxCount <= 0) return 0;
2319 get_server_window_text( hwnd, lpString, nMaxCount );
2320 return strlenW(lpString);
2324 /*******************************************************************
2325 * SetWindowTextA (USER32.@)
2326 * SetWindowText (USER32.@)
2328 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2330 if (is_broadcast(hwnd))
2332 SetLastError( ERROR_INVALID_PARAMETER );
2335 if (!WIN_IsCurrentProcess( hwnd ))
2336 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2337 debugstr_a(lpString), hwnd );
2338 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2342 /*******************************************************************
2343 * SetWindowTextW (USER32.@)
2345 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2347 if (is_broadcast(hwnd))
2349 SetLastError( ERROR_INVALID_PARAMETER );
2352 if (!WIN_IsCurrentProcess( hwnd ))
2353 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2354 debugstr_w(lpString), hwnd );
2355 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2359 /*******************************************************************
2360 * GetWindowTextLengthA (USER32.@)
2362 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2364 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2367 /*******************************************************************
2368 * GetWindowTextLengthW (USER32.@)
2370 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2372 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2376 /*******************************************************************
2377 * IsWindow (USER32.@)
2379 BOOL WINAPI IsWindow( HWND hwnd )
2384 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2385 if (ptr == WND_DESKTOP) return TRUE;
2387 if (ptr != WND_OTHER_PROCESS)
2389 WIN_ReleasePtr( ptr );
2393 /* check other processes */
2394 SERVER_START_REQ( get_window_info )
2397 ret = !wine_server_call_err( req );
2404 /***********************************************************************
2405 * GetWindowThreadProcessId (USER32.@)
2407 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2412 if (!(ptr = WIN_GetPtr( hwnd )))
2414 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2418 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2420 /* got a valid window */
2422 if (process) *process = GetCurrentProcessId();
2423 WIN_ReleasePtr( ptr );
2427 /* check other processes */
2428 SERVER_START_REQ( get_window_info )
2431 if (!wine_server_call_err( req ))
2433 tid = (DWORD)reply->tid;
2434 if (process) *process = (DWORD)reply->pid;
2442 /*****************************************************************
2443 * GetParent (USER32.@)
2445 HWND WINAPI GetParent( HWND hwnd )
2450 if (!(wndPtr = WIN_GetPtr( hwnd )))
2452 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2455 if (wndPtr == WND_DESKTOP) return 0;
2456 if (wndPtr == WND_OTHER_PROCESS)
2458 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2459 if (style & (WS_POPUP | WS_CHILD))
2461 SERVER_START_REQ( get_window_tree )
2464 if (!wine_server_call_err( req ))
2466 if (style & WS_POPUP) retvalue = reply->owner;
2467 else if (style & WS_CHILD) retvalue = reply->parent;
2475 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2476 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2477 WIN_ReleasePtr( wndPtr );
2483 /*****************************************************************
2484 * GetAncestor (USER32.@)
2486 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2489 HWND *list, ret = 0;
2494 if (!(win = WIN_GetPtr( hwnd )))
2496 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2499 if (win == WND_DESKTOP) return 0;
2500 if (win != WND_OTHER_PROCESS)
2503 WIN_ReleasePtr( win );
2505 else /* need to query the server */
2507 SERVER_START_REQ( get_window_tree )
2510 if (!wine_server_call_err( req )) ret = reply->parent;
2517 if (!(list = list_window_parents( hwnd ))) return 0;
2519 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2523 while (list[count]) count++;
2524 ret = list[count - 2]; /* get the one before the desktop */
2526 HeapFree( GetProcessHeap(), 0, list );
2530 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2533 HWND parent = GetParent( ret );
2543 /*****************************************************************
2544 * SetParent (USER32.@)
2546 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2550 if (is_broadcast(hwnd) || is_broadcast(parent))
2552 SetLastError(ERROR_INVALID_PARAMETER);
2556 if (!parent) parent = GetDesktopWindow();
2557 else parent = WIN_GetFullHandle( parent );
2559 if (!IsWindow( parent ))
2561 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2565 /* Some applications try to set a child as a parent */
2566 if (IsChild(hwnd, parent))
2568 SetLastError( ERROR_INVALID_PARAMETER );
2572 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2573 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2575 return USER_Driver->pSetParent( full_handle, parent );
2579 /*******************************************************************
2580 * IsChild (USER32.@)
2582 BOOL WINAPI IsChild( HWND parent, HWND child )
2584 HWND *list = list_window_parents( child );
2588 if (!list) return FALSE;
2589 parent = WIN_GetFullHandle( parent );
2590 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2591 ret = (list[i] != 0);
2592 HeapFree( GetProcessHeap(), 0, list );
2597 /***********************************************************************
2598 * IsWindowVisible (USER32.@)
2600 BOOL WINAPI IsWindowVisible( HWND hwnd )
2606 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2607 if (!(list = list_window_parents( hwnd ))) return TRUE;
2608 for (i = 0; list[i]; i++)
2609 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2611 HeapFree( GetProcessHeap(), 0, list );
2616 /***********************************************************************
2617 * WIN_IsWindowDrawable
2619 * hwnd is drawable when it is visible, all parents are not
2620 * minimized, and it is itself not minimized unless we are
2621 * trying to draw its default class icon.
2623 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2628 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2630 if (!(style & WS_VISIBLE)) return FALSE;
2631 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2633 if (!(list = list_window_parents( hwnd ))) return TRUE;
2634 for (i = 0; list[i]; i++)
2635 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2638 HeapFree( GetProcessHeap(), 0, list );
2643 /*******************************************************************
2644 * GetTopWindow (USER32.@)
2646 HWND WINAPI GetTopWindow( HWND hwnd )
2648 if (!hwnd) hwnd = GetDesktopWindow();
2649 return GetWindow( hwnd, GW_CHILD );
2653 /*******************************************************************
2654 * GetWindow (USER32.@)
2656 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2660 if (rel == GW_OWNER) /* this one may be available locally */
2662 WND *wndPtr = WIN_GetPtr( hwnd );
2665 SetLastError( ERROR_INVALID_HANDLE );
2668 if (wndPtr == WND_DESKTOP) return 0;
2669 if (wndPtr != WND_OTHER_PROCESS)
2671 retval = wndPtr->owner;
2672 WIN_ReleasePtr( wndPtr );
2675 /* else fall through to server call */
2678 SERVER_START_REQ( get_window_tree )
2681 if (!wine_server_call_err( req ))
2686 retval = reply->first_sibling;
2689 retval = reply->last_sibling;
2692 retval = reply->next_sibling;
2695 retval = reply->prev_sibling;
2698 retval = reply->owner;
2701 retval = reply->first_child;
2711 /*******************************************************************
2712 * ShowOwnedPopups (USER32.@)
2714 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2718 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2720 if (!win_array) return TRUE;
2722 while (win_array[count]) count++;
2723 while (--count >= 0)
2725 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2726 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2727 if (pWnd == WND_OTHER_PROCESS) continue;
2730 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2732 WIN_ReleasePtr( pWnd );
2733 /* In Windows, ShowOwnedPopups(TRUE) generates
2734 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2735 * regardless of the state of the owner
2737 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2743 if (pWnd->dwStyle & WS_VISIBLE)
2745 WIN_ReleasePtr( pWnd );
2746 /* In Windows, ShowOwnedPopups(FALSE) generates
2747 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2748 * regardless of the state of the owner
2750 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2754 WIN_ReleasePtr( pWnd );
2756 HeapFree( GetProcessHeap(), 0, win_array );
2761 /*******************************************************************
2762 * GetLastActivePopup (USER32.@)
2764 HWND WINAPI GetLastActivePopup( HWND hwnd )
2768 SERVER_START_REQ( get_window_info )
2771 if (!wine_server_call_err( req )) retval = reply->last_active;
2778 /*******************************************************************
2781 * Build an array of the children of a given window. The array must be
2782 * freed with HeapFree. Returns NULL when no windows are found.
2784 HWND *WIN_ListChildren( HWND hwnd )
2786 return list_window_children( hwnd, 0, 0 );
2790 /*******************************************************************
2791 * EnumWindows (USER32.@)
2793 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2799 USER_CheckNotLock();
2801 /* We have to build a list of all windows first, to avoid */
2802 /* unpleasant side-effects, for instance if the callback */
2803 /* function changes the Z-order of the windows. */
2805 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2807 /* Now call the callback function for every window */
2809 for (i = 0; list[i]; i++)
2811 /* Make sure that the window still exists */
2812 if (!IsWindow( list[i] )) continue;
2813 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2815 HeapFree( GetProcessHeap(), 0, list );
2820 /**********************************************************************
2821 * EnumThreadWindows (USER32.@)
2823 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2828 USER_CheckNotLock();
2830 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2832 /* Now call the callback function for every window */
2834 for (i = 0; list[i]; i++)
2835 if (!func( list[i], lParam )) break;
2836 HeapFree( GetProcessHeap(), 0, list );
2841 /**********************************************************************
2842 * WIN_EnumChildWindows
2844 * Helper function for EnumChildWindows().
2846 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2851 for ( ; *list; list++)
2853 /* Make sure that the window still exists */
2854 if (!IsWindow( *list )) continue;
2855 /* Build children list first */
2856 childList = WIN_ListChildren( *list );
2858 ret = func( *list, lParam );
2862 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2863 HeapFree( GetProcessHeap(), 0, childList );
2865 if (!ret) return FALSE;
2871 /**********************************************************************
2872 * EnumChildWindows (USER32.@)
2874 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2879 USER_CheckNotLock();
2881 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2882 ret = WIN_EnumChildWindows( list, func, lParam );
2883 HeapFree( GetProcessHeap(), 0, list );
2888 /*******************************************************************
2889 * AnyPopup (USER.52)
2891 BOOL16 WINAPI AnyPopup16(void)
2897 /*******************************************************************
2898 * AnyPopup (USER32.@)
2900 BOOL WINAPI AnyPopup(void)
2904 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2906 if (!list) return FALSE;
2907 for (i = 0; list[i]; i++)
2909 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2911 retvalue = (list[i] != 0);
2912 HeapFree( GetProcessHeap(), 0, list );
2917 /*******************************************************************
2918 * FlashWindow (USER32.@)
2920 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2924 TRACE("%p\n", hWnd);
2926 if (IsIconic( hWnd ))
2928 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2930 wndPtr = WIN_GetPtr(hWnd);
2931 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2932 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2934 wndPtr->flags |= WIN_NCACTIVATED;
2938 wndPtr->flags &= ~WIN_NCACTIVATED;
2940 WIN_ReleasePtr( wndPtr );
2947 wndPtr = WIN_GetPtr(hWnd);
2948 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2949 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2951 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2952 else wparam = (hWnd == GetForegroundWindow());
2954 WIN_ReleasePtr( wndPtr );
2955 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2960 /*******************************************************************
2961 * FlashWindowEx (USER32.@)
2963 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
2965 FIXME("%p\n", pfwi);
2969 /*******************************************************************
2970 * GetWindowContextHelpId (USER32.@)
2972 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2975 WND *wnd = WIN_GetPtr( hwnd );
2976 if (!wnd || wnd == WND_DESKTOP) return 0;
2977 if (wnd == WND_OTHER_PROCESS)
2979 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2982 retval = wnd->helpContext;
2983 WIN_ReleasePtr( wnd );
2988 /*******************************************************************
2989 * SetWindowContextHelpId (USER32.@)
2991 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2993 WND *wnd = WIN_GetPtr( hwnd );
2994 if (!wnd || wnd == WND_DESKTOP) return FALSE;
2995 if (wnd == WND_OTHER_PROCESS)
2997 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3000 wnd->helpContext = id;
3001 WIN_ReleasePtr( wnd );
3006 /*******************************************************************
3007 * DragDetect (USER32.@)
3009 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3013 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3014 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3016 rect.left = pt.x - wDragWidth;
3017 rect.right = pt.x + wDragWidth;
3019 rect.top = pt.y - wDragHeight;
3020 rect.bottom = pt.y + wDragHeight;
3026 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3028 if( msg.message == WM_LBUTTONUP )
3033 if( msg.message == WM_MOUSEMOVE )
3036 tmp.x = LOWORD(msg.lParam);
3037 tmp.y = HIWORD(msg.lParam);
3038 if( !PtInRect( &rect, tmp ))
3050 /******************************************************************************
3051 * GetWindowModuleFileNameA (USER32.@)
3053 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3055 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3056 hwnd, lpszFileName, cchFileNameMax);
3060 /******************************************************************************
3061 * GetWindowModuleFileNameW (USER32.@)
3063 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3065 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3066 hwnd, lpszFileName, cchFileNameMax);
3070 /******************************************************************************
3071 * GetWindowInfo (USER32.@)
3073 * Note: tests show that Windows doesn't check cbSize of the structure.
3075 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3077 if (!pwi) return FALSE;
3078 if (!IsWindow(hwnd)) return FALSE;
3080 GetWindowRect(hwnd, &pwi->rcWindow);
3081 GetClientRect(hwnd, &pwi->rcClient);
3082 /* translate to screen coordinates */
3083 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3085 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3086 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3087 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3089 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3090 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3092 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3093 pwi->wCreatorVersion = 0x0400;
3098 /******************************************************************************
3099 * SwitchDesktop (USER32.@)
3101 * NOTES: Sets the current input or interactive desktop.
3103 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3105 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3109 /*****************************************************************************
3110 * SetLayeredWindowAttributes (USER32.@)
3112 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3113 BYTE bAlpha, DWORD dwFlags )
3115 FIXME("(%p,0x%.8lx,%d,%ld): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3119 /*****************************************************************************
3120 * UpdateLayeredWindow (USER32.@)
3122 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3123 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3126 FIXME("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%ld): stub!\n",
3127 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);