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_GROUP) TRACE(" WS_GROUP");
743 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
744 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
745 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
747 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
748 #define DUMPED_STYLES \
768 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
773 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
774 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
775 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
776 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
777 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
778 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
779 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
780 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
781 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
782 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
783 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
784 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
785 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
786 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
787 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
788 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
789 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
790 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
792 #define DUMPED_EX_STYLES \
793 (WS_EX_DLGMODALFRAME | \
795 WS_EX_NOPARENTNOTIFY | \
797 WS_EX_ACCEPTFILES | \
798 WS_EX_TRANSPARENT | \
803 WS_EX_CONTEXTHELP | \
806 WS_EX_LEFTSCROLLBAR | \
807 WS_EX_CONTROLPARENT | \
812 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
814 #undef DUMPED_EX_STYLES
818 /***********************************************************************
821 * Implementation of CreateWindowEx().
823 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
824 WINDOWPROCTYPE type )
828 HWND hwnd, parent, owner, top_child = 0;
829 BOOL unicode = (type == WIN_PROC_32W);
831 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
832 (type == WIN_PROC_32W) ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
833 (type == WIN_PROC_32W) ? debugstr_w((LPCWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
834 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
835 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
837 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
839 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
840 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
842 /* Fix the styles for MDI children */
843 if (cs->dwExStyle & WS_EX_MDICHILD)
845 MDICREATESTRUCTA mdi_cs;
848 wndPtr = WIN_GetPtr(cs->hwndParent);
849 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
851 flags = wndPtr->flags;
852 WIN_ReleasePtr(wndPtr);
855 if (!(flags & WIN_ISMDICLIENT))
857 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
861 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
862 * MDICREATESTRUCT members have the originally passed values.
864 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
865 * have the same layout.
867 mdi_cs.szClass = cs->lpszClass;
868 mdi_cs.szTitle = cs->lpszName;
869 mdi_cs.hOwner = cs->hInstance;
874 mdi_cs.style = cs->style;
875 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
877 cs->lpCreateParams = (LPVOID)&mdi_cs;
879 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
881 if (cs->style & WS_POPUP)
883 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
886 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
890 cs->style &= ~WS_POPUP;
891 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
892 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
895 top_child = GetWindow(cs->hwndParent, GW_CHILD);
899 /* Restore current maximized child */
900 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
902 TRACE("Restoring current maximized child %p\n", top_child);
903 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
904 ShowWindow(top_child, SW_RESTORE);
905 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
910 /* Find the parent window */
912 parent = GetDesktopWindow();
915 if (cs->hwndParent == HWND_MESSAGE)
917 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
918 * message window (style: WS_POPUP|WS_DISABLED)
920 FIXME("Parent is HWND_MESSAGE\n");
922 else if (cs->hwndParent)
924 /* Make sure parent is valid */
925 if (!IsWindow( cs->hwndParent ))
927 WARN("Bad parent %p\n", cs->hwndParent );
930 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
931 parent = WIN_GetFullHandle(cs->hwndParent);
933 owner = GetAncestor( cs->hwndParent, GA_ROOT );
935 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
937 WARN("No parent for child window\n" );
938 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
941 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
943 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
944 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
945 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
946 cs->dwExStyle |= WS_EX_WINDOWEDGE;
948 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
950 /* Create the window structure */
952 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
954 TRACE("out of memory\n" );
957 hwnd = wndPtr->hwndSelf;
959 /* Fill the window structure */
961 wndPtr->tid = GetCurrentThreadId();
962 wndPtr->owner = owner;
963 wndPtr->parent = parent;
964 wndPtr->hInstance = cs->hInstance;
966 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
967 wndPtr->dwExStyle = cs->dwExStyle;
969 wndPtr->helpContext = 0;
970 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
971 wndPtr->pVScroll = NULL;
972 wndPtr->pHScroll = NULL;
973 wndPtr->userdata = 0;
975 wndPtr->hIconSmall = 0;
976 wndPtr->hSysMenu = 0;
978 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
981 * Correct the window styles.
983 * It affects only the style loaded into the WIN structure.
986 if (!(wndPtr->dwStyle & WS_CHILD))
988 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
989 if (!(wndPtr->dwStyle & WS_POPUP))
990 wndPtr->dwStyle |= WS_CAPTION;
994 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
995 * why does the user get to set it?
998 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
999 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1000 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1002 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1004 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1005 wndPtr->flags |= WIN_NEED_SIZE;
1007 SERVER_START_REQ( set_window_info )
1010 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1011 req->style = wndPtr->dwStyle;
1012 req->ex_style = wndPtr->dwExStyle;
1013 req->instance = (void *)wndPtr->hInstance;
1014 req->is_unicode = (type == WIN_PROC_32W);
1015 req->extra_offset = -1;
1016 wine_server_call( req );
1020 /* Set the window menu */
1022 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1023 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1027 if (!MENU_SetMenu(hwnd, cs->hMenu))
1029 WIN_ReleasePtr( wndPtr );
1030 free_window_handle( hwnd );
1036 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1039 if (!cs->hInstance || HIWORD(cs->hInstance))
1040 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1042 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1044 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1048 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1049 WIN_ReleasePtr( wndPtr );
1051 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1053 WIN_DestroyWindow( hwnd );
1057 /* Notify the parent window only */
1059 send_parent_notify( hwnd, WM_CREATE );
1060 if (!IsWindow( hwnd )) return 0;
1062 if (cs->style & WS_VISIBLE)
1064 if (cs->style & WS_MAXIMIZE)
1065 sw = SW_SHOWMAXIMIZED;
1066 else if (cs->style & WS_MINIMIZE)
1067 sw = SW_SHOWMINIMIZED;
1069 ShowWindow( hwnd, sw );
1070 if (cs->dwExStyle & WS_EX_MDICHILD)
1072 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1073 /* ShowWindow won't activate child windows */
1074 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1078 /* Call WH_SHELL hook */
1080 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1081 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1083 TRACE("created window %p\n", hwnd);
1088 /***********************************************************************
1089 * CreateWindow (USER.41)
1091 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1092 DWORD style, INT16 x, INT16 y, INT16 width,
1093 INT16 height, HWND16 parent, HMENU16 menu,
1094 HINSTANCE16 instance, LPVOID data )
1096 return CreateWindowEx16( 0, className, windowName, style,
1097 x, y, width, height, parent, menu, instance, data );
1101 /***********************************************************************
1102 * CreateWindowEx (USER.452)
1104 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1105 LPCSTR windowName, DWORD style, INT16 x,
1106 INT16 y, INT16 width, INT16 height,
1107 HWND16 parent, HMENU16 menu,
1108 HINSTANCE16 instance, LPVOID data )
1114 /* Find the class atom */
1116 if (HIWORD(className))
1118 if (!(classAtom = GlobalFindAtomA( className )))
1120 ERR( "bad class name %s\n", debugstr_a(className) );
1126 classAtom = LOWORD(className);
1127 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1129 ERR( "bad atom %x\n", classAtom);
1135 /* Fix the coordinates */
1137 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1138 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1139 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1140 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1142 /* Create the window */
1144 cs.lpCreateParams = data;
1145 cs.hInstance = HINSTANCE_32(instance);
1146 cs.hMenu = HMENU_32(menu);
1147 cs.hwndParent = WIN_Handle32( parent );
1149 cs.lpszName = windowName;
1150 cs.lpszClass = className;
1151 cs.dwExStyle = exStyle;
1153 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1157 /***********************************************************************
1158 * CreateWindowExA (USER32.@)
1160 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1161 LPCSTR windowName, DWORD style, INT x,
1162 INT y, INT width, INT height,
1163 HWND parent, HMENU menu,
1164 HINSTANCE instance, LPVOID data )
1170 /* Find the class atom */
1172 if (HIWORD(className))
1174 if (!(classAtom = GlobalFindAtomA( className )))
1176 ERR( "bad class name %s\n", debugstr_a(className) );
1182 classAtom = LOWORD(className);
1183 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1185 ERR( "bad atom %x\n", classAtom);
1191 /* Create the window */
1193 cs.lpCreateParams = data;
1194 cs.hInstance = instance;
1196 cs.hwndParent = parent;
1202 cs.lpszName = windowName;
1203 cs.lpszClass = className;
1204 cs.dwExStyle = exStyle;
1206 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1210 /***********************************************************************
1211 * CreateWindowExW (USER32.@)
1213 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1214 LPCWSTR windowName, DWORD style, INT x,
1215 INT y, INT width, INT height,
1216 HWND parent, HMENU menu,
1217 HINSTANCE instance, LPVOID data )
1223 /* Find the class atom */
1225 if (HIWORD(className))
1227 if (!(classAtom = GlobalFindAtomW( className )))
1229 ERR( "bad class name %s\n", debugstr_w(className) );
1235 classAtom = LOWORD(className);
1236 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1238 ERR( "bad atom %x\n", classAtom);
1244 /* Create the window */
1246 cs.lpCreateParams = data;
1247 cs.hInstance = instance;
1249 cs.hwndParent = parent;
1255 cs.lpszName = windowName;
1256 cs.lpszClass = className;
1257 cs.dwExStyle = exStyle;
1259 /* Note: we rely on the fact that CREATESTRUCTA and */
1260 /* CREATESTRUCTW have the same layout. */
1261 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1265 /***********************************************************************
1266 * WIN_SendDestroyMsg
1268 static void WIN_SendDestroyMsg( HWND hwnd )
1272 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1274 if (hwnd == info.hwndCaret) DestroyCaret();
1275 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1277 USER_Driver->pResetSelectionOwner( hwnd, TRUE );
1280 * Send the WM_DESTROY to the window.
1282 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1285 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1286 * make sure that the window still exists when we come back.
1293 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1295 for (i = 0; pWndArray[i]; i++)
1297 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1299 HeapFree( GetProcessHeap(), 0, pWndArray );
1302 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1306 /***********************************************************************
1307 * DestroyWindow (USER32.@)
1309 BOOL WINAPI DestroyWindow( HWND hwnd )
1313 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1315 SetLastError( ERROR_ACCESS_DENIED );
1319 TRACE("(%p)\n", hwnd);
1323 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1325 if (MENU_IsMenuActive() == hwnd)
1328 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1332 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1333 send_parent_notify( hwnd, WM_DESTROY );
1335 else if (!GetWindow( hwnd, GW_OWNER ))
1337 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1338 /* FIXME: clean up palette - see "Internals" p.352 */
1341 if (!IsWindow(hwnd)) return TRUE;
1343 USER_Driver->pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1345 /* Hide the window */
1346 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1348 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1350 ShowWindow( hwnd, SW_HIDE );
1352 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1353 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1356 if (!IsWindow(hwnd)) return TRUE;
1358 /* Recursively destroy owned windows */
1365 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1368 for (i = 0; list[i]; i++)
1370 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1371 if (WIN_IsCurrentThread( list[i] ))
1373 DestroyWindow( list[i] );
1377 WIN_SetOwner( list[i], 0 );
1379 HeapFree( GetProcessHeap(), 0, list );
1381 if (!got_one) break;
1385 /* Send destroy messages */
1387 WIN_SendDestroyMsg( hwnd );
1388 if (!IsWindow( hwnd )) return TRUE;
1390 if (GetClipboardOwner() == hwnd)
1391 CLIPBOARD_ReleaseOwner();
1393 /* Destroy the window storage */
1395 WIN_DestroyWindow( hwnd );
1400 /***********************************************************************
1401 * CloseWindow (USER32.@)
1403 BOOL WINAPI CloseWindow( HWND hwnd )
1405 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1406 ShowWindow( hwnd, SW_MINIMIZE );
1411 /***********************************************************************
1412 * OpenIcon (USER32.@)
1414 BOOL WINAPI OpenIcon( HWND hwnd )
1416 if (!IsIconic( hwnd )) return FALSE;
1417 ShowWindow( hwnd, SW_SHOWNORMAL );
1422 /***********************************************************************
1425 * Implementation of FindWindow() and FindWindowEx().
1427 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1432 WCHAR *buffer = NULL;
1434 if (!parent) parent = GetDesktopWindow();
1437 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1438 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1441 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1445 child = WIN_GetFullHandle( child );
1446 while (list[i] && list[i] != child) i++;
1447 if (!list[i]) goto done;
1448 i++; /* start from next window */
1455 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1462 HeapFree( GetProcessHeap(), 0, list );
1463 HeapFree( GetProcessHeap(), 0, buffer );
1469 /***********************************************************************
1470 * FindWindowA (USER32.@)
1472 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1474 HWND ret = FindWindowExA( 0, 0, className, title );
1475 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1480 /***********************************************************************
1481 * FindWindowExA (USER32.@)
1483 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1484 LPCSTR className, LPCSTR title )
1493 /* If the atom doesn't exist, then no class */
1494 /* with this name exists either. */
1495 if (!(atom = GlobalFindAtomA( className )))
1497 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1501 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1503 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1504 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1505 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1506 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1507 HeapFree( GetProcessHeap(), 0, buffer );
1512 /***********************************************************************
1513 * FindWindowExW (USER32.@)
1515 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1516 LPCWSTR className, LPCWSTR title )
1522 /* If the atom doesn't exist, then no class */
1523 /* with this name exists either. */
1524 if (!(atom = GlobalFindAtomW( className )))
1526 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1530 return WIN_FindWindow( parent, child, atom, title );
1534 /***********************************************************************
1535 * FindWindowW (USER32.@)
1537 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1539 return FindWindowExW( 0, 0, className, title );
1543 /**********************************************************************
1544 * GetDesktopWindow (USER32.@)
1546 HWND WINAPI GetDesktopWindow(void)
1548 struct user_thread_info *thread_info = get_user_thread_info();
1550 if (!thread_info->desktop)
1552 SERVER_START_REQ( get_desktop_window )
1554 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1557 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1558 ERR( "failed to create desktop window\n" );
1560 return thread_info->desktop;
1564 /*******************************************************************
1565 * EnableWindow (USER32.@)
1567 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1572 if (is_broadcast(hwnd))
1574 SetLastError( ERROR_INVALID_PARAMETER );
1578 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1579 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1583 TRACE("( %p, %d )\n", hwnd, enable);
1585 retvalue = !IsWindowEnabled( hwnd );
1587 if (enable && retvalue)
1589 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1590 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1592 else if (!enable && !retvalue)
1596 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1598 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1600 if (hwnd == GetFocus())
1601 SetFocus( 0 ); /* A disabled window can't have the focus */
1603 capture_wnd = GetCapture();
1604 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1605 ReleaseCapture(); /* A disabled window can't capture the mouse */
1607 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1613 /***********************************************************************
1614 * IsWindowEnabled (USER32.@)
1616 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1618 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1622 /***********************************************************************
1623 * IsWindowUnicode (USER32.@)
1625 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1628 BOOL retvalue = FALSE;
1630 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1632 if (wndPtr == WND_DESKTOP) return TRUE;
1634 if (wndPtr != WND_OTHER_PROCESS)
1636 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1637 WIN_ReleasePtr( wndPtr );
1641 SERVER_START_REQ( get_window_info )
1644 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1652 /**********************************************************************
1653 * GetWindowWord (USER32.@)
1655 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1660 WND *wndPtr = WIN_GetPtr( hwnd );
1663 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1666 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1668 SERVER_START_REQ( set_window_info )
1671 req->flags = 0; /* don't set anything, just retrieve */
1672 req->extra_offset = offset;
1673 req->extra_size = sizeof(retvalue);
1674 if (!wine_server_call_err( req ))
1675 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1680 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1682 WARN("Invalid offset %d\n", offset );
1683 SetLastError( ERROR_INVALID_INDEX );
1685 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1686 WIN_ReleasePtr( wndPtr );
1692 case GWLP_HWNDPARENT:
1693 return GetWindowLongPtrW( hwnd, offset );
1695 case GWLP_HINSTANCE:
1697 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1699 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1703 WARN("Invalid offset %d\n", offset );
1709 /**********************************************************************
1710 * SetWindowWord (USER32.@)
1712 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1720 case GWLP_HINSTANCE:
1721 case GWLP_HWNDPARENT:
1722 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1726 WARN("Invalid offset %d\n", offset );
1727 SetLastError( ERROR_INVALID_INDEX );
1732 wndPtr = WIN_GetPtr( hwnd );
1733 if (wndPtr == WND_DESKTOP)
1735 SetLastError( ERROR_ACCESS_DENIED );
1738 if (wndPtr == WND_OTHER_PROCESS)
1741 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1742 offset, newval, hwnd );
1747 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1751 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1753 WARN("Invalid offset %d\n", offset );
1754 WIN_ReleasePtr(wndPtr);
1755 SetLastError( ERROR_INVALID_INDEX );
1759 SERVER_START_REQ( set_window_info )
1762 req->flags = SET_WIN_EXTRA;
1763 req->extra_offset = offset;
1764 req->extra_size = sizeof(newval);
1765 memcpy( &req->extra_value, &newval, sizeof(newval) );
1766 if (!wine_server_call_err( req ))
1768 void *ptr = (char *)wndPtr->wExtra + offset;
1769 memcpy( &retval, ptr, sizeof(retval) );
1770 memcpy( ptr, &newval, sizeof(newval) );
1774 WIN_ReleasePtr( wndPtr );
1779 /**********************************************************************
1782 * Helper function for GetWindowLong().
1784 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1786 LONG_PTR retvalue = 0;
1789 if (offset == GWLP_HWNDPARENT)
1791 HWND parent = GetAncestor( hwnd, GA_PARENT );
1792 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1793 return (ULONG_PTR)parent;
1796 if (!(wndPtr = WIN_GetPtr( hwnd )))
1798 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1802 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1804 if (offset == GWLP_WNDPROC)
1806 SetLastError( ERROR_ACCESS_DENIED );
1809 SERVER_START_REQ( set_window_info )
1812 req->flags = 0; /* don't set anything, just retrieve */
1813 req->extra_offset = (offset >= 0) ? offset : -1;
1814 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1815 if (!wine_server_call_err( req ))
1819 case GWL_STYLE: retvalue = reply->old_style; break;
1820 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1821 case GWLP_ID: retvalue = reply->old_id; break;
1822 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1823 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1825 if (offset >= 0) retvalue = reply->old_extra_value;
1826 else SetLastError( ERROR_INVALID_INDEX );
1835 /* now we have a valid wndPtr */
1839 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1842 * Some programs try to access last element from 16 bit
1843 * code using illegal offset value. Hopefully this is
1844 * what those programs really expect.
1846 if (type == WIN_PROC_16 &&
1847 wndPtr->cbWndExtra >= 4 &&
1848 offset == wndPtr->cbWndExtra - sizeof(WORD))
1850 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1852 ERR( "- replaced invalid offset %d with %d\n",
1855 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset2);
1856 WIN_ReleasePtr( wndPtr );
1859 WARN("Invalid offset %d\n", offset );
1860 WIN_ReleasePtr( wndPtr );
1861 SetLastError( ERROR_INVALID_INDEX );
1864 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
1865 /* Special case for dialog window procedure */
1866 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1867 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, type );
1868 WIN_ReleasePtr( wndPtr );
1874 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1875 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1876 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1877 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1878 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type ); break;
1879 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1881 WARN("Unknown offset %d\n", offset );
1882 SetLastError( ERROR_INVALID_INDEX );
1885 WIN_ReleasePtr(wndPtr);
1890 /**********************************************************************
1893 * Helper function for SetWindowLong().
1895 * 0 is the failure code. However, in the case of failure SetLastError
1896 * must be set to distinguish between a 0 return value and a failure.
1898 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval,
1899 WINDOWPROCTYPE type )
1903 LONG_PTR retval = 0;
1906 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1908 if (is_broadcast(hwnd))
1910 SetLastError( ERROR_INVALID_PARAMETER );
1914 if (!(wndPtr = WIN_GetPtr( hwnd )))
1916 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1919 if (wndPtr == WND_DESKTOP)
1921 /* can't change anything on the desktop window */
1922 SetLastError( ERROR_ACCESS_DENIED );
1925 if (wndPtr == WND_OTHER_PROCESS)
1927 if (offset == GWLP_WNDPROC)
1929 SetLastError( ERROR_ACCESS_DENIED );
1932 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1935 /* first some special cases */
1941 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1942 style.styleNew = newval;
1943 WIN_ReleasePtr( wndPtr );
1944 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1945 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1946 newval = style.styleNew;
1948 case GWLP_HWNDPARENT:
1949 if (wndPtr->parent == GetDesktopWindow())
1951 WIN_ReleasePtr( wndPtr );
1952 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1956 WIN_ReleasePtr( wndPtr );
1957 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1961 WINDOWPROCTYPE old_type = WINPROC_GetProcType( wndPtr->winproc );
1962 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type );
1963 wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, type );
1964 if (old_type == type)
1966 WIN_ReleasePtr( wndPtr );
1969 /* update is_unicode flag on the server side */
1973 case GWLP_HINSTANCE:
1977 if ((wndPtr->cbWndExtra + sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1979 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1980 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, type );
1981 *ptr = WINPROC_AllocProc( (WNDPROC)newval, type );
1982 WIN_ReleasePtr( wndPtr );
1987 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
1989 WARN("Invalid offset %d\n", offset );
1990 WIN_ReleasePtr( wndPtr );
1991 SetLastError( ERROR_INVALID_INDEX );
1996 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
1997 if (*ptr == newval) /* already set to the same value */
1999 WIN_ReleasePtr( wndPtr );
2006 SERVER_START_REQ( set_window_info )
2009 req->extra_offset = -1;
2013 req->flags = SET_WIN_STYLE;
2014 req->style = newval;
2017 req->flags = SET_WIN_EXSTYLE;
2018 req->ex_style = newval;
2021 req->flags = SET_WIN_ID;
2024 case GWLP_HINSTANCE:
2025 req->flags = SET_WIN_INSTANCE;
2026 req->instance = (void *)newval;
2029 req->flags = SET_WIN_UNICODE;
2030 req->is_unicode = (type == WIN_PROC_32W);
2033 req->flags = SET_WIN_USERDATA;
2034 req->user_data = (void *)newval;
2037 req->flags = SET_WIN_EXTRA;
2038 req->extra_offset = offset;
2039 req->extra_size = sizeof(newval);
2040 memcpy( &req->extra_value, &newval, sizeof(newval) );
2042 if ((ok = !wine_server_call_err( req )))
2047 wndPtr->dwStyle = newval;
2048 retval = reply->old_style;
2051 wndPtr->dwExStyle = newval;
2052 retval = reply->old_ex_style;
2055 wndPtr->wIDmenu = newval;
2056 retval = reply->old_id;
2058 case GWLP_HINSTANCE:
2059 wndPtr->hInstance = (HINSTANCE)newval;
2060 retval = (ULONG_PTR)reply->old_instance;
2065 wndPtr->userdata = newval;
2066 retval = (ULONG_PTR)reply->old_user_data;
2070 void *ptr = (char *)wndPtr->wExtra + offset;
2071 memcpy( &retval, ptr, sizeof(retval) );
2072 memcpy( ptr, &newval, sizeof(newval) );
2079 WIN_ReleasePtr( wndPtr );
2083 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2085 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2086 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2092 /**********************************************************************
2093 * GetWindowLong (USER.135)
2095 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2097 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2101 /**********************************************************************
2102 * GetWindowLongA (USER32.@)
2104 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2106 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2110 /**********************************************************************
2111 * GetWindowLongW (USER32.@)
2113 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2115 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2119 /**********************************************************************
2120 * SetWindowLong (USER.136)
2122 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2124 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2128 /**********************************************************************
2129 * SetWindowLongA (USER32.@)
2131 * See SetWindowLongW.
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 * SetWindowTextA (USER32.@)
2280 * SetWindowText (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 )
2968 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
2969 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
2971 rect.left = pt.x - wDragWidth;
2972 rect.right = pt.x + wDragWidth;
2974 rect.top = pt.y - wDragHeight;
2975 rect.bottom = pt.y + wDragHeight;
2981 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
2983 if( msg.message == WM_LBUTTONUP )
2988 if( msg.message == WM_MOUSEMOVE )
2991 tmp.x = LOWORD(msg.lParam);
2992 tmp.y = HIWORD(msg.lParam);
2993 if( !PtInRect( &rect, tmp ))
3005 /******************************************************************************
3006 * GetWindowModuleFileNameA (USER32.@)
3008 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3010 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3011 hwnd, lpszFileName, cchFileNameMax);
3015 /******************************************************************************
3016 * GetWindowModuleFileNameW (USER32.@)
3018 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3020 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3021 hwnd, lpszFileName, cchFileNameMax);
3025 /******************************************************************************
3026 * GetWindowInfo (USER32.@)
3028 * Note: tests show that Windows doesn't check cbSize of the structure.
3030 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3032 if (!pwi) return FALSE;
3033 if (!IsWindow(hwnd)) return FALSE;
3035 GetWindowRect(hwnd, &pwi->rcWindow);
3036 GetClientRect(hwnd, &pwi->rcClient);
3037 /* translate to screen coordinates */
3038 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3040 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3041 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3042 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3044 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3045 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3047 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3048 pwi->wCreatorVersion = 0x0400;
3053 /******************************************************************************
3054 * SwitchDesktop (USER32.@)
3056 * NOTES: Sets the current input or interactive desktop.
3058 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3060 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3064 /*****************************************************************************
3065 * SetLayeredWindowAttributes (USER32.@)
3067 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3068 BYTE bAlpha, DWORD dwFlags )
3070 FIXME("(%p,0x%.8lx,%d,%ld): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);