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 struct tagCLASS *class = NULL;
63 user_handle_t handle = 0;
66 /* if 16-bit instance, map to module handle */
67 if (instance && !HIWORD(instance))
68 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
70 SERVER_START_REQ( create_window )
75 req->instance = instance;
76 if (!wine_server_call_err( req ))
78 handle = reply->handle;
79 extra_bytes = reply->extra;
80 class = reply->class_ptr;
87 WARN( "error %ld creating window\n", GetLastError() );
91 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
93 SERVER_START_REQ( destroy_window )
96 wine_server_call( req );
99 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
105 index = USER_HANDLE_TO_INDEX(handle);
106 assert( index < NB_USER_HANDLES );
107 user_handles[index] = win;
108 win->hwndSelf = handle;
109 win->dwMagic = WND_MAGIC;
110 win->cbWndExtra = extra_bytes;
111 memset( win->wExtra, 0, extra_bytes );
112 CLASS_AddWindow( class, win, type );
117 /***********************************************************************
120 * Free a window handle.
122 static WND *free_window_handle( HWND hwnd )
125 WORD index = USER_HANDLE_TO_INDEX(hwnd);
127 if (index >= NB_USER_HANDLES) return NULL;
129 if ((ptr = user_handles[index]))
131 SERVER_START_REQ( destroy_window )
134 if (!wine_server_call_err( req ))
136 user_handles[index] = NULL;
145 HeapFree( GetProcessHeap(), 0, ptr );
150 /*******************************************************************
151 * list_window_children
153 * Build an array of the children of a given window. The array must be
154 * freed with HeapFree. Returns NULL when no windows are found.
156 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
165 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
167 SERVER_START_REQ( get_window_children )
172 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
173 if (!wine_server_call( req )) count = reply->count;
176 if (count && count < size)
181 HeapFree( GetProcessHeap(), 0, list );
183 size = count + 1; /* restart with a large enough buffer */
189 /*******************************************************************
190 * list_window_parents
192 * Build an array of all parents of a given window, starting with
193 * the immediate parent. The array must be freed with HeapFree.
194 * Returns NULL if window is a top-level window.
196 static HWND *list_window_parents( HWND hwnd )
200 int pos = 0, size = 16, count = 0;
202 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
207 if (!(win = WIN_GetPtr( current ))) goto empty;
208 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
209 if (win == WND_DESKTOP)
211 if (!pos) goto empty;
215 list[pos] = current = win->parent;
216 WIN_ReleasePtr( win );
217 if (++pos == size - 1)
219 /* need to grow the list */
220 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
221 if (!new_list) goto empty;
227 /* at least one parent belongs to another process, have to query the server */
232 SERVER_START_REQ( get_window_parents )
235 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
236 if (!wine_server_call( req )) count = reply->count;
239 if (!count) goto empty;
245 HeapFree( GetProcessHeap(), 0, list );
247 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
251 HeapFree( GetProcessHeap(), 0, list );
256 /*******************************************************************
259 static void send_parent_notify( HWND hwnd, UINT msg )
261 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
262 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
263 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
264 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
268 /*******************************************************************
269 * get_server_window_text
271 * Retrieve the window text from the server.
273 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
277 SERVER_START_REQ( get_window_text )
280 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
281 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
284 text[len / sizeof(WCHAR)] = 0;
288 /***********************************************************************
291 * Return a pointer to the WND structure if local to the process,
292 * or WND_OTHER_PROCESS if handle may be valid in other process.
293 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
295 WND *WIN_GetPtr( HWND hwnd )
298 WORD index = USER_HANDLE_TO_INDEX(hwnd);
300 if (index >= NB_USER_HANDLES) return NULL;
303 if ((ptr = user_handles[index]))
305 if (ptr->dwMagic == WND_MAGIC &&
306 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
310 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
312 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
315 else ptr = WND_OTHER_PROCESS;
321 /***********************************************************************
322 * WIN_IsCurrentProcess
324 * Check whether a given window belongs to the current process (and return the full handle).
326 HWND WIN_IsCurrentProcess( HWND hwnd )
331 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
333 WIN_ReleasePtr( ptr );
338 /***********************************************************************
339 * WIN_IsCurrentThread
341 * Check whether a given window belongs to the current thread (and return the full handle).
343 HWND WIN_IsCurrentThread( HWND hwnd )
348 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
349 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
350 WIN_ReleasePtr( ptr );
355 /***********************************************************************
358 * Convert a 16-bit window handle to a full 32-bit handle.
360 HWND WIN_Handle32( HWND16 hwnd16 )
363 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
365 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
366 /* do sign extension for -2 and -3 */
367 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
369 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
371 if (ptr == WND_DESKTOP) return GetDesktopWindow();
373 if (ptr != WND_OTHER_PROCESS)
375 hwnd = ptr->hwndSelf;
376 WIN_ReleasePtr( ptr );
378 else /* may belong to another process */
380 SERVER_START_REQ( get_window_info )
383 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
391 /***********************************************************************
394 * Change the owner of a window.
396 HWND WIN_SetOwner( HWND hwnd, HWND owner )
398 WND *win = WIN_GetPtr( hwnd );
401 if (!win || win == WND_DESKTOP) return 0;
402 if (win == WND_OTHER_PROCESS)
404 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
407 SERVER_START_REQ( set_window_owner )
411 if (!wine_server_call( req ))
413 win->owner = reply->full_owner;
414 ret = reply->prev_owner;
418 WIN_ReleasePtr( win );
423 /***********************************************************************
426 * Change the style of a window.
428 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
431 ULONG new_style, old_style = 0;
432 WND *win = WIN_GetPtr( hwnd );
434 if (!win || win == WND_DESKTOP) return 0;
435 if (win == WND_OTHER_PROCESS)
438 ERR( "cannot set style %lx/%lx on other process window %p\n",
439 set_bits, clear_bits, hwnd );
442 new_style = (win->dwStyle | set_bits) & ~clear_bits;
443 if (new_style == win->dwStyle)
445 WIN_ReleasePtr( win );
448 SERVER_START_REQ( set_window_info )
451 req->flags = SET_WIN_STYLE;
452 req->style = new_style;
453 req->extra_offset = -1;
454 if ((ok = !wine_server_call( req )))
456 old_style = reply->old_style;
457 win->dwStyle = new_style;
461 WIN_ReleasePtr( win );
462 if (ok) USER_Driver->pSetWindowStyle( hwnd, old_style );
467 /***********************************************************************
470 * Get the window and client rectangles.
472 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
474 WND *win = WIN_GetPtr( hwnd );
477 if (!win) return FALSE;
478 if (win == WND_DESKTOP)
481 rect.left = rect.top = 0;
482 rect.right = GetSystemMetrics(SM_CXSCREEN);
483 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
484 if (rectWindow) *rectWindow = rect;
485 if (rectClient) *rectClient = rect;
487 else if (win == WND_OTHER_PROCESS)
489 SERVER_START_REQ( get_window_rectangles )
492 if ((ret = !wine_server_call( req )))
496 rectWindow->left = reply->window.left;
497 rectWindow->top = reply->window.top;
498 rectWindow->right = reply->window.right;
499 rectWindow->bottom = reply->window.bottom;
503 rectClient->left = reply->client.left;
504 rectClient->top = reply->client.top;
505 rectClient->right = reply->client.right;
506 rectClient->bottom = reply->client.bottom;
514 if (rectWindow) *rectWindow = win->rectWindow;
515 if (rectClient) *rectClient = win->rectClient;
516 WIN_ReleasePtr( win );
522 /***********************************************************************
525 * Destroy storage associated to a window. "Internals" p.358
527 LRESULT WIN_DestroyWindow( HWND hwnd )
531 HMENU menu = 0, sys_menu;
533 TRACE("%p\n", hwnd );
535 /* free child windows */
536 if ((list = WIN_ListChildren( hwnd )))
539 for (i = 0; list[i]; i++)
541 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
542 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
544 HeapFree( GetProcessHeap(), 0, list );
547 /* Unlink now so we won't bother with the children later on */
548 SERVER_START_REQ( set_parent )
552 wine_server_call( req );
557 * Send the WM_NCDESTROY to the window being destroyed.
559 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
561 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
563 WINPOS_CheckInternalPos( hwnd );
565 /* free resources associated with the window */
567 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
568 if (!(wndPtr->dwStyle & WS_CHILD)) menu = (HMENU)wndPtr->wIDmenu;
569 sys_menu = wndPtr->hSysMenu;
570 WIN_ReleasePtr( wndPtr );
572 if (menu) DestroyMenu( menu );
573 if (sys_menu) DestroyMenu( sys_menu );
575 USER_Driver->pDestroyWindow( hwnd );
577 free_window_handle( hwnd );
581 /***********************************************************************
582 * WIN_DestroyThreadWindows
584 * Destroy all children of 'wnd' owned by the current thread.
585 * Return TRUE if something was done.
587 void WIN_DestroyThreadWindows( HWND hwnd )
592 if (!(list = WIN_ListChildren( hwnd ))) return;
593 for (i = 0; list[i]; i++)
595 if (WIN_IsCurrentThread( list[i] ))
596 DestroyWindow( list[i] );
598 WIN_DestroyThreadWindows( list[i] );
600 HeapFree( GetProcessHeap(), 0, list );
604 /***********************************************************************
607 * Fix the coordinates - Helper for WIN_CreateWindowEx.
608 * returns default show mode in sw.
609 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
611 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
615 if (cs->dwExStyle & WS_EX_MDICHILD)
619 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
620 if (!(cs->style & WS_POPUP)) cs->hMenu = (HMENU)id;
622 TRACE("MDI child id %04x\n", id);
625 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
626 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
628 if (cs->style & (WS_CHILD | WS_POPUP))
630 if (cs->dwExStyle & WS_EX_MDICHILD)
632 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
637 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
639 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
644 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
646 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
650 else /* overlapped window */
654 GetStartupInfoW( &info );
656 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
658 /* Never believe Microsoft's documentation... CreateWindowEx doc says
659 * that if an overlapped window is created with WS_VISIBLE style bit
660 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
661 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
664 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
665 * 2) it does not ignore the y parameter as the docs claim; instead, it
666 * uses it as second parameter to ShowWindow() unless y is either
667 * CW_USEDEFAULT or CW_USEDEFAULT16.
669 * The fact that we didn't do 2) caused bogus windows pop up when wine
670 * was running apps that were using this obscure feature. Example -
671 * calc.exe that comes with Win98 (only Win98, it's different from
672 * the one that comes with Win95 and NT)
674 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
675 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
676 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
679 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
681 if (info.dwFlags & STARTF_USESIZE)
683 cs->cx = info.dwXSize;
684 cs->cy = info.dwYSize;
686 else /* if no other hint from the app, pick 3/4 of the screen real estate */
689 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
690 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
691 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
694 /* Handle case where only the cy values is set to default */
695 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
698 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
699 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
705 /* neither x nor cx are default. Check the y values .
706 * In the trace we see Outlook and Outlook Express using
707 * cy set to CW_USEDEFAULT when opening the address book.
709 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
711 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
712 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
713 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
718 /***********************************************************************
721 static void dump_window_styles( DWORD style, DWORD exstyle )
724 if(style & WS_POPUP) TRACE(" WS_POPUP");
725 if(style & WS_CHILD) TRACE(" WS_CHILD");
726 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
727 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
728 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
729 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
730 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
731 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
732 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
735 if(style & WS_BORDER) TRACE(" WS_BORDER");
736 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
738 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
739 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
740 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
741 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
742 if (style & WS_CHILD)
744 if(style & WS_GROUP) TRACE(" WS_GROUP");
745 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
749 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
750 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
753 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
754 #define DUMPED_STYLES \
774 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
779 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
780 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
781 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
782 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
783 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
784 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
785 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
786 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
787 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
788 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
789 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
790 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
791 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
792 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
793 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
794 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
795 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
796 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
798 #define DUMPED_EX_STYLES \
799 (WS_EX_DLGMODALFRAME | \
801 WS_EX_NOPARENTNOTIFY | \
803 WS_EX_ACCEPTFILES | \
804 WS_EX_TRANSPARENT | \
809 WS_EX_CONTEXTHELP | \
812 WS_EX_LEFTSCROLLBAR | \
813 WS_EX_CONTROLPARENT | \
818 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
820 #undef DUMPED_EX_STYLES
824 /***********************************************************************
827 * Implementation of CreateWindowEx().
829 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
830 WINDOWPROCTYPE type )
834 HWND hwnd, parent, owner, top_child = 0;
835 BOOL unicode = (type == WIN_PROC_32W);
836 MDICREATESTRUCTA mdi_cs;
838 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
839 (type == WIN_PROC_32W) ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
840 (type == WIN_PROC_32W) ? debugstr_w((LPCWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
841 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
842 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
844 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
846 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
847 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
849 /* Fix the styles for MDI children */
850 if (cs->dwExStyle & WS_EX_MDICHILD)
854 wndPtr = WIN_GetPtr(cs->hwndParent);
855 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
857 flags = wndPtr->flags;
858 WIN_ReleasePtr(wndPtr);
861 if (!(flags & WIN_ISMDICLIENT))
863 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
867 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
868 * MDICREATESTRUCT members have the originally passed values.
870 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
871 * have the same layout.
873 mdi_cs.szClass = cs->lpszClass;
874 mdi_cs.szTitle = cs->lpszName;
875 mdi_cs.hOwner = cs->hInstance;
880 mdi_cs.style = cs->style;
881 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
883 cs->lpCreateParams = (LPVOID)&mdi_cs;
885 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
887 if (cs->style & WS_POPUP)
889 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
892 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
896 cs->style &= ~WS_POPUP;
897 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
898 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
901 top_child = GetWindow(cs->hwndParent, GW_CHILD);
905 /* Restore current maximized child */
906 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
908 TRACE("Restoring current maximized child %p\n", top_child);
909 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
910 ShowWindow(top_child, SW_RESTORE);
911 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
916 /* Find the parent window */
918 parent = GetDesktopWindow();
921 if (cs->hwndParent == HWND_MESSAGE)
923 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
924 * message window (style: WS_POPUP|WS_DISABLED)
926 FIXME("Parent is HWND_MESSAGE\n");
928 else if (cs->hwndParent)
930 /* Make sure parent is valid */
931 if (!IsWindow( cs->hwndParent ))
933 WARN("Bad parent %p\n", cs->hwndParent );
936 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
937 parent = WIN_GetFullHandle(cs->hwndParent);
939 owner = GetAncestor( cs->hwndParent, GA_ROOT );
941 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
943 WARN("No parent for child window\n" );
944 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
947 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
949 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
950 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
951 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
952 cs->dwExStyle |= WS_EX_WINDOWEDGE;
954 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
956 /* Create the window structure */
958 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
960 TRACE("out of memory\n" );
963 hwnd = wndPtr->hwndSelf;
965 /* Fill the window structure */
967 wndPtr->tid = GetCurrentThreadId();
968 wndPtr->owner = owner;
969 wndPtr->parent = parent;
970 wndPtr->hInstance = cs->hInstance;
972 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
973 wndPtr->dwExStyle = cs->dwExStyle;
975 wndPtr->helpContext = 0;
976 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
977 wndPtr->pVScroll = NULL;
978 wndPtr->pHScroll = NULL;
979 wndPtr->userdata = 0;
981 wndPtr->hIconSmall = 0;
982 wndPtr->hSysMenu = 0;
984 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
987 * Correct the window styles.
989 * It affects only the style loaded into the WIN structure.
992 if (!(wndPtr->dwStyle & WS_CHILD))
994 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
995 if (!(wndPtr->dwStyle & WS_POPUP))
996 wndPtr->dwStyle |= WS_CAPTION;
1000 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1001 * why does the user get to set it?
1004 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1005 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1006 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1008 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1010 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1011 wndPtr->flags |= WIN_NEED_SIZE;
1013 SERVER_START_REQ( set_window_info )
1016 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1017 req->style = wndPtr->dwStyle;
1018 req->ex_style = wndPtr->dwExStyle;
1019 req->instance = (void *)wndPtr->hInstance;
1020 req->is_unicode = (type == WIN_PROC_32W);
1021 req->extra_offset = -1;
1022 wine_server_call( req );
1026 /* Set the window menu */
1028 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1029 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1033 if (!MENU_SetMenu(hwnd, cs->hMenu))
1035 WIN_ReleasePtr( wndPtr );
1036 free_window_handle( hwnd );
1042 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1045 if (!cs->hInstance || HIWORD(cs->hInstance))
1046 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1048 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1050 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1054 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1055 WIN_ReleasePtr( wndPtr );
1057 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1059 WIN_DestroyWindow( hwnd );
1063 /* Notify the parent window only */
1065 send_parent_notify( hwnd, WM_CREATE );
1066 if (!IsWindow( hwnd )) return 0;
1068 if (cs->style & WS_VISIBLE)
1070 if (cs->style & WS_MAXIMIZE)
1072 else if (cs->style & WS_MINIMIZE)
1073 sw = SW_SHOWMINIMIZED;
1075 ShowWindow( hwnd, sw );
1076 if (cs->dwExStyle & WS_EX_MDICHILD)
1078 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1079 /* ShowWindow won't activate child windows */
1080 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1084 /* Call WH_SHELL hook */
1086 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1087 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1089 TRACE("created window %p\n", hwnd);
1094 /***********************************************************************
1095 * CreateWindow (USER.41)
1097 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1098 DWORD style, INT16 x, INT16 y, INT16 width,
1099 INT16 height, HWND16 parent, HMENU16 menu,
1100 HINSTANCE16 instance, LPVOID data )
1102 return CreateWindowEx16( 0, className, windowName, style,
1103 x, y, width, height, parent, menu, instance, data );
1107 /***********************************************************************
1108 * CreateWindowEx (USER.452)
1110 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1111 LPCSTR windowName, DWORD style, INT16 x,
1112 INT16 y, INT16 width, INT16 height,
1113 HWND16 parent, HMENU16 menu,
1114 HINSTANCE16 instance, LPVOID data )
1120 /* Find the class atom */
1122 if (HIWORD(className))
1124 if (!(classAtom = GlobalFindAtomA( className )))
1126 ERR( "bad class name %s\n", debugstr_a(className) );
1132 classAtom = LOWORD(className);
1133 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1135 ERR( "bad atom %x\n", classAtom);
1141 /* Fix the coordinates */
1143 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1144 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1145 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1146 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1148 /* Create the window */
1150 cs.lpCreateParams = data;
1151 cs.hInstance = HINSTANCE_32(instance);
1152 cs.hMenu = HMENU_32(menu);
1153 cs.hwndParent = WIN_Handle32( parent );
1155 cs.lpszName = windowName;
1156 cs.lpszClass = className;
1157 cs.dwExStyle = exStyle;
1159 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1163 /***********************************************************************
1164 * CreateWindowExA (USER32.@)
1166 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1167 LPCSTR windowName, DWORD style, INT x,
1168 INT y, INT width, INT height,
1169 HWND parent, HMENU menu,
1170 HINSTANCE instance, LPVOID data )
1176 /* Find the class atom */
1178 if (HIWORD(className))
1180 if (!(classAtom = GlobalFindAtomA( className )))
1182 ERR( "bad class name %s\n", debugstr_a(className) );
1188 classAtom = LOWORD(className);
1189 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1191 ERR( "bad atom %x\n", classAtom);
1197 /* Create the window */
1199 cs.lpCreateParams = data;
1200 cs.hInstance = instance;
1202 cs.hwndParent = parent;
1208 cs.lpszName = windowName;
1209 cs.lpszClass = className;
1210 cs.dwExStyle = exStyle;
1212 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1216 /***********************************************************************
1217 * CreateWindowExW (USER32.@)
1219 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1220 LPCWSTR windowName, DWORD style, INT x,
1221 INT y, INT width, INT height,
1222 HWND parent, HMENU menu,
1223 HINSTANCE instance, LPVOID data )
1229 /* Find the class atom */
1231 if (HIWORD(className))
1233 if (!(classAtom = GlobalFindAtomW( className )))
1235 ERR( "bad class name %s\n", debugstr_w(className) );
1241 classAtom = LOWORD(className);
1242 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1244 ERR( "bad atom %x\n", classAtom);
1250 /* Create the window */
1252 cs.lpCreateParams = data;
1253 cs.hInstance = instance;
1255 cs.hwndParent = parent;
1261 cs.lpszName = windowName;
1262 cs.lpszClass = className;
1263 cs.dwExStyle = exStyle;
1265 /* Note: we rely on the fact that CREATESTRUCTA and */
1266 /* CREATESTRUCTW have the same layout. */
1267 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1271 /***********************************************************************
1272 * WIN_SendDestroyMsg
1274 static void WIN_SendDestroyMsg( HWND hwnd )
1278 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1280 if (hwnd == info.hwndCaret) DestroyCaret();
1281 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1283 USER_Driver->pResetSelectionOwner( hwnd, TRUE );
1286 * Send the WM_DESTROY to the window.
1288 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1291 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1292 * make sure that the window still exists when we come back.
1299 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1301 for (i = 0; pWndArray[i]; i++)
1303 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1305 HeapFree( GetProcessHeap(), 0, pWndArray );
1308 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1312 /***********************************************************************
1313 * DestroyWindow (USER32.@)
1315 BOOL WINAPI DestroyWindow( HWND hwnd )
1319 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1321 SetLastError( ERROR_ACCESS_DENIED );
1325 TRACE("(%p)\n", hwnd);
1329 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1331 if (MENU_IsMenuActive() == hwnd)
1334 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1338 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1339 send_parent_notify( hwnd, WM_DESTROY );
1341 else if (!GetWindow( hwnd, GW_OWNER ))
1343 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1344 /* FIXME: clean up palette - see "Internals" p.352 */
1347 if (!IsWindow(hwnd)) return TRUE;
1349 USER_Driver->pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1351 /* Hide the window */
1352 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1354 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1356 ShowWindow( hwnd, SW_HIDE );
1358 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1359 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1362 if (!IsWindow(hwnd)) return TRUE;
1364 /* Recursively destroy owned windows */
1371 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1374 for (i = 0; list[i]; i++)
1376 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1377 if (WIN_IsCurrentThread( list[i] ))
1379 DestroyWindow( list[i] );
1383 WIN_SetOwner( list[i], 0 );
1385 HeapFree( GetProcessHeap(), 0, list );
1387 if (!got_one) break;
1391 /* Send destroy messages */
1393 WIN_SendDestroyMsg( hwnd );
1394 if (!IsWindow( hwnd )) return TRUE;
1396 if (GetClipboardOwner() == hwnd)
1397 CLIPBOARD_ReleaseOwner();
1399 /* Destroy the window storage */
1401 WIN_DestroyWindow( hwnd );
1406 /***********************************************************************
1407 * CloseWindow (USER32.@)
1409 BOOL WINAPI CloseWindow( HWND hwnd )
1411 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1412 ShowWindow( hwnd, SW_MINIMIZE );
1417 /***********************************************************************
1418 * OpenIcon (USER32.@)
1420 BOOL WINAPI OpenIcon( HWND hwnd )
1422 if (!IsIconic( hwnd )) return FALSE;
1423 ShowWindow( hwnd, SW_SHOWNORMAL );
1428 /***********************************************************************
1431 * Implementation of FindWindow() and FindWindowEx().
1433 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1438 WCHAR *buffer = NULL;
1440 if (!parent) parent = GetDesktopWindow();
1443 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1444 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1447 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1451 child = WIN_GetFullHandle( child );
1452 while (list[i] && list[i] != child) i++;
1453 if (!list[i]) goto done;
1454 i++; /* start from next window */
1461 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1468 HeapFree( GetProcessHeap(), 0, list );
1469 HeapFree( GetProcessHeap(), 0, buffer );
1475 /***********************************************************************
1476 * FindWindowA (USER32.@)
1478 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1480 HWND ret = FindWindowExA( 0, 0, className, title );
1481 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1486 /***********************************************************************
1487 * FindWindowExA (USER32.@)
1489 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1490 LPCSTR className, LPCSTR title )
1499 /* If the atom doesn't exist, then no class */
1500 /* with this name exists either. */
1501 if (!(atom = GlobalFindAtomA( className )))
1503 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1507 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1509 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1510 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1511 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1512 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1513 HeapFree( GetProcessHeap(), 0, buffer );
1518 /***********************************************************************
1519 * FindWindowExW (USER32.@)
1521 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1522 LPCWSTR className, LPCWSTR title )
1528 /* If the atom doesn't exist, then no class */
1529 /* with this name exists either. */
1530 if (!(atom = GlobalFindAtomW( className )))
1532 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1536 return WIN_FindWindow( parent, child, atom, title );
1540 /***********************************************************************
1541 * FindWindowW (USER32.@)
1543 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1545 return FindWindowExW( 0, 0, className, title );
1549 /**********************************************************************
1550 * GetDesktopWindow (USER32.@)
1552 HWND WINAPI GetDesktopWindow(void)
1554 struct user_thread_info *thread_info = get_user_thread_info();
1556 if (!thread_info->desktop)
1558 SERVER_START_REQ( get_desktop_window )
1560 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1563 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1564 ERR( "failed to create desktop window\n" );
1566 return thread_info->desktop;
1570 /*******************************************************************
1571 * EnableWindow (USER32.@)
1573 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1578 if (is_broadcast(hwnd))
1580 SetLastError( ERROR_INVALID_PARAMETER );
1584 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1585 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1589 TRACE("( %p, %d )\n", hwnd, enable);
1591 retvalue = !IsWindowEnabled( hwnd );
1593 if (enable && retvalue)
1595 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1596 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1598 else if (!enable && !retvalue)
1602 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1604 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1606 if (hwnd == GetFocus())
1607 SetFocus( 0 ); /* A disabled window can't have the focus */
1609 capture_wnd = GetCapture();
1610 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1611 ReleaseCapture(); /* A disabled window can't capture the mouse */
1613 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1619 /***********************************************************************
1620 * IsWindowEnabled (USER32.@)
1622 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1624 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1628 /***********************************************************************
1629 * IsWindowUnicode (USER32.@)
1631 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1634 BOOL retvalue = FALSE;
1636 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1638 if (wndPtr == WND_DESKTOP) return TRUE;
1640 if (wndPtr != WND_OTHER_PROCESS)
1642 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1643 WIN_ReleasePtr( wndPtr );
1647 SERVER_START_REQ( get_window_info )
1650 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1658 /**********************************************************************
1659 * GetWindowWord (USER32.@)
1661 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1666 WND *wndPtr = WIN_GetPtr( hwnd );
1669 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1672 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1674 SERVER_START_REQ( set_window_info )
1677 req->flags = 0; /* don't set anything, just retrieve */
1678 req->extra_offset = offset;
1679 req->extra_size = sizeof(retvalue);
1680 if (!wine_server_call_err( req ))
1681 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1686 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1688 WARN("Invalid offset %d\n", offset );
1689 SetLastError( ERROR_INVALID_INDEX );
1691 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1692 WIN_ReleasePtr( wndPtr );
1698 case GWLP_HWNDPARENT:
1699 return GetWindowLongPtrW( hwnd, offset );
1701 case GWLP_HINSTANCE:
1703 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1705 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1709 WARN("Invalid offset %d\n", offset );
1715 /**********************************************************************
1716 * SetWindowWord (USER32.@)
1718 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1726 case GWLP_HINSTANCE:
1727 case GWLP_HWNDPARENT:
1728 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1732 WARN("Invalid offset %d\n", offset );
1733 SetLastError( ERROR_INVALID_INDEX );
1738 wndPtr = WIN_GetPtr( hwnd );
1739 if (wndPtr == WND_DESKTOP)
1741 SetLastError( ERROR_ACCESS_DENIED );
1744 if (wndPtr == WND_OTHER_PROCESS)
1747 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1748 offset, newval, hwnd );
1753 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1757 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1759 WARN("Invalid offset %d\n", offset );
1760 WIN_ReleasePtr(wndPtr);
1761 SetLastError( ERROR_INVALID_INDEX );
1765 SERVER_START_REQ( set_window_info )
1768 req->flags = SET_WIN_EXTRA;
1769 req->extra_offset = offset;
1770 req->extra_size = sizeof(newval);
1771 memcpy( &req->extra_value, &newval, sizeof(newval) );
1772 if (!wine_server_call_err( req ))
1774 void *ptr = (char *)wndPtr->wExtra + offset;
1775 memcpy( &retval, ptr, sizeof(retval) );
1776 memcpy( ptr, &newval, sizeof(newval) );
1780 WIN_ReleasePtr( wndPtr );
1785 /**********************************************************************
1788 * Helper function for GetWindowLong().
1790 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1792 LONG_PTR retvalue = 0;
1795 if (offset == GWLP_HWNDPARENT)
1797 HWND parent = GetAncestor( hwnd, GA_PARENT );
1798 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1799 return (ULONG_PTR)parent;
1802 if (!(wndPtr = WIN_GetPtr( hwnd )))
1804 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1808 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1810 if (offset == GWLP_WNDPROC)
1812 SetLastError( ERROR_ACCESS_DENIED );
1815 SERVER_START_REQ( set_window_info )
1818 req->flags = 0; /* don't set anything, just retrieve */
1819 req->extra_offset = (offset >= 0) ? offset : -1;
1820 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1821 if (!wine_server_call_err( req ))
1825 case GWL_STYLE: retvalue = reply->old_style; break;
1826 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1827 case GWLP_ID: retvalue = reply->old_id; break;
1828 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1829 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1831 if (offset >= 0) retvalue = reply->old_extra_value;
1832 else SetLastError( ERROR_INVALID_INDEX );
1841 /* now we have a valid wndPtr */
1845 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1848 * Some programs try to access last element from 16 bit
1849 * code using illegal offset value. Hopefully this is
1850 * what those programs really expect.
1852 if (type == WIN_PROC_16 &&
1853 wndPtr->cbWndExtra >= 4 &&
1854 offset == wndPtr->cbWndExtra - sizeof(WORD))
1856 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1858 ERR( "- replaced invalid offset %d with %d\n",
1861 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset2);
1862 WIN_ReleasePtr( wndPtr );
1865 WARN("Invalid offset %d\n", offset );
1866 WIN_ReleasePtr( wndPtr );
1867 SetLastError( ERROR_INVALID_INDEX );
1870 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
1871 /* Special case for dialog window procedure */
1872 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1873 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, type );
1874 WIN_ReleasePtr( wndPtr );
1880 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1881 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1882 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1883 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1884 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type ); break;
1885 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1887 WARN("Unknown offset %d\n", offset );
1888 SetLastError( ERROR_INVALID_INDEX );
1891 WIN_ReleasePtr(wndPtr);
1896 /**********************************************************************
1899 * Helper function for SetWindowLong().
1901 * 0 is the failure code. However, in the case of failure SetLastError
1902 * must be set to distinguish between a 0 return value and a failure.
1904 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval,
1905 WINDOWPROCTYPE type )
1909 LONG_PTR retval = 0;
1912 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1914 if (is_broadcast(hwnd))
1916 SetLastError( ERROR_INVALID_PARAMETER );
1920 if (!(wndPtr = WIN_GetPtr( hwnd )))
1922 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1925 if (wndPtr == WND_DESKTOP)
1927 /* can't change anything on the desktop window */
1928 SetLastError( ERROR_ACCESS_DENIED );
1931 if (wndPtr == WND_OTHER_PROCESS)
1933 if (offset == GWLP_WNDPROC)
1935 SetLastError( ERROR_ACCESS_DENIED );
1938 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1941 /* first some special cases */
1947 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1948 style.styleNew = newval;
1949 WIN_ReleasePtr( wndPtr );
1950 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1951 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1952 newval = style.styleNew;
1954 case GWLP_HWNDPARENT:
1955 if (wndPtr->parent == GetDesktopWindow())
1957 WIN_ReleasePtr( wndPtr );
1958 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1962 WIN_ReleasePtr( wndPtr );
1963 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1967 WINDOWPROCTYPE old_type = WINPROC_GetProcType( wndPtr->winproc );
1968 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type );
1969 wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, type );
1970 if (old_type == type)
1972 WIN_ReleasePtr( wndPtr );
1975 /* update is_unicode flag on the server side */
1979 case GWLP_HINSTANCE:
1983 if ((wndPtr->cbWndExtra + sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1985 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1986 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, type );
1987 *ptr = WINPROC_AllocProc( (WNDPROC)newval, type );
1988 WIN_ReleasePtr( wndPtr );
1993 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
1995 WARN("Invalid offset %d\n", offset );
1996 WIN_ReleasePtr( wndPtr );
1997 SetLastError( ERROR_INVALID_INDEX );
2002 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2003 if (*ptr == newval) /* already set to the same value */
2005 WIN_ReleasePtr( wndPtr );
2012 SERVER_START_REQ( set_window_info )
2015 req->extra_offset = -1;
2019 req->flags = SET_WIN_STYLE;
2020 req->style = newval;
2023 req->flags = SET_WIN_EXSTYLE;
2024 req->ex_style = newval;
2027 req->flags = SET_WIN_ID;
2030 case GWLP_HINSTANCE:
2031 req->flags = SET_WIN_INSTANCE;
2032 req->instance = (void *)newval;
2035 req->flags = SET_WIN_UNICODE;
2036 req->is_unicode = (type == WIN_PROC_32W);
2039 req->flags = SET_WIN_USERDATA;
2040 req->user_data = (void *)newval;
2043 req->flags = SET_WIN_EXTRA;
2044 req->extra_offset = offset;
2045 req->extra_size = sizeof(newval);
2046 memcpy( &req->extra_value, &newval, sizeof(newval) );
2048 if ((ok = !wine_server_call_err( req )))
2053 wndPtr->dwStyle = newval;
2054 retval = reply->old_style;
2057 wndPtr->dwExStyle = newval;
2058 retval = reply->old_ex_style;
2061 wndPtr->wIDmenu = newval;
2062 retval = reply->old_id;
2064 case GWLP_HINSTANCE:
2065 wndPtr->hInstance = (HINSTANCE)newval;
2066 retval = (ULONG_PTR)reply->old_instance;
2071 wndPtr->userdata = newval;
2072 retval = (ULONG_PTR)reply->old_user_data;
2076 void *ptr = (char *)wndPtr->wExtra + offset;
2077 memcpy( &retval, ptr, sizeof(retval) );
2078 memcpy( ptr, &newval, sizeof(newval) );
2085 WIN_ReleasePtr( wndPtr );
2089 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2091 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2092 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2098 /**********************************************************************
2099 * GetWindowLong (USER.135)
2101 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2103 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2107 /**********************************************************************
2108 * GetWindowLongA (USER32.@)
2110 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2112 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2116 /**********************************************************************
2117 * GetWindowLongW (USER32.@)
2119 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2121 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2125 /**********************************************************************
2126 * SetWindowLong (USER.136)
2128 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2130 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2134 /**********************************************************************
2135 * SetWindowLongA (USER32.@)
2137 * See SetWindowLongW.
2139 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2141 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2145 /**********************************************************************
2146 * SetWindowLongW (USER32.@) Set window attribute
2148 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2149 * value in a window's extra memory.
2151 * The _hwnd_ parameter specifies the window. is the handle to a
2152 * window that has extra memory. The _newval_ parameter contains the
2153 * new attribute or extra memory value. If positive, the _offset_
2154 * parameter is the byte-addressed location in the window's extra
2155 * memory to set. If negative, _offset_ specifies the window
2156 * attribute to set, and should be one of the following values:
2158 * GWL_EXSTYLE The window's extended window style
2160 * GWL_STYLE The window's window style.
2162 * GWLP_WNDPROC Pointer to the window's window procedure.
2164 * GWLP_HINSTANCE The window's pplication instance handle.
2166 * GWLP_ID The window's identifier.
2168 * GWLP_USERDATA The window's user-specified data.
2170 * If the window is a dialog box, the _offset_ parameter can be one of
2171 * the following values:
2173 * DWLP_DLGPROC The address of the window's dialog box procedure.
2175 * DWLP_MSGRESULT The return value of a message
2176 * that the dialog box procedure processed.
2178 * DWLP_USER Application specific information.
2182 * If successful, returns the previous value located at _offset_. Otherwise,
2187 * Extra memory for a window class is specified by a nonzero cbWndExtra
2188 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2189 * time of class creation.
2191 * Using GWL_WNDPROC to set a new window procedure effectively creates
2192 * a window subclass. Use CallWindowProc() in the new windows procedure
2193 * to pass messages to the superclass's window procedure.
2195 * The user data is reserved for use by the application which created
2198 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2199 * instead, call the EnableWindow() function to change the window's
2202 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2203 * SetParent() instead.
2206 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2207 * it sends WM_STYLECHANGING before changing the settings
2208 * and WM_STYLECHANGED afterwards.
2209 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2211 LONG WINAPI SetWindowLongW(
2212 HWND hwnd, /* [in] window to alter */
2213 INT offset, /* [in] offset, in bytes, of location to alter */
2214 LONG newval /* [in] new value of location */
2216 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2220 /*******************************************************************
2221 * GetWindowTextA (USER32.@)
2223 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2227 if (!lpString) return 0;
2229 if (WIN_IsCurrentProcess( hwnd ))
2230 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2232 /* when window belongs to other process, don't send a message */
2233 if (nMaxCount <= 0) return 0;
2234 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2235 get_server_window_text( hwnd, buffer, nMaxCount );
2236 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2237 lpString[nMaxCount-1] = 0;
2238 HeapFree( GetProcessHeap(), 0, buffer );
2239 return strlen(lpString);
2243 /*******************************************************************
2244 * InternalGetWindowText (USER32.@)
2246 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2250 if (nMaxCount <= 0) return 0;
2251 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2252 if (win == WND_DESKTOP) lpString[0] = 0;
2253 else if (win != WND_OTHER_PROCESS)
2255 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2256 else lpString[0] = 0;
2257 WIN_ReleasePtr( win );
2261 get_server_window_text( hwnd, lpString, nMaxCount );
2263 return strlenW(lpString);
2267 /*******************************************************************
2268 * GetWindowTextW (USER32.@)
2270 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2272 if (!lpString) return 0;
2274 if (WIN_IsCurrentProcess( hwnd ))
2275 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2277 /* when window belongs to other process, don't send a message */
2278 if (nMaxCount <= 0) return 0;
2279 get_server_window_text( hwnd, lpString, nMaxCount );
2280 return strlenW(lpString);
2284 /*******************************************************************
2285 * SetWindowTextA (USER32.@)
2286 * SetWindowText (USER32.@)
2288 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2290 if (is_broadcast(hwnd))
2292 SetLastError( ERROR_INVALID_PARAMETER );
2295 if (!WIN_IsCurrentProcess( hwnd ))
2296 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2297 debugstr_a(lpString), hwnd );
2298 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2302 /*******************************************************************
2303 * SetWindowTextW (USER32.@)
2305 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2307 if (is_broadcast(hwnd))
2309 SetLastError( ERROR_INVALID_PARAMETER );
2312 if (!WIN_IsCurrentProcess( hwnd ))
2313 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2314 debugstr_w(lpString), hwnd );
2315 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2319 /*******************************************************************
2320 * GetWindowTextLengthA (USER32.@)
2322 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2324 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2327 /*******************************************************************
2328 * GetWindowTextLengthW (USER32.@)
2330 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2332 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2336 /*******************************************************************
2337 * IsWindow (USER32.@)
2339 BOOL WINAPI IsWindow( HWND hwnd )
2344 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2345 if (ptr == WND_DESKTOP) return TRUE;
2347 if (ptr != WND_OTHER_PROCESS)
2349 WIN_ReleasePtr( ptr );
2353 /* check other processes */
2354 SERVER_START_REQ( get_window_info )
2357 ret = !wine_server_call_err( req );
2364 /***********************************************************************
2365 * GetWindowThreadProcessId (USER32.@)
2367 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2372 if (!(ptr = WIN_GetPtr( hwnd )))
2374 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2378 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2380 /* got a valid window */
2382 if (process) *process = GetCurrentProcessId();
2383 WIN_ReleasePtr( ptr );
2387 /* check other processes */
2388 SERVER_START_REQ( get_window_info )
2391 if (!wine_server_call_err( req ))
2393 tid = (DWORD)reply->tid;
2394 if (process) *process = (DWORD)reply->pid;
2402 /*****************************************************************
2403 * GetParent (USER32.@)
2405 HWND WINAPI GetParent( HWND hwnd )
2410 if (!(wndPtr = WIN_GetPtr( hwnd )))
2412 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2415 if (wndPtr == WND_DESKTOP) return 0;
2416 if (wndPtr == WND_OTHER_PROCESS)
2418 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2419 if (style & (WS_POPUP | WS_CHILD))
2421 SERVER_START_REQ( get_window_tree )
2424 if (!wine_server_call_err( req ))
2426 if (style & WS_POPUP) retvalue = reply->owner;
2427 else if (style & WS_CHILD) retvalue = reply->parent;
2435 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2436 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2437 WIN_ReleasePtr( wndPtr );
2443 /*****************************************************************
2444 * GetAncestor (USER32.@)
2446 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2449 HWND *list, ret = 0;
2454 if (!(win = WIN_GetPtr( hwnd )))
2456 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2459 if (win == WND_DESKTOP) return 0;
2460 if (win != WND_OTHER_PROCESS)
2463 WIN_ReleasePtr( win );
2465 else /* need to query the server */
2467 SERVER_START_REQ( get_window_tree )
2470 if (!wine_server_call_err( req )) ret = reply->parent;
2477 if (!(list = list_window_parents( hwnd ))) return 0;
2479 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2483 while (list[count]) count++;
2484 ret = list[count - 2]; /* get the one before the desktop */
2486 HeapFree( GetProcessHeap(), 0, list );
2490 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2493 HWND parent = GetParent( ret );
2503 /*****************************************************************
2504 * SetParent (USER32.@)
2506 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2510 if (is_broadcast(hwnd) || is_broadcast(parent))
2512 SetLastError(ERROR_INVALID_PARAMETER);
2516 if (!parent) parent = GetDesktopWindow();
2517 else parent = WIN_GetFullHandle( parent );
2519 if (!IsWindow( parent ))
2521 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2525 /* Some applications try to set a child as a parent */
2526 if (IsChild(hwnd, parent))
2528 SetLastError( ERROR_INVALID_PARAMETER );
2532 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2533 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2535 return USER_Driver->pSetParent( full_handle, parent );
2539 /*******************************************************************
2540 * IsChild (USER32.@)
2542 BOOL WINAPI IsChild( HWND parent, HWND child )
2544 HWND *list = list_window_parents( child );
2548 if (!list) return FALSE;
2549 parent = WIN_GetFullHandle( parent );
2550 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2551 ret = (list[i] != 0);
2552 HeapFree( GetProcessHeap(), 0, list );
2557 /***********************************************************************
2558 * IsWindowVisible (USER32.@)
2560 BOOL WINAPI IsWindowVisible( HWND hwnd )
2566 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2567 if (!(list = list_window_parents( hwnd ))) return TRUE;
2568 for (i = 0; list[i]; i++)
2569 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2571 HeapFree( GetProcessHeap(), 0, list );
2576 /***********************************************************************
2577 * WIN_IsWindowDrawable
2579 * hwnd is drawable when it is visible, all parents are not
2580 * minimized, and it is itself not minimized unless we are
2581 * trying to draw its default class icon.
2583 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2588 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2590 if (!(style & WS_VISIBLE)) return FALSE;
2591 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2593 if (!(list = list_window_parents( hwnd ))) return TRUE;
2594 for (i = 0; list[i]; i++)
2595 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2598 HeapFree( GetProcessHeap(), 0, list );
2603 /*******************************************************************
2604 * GetTopWindow (USER32.@)
2606 HWND WINAPI GetTopWindow( HWND hwnd )
2608 if (!hwnd) hwnd = GetDesktopWindow();
2609 return GetWindow( hwnd, GW_CHILD );
2613 /*******************************************************************
2614 * GetWindow (USER32.@)
2616 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2620 if (rel == GW_OWNER) /* this one may be available locally */
2622 WND *wndPtr = WIN_GetPtr( hwnd );
2625 SetLastError( ERROR_INVALID_HANDLE );
2628 if (wndPtr == WND_DESKTOP) return 0;
2629 if (wndPtr != WND_OTHER_PROCESS)
2631 retval = wndPtr->owner;
2632 WIN_ReleasePtr( wndPtr );
2635 /* else fall through to server call */
2638 SERVER_START_REQ( get_window_tree )
2641 if (!wine_server_call_err( req ))
2646 retval = reply->first_sibling;
2649 retval = reply->last_sibling;
2652 retval = reply->next_sibling;
2655 retval = reply->prev_sibling;
2658 retval = reply->owner;
2661 retval = reply->first_child;
2671 /*******************************************************************
2672 * ShowOwnedPopups (USER32.@)
2674 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2678 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2680 if (!win_array) return TRUE;
2682 while (win_array[count]) count++;
2683 while (--count >= 0)
2685 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2686 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2687 if (pWnd == WND_OTHER_PROCESS) continue;
2690 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2692 WIN_ReleasePtr( pWnd );
2693 /* In Windows, ShowOwnedPopups(TRUE) generates
2694 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2695 * regardless of the state of the owner
2697 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2703 if (pWnd->dwStyle & WS_VISIBLE)
2705 WIN_ReleasePtr( pWnd );
2706 /* In Windows, ShowOwnedPopups(FALSE) generates
2707 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2708 * regardless of the state of the owner
2710 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2714 WIN_ReleasePtr( pWnd );
2716 HeapFree( GetProcessHeap(), 0, win_array );
2721 /*******************************************************************
2722 * GetLastActivePopup (USER32.@)
2724 HWND WINAPI GetLastActivePopup( HWND hwnd )
2728 SERVER_START_REQ( get_window_info )
2731 if (!wine_server_call_err( req )) retval = reply->last_active;
2738 /*******************************************************************
2741 * Build an array of the children of a given window. The array must be
2742 * freed with HeapFree. Returns NULL when no windows are found.
2744 HWND *WIN_ListChildren( HWND hwnd )
2746 return list_window_children( hwnd, 0, 0 );
2750 /*******************************************************************
2751 * EnumWindows (USER32.@)
2753 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2759 USER_CheckNotLock();
2761 /* We have to build a list of all windows first, to avoid */
2762 /* unpleasant side-effects, for instance if the callback */
2763 /* function changes the Z-order of the windows. */
2765 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2767 /* Now call the callback function for every window */
2769 for (i = 0; list[i]; i++)
2771 /* Make sure that the window still exists */
2772 if (!IsWindow( list[i] )) continue;
2773 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2775 HeapFree( GetProcessHeap(), 0, list );
2780 /**********************************************************************
2781 * EnumThreadWindows (USER32.@)
2783 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2788 USER_CheckNotLock();
2790 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2792 /* Now call the callback function for every window */
2794 for (i = 0; list[i]; i++)
2795 if (!func( list[i], lParam )) break;
2796 HeapFree( GetProcessHeap(), 0, list );
2801 /**********************************************************************
2802 * WIN_EnumChildWindows
2804 * Helper function for EnumChildWindows().
2806 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2811 for ( ; *list; list++)
2813 /* Make sure that the window still exists */
2814 if (!IsWindow( *list )) continue;
2815 /* Build children list first */
2816 childList = WIN_ListChildren( *list );
2818 ret = func( *list, lParam );
2822 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2823 HeapFree( GetProcessHeap(), 0, childList );
2825 if (!ret) return FALSE;
2831 /**********************************************************************
2832 * EnumChildWindows (USER32.@)
2834 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2839 USER_CheckNotLock();
2841 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2842 ret = WIN_EnumChildWindows( list, func, lParam );
2843 HeapFree( GetProcessHeap(), 0, list );
2848 /*******************************************************************
2849 * AnyPopup (USER.52)
2851 BOOL16 WINAPI AnyPopup16(void)
2857 /*******************************************************************
2858 * AnyPopup (USER32.@)
2860 BOOL WINAPI AnyPopup(void)
2864 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2866 if (!list) return FALSE;
2867 for (i = 0; list[i]; i++)
2869 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2871 retvalue = (list[i] != 0);
2872 HeapFree( GetProcessHeap(), 0, list );
2877 /*******************************************************************
2878 * FlashWindow (USER32.@)
2880 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2884 TRACE("%p\n", hWnd);
2886 if (IsIconic( hWnd ))
2888 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2890 wndPtr = WIN_GetPtr(hWnd);
2891 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2892 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2894 wndPtr->flags |= WIN_NCACTIVATED;
2898 wndPtr->flags &= ~WIN_NCACTIVATED;
2900 WIN_ReleasePtr( wndPtr );
2907 wndPtr = WIN_GetPtr(hWnd);
2908 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2909 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2911 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2912 else wparam = (hWnd == GetForegroundWindow());
2914 WIN_ReleasePtr( wndPtr );
2915 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2920 /*******************************************************************
2921 * FlashWindowEx (USER32.@)
2923 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
2925 FIXME("%p\n", pfwi);
2929 /*******************************************************************
2930 * GetWindowContextHelpId (USER32.@)
2932 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2935 WND *wnd = WIN_GetPtr( hwnd );
2936 if (!wnd || wnd == WND_DESKTOP) return 0;
2937 if (wnd == WND_OTHER_PROCESS)
2939 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2942 retval = wnd->helpContext;
2943 WIN_ReleasePtr( wnd );
2948 /*******************************************************************
2949 * SetWindowContextHelpId (USER32.@)
2951 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2953 WND *wnd = WIN_GetPtr( hwnd );
2954 if (!wnd || wnd == WND_DESKTOP) return FALSE;
2955 if (wnd == WND_OTHER_PROCESS)
2957 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2960 wnd->helpContext = id;
2961 WIN_ReleasePtr( wnd );
2966 /*******************************************************************
2967 * DragDetect (USER32.@)
2969 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2973 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
2974 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
2976 rect.left = pt.x - wDragWidth;
2977 rect.right = pt.x + wDragWidth;
2979 rect.top = pt.y - wDragHeight;
2980 rect.bottom = pt.y + wDragHeight;
2986 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
2988 if( msg.message == WM_LBUTTONUP )
2993 if( msg.message == WM_MOUSEMOVE )
2996 tmp.x = LOWORD(msg.lParam);
2997 tmp.y = HIWORD(msg.lParam);
2998 if( !PtInRect( &rect, tmp ))
3010 /******************************************************************************
3011 * GetWindowModuleFileNameA (USER32.@)
3013 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3015 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3016 hwnd, lpszFileName, cchFileNameMax);
3020 /******************************************************************************
3021 * GetWindowModuleFileNameW (USER32.@)
3023 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3025 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3026 hwnd, lpszFileName, cchFileNameMax);
3030 /******************************************************************************
3031 * GetWindowInfo (USER32.@)
3033 * Note: tests show that Windows doesn't check cbSize of the structure.
3035 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3037 if (!pwi) return FALSE;
3038 if (!IsWindow(hwnd)) return FALSE;
3040 GetWindowRect(hwnd, &pwi->rcWindow);
3041 GetClientRect(hwnd, &pwi->rcClient);
3042 /* translate to screen coordinates */
3043 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3045 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3046 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3047 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3049 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3050 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3052 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3053 pwi->wCreatorVersion = 0x0400;
3058 /******************************************************************************
3059 * SwitchDesktop (USER32.@)
3061 * NOTES: Sets the current input or interactive desktop.
3063 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3065 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3069 /*****************************************************************************
3070 * SetLayeredWindowAttributes (USER32.@)
3072 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3073 BYTE bAlpha, DWORD dwFlags )
3075 FIXME("(%p,0x%.8lx,%d,%ld): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3079 /*****************************************************************************
3080 * UpdateLayeredWindow (USER32.@)
3082 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3083 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3086 FIXME("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%ld): stub!\n",
3087 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);