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 /**********************************************************************/
49 static WORD wDragWidth = 4;
50 static WORD wDragHeight= 3;
52 static void *user_handles[NB_USER_HANDLES];
54 /***********************************************************************
55 * create_window_handle
57 * Create a window handle with the server.
59 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
60 HINSTANCE instance, WINDOWPROCTYPE type )
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 extra_bytes = reply->extra;
82 class = reply->class_ptr;
89 WARN( "error %ld creating window\n", GetLastError() );
93 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
95 SERVER_START_REQ( destroy_window )
98 wine_server_call( req );
101 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
107 index = USER_HANDLE_TO_INDEX(handle);
108 assert( index < NB_USER_HANDLES );
109 user_handles[index] = win;
110 win->hwndSelf = handle;
111 win->dwMagic = WND_MAGIC;
112 win->cbWndExtra = extra_bytes;
113 memset( win->wExtra, 0, extra_bytes );
114 CLASS_AddWindow( class, win, type );
119 /***********************************************************************
122 * Free a window handle.
124 static WND *free_window_handle( HWND hwnd )
127 WORD index = USER_HANDLE_TO_INDEX(hwnd);
129 if (index >= NB_USER_HANDLES) return NULL;
131 if ((ptr = user_handles[index]))
133 SERVER_START_REQ( destroy_window )
136 if (!wine_server_call_err( req ))
138 user_handles[index] = NULL;
147 HeapFree( GetProcessHeap(), 0, ptr );
152 /*******************************************************************
153 * list_window_children
155 * Build an array of the children of a given window. The array must be
156 * freed with HeapFree. Returns NULL when no windows are found.
158 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
167 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
169 SERVER_START_REQ( get_window_children )
174 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
175 if (!wine_server_call( req )) count = reply->count;
178 if (count && count < size)
183 HeapFree( GetProcessHeap(), 0, list );
185 size = count + 1; /* restart with a large enough buffer */
191 /*******************************************************************
192 * list_window_parents
194 * Build an array of all parents of a given window, starting with
195 * the immediate parent. The array must be freed with HeapFree.
196 * Returns NULL if window is a top-level window.
198 static HWND *list_window_parents( HWND hwnd )
202 int pos = 0, size = 16, count = 0;
204 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
209 if (!(win = WIN_GetPtr( current ))) goto empty;
210 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
211 if (win == WND_DESKTOP)
213 if (!pos) goto empty;
217 list[pos] = current = win->parent;
218 WIN_ReleasePtr( win );
219 if (++pos == size - 1)
221 /* need to grow the list */
222 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
223 if (!new_list) goto empty;
229 /* at least one parent belongs to another process, have to query the server */
234 SERVER_START_REQ( get_window_parents )
237 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
238 if (!wine_server_call( req )) count = reply->count;
241 if (!count) goto empty;
247 HeapFree( GetProcessHeap(), 0, list );
249 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
253 HeapFree( GetProcessHeap(), 0, list );
258 /*******************************************************************
261 static void send_parent_notify( HWND hwnd, UINT msg )
263 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
264 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
265 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
266 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
270 /*******************************************************************
271 * get_server_window_text
273 * Retrieve the window text from the server.
275 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
279 SERVER_START_REQ( get_window_text )
282 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
283 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
286 text[len / sizeof(WCHAR)] = 0;
290 /***********************************************************************
293 * Return a pointer to the WND structure if local to the process,
294 * or WND_OTHER_PROCESS if handle may be valid in other process.
295 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
297 WND *WIN_GetPtr( HWND hwnd )
300 WORD index = USER_HANDLE_TO_INDEX(hwnd);
302 if (index >= NB_USER_HANDLES) return NULL;
305 if ((ptr = user_handles[index]))
307 if (ptr->dwMagic == WND_MAGIC &&
308 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
312 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
314 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
317 else ptr = WND_OTHER_PROCESS;
323 /***********************************************************************
324 * WIN_IsCurrentProcess
326 * Check whether a given window belongs to the current process (and return the full handle).
328 HWND WIN_IsCurrentProcess( HWND hwnd )
333 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
335 WIN_ReleasePtr( ptr );
340 /***********************************************************************
341 * WIN_IsCurrentThread
343 * Check whether a given window belongs to the current thread (and return the full handle).
345 HWND WIN_IsCurrentThread( HWND hwnd )
350 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
351 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
352 WIN_ReleasePtr( ptr );
357 /***********************************************************************
360 * Convert a 16-bit window handle to a full 32-bit handle.
362 HWND WIN_Handle32( HWND16 hwnd16 )
365 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
367 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
368 /* do sign extension for -2 and -3 */
369 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
371 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
373 if (ptr == WND_DESKTOP) return GetDesktopWindow();
375 if (ptr != WND_OTHER_PROCESS)
377 hwnd = ptr->hwndSelf;
378 WIN_ReleasePtr( ptr );
380 else /* may belong to another process */
382 SERVER_START_REQ( get_window_info )
385 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
393 /***********************************************************************
396 * Change the owner of a window.
398 HWND WIN_SetOwner( HWND hwnd, HWND owner )
400 WND *win = WIN_GetPtr( hwnd );
403 if (!win || win == WND_DESKTOP) return 0;
404 if (win == WND_OTHER_PROCESS)
406 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
409 SERVER_START_REQ( set_window_owner )
413 if (!wine_server_call( req ))
415 win->owner = reply->full_owner;
416 ret = reply->prev_owner;
420 WIN_ReleasePtr( win );
425 /***********************************************************************
428 * Change the style of a window.
430 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
433 ULONG new_style, old_style = 0;
434 WND *win = WIN_GetPtr( hwnd );
436 if (!win || win == WND_DESKTOP) return 0;
437 if (win == WND_OTHER_PROCESS)
440 ERR( "cannot set style %lx/%lx on other process window %p\n",
441 set_bits, clear_bits, hwnd );
444 new_style = (win->dwStyle | set_bits) & ~clear_bits;
445 if (new_style == win->dwStyle)
447 WIN_ReleasePtr( win );
450 SERVER_START_REQ( set_window_info )
453 req->flags = SET_WIN_STYLE;
454 req->style = new_style;
455 req->extra_offset = -1;
456 if ((ok = !wine_server_call( req )))
458 old_style = reply->old_style;
459 win->dwStyle = new_style;
463 WIN_ReleasePtr( win );
464 if (ok) USER_Driver->pSetWindowStyle( hwnd, old_style );
469 /***********************************************************************
472 * Get the window and client rectangles.
474 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
476 WND *win = WIN_GetPtr( hwnd );
479 if (!win) return FALSE;
480 if (win == WND_DESKTOP)
483 rect.left = rect.top = 0;
484 rect.right = GetSystemMetrics(SM_CXSCREEN);
485 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
486 if (rectWindow) *rectWindow = rect;
487 if (rectClient) *rectClient = rect;
489 else if (win == WND_OTHER_PROCESS)
491 SERVER_START_REQ( get_window_rectangles )
494 if ((ret = !wine_server_call( req )))
498 rectWindow->left = reply->window.left;
499 rectWindow->top = reply->window.top;
500 rectWindow->right = reply->window.right;
501 rectWindow->bottom = reply->window.bottom;
505 rectClient->left = reply->client.left;
506 rectClient->top = reply->client.top;
507 rectClient->right = reply->client.right;
508 rectClient->bottom = reply->client.bottom;
516 if (rectWindow) *rectWindow = win->rectWindow;
517 if (rectClient) *rectClient = win->rectClient;
518 WIN_ReleasePtr( win );
524 /***********************************************************************
527 * Destroy storage associated to a window. "Internals" p.358
529 LRESULT WIN_DestroyWindow( HWND hwnd )
533 HMENU menu = 0, sys_menu;
535 TRACE("%p\n", hwnd );
537 /* free child windows */
538 if ((list = WIN_ListChildren( hwnd )))
541 for (i = 0; list[i]; i++)
543 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
544 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
546 HeapFree( GetProcessHeap(), 0, list );
549 /* Unlink now so we won't bother with the children later on */
550 SERVER_START_REQ( set_parent )
554 wine_server_call( req );
559 * Send the WM_NCDESTROY to the window being destroyed.
561 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
563 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
565 WINPOS_CheckInternalPos( hwnd );
567 /* free resources associated with the window */
569 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
570 if (!(wndPtr->dwStyle & WS_CHILD)) menu = (HMENU)wndPtr->wIDmenu;
571 sys_menu = wndPtr->hSysMenu;
572 WIN_ReleasePtr( wndPtr );
574 if (menu) DestroyMenu( menu );
575 if (sys_menu) DestroyMenu( sys_menu );
577 USER_Driver->pDestroyWindow( hwnd );
579 free_window_handle( hwnd );
583 /***********************************************************************
584 * WIN_DestroyThreadWindows
586 * Destroy all children of 'wnd' owned by the current thread.
587 * Return TRUE if something was done.
589 void WIN_DestroyThreadWindows( HWND hwnd )
594 if (!(list = WIN_ListChildren( hwnd ))) return;
595 for (i = 0; list[i]; i++)
597 if (WIN_IsCurrentThread( list[i] ))
598 DestroyWindow( list[i] );
600 WIN_DestroyThreadWindows( list[i] );
602 HeapFree( GetProcessHeap(), 0, list );
606 /***********************************************************************
609 * Fix the coordinates - Helper for WIN_CreateWindowEx.
610 * returns default show mode in sw.
611 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
613 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
617 if (cs->dwExStyle & WS_EX_MDICHILD)
621 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
622 if (!(cs->style & WS_POPUP)) cs->hMenu = (HMENU)id;
624 TRACE("MDI child id %04x\n", id);
627 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
628 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
630 if (cs->style & (WS_CHILD | WS_POPUP))
632 if (cs->dwExStyle & WS_EX_MDICHILD)
634 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
639 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
641 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
646 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
648 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
652 else /* overlapped window */
656 GetStartupInfoW( &info );
658 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
660 /* Never believe Microsoft's documentation... CreateWindowEx doc says
661 * that if an overlapped window is created with WS_VISIBLE style bit
662 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
663 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
666 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
667 * 2) it does not ignore the y parameter as the docs claim; instead, it
668 * uses it as second parameter to ShowWindow() unless y is either
669 * CW_USEDEFAULT or CW_USEDEFAULT16.
671 * The fact that we didn't do 2) caused bogus windows pop up when wine
672 * was running apps that were using this obscure feature. Example -
673 * calc.exe that comes with Win98 (only Win98, it's different from
674 * the one that comes with Win95 and NT)
676 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
677 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
678 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
681 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
683 if (info.dwFlags & STARTF_USESIZE)
685 cs->cx = info.dwXSize;
686 cs->cy = info.dwYSize;
688 else /* if no other hint from the app, pick 3/4 of the screen real estate */
691 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
692 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
693 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
696 /* Handle case where only the cy values is set to default */
697 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
700 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
701 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
707 /* neither x nor cx are default. Check the y values .
708 * In the trace we see Outlook and Outlook Express using
709 * cy set to CW_USEDEFAULT when opening the address book.
711 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
713 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
714 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
715 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
720 /***********************************************************************
723 static void dump_window_styles( DWORD style, DWORD exstyle )
726 if(style & WS_POPUP) TRACE(" WS_POPUP");
727 if(style & WS_CHILD) TRACE(" WS_CHILD");
728 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
729 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
730 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
731 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
732 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
733 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
734 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
737 if(style & WS_BORDER) TRACE(" WS_BORDER");
738 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
740 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
741 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
742 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
743 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
744 if(style & WS_GROUP) TRACE(" WS_GROUP");
745 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
746 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
747 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
749 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
750 #define DUMPED_STYLES \
770 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
775 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
776 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
777 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
778 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
779 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
780 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
781 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
782 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
783 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
784 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
785 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
786 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
787 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
788 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
789 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
790 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
791 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
792 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
794 #define DUMPED_EX_STYLES \
795 (WS_EX_DLGMODALFRAME | \
797 WS_EX_NOPARENTNOTIFY | \
799 WS_EX_ACCEPTFILES | \
800 WS_EX_TRANSPARENT | \
805 WS_EX_CONTEXTHELP | \
808 WS_EX_LEFTSCROLLBAR | \
809 WS_EX_CONTROLPARENT | \
814 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
816 #undef DUMPED_EX_STYLES
820 /***********************************************************************
823 * Implementation of CreateWindowEx().
825 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
826 WINDOWPROCTYPE type )
830 HWND hwnd, parent, owner, top_child = 0;
831 BOOL unicode = (type == WIN_PROC_32W);
833 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
834 (type == WIN_PROC_32W) ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
835 (type == WIN_PROC_32W) ? debugstr_w((LPCWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
836 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
837 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
839 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
841 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
842 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
844 /* Fix the styles for MDI children */
845 if (cs->dwExStyle & WS_EX_MDICHILD)
847 MDICREATESTRUCTA mdi_cs;
850 wndPtr = WIN_GetPtr(cs->hwndParent);
851 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
853 flags = wndPtr->flags;
854 WIN_ReleasePtr(wndPtr);
857 if (!(flags & WIN_ISMDICLIENT))
859 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
863 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
864 * MDICREATESTRUCT members have the originally passed values.
866 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
867 * have the same layout.
869 mdi_cs.szClass = cs->lpszClass;
870 mdi_cs.szTitle = cs->lpszName;
871 mdi_cs.hOwner = cs->hInstance;
876 mdi_cs.style = cs->style;
877 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
879 cs->lpCreateParams = (LPVOID)&mdi_cs;
881 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
883 if (cs->style & WS_POPUP)
885 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
888 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
892 cs->style &= ~WS_POPUP;
893 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
894 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
897 top_child = GetWindow(cs->hwndParent, GW_CHILD);
901 /* Restore current maximized child */
902 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
904 TRACE("Restoring current maximized child %p\n", top_child);
905 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
906 ShowWindow(top_child, SW_RESTORE);
907 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
912 /* Find the parent window */
914 parent = GetDesktopWindow();
917 if (cs->hwndParent == HWND_MESSAGE)
919 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
920 * message window (style: WS_POPUP|WS_DISABLED)
922 FIXME("Parent is HWND_MESSAGE\n");
924 else if (cs->hwndParent)
926 /* Make sure parent is valid */
927 if (!IsWindow( cs->hwndParent ))
929 WARN("Bad parent %p\n", cs->hwndParent );
932 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
933 parent = WIN_GetFullHandle(cs->hwndParent);
935 owner = GetAncestor( cs->hwndParent, GA_ROOT );
937 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
939 WARN("No parent for child window\n" );
940 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
943 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
945 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
946 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
947 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
948 cs->dwExStyle |= WS_EX_WINDOWEDGE;
950 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
952 /* Create the window structure */
954 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
956 TRACE("out of memory\n" );
959 hwnd = wndPtr->hwndSelf;
961 /* Fill the window structure */
963 wndPtr->tid = GetCurrentThreadId();
964 wndPtr->owner = owner;
965 wndPtr->parent = parent;
966 wndPtr->hInstance = cs->hInstance;
968 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
969 wndPtr->dwExStyle = cs->dwExStyle;
971 wndPtr->helpContext = 0;
972 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
973 wndPtr->pVScroll = NULL;
974 wndPtr->pHScroll = NULL;
975 wndPtr->userdata = 0;
977 wndPtr->hIconSmall = 0;
978 wndPtr->hSysMenu = 0;
980 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
983 * Correct the window styles.
985 * It affects only the style loaded into the WIN structure.
988 if (!(wndPtr->dwStyle & WS_CHILD))
990 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
991 if (!(wndPtr->dwStyle & WS_POPUP))
992 wndPtr->dwStyle |= WS_CAPTION;
996 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
997 * why does the user get to set it?
1000 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1001 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1002 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1004 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1006 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1007 wndPtr->flags |= WIN_NEED_SIZE;
1009 SERVER_START_REQ( set_window_info )
1012 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1013 req->style = wndPtr->dwStyle;
1014 req->ex_style = wndPtr->dwExStyle;
1015 req->instance = (void *)wndPtr->hInstance;
1016 req->is_unicode = (type == WIN_PROC_32W);
1017 req->extra_offset = -1;
1018 wine_server_call( req );
1022 /* Set the window menu */
1024 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1025 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1029 if (!MENU_SetMenu(hwnd, cs->hMenu))
1031 WIN_ReleasePtr( wndPtr );
1032 free_window_handle( hwnd );
1038 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1041 if (!cs->hInstance || HIWORD(cs->hInstance))
1042 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1044 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1046 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1050 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1051 WIN_ReleasePtr( wndPtr );
1053 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1055 WIN_DestroyWindow( hwnd );
1059 /* Notify the parent window only */
1061 send_parent_notify( hwnd, WM_CREATE );
1062 if (!IsWindow( hwnd )) return 0;
1064 if (cs->style & WS_VISIBLE)
1066 if (cs->style & WS_MAXIMIZE)
1067 sw = SW_SHOWMAXIMIZED;
1068 else if (cs->style & WS_MINIMIZE)
1069 sw = SW_SHOWMINIMIZED;
1071 ShowWindow( hwnd, sw );
1072 if (cs->dwExStyle & WS_EX_MDICHILD)
1074 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1075 /* ShowWindow won't activate child windows */
1076 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1080 /* Call WH_SHELL hook */
1082 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1083 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1085 TRACE("created window %p\n", hwnd);
1090 /***********************************************************************
1091 * CreateWindow (USER.41)
1093 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1094 DWORD style, INT16 x, INT16 y, INT16 width,
1095 INT16 height, HWND16 parent, HMENU16 menu,
1096 HINSTANCE16 instance, LPVOID data )
1098 return CreateWindowEx16( 0, className, windowName, style,
1099 x, y, width, height, parent, menu, instance, data );
1103 /***********************************************************************
1104 * CreateWindowEx (USER.452)
1106 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1107 LPCSTR windowName, DWORD style, INT16 x,
1108 INT16 y, INT16 width, INT16 height,
1109 HWND16 parent, HMENU16 menu,
1110 HINSTANCE16 instance, LPVOID data )
1116 /* Find the class atom */
1118 if (HIWORD(className))
1120 if (!(classAtom = GlobalFindAtomA( className )))
1122 ERR( "bad class name %s\n", debugstr_a(className) );
1128 classAtom = LOWORD(className);
1129 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1131 ERR( "bad atom %x\n", classAtom);
1137 /* Fix the coordinates */
1139 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1140 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1141 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1142 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1144 /* Create the window */
1146 cs.lpCreateParams = data;
1147 cs.hInstance = HINSTANCE_32(instance);
1148 cs.hMenu = HMENU_32(menu);
1149 cs.hwndParent = WIN_Handle32( parent );
1151 cs.lpszName = windowName;
1152 cs.lpszClass = className;
1153 cs.dwExStyle = exStyle;
1155 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1159 /***********************************************************************
1160 * CreateWindowExA (USER32.@)
1162 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1163 LPCSTR windowName, DWORD style, INT x,
1164 INT y, INT width, INT height,
1165 HWND parent, HMENU menu,
1166 HINSTANCE instance, LPVOID data )
1172 /* Find the class atom */
1174 if (HIWORD(className))
1176 if (!(classAtom = GlobalFindAtomA( className )))
1178 ERR( "bad class name %s\n", debugstr_a(className) );
1184 classAtom = LOWORD(className);
1185 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1187 ERR( "bad atom %x\n", classAtom);
1193 /* Create the window */
1195 cs.lpCreateParams = data;
1196 cs.hInstance = instance;
1198 cs.hwndParent = parent;
1204 cs.lpszName = windowName;
1205 cs.lpszClass = className;
1206 cs.dwExStyle = exStyle;
1208 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1212 /***********************************************************************
1213 * CreateWindowExW (USER32.@)
1215 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1216 LPCWSTR windowName, DWORD style, INT x,
1217 INT y, INT width, INT height,
1218 HWND parent, HMENU menu,
1219 HINSTANCE instance, LPVOID data )
1225 /* Find the class atom */
1227 if (HIWORD(className))
1229 if (!(classAtom = GlobalFindAtomW( className )))
1231 ERR( "bad class name %s\n", debugstr_w(className) );
1237 classAtom = LOWORD(className);
1238 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1240 ERR( "bad atom %x\n", classAtom);
1246 /* Create the window */
1248 cs.lpCreateParams = data;
1249 cs.hInstance = instance;
1251 cs.hwndParent = parent;
1257 cs.lpszName = windowName;
1258 cs.lpszClass = className;
1259 cs.dwExStyle = exStyle;
1261 /* Note: we rely on the fact that CREATESTRUCTA and */
1262 /* CREATESTRUCTW have the same layout. */
1263 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1267 /***********************************************************************
1268 * WIN_SendDestroyMsg
1270 static void WIN_SendDestroyMsg( HWND hwnd )
1274 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1276 if (hwnd == info.hwndCaret) DestroyCaret();
1277 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1279 USER_Driver->pResetSelectionOwner( hwnd, TRUE );
1282 * Send the WM_DESTROY to the window.
1284 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1287 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1288 * make sure that the window still exists when we come back.
1295 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1297 for (i = 0; pWndArray[i]; i++)
1299 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1301 HeapFree( GetProcessHeap(), 0, pWndArray );
1304 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1308 /***********************************************************************
1309 * DestroyWindow (USER32.@)
1311 BOOL WINAPI DestroyWindow( HWND hwnd )
1315 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1317 SetLastError( ERROR_ACCESS_DENIED );
1321 TRACE("(%p)\n", hwnd);
1325 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1327 if (MENU_IsMenuActive() == hwnd)
1330 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1334 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1335 send_parent_notify( hwnd, WM_DESTROY );
1337 else if (!GetWindow( hwnd, GW_OWNER ))
1339 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1340 /* FIXME: clean up palette - see "Internals" p.352 */
1343 if (!IsWindow(hwnd)) return TRUE;
1345 USER_Driver->pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1347 /* Hide the window */
1348 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1350 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1352 ShowWindow( hwnd, SW_HIDE );
1354 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1355 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1358 if (!IsWindow(hwnd)) return TRUE;
1360 /* Recursively destroy owned windows */
1367 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1370 for (i = 0; list[i]; i++)
1372 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1373 if (WIN_IsCurrentThread( list[i] ))
1375 DestroyWindow( list[i] );
1379 WIN_SetOwner( list[i], 0 );
1381 HeapFree( GetProcessHeap(), 0, list );
1383 if (!got_one) break;
1387 /* Send destroy messages */
1389 WIN_SendDestroyMsg( hwnd );
1390 if (!IsWindow( hwnd )) return TRUE;
1392 if (GetClipboardOwner() == hwnd)
1393 CLIPBOARD_ReleaseOwner();
1395 /* Destroy the window storage */
1397 WIN_DestroyWindow( hwnd );
1402 /***********************************************************************
1403 * CloseWindow (USER32.@)
1405 BOOL WINAPI CloseWindow( HWND hwnd )
1407 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1408 ShowWindow( hwnd, SW_MINIMIZE );
1413 /***********************************************************************
1414 * OpenIcon (USER32.@)
1416 BOOL WINAPI OpenIcon( HWND hwnd )
1418 if (!IsIconic( hwnd )) return FALSE;
1419 ShowWindow( hwnd, SW_SHOWNORMAL );
1424 /***********************************************************************
1427 * Implementation of FindWindow() and FindWindowEx().
1429 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1434 WCHAR *buffer = NULL;
1436 if (!parent) parent = GetDesktopWindow();
1439 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1440 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1443 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1447 child = WIN_GetFullHandle( child );
1448 while (list[i] && list[i] != child) i++;
1449 if (!list[i]) goto done;
1450 i++; /* start from next window */
1457 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1464 HeapFree( GetProcessHeap(), 0, list );
1465 HeapFree( GetProcessHeap(), 0, buffer );
1471 /***********************************************************************
1472 * FindWindowA (USER32.@)
1474 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1476 HWND ret = FindWindowExA( 0, 0, className, title );
1477 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1482 /***********************************************************************
1483 * FindWindowExA (USER32.@)
1485 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1486 LPCSTR className, LPCSTR title )
1495 /* If the atom doesn't exist, then no class */
1496 /* with this name exists either. */
1497 if (!(atom = GlobalFindAtomA( className )))
1499 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1503 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1505 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1506 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1507 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1508 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1509 HeapFree( GetProcessHeap(), 0, buffer );
1514 /***********************************************************************
1515 * FindWindowExW (USER32.@)
1517 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1518 LPCWSTR className, LPCWSTR title )
1524 /* If the atom doesn't exist, then no class */
1525 /* with this name exists either. */
1526 if (!(atom = GlobalFindAtomW( className )))
1528 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1532 return WIN_FindWindow( parent, child, atom, title );
1536 /***********************************************************************
1537 * FindWindowW (USER32.@)
1539 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1541 return FindWindowExW( 0, 0, className, title );
1545 /**********************************************************************
1546 * GetDesktopWindow (USER32.@)
1548 HWND WINAPI GetDesktopWindow(void)
1550 struct user_thread_info *thread_info = get_user_thread_info();
1552 if (!thread_info->desktop)
1554 SERVER_START_REQ( get_desktop_window )
1556 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1559 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1560 ERR( "failed to create desktop window\n" );
1562 return thread_info->desktop;
1566 /*******************************************************************
1567 * EnableWindow (USER32.@)
1569 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1574 if (is_broadcast(hwnd))
1576 SetLastError( ERROR_INVALID_PARAMETER );
1580 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1581 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1585 TRACE("( %p, %d )\n", hwnd, enable);
1587 retvalue = !IsWindowEnabled( hwnd );
1589 if (enable && retvalue)
1591 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1592 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1594 else if (!enable && !retvalue)
1598 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1600 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1602 if (hwnd == GetFocus())
1603 SetFocus( 0 ); /* A disabled window can't have the focus */
1605 capture_wnd = GetCapture();
1606 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1607 ReleaseCapture(); /* A disabled window can't capture the mouse */
1609 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1615 /***********************************************************************
1616 * IsWindowEnabled (USER32.@)
1618 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1620 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1624 /***********************************************************************
1625 * IsWindowUnicode (USER32.@)
1627 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1630 BOOL retvalue = FALSE;
1632 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1634 if (wndPtr == WND_DESKTOP) return TRUE;
1636 if (wndPtr != WND_OTHER_PROCESS)
1638 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1639 WIN_ReleasePtr( wndPtr );
1643 SERVER_START_REQ( get_window_info )
1646 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1654 /**********************************************************************
1655 * GetWindowWord (USER32.@)
1657 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1662 WND *wndPtr = WIN_GetPtr( hwnd );
1665 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1668 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1670 SERVER_START_REQ( set_window_info )
1673 req->flags = 0; /* don't set anything, just retrieve */
1674 req->extra_offset = offset;
1675 req->extra_size = sizeof(retvalue);
1676 if (!wine_server_call_err( req ))
1677 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1682 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1684 WARN("Invalid offset %d\n", offset );
1685 SetLastError( ERROR_INVALID_INDEX );
1687 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1688 WIN_ReleasePtr( wndPtr );
1694 case GWLP_HWNDPARENT:
1695 return GetWindowLongPtrW( hwnd, offset );
1697 case GWLP_HINSTANCE:
1699 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1701 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1705 WARN("Invalid offset %d\n", offset );
1711 /**********************************************************************
1712 * SetWindowWord (USER32.@)
1714 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1722 case GWLP_HINSTANCE:
1723 case GWLP_HWNDPARENT:
1724 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1728 WARN("Invalid offset %d\n", offset );
1729 SetLastError( ERROR_INVALID_INDEX );
1734 wndPtr = WIN_GetPtr( hwnd );
1735 if (wndPtr == WND_DESKTOP)
1737 SetLastError( ERROR_ACCESS_DENIED );
1740 if (wndPtr == WND_OTHER_PROCESS)
1743 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1744 offset, newval, hwnd );
1749 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1753 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1755 WARN("Invalid offset %d\n", offset );
1756 WIN_ReleasePtr(wndPtr);
1757 SetLastError( ERROR_INVALID_INDEX );
1761 SERVER_START_REQ( set_window_info )
1764 req->flags = SET_WIN_EXTRA;
1765 req->extra_offset = offset;
1766 req->extra_size = sizeof(newval);
1767 memcpy( &req->extra_value, &newval, sizeof(newval) );
1768 if (!wine_server_call_err( req ))
1770 void *ptr = (char *)wndPtr->wExtra + offset;
1771 memcpy( &retval, ptr, sizeof(retval) );
1772 memcpy( ptr, &newval, sizeof(newval) );
1776 WIN_ReleasePtr( wndPtr );
1781 /**********************************************************************
1784 * Helper function for GetWindowLong().
1786 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1788 LONG_PTR retvalue = 0;
1791 if (offset == GWLP_HWNDPARENT)
1793 HWND parent = GetAncestor( hwnd, GA_PARENT );
1794 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1795 return (ULONG_PTR)parent;
1798 if (!(wndPtr = WIN_GetPtr( hwnd )))
1800 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1804 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1806 if (offset == GWLP_WNDPROC)
1808 SetLastError( ERROR_ACCESS_DENIED );
1811 SERVER_START_REQ( set_window_info )
1814 req->flags = 0; /* don't set anything, just retrieve */
1815 req->extra_offset = (offset >= 0) ? offset : -1;
1816 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1817 if (!wine_server_call_err( req ))
1821 case GWL_STYLE: retvalue = reply->old_style; break;
1822 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1823 case GWLP_ID: retvalue = reply->old_id; break;
1824 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1825 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1827 if (offset >= 0) retvalue = reply->old_extra_value;
1828 else SetLastError( ERROR_INVALID_INDEX );
1837 /* now we have a valid wndPtr */
1841 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1844 * Some programs try to access last element from 16 bit
1845 * code using illegal offset value. Hopefully this is
1846 * what those programs really expect.
1848 if (type == WIN_PROC_16 &&
1849 wndPtr->cbWndExtra >= 4 &&
1850 offset == wndPtr->cbWndExtra - sizeof(WORD))
1852 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1854 ERR( "- replaced invalid offset %d with %d\n",
1857 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset2);
1858 WIN_ReleasePtr( wndPtr );
1861 WARN("Invalid offset %d\n", offset );
1862 WIN_ReleasePtr( wndPtr );
1863 SetLastError( ERROR_INVALID_INDEX );
1866 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
1867 /* Special case for dialog window procedure */
1868 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1869 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, type );
1870 WIN_ReleasePtr( wndPtr );
1876 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1877 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1878 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1879 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1880 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type ); break;
1881 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1883 WARN("Unknown offset %d\n", offset );
1884 SetLastError( ERROR_INVALID_INDEX );
1887 WIN_ReleasePtr(wndPtr);
1892 /**********************************************************************
1895 * Helper function for SetWindowLong().
1897 * 0 is the failure code. However, in the case of failure SetLastError
1898 * must be set to distinguish between a 0 return value and a failure.
1900 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval,
1901 WINDOWPROCTYPE type )
1905 LONG_PTR retval = 0;
1908 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1910 if (is_broadcast(hwnd))
1912 SetLastError( ERROR_INVALID_PARAMETER );
1916 if (!(wndPtr = WIN_GetPtr( hwnd )))
1918 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1921 if (wndPtr == WND_DESKTOP)
1923 /* can't change anything on the desktop window */
1924 SetLastError( ERROR_ACCESS_DENIED );
1927 if (wndPtr == WND_OTHER_PROCESS)
1929 if (offset == GWLP_WNDPROC)
1931 SetLastError( ERROR_ACCESS_DENIED );
1934 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1937 /* first some special cases */
1943 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1944 style.styleNew = newval;
1945 WIN_ReleasePtr( wndPtr );
1946 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1947 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1948 newval = style.styleNew;
1950 case GWLP_HWNDPARENT:
1951 if (wndPtr->parent == GetDesktopWindow())
1953 WIN_ReleasePtr( wndPtr );
1954 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1958 WIN_ReleasePtr( wndPtr );
1959 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1963 WINDOWPROCTYPE old_type = WINPROC_GetProcType( wndPtr->winproc );
1964 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type );
1965 wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, type );
1966 if (old_type == type)
1968 WIN_ReleasePtr( wndPtr );
1971 /* update is_unicode flag on the server side */
1975 case GWLP_HINSTANCE:
1979 if ((wndPtr->cbWndExtra + sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1981 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1982 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, type );
1983 *ptr = WINPROC_AllocProc( (WNDPROC)newval, type );
1984 WIN_ReleasePtr( wndPtr );
1989 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
1991 WARN("Invalid offset %d\n", offset );
1992 WIN_ReleasePtr( wndPtr );
1993 SetLastError( ERROR_INVALID_INDEX );
1998 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
1999 if (*ptr == newval) /* already set to the same value */
2001 WIN_ReleasePtr( wndPtr );
2008 SERVER_START_REQ( set_window_info )
2011 req->extra_offset = -1;
2015 req->flags = SET_WIN_STYLE;
2016 req->style = newval;
2019 req->flags = SET_WIN_EXSTYLE;
2020 req->ex_style = newval;
2023 req->flags = SET_WIN_ID;
2026 case GWLP_HINSTANCE:
2027 req->flags = SET_WIN_INSTANCE;
2028 req->instance = (void *)newval;
2031 req->flags = SET_WIN_UNICODE;
2032 req->is_unicode = (type == WIN_PROC_32W);
2035 req->flags = SET_WIN_USERDATA;
2036 req->user_data = (void *)newval;
2039 req->flags = SET_WIN_EXTRA;
2040 req->extra_offset = offset;
2041 req->extra_size = sizeof(newval);
2042 memcpy( &req->extra_value, &newval, sizeof(newval) );
2044 if ((ok = !wine_server_call_err( req )))
2049 wndPtr->dwStyle = newval;
2050 retval = reply->old_style;
2053 wndPtr->dwExStyle = newval;
2054 retval = reply->old_ex_style;
2057 wndPtr->wIDmenu = newval;
2058 retval = reply->old_id;
2060 case GWLP_HINSTANCE:
2061 wndPtr->hInstance = (HINSTANCE)newval;
2062 retval = (ULONG_PTR)reply->old_instance;
2067 wndPtr->userdata = newval;
2068 retval = (ULONG_PTR)reply->old_user_data;
2072 void *ptr = (char *)wndPtr->wExtra + offset;
2073 memcpy( &retval, ptr, sizeof(retval) );
2074 memcpy( ptr, &newval, sizeof(newval) );
2081 WIN_ReleasePtr( wndPtr );
2085 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2087 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2088 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2094 /**********************************************************************
2095 * GetWindowLong (USER.135)
2097 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2099 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2103 /**********************************************************************
2104 * GetWindowLongA (USER32.@)
2106 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2108 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2112 /**********************************************************************
2113 * GetWindowLongW (USER32.@)
2115 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2117 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2121 /**********************************************************************
2122 * SetWindowLong (USER.136)
2124 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2126 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2130 /**********************************************************************
2131 * SetWindowLongA (USER32.@)
2133 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2135 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2139 /**********************************************************************
2140 * SetWindowLongW (USER32.@) Set window attribute
2142 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2143 * value in a window's extra memory.
2145 * The _hwnd_ parameter specifies the window. is the handle to a
2146 * window that has extra memory. The _newval_ parameter contains the
2147 * new attribute or extra memory value. If positive, the _offset_
2148 * parameter is the byte-addressed location in the window's extra
2149 * memory to set. If negative, _offset_ specifies the window
2150 * attribute to set, and should be one of the following values:
2152 * GWL_EXSTYLE The window's extended window style
2154 * GWL_STYLE The window's window style.
2156 * GWLP_WNDPROC Pointer to the window's window procedure.
2158 * GWLP_HINSTANCE The window's pplication instance handle.
2160 * GWLP_ID The window's identifier.
2162 * GWLP_USERDATA The window's user-specified data.
2164 * If the window is a dialog box, the _offset_ parameter can be one of
2165 * the following values:
2167 * DWLP_DLGPROC The address of the window's dialog box procedure.
2169 * DWLP_MSGRESULT The return value of a message
2170 * that the dialog box procedure processed.
2172 * DWLP_USER Application specific information.
2176 * If successful, returns the previous value located at _offset_. Otherwise,
2181 * Extra memory for a window class is specified by a nonzero cbWndExtra
2182 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2183 * time of class creation.
2185 * Using GWL_WNDPROC to set a new window procedure effectively creates
2186 * a window subclass. Use CallWindowProc() in the new windows procedure
2187 * to pass messages to the superclass's window procedure.
2189 * The user data is reserved for use by the application which created
2192 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2193 * instead, call the EnableWindow() function to change the window's
2196 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2197 * SetParent() instead.
2200 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2201 * it sends WM_STYLECHANGING before changing the settings
2202 * and WM_STYLECHANGED afterwards.
2203 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2205 LONG WINAPI SetWindowLongW(
2206 HWND hwnd, /* [in] window to alter */
2207 INT offset, /* [in] offset, in bytes, of location to alter */
2208 LONG newval /* [in] new value of location */
2210 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2214 /*******************************************************************
2215 * GetWindowTextA (USER32.@)
2217 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2221 if (!lpString) return 0;
2223 if (WIN_IsCurrentProcess( hwnd ))
2224 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2226 /* when window belongs to other process, don't send a message */
2227 if (nMaxCount <= 0) return 0;
2228 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2229 get_server_window_text( hwnd, buffer, nMaxCount );
2230 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2231 lpString[nMaxCount-1] = 0;
2232 HeapFree( GetProcessHeap(), 0, buffer );
2233 return strlen(lpString);
2237 /*******************************************************************
2238 * InternalGetWindowText (USER32.@)
2240 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2244 if (nMaxCount <= 0) return 0;
2245 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2246 if (win == WND_DESKTOP) lpString[0] = 0;
2247 else if (win != WND_OTHER_PROCESS)
2249 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2250 else lpString[0] = 0;
2251 WIN_ReleasePtr( win );
2255 get_server_window_text( hwnd, lpString, nMaxCount );
2257 return strlenW(lpString);
2261 /*******************************************************************
2262 * GetWindowTextW (USER32.@)
2264 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2266 if (!lpString) return 0;
2268 if (WIN_IsCurrentProcess( hwnd ))
2269 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2271 /* when window belongs to other process, don't send a message */
2272 if (nMaxCount <= 0) return 0;
2273 get_server_window_text( hwnd, lpString, nMaxCount );
2274 return strlenW(lpString);
2278 /*******************************************************************
2279 * SetWindowText (USER32.@)
2280 * SetWindowTextA (USER32.@)
2282 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2284 if (is_broadcast(hwnd))
2286 SetLastError( ERROR_INVALID_PARAMETER );
2289 if (!WIN_IsCurrentProcess( hwnd ))
2290 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2291 debugstr_a(lpString), hwnd );
2292 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2296 /*******************************************************************
2297 * SetWindowTextW (USER32.@)
2299 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2301 if (is_broadcast(hwnd))
2303 SetLastError( ERROR_INVALID_PARAMETER );
2306 if (!WIN_IsCurrentProcess( hwnd ))
2307 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2308 debugstr_w(lpString), hwnd );
2309 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2313 /*******************************************************************
2314 * GetWindowTextLengthA (USER32.@)
2316 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2318 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2321 /*******************************************************************
2322 * GetWindowTextLengthW (USER32.@)
2324 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2326 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2330 /*******************************************************************
2331 * IsWindow (USER32.@)
2333 BOOL WINAPI IsWindow( HWND hwnd )
2338 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2339 if (ptr == WND_DESKTOP) return TRUE;
2341 if (ptr != WND_OTHER_PROCESS)
2343 WIN_ReleasePtr( ptr );
2347 /* check other processes */
2348 SERVER_START_REQ( get_window_info )
2351 ret = !wine_server_call_err( req );
2358 /***********************************************************************
2359 * GetWindowThreadProcessId (USER32.@)
2361 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2366 if (!(ptr = WIN_GetPtr( hwnd )))
2368 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2372 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2374 /* got a valid window */
2376 if (process) *process = GetCurrentProcessId();
2377 WIN_ReleasePtr( ptr );
2381 /* check other processes */
2382 SERVER_START_REQ( get_window_info )
2385 if (!wine_server_call_err( req ))
2387 tid = (DWORD)reply->tid;
2388 if (process) *process = (DWORD)reply->pid;
2396 /*****************************************************************
2397 * GetParent (USER32.@)
2399 HWND WINAPI GetParent( HWND hwnd )
2404 if (!(wndPtr = WIN_GetPtr( hwnd )))
2406 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2409 if (wndPtr == WND_DESKTOP) return 0;
2410 if (wndPtr == WND_OTHER_PROCESS)
2412 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2413 if (style & (WS_POPUP | WS_CHILD))
2415 SERVER_START_REQ( get_window_tree )
2418 if (!wine_server_call_err( req ))
2420 if (style & WS_POPUP) retvalue = reply->owner;
2421 else if (style & WS_CHILD) retvalue = reply->parent;
2429 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2430 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2431 WIN_ReleasePtr( wndPtr );
2437 /*****************************************************************
2438 * GetAncestor (USER32.@)
2440 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2443 HWND *list, ret = 0;
2448 if (!(win = WIN_GetPtr( hwnd )))
2450 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2453 if (win == WND_DESKTOP) return 0;
2454 if (win != WND_OTHER_PROCESS)
2457 WIN_ReleasePtr( win );
2459 else /* need to query the server */
2461 SERVER_START_REQ( get_window_tree )
2464 if (!wine_server_call_err( req )) ret = reply->parent;
2471 if (!(list = list_window_parents( hwnd ))) return 0;
2473 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2477 while (list[count]) count++;
2478 ret = list[count - 2]; /* get the one before the desktop */
2480 HeapFree( GetProcessHeap(), 0, list );
2484 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2487 HWND parent = GetParent( ret );
2497 /*****************************************************************
2498 * SetParent (USER32.@)
2500 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2504 if (is_broadcast(hwnd) || is_broadcast(parent))
2506 SetLastError(ERROR_INVALID_PARAMETER);
2510 if (!parent) parent = GetDesktopWindow();
2511 else parent = WIN_GetFullHandle( parent );
2513 if (!IsWindow( parent ))
2515 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2519 /* Some applications try to set a child as a parent */
2520 if (IsChild(hwnd, parent))
2522 SetLastError( ERROR_INVALID_PARAMETER );
2526 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2527 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2529 return USER_Driver->pSetParent( full_handle, parent );
2533 /*******************************************************************
2534 * IsChild (USER32.@)
2536 BOOL WINAPI IsChild( HWND parent, HWND child )
2538 HWND *list = list_window_parents( child );
2542 if (!list) return FALSE;
2543 parent = WIN_GetFullHandle( parent );
2544 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2545 ret = (list[i] != 0);
2546 HeapFree( GetProcessHeap(), 0, list );
2551 /***********************************************************************
2552 * IsWindowVisible (USER32.@)
2554 BOOL WINAPI IsWindowVisible( HWND hwnd )
2560 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2561 if (!(list = list_window_parents( hwnd ))) return TRUE;
2562 for (i = 0; list[i]; i++)
2563 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2565 HeapFree( GetProcessHeap(), 0, list );
2570 /***********************************************************************
2571 * WIN_IsWindowDrawable
2573 * hwnd is drawable when it is visible, all parents are not
2574 * minimized, and it is itself not minimized unless we are
2575 * trying to draw its default class icon.
2577 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2582 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2584 if (!(style & WS_VISIBLE)) return FALSE;
2585 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2587 if (!(list = list_window_parents( hwnd ))) return TRUE;
2588 for (i = 0; list[i]; i++)
2589 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2592 HeapFree( GetProcessHeap(), 0, list );
2597 /*******************************************************************
2598 * GetTopWindow (USER32.@)
2600 HWND WINAPI GetTopWindow( HWND hwnd )
2602 if (!hwnd) hwnd = GetDesktopWindow();
2603 return GetWindow( hwnd, GW_CHILD );
2607 /*******************************************************************
2608 * GetWindow (USER32.@)
2610 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2614 if (rel == GW_OWNER) /* this one may be available locally */
2616 WND *wndPtr = WIN_GetPtr( hwnd );
2619 SetLastError( ERROR_INVALID_HANDLE );
2622 if (wndPtr == WND_DESKTOP) return 0;
2623 if (wndPtr != WND_OTHER_PROCESS)
2625 retval = wndPtr->owner;
2626 WIN_ReleasePtr( wndPtr );
2629 /* else fall through to server call */
2632 SERVER_START_REQ( get_window_tree )
2635 if (!wine_server_call_err( req ))
2640 retval = reply->first_sibling;
2643 retval = reply->last_sibling;
2646 retval = reply->next_sibling;
2649 retval = reply->prev_sibling;
2652 retval = reply->owner;
2655 retval = reply->first_child;
2665 /*******************************************************************
2666 * ShowOwnedPopups (USER32.@)
2668 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2672 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2674 if (!win_array) return TRUE;
2676 while (win_array[count]) count++;
2677 while (--count >= 0)
2679 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2680 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2681 if (pWnd == WND_OTHER_PROCESS) continue;
2684 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2686 WIN_ReleasePtr( pWnd );
2687 /* In Windows, ShowOwnedPopups(TRUE) generates
2688 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2689 * regardless of the state of the owner
2691 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2697 if (pWnd->dwStyle & WS_VISIBLE)
2699 WIN_ReleasePtr( pWnd );
2700 /* In Windows, ShowOwnedPopups(FALSE) generates
2701 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2702 * regardless of the state of the owner
2704 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2708 WIN_ReleasePtr( pWnd );
2710 HeapFree( GetProcessHeap(), 0, win_array );
2715 /*******************************************************************
2716 * GetLastActivePopup (USER32.@)
2718 HWND WINAPI GetLastActivePopup( HWND hwnd )
2722 SERVER_START_REQ( get_window_info )
2725 if (!wine_server_call_err( req )) retval = reply->last_active;
2732 /*******************************************************************
2735 * Build an array of the children of a given window. The array must be
2736 * freed with HeapFree. Returns NULL when no windows are found.
2738 HWND *WIN_ListChildren( HWND hwnd )
2740 return list_window_children( hwnd, 0, 0 );
2744 /*******************************************************************
2745 * EnumWindows (USER32.@)
2747 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2753 USER_CheckNotLock();
2755 /* We have to build a list of all windows first, to avoid */
2756 /* unpleasant side-effects, for instance if the callback */
2757 /* function changes the Z-order of the windows. */
2759 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2761 /* Now call the callback function for every window */
2763 for (i = 0; list[i]; i++)
2765 /* Make sure that the window still exists */
2766 if (!IsWindow( list[i] )) continue;
2767 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2769 HeapFree( GetProcessHeap(), 0, list );
2774 /**********************************************************************
2775 * EnumThreadWindows (USER32.@)
2777 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2782 USER_CheckNotLock();
2784 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2786 /* Now call the callback function for every window */
2788 for (i = 0; list[i]; i++)
2789 if (!func( list[i], lParam )) break;
2790 HeapFree( GetProcessHeap(), 0, list );
2795 /**********************************************************************
2796 * WIN_EnumChildWindows
2798 * Helper function for EnumChildWindows().
2800 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2805 for ( ; *list; list++)
2807 /* Make sure that the window still exists */
2808 if (!IsWindow( *list )) continue;
2809 /* skip owned windows */
2810 if (GetWindow( *list, GW_OWNER )) continue;
2811 /* Build children list first */
2812 childList = WIN_ListChildren( *list );
2814 ret = func( *list, lParam );
2818 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2819 HeapFree( GetProcessHeap(), 0, childList );
2821 if (!ret) return FALSE;
2827 /**********************************************************************
2828 * EnumChildWindows (USER32.@)
2830 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2834 USER_CheckNotLock();
2836 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2837 WIN_EnumChildWindows( list, func, lParam );
2838 HeapFree( GetProcessHeap(), 0, list );
2843 /*******************************************************************
2844 * AnyPopup (USER.52)
2846 BOOL16 WINAPI AnyPopup16(void)
2852 /*******************************************************************
2853 * AnyPopup (USER32.@)
2855 BOOL WINAPI AnyPopup(void)
2859 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2861 if (!list) return FALSE;
2862 for (i = 0; list[i]; i++)
2864 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2866 retvalue = (list[i] != 0);
2867 HeapFree( GetProcessHeap(), 0, list );
2872 /*******************************************************************
2873 * FlashWindow (USER32.@)
2875 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2879 TRACE("%p\n", hWnd);
2881 if (IsIconic( hWnd ))
2883 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2885 wndPtr = WIN_GetPtr(hWnd);
2886 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2887 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2889 wndPtr->flags |= WIN_NCACTIVATED;
2893 wndPtr->flags &= ~WIN_NCACTIVATED;
2895 WIN_ReleasePtr( wndPtr );
2902 wndPtr = WIN_GetPtr(hWnd);
2903 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2904 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2906 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2907 else wparam = (hWnd == GetForegroundWindow());
2909 WIN_ReleasePtr( wndPtr );
2910 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2915 /*******************************************************************
2916 * FlashWindowEx (USER32.@)
2918 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
2920 FIXME("%p\n", pfwi);
2924 /*******************************************************************
2925 * GetWindowContextHelpId (USER32.@)
2927 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2930 WND *wnd = WIN_GetPtr( hwnd );
2931 if (!wnd || wnd == WND_DESKTOP) return 0;
2932 if (wnd == WND_OTHER_PROCESS)
2934 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2937 retval = wnd->helpContext;
2938 WIN_ReleasePtr( wnd );
2943 /*******************************************************************
2944 * SetWindowContextHelpId (USER32.@)
2946 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2948 WND *wnd = WIN_GetPtr( hwnd );
2949 if (!wnd || wnd == WND_DESKTOP) return FALSE;
2950 if (wnd == WND_OTHER_PROCESS)
2952 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2955 wnd->helpContext = id;
2956 WIN_ReleasePtr( wnd );
2961 /*******************************************************************
2962 * DragDetect (USER32.@)
2964 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2969 rect.left = pt.x - wDragWidth;
2970 rect.right = pt.x + wDragWidth;
2972 rect.top = pt.y - wDragHeight;
2973 rect.bottom = pt.y + wDragHeight;
2979 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
2981 if( msg.message == WM_LBUTTONUP )
2986 if( msg.message == WM_MOUSEMOVE )
2989 tmp.x = LOWORD(msg.lParam);
2990 tmp.y = HIWORD(msg.lParam);
2991 if( !PtInRect( &rect, tmp ))
3003 /******************************************************************************
3004 * GetWindowModuleFileNameA (USER32.@)
3006 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3008 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3009 hwnd, lpszFileName, cchFileNameMax);
3013 /******************************************************************************
3014 * GetWindowModuleFileNameW (USER32.@)
3016 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3018 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3019 hwnd, lpszFileName, cchFileNameMax);
3023 /******************************************************************************
3024 * GetWindowInfo (USER32.@)
3026 * Note: tests show that Windows doesn't check cbSize of the structure.
3028 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3030 if (!pwi) return FALSE;
3031 if (!IsWindow(hwnd)) return FALSE;
3033 GetWindowRect(hwnd, &pwi->rcWindow);
3034 GetClientRect(hwnd, &pwi->rcClient);
3035 /* translate to screen coordinates */
3036 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3038 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3039 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3040 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3042 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3043 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3045 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3046 pwi->wCreatorVersion = 0x0400;
3051 /******************************************************************************
3052 * SwitchDesktop (USER32.@)
3054 * NOTES: Sets the current input or interactive desktop.
3056 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3058 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3062 /*****************************************************************************
3063 * SetLayeredWindowAttributes (USER32.@)
3065 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3066 BYTE bAlpha, DWORD dwFlags )
3068 FIXME("(%p,0x%.8lx,%d,%ld): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);