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"
38 #include "cursoricon.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(win);
44 WINE_DECLARE_DEBUG_CHANNEL(msg);
46 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
47 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
49 /**********************************************************************/
52 static HWND hwndDesktop;
54 static WORD wDragWidth = 4;
55 static WORD wDragHeight= 3;
57 static void *user_handles[NB_USER_HANDLES];
59 /***********************************************************************
60 * create_window_handle
62 * Create a window handle with the server.
64 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
65 HINSTANCE instance, WINDOWPROCTYPE type )
69 struct tagCLASS *class = NULL;
70 user_handle_t handle = 0;
73 /* if 16-bit instance, map to module handle */
74 if (instance && !HIWORD(instance))
75 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
77 SERVER_START_REQ( create_window )
82 req->instance = instance;
83 if (!wine_server_call_err( req ))
85 handle = reply->handle;
86 extra_bytes = reply->extra;
87 class = reply->class_ptr;
94 WARN( "error %ld creating window\n", GetLastError() );
98 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
100 SERVER_START_REQ( destroy_window )
102 req->handle = handle;
103 wine_server_call( req );
106 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
112 index = USER_HANDLE_TO_INDEX(handle);
113 assert( index < NB_USER_HANDLES );
114 user_handles[index] = win;
115 win->hwndSelf = handle;
116 win->dwMagic = WND_MAGIC;
117 win->cbWndExtra = extra_bytes;
118 memset( win->wExtra, 0, extra_bytes );
119 CLASS_AddWindow( class, win, type );
124 /***********************************************************************
127 * Free a window handle.
129 static WND *free_window_handle( HWND hwnd )
132 WORD index = USER_HANDLE_TO_INDEX(hwnd);
134 if (index >= NB_USER_HANDLES) return NULL;
136 if ((ptr = user_handles[index]))
138 SERVER_START_REQ( destroy_window )
141 if (!wine_server_call_err( req ))
142 user_handles[index] = NULL;
150 HeapFree( GetProcessHeap(), 0, ptr );
155 /*******************************************************************
156 * list_window_children
158 * Build an array of the children of a given window. The array must be
159 * freed with HeapFree. Returns NULL when no windows are found.
161 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
170 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
172 SERVER_START_REQ( get_window_children )
177 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
178 if (!wine_server_call( req )) count = reply->count;
181 if (count && count < size)
186 HeapFree( GetProcessHeap(), 0, list );
188 size = count + 1; /* restart with a large enough buffer */
194 /*******************************************************************
195 * list_window_parents
197 * Build an array of all parents of a given window, starting with
198 * the immediate parent. The array must be freed with HeapFree.
199 * Returns NULL if window is a top-level window.
201 static HWND *list_window_parents( HWND hwnd )
205 int pos = 0, size = 16, count = 0;
207 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
212 if (!(win = WIN_GetPtr( current ))) goto empty;
213 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
214 if (win == WND_DESKTOP)
216 if (!pos) goto empty;
220 list[pos] = current = win->parent;
221 WIN_ReleasePtr( win );
222 if (++pos == size - 1)
224 /* need to grow the list */
225 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
226 if (!new_list) goto empty;
232 /* at least one parent belongs to another process, have to query the server */
237 SERVER_START_REQ( get_window_parents )
240 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
241 if (!wine_server_call( req )) count = reply->count;
244 if (!count) goto empty;
250 HeapFree( GetProcessHeap(), 0, list );
252 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
256 HeapFree( GetProcessHeap(), 0, list );
261 /*******************************************************************
264 static void send_parent_notify( HWND hwnd, UINT msg )
266 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
267 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
268 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
269 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
273 /*******************************************************************
274 * get_server_window_text
276 * Retrieve the window text from the server.
278 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
282 SERVER_START_REQ( get_window_text )
285 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
286 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
289 text[len / sizeof(WCHAR)] = 0;
293 /***********************************************************************
296 * Return a pointer to the WND structure if local to the process,
297 * or WND_OTHER_PROCESS if handle may be valid in other process.
298 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
300 WND *WIN_GetPtr( HWND hwnd )
303 WORD index = USER_HANDLE_TO_INDEX(hwnd);
305 if (index >= NB_USER_HANDLES) return NULL;
308 if ((ptr = user_handles[index]))
310 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
314 else if (index == USER_HANDLE_TO_INDEX(hwndDesktop))
316 if (!HIWORD(hwnd) || hwnd == GetDesktopWindow()) ptr = WND_DESKTOP;
319 else ptr = WND_OTHER_PROCESS;
325 /***********************************************************************
326 * WIN_IsCurrentProcess
328 * Check whether a given window belongs to the current process (and return the full handle).
330 HWND WIN_IsCurrentProcess( HWND hwnd )
335 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
337 WIN_ReleasePtr( ptr );
342 /***********************************************************************
343 * WIN_IsCurrentThread
345 * Check whether a given window belongs to the current thread (and return the full handle).
347 HWND WIN_IsCurrentThread( HWND hwnd )
352 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
353 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
354 WIN_ReleasePtr( ptr );
359 /***********************************************************************
362 * Convert a 16-bit window handle to a full 32-bit handle.
364 HWND WIN_Handle32( HWND16 hwnd16 )
367 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
369 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
370 /* do sign extension for -2 and -3 */
371 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
373 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
375 if (ptr == WND_DESKTOP) return GetDesktopWindow();
377 if (ptr != WND_OTHER_PROCESS)
379 hwnd = ptr->hwndSelf;
380 WIN_ReleasePtr( ptr );
382 else /* may belong to another process */
384 SERVER_START_REQ( get_window_info )
387 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
395 /***********************************************************************
398 * Change the owner of a window.
400 HWND WIN_SetOwner( HWND hwnd, HWND owner )
402 WND *win = WIN_GetPtr( hwnd );
405 if (!win || win == WND_DESKTOP) return 0;
406 if (win == WND_OTHER_PROCESS)
408 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
411 SERVER_START_REQ( set_window_owner )
415 if (!wine_server_call( req ))
417 win->owner = reply->full_owner;
418 ret = reply->prev_owner;
422 WIN_ReleasePtr( win );
427 /***********************************************************************
430 * Change the style of a window.
432 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
435 ULONG new_style, old_style = 0;
436 WND *win = WIN_GetPtr( hwnd );
438 if (!win || win == WND_DESKTOP) return 0;
439 if (win == WND_OTHER_PROCESS)
442 ERR( "cannot set style %lx/%lx on other process window %p\n",
443 set_bits, clear_bits, hwnd );
446 new_style = (win->dwStyle | set_bits) & ~clear_bits;
447 if (new_style == win->dwStyle)
449 WIN_ReleasePtr( win );
452 SERVER_START_REQ( set_window_info )
455 req->flags = SET_WIN_STYLE;
456 req->style = new_style;
457 req->extra_offset = -1;
458 if ((ok = !wine_server_call( req )))
460 old_style = reply->old_style;
461 win->dwStyle = new_style;
465 WIN_ReleasePtr( win );
466 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, old_style );
471 /***********************************************************************
474 * Get the window and client rectangles.
476 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
478 WND *win = WIN_GetPtr( hwnd );
481 if (!win) return FALSE;
482 if (win == WND_DESKTOP)
485 rect.left = rect.top = 0;
486 rect.right = GetSystemMetrics(SM_CXSCREEN);
487 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
488 if (rectWindow) *rectWindow = rect;
489 if (rectClient) *rectClient = rect;
491 else if (win == WND_OTHER_PROCESS)
493 SERVER_START_REQ( get_window_rectangles )
496 if ((ret = !wine_server_call( req )))
500 rectWindow->left = reply->window.left;
501 rectWindow->top = reply->window.top;
502 rectWindow->right = reply->window.right;
503 rectWindow->bottom = reply->window.bottom;
507 rectClient->left = reply->client.left;
508 rectClient->top = reply->client.top;
509 rectClient->right = reply->client.right;
510 rectClient->bottom = reply->client.bottom;
518 if (rectWindow) *rectWindow = win->rectWindow;
519 if (rectClient) *rectClient = win->rectClient;
520 WIN_ReleasePtr( win );
526 /***********************************************************************
529 * Destroy storage associated to a window. "Internals" p.358
531 LRESULT WIN_DestroyWindow( HWND hwnd )
535 HMENU menu = 0, sys_menu;
537 TRACE("%p\n", hwnd );
539 /* free child windows */
540 if ((list = WIN_ListChildren( hwnd )))
543 for (i = 0; list[i]; i++)
545 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
546 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
548 HeapFree( GetProcessHeap(), 0, list );
551 /* Unlink now so we won't bother with the children later on */
552 SERVER_START_REQ( set_parent )
556 wine_server_call( req );
561 * Send the WM_NCDESTROY to the window being destroyed.
563 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
565 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
567 WINPOS_CheckInternalPos( hwnd );
569 /* free resources associated with the window */
571 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
572 if (!(wndPtr->dwStyle & WS_CHILD)) menu = (HMENU)wndPtr->wIDmenu;
573 sys_menu = wndPtr->hSysMenu;
574 WIN_ReleasePtr( wndPtr );
576 if (menu) DestroyMenu( menu );
577 if (sys_menu) DestroyMenu( sys_menu );
579 if (USER_Driver.pDestroyWindow) USER_Driver.pDestroyWindow( hwnd );
581 free_window_handle( hwnd );
585 /***********************************************************************
586 * WIN_DestroyThreadWindows
588 * Destroy all children of 'wnd' owned by the current thread.
589 * Return TRUE if something was done.
591 void WIN_DestroyThreadWindows( HWND hwnd )
596 if (!(list = WIN_ListChildren( hwnd ))) return;
597 for (i = 0; list[i]; i++)
599 if (WIN_IsCurrentThread( list[i] ))
600 DestroyWindow( list[i] );
602 WIN_DestroyThreadWindows( list[i] );
604 HeapFree( GetProcessHeap(), 0, list );
607 /***********************************************************************
608 * WIN_CreateDesktopWindow
610 * Create the desktop window.
612 BOOL WIN_CreateDesktopWindow(void)
616 TRACE("Creating desktop window\n");
618 if (!WINPOS_CreateInternalPosAtom()) return FALSE;
620 SERVER_START_REQ( create_window )
624 req->atom = LOWORD(DESKTOP_CLASS_ATOM);
626 if (!wine_server_call_err( req )) hwndDesktop = reply->handle;
632 ERR( "error %ld creating desktop window\n", GetLastError() );
636 cs.lpCreateParams = NULL;
642 cs.cx = GetSystemMetrics( SM_CXSCREEN );
643 cs.cy = GetSystemMetrics( SM_CYSCREEN );
644 cs.style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
647 cs.lpszClass = DESKTOP_CLASS_ATOM;
649 return USER_Driver.pCreateWindow( hwndDesktop, &cs, TRUE );
653 /***********************************************************************
656 * Fix the coordinates - Helper for WIN_CreateWindowEx.
657 * returns default show mode in sw.
658 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
660 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
664 if (cs->dwExStyle & WS_EX_MDICHILD)
668 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
669 if (!(cs->style & WS_POPUP)) cs->hMenu = (HMENU)id;
671 TRACE("MDI child id %04x\n", id);
674 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
675 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
677 if (cs->style & (WS_CHILD | WS_POPUP))
679 if (cs->dwExStyle & WS_EX_MDICHILD)
681 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
686 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
688 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
693 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
695 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
699 else /* overlapped window */
703 GetStartupInfoW( &info );
705 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
707 /* Never believe Microsoft's documentation... CreateWindowEx doc says
708 * that if an overlapped window is created with WS_VISIBLE style bit
709 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
710 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
713 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
714 * 2) it does not ignore the y parameter as the docs claim; instead, it
715 * uses it as second parameter to ShowWindow() unless y is either
716 * CW_USEDEFAULT or CW_USEDEFAULT16.
718 * The fact that we didn't do 2) caused bogus windows pop up when wine
719 * was running apps that were using this obscure feature. Example -
720 * calc.exe that comes with Win98 (only Win98, it's different from
721 * the one that comes with Win95 and NT)
723 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
724 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
725 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
728 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
730 if (info.dwFlags & STARTF_USESIZE)
732 cs->cx = info.dwXSize;
733 cs->cy = info.dwYSize;
735 else /* if no other hint from the app, pick 3/4 of the screen real estate */
738 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
739 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
740 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
743 /* Handle case where only the cy values is set to default */
744 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
747 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
748 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
754 /* neither x nor cx are default. Check the y values .
755 * In the trace we see Outlook and Outlook Express using
756 * cy set to CW_USEDEFAULT when opening the address book.
758 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
760 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
761 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
762 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
767 /***********************************************************************
770 static void dump_window_styles( DWORD style, DWORD exstyle )
773 if(style & WS_POPUP) TRACE(" WS_POPUP");
774 if(style & WS_CHILD) TRACE(" WS_CHILD");
775 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
776 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
777 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
778 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
779 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
780 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
781 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
784 if(style & WS_BORDER) TRACE(" WS_BORDER");
785 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
787 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
788 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
789 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
790 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
791 if(style & WS_GROUP) TRACE(" WS_GROUP");
792 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
793 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
794 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
796 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
797 #define DUMPED_STYLES \
817 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
822 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
823 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
824 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
825 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
826 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
827 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
828 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
829 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
830 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
831 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
832 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
833 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
834 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
835 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
836 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
837 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
838 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
839 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
841 #define DUMPED_EX_STYLES \
842 (WS_EX_DLGMODALFRAME | \
844 WS_EX_NOPARENTNOTIFY | \
846 WS_EX_ACCEPTFILES | \
847 WS_EX_TRANSPARENT | \
852 WS_EX_CONTEXTHELP | \
855 WS_EX_LEFTSCROLLBAR | \
856 WS_EX_CONTROLPARENT | \
861 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
863 #undef DUMPED_EX_STYLES
867 /***********************************************************************
870 * Implementation of CreateWindowEx().
872 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
873 WINDOWPROCTYPE type )
877 HWND hwnd, parent, owner, top_child = 0;
878 BOOL unicode = (type == WIN_PROC_32W);
880 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
881 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
882 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
883 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
884 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
886 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
888 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
889 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
891 /* Fix the styles for MDI children */
892 if (cs->dwExStyle & WS_EX_MDICHILD)
894 MDICREATESTRUCTA mdi_cs;
897 wndPtr = WIN_GetPtr(cs->hwndParent);
898 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
900 flags = wndPtr->flags;
901 WIN_ReleasePtr(wndPtr);
904 if (!(flags & WIN_ISMDICLIENT))
906 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
910 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
911 * MDICREATESTRUCT members have the originally passed values.
913 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
914 * have the same layout.
916 mdi_cs.szClass = cs->lpszClass;
917 mdi_cs.szTitle = cs->lpszName;
918 mdi_cs.hOwner = cs->hInstance;
923 mdi_cs.style = cs->style;
924 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
926 cs->lpCreateParams = (LPVOID)&mdi_cs;
928 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
930 if (cs->style & WS_POPUP)
932 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
935 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
939 cs->style &= ~WS_POPUP;
940 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
941 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
944 top_child = GetWindow(cs->hwndParent, GW_CHILD);
948 /* Restore current maximized child */
949 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
951 TRACE("Restoring current maximized child %p\n", top_child);
952 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
953 ShowWindow(top_child, SW_RESTORE);
954 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
959 /* Find the parent window */
961 parent = GetDesktopWindow();
964 if (cs->hwndParent == HWND_MESSAGE)
966 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
967 * message window (style: WS_POPUP|WS_DISABLED)
969 FIXME("Parent is HWND_MESSAGE\n");
971 else if (cs->hwndParent)
973 /* Make sure parent is valid */
974 if (!IsWindow( cs->hwndParent ))
976 WARN("Bad parent %p\n", cs->hwndParent );
979 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
980 parent = WIN_GetFullHandle(cs->hwndParent);
982 owner = GetAncestor( cs->hwndParent, GA_ROOT );
984 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
986 WARN("No parent for child window\n" );
987 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
990 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
992 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
993 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
994 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
995 cs->dwExStyle |= WS_EX_WINDOWEDGE;
997 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
999 /* Create the window structure */
1001 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
1003 TRACE("out of memory\n" );
1006 hwnd = wndPtr->hwndSelf;
1008 /* Fill the window structure */
1010 wndPtr->tid = GetCurrentThreadId();
1011 wndPtr->owner = owner;
1012 wndPtr->parent = parent;
1013 wndPtr->hInstance = cs->hInstance;
1014 wndPtr->text = NULL;
1015 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1016 wndPtr->dwExStyle = cs->dwExStyle;
1017 wndPtr->wIDmenu = 0;
1018 wndPtr->helpContext = 0;
1019 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1020 wndPtr->pVScroll = NULL;
1021 wndPtr->pHScroll = NULL;
1022 wndPtr->userdata = 0;
1024 wndPtr->hIconSmall = 0;
1025 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, (HMENU)-1 ) : 0;
1028 * Correct the window styles.
1030 * It affects only the style loaded into the WIN structure.
1033 if (!(wndPtr->dwStyle & WS_CHILD))
1035 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1036 if (!(wndPtr->dwStyle & WS_POPUP))
1037 wndPtr->dwStyle |= WS_CAPTION;
1041 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1042 * why does the user get to set it?
1045 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1046 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1047 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1049 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1051 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1052 wndPtr->flags |= WIN_NEED_SIZE;
1054 SERVER_START_REQ( set_window_info )
1057 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1058 req->style = wndPtr->dwStyle;
1059 req->ex_style = wndPtr->dwExStyle;
1060 req->instance = (void *)wndPtr->hInstance;
1061 req->extra_offset = -1;
1062 wine_server_call( req );
1066 /* Set the window menu */
1068 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1069 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1071 if (cs->hMenu) MENU_SetMenu(hwnd, cs->hMenu);
1074 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1077 if (HIWORD(cs->hInstance))
1078 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1080 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1082 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1086 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1087 WIN_ReleasePtr( wndPtr );
1089 if (!USER_Driver.pCreateWindow || !USER_Driver.pCreateWindow( hwnd, cs, unicode))
1091 WIN_DestroyWindow( hwnd );
1095 /* Notify the parent window only */
1097 send_parent_notify( hwnd, WM_CREATE );
1098 if (!IsWindow( hwnd )) return 0;
1100 if (cs->style & WS_VISIBLE)
1102 if (cs->style & WS_MAXIMIZE)
1103 sw = SW_SHOWMAXIMIZED;
1104 else if (cs->style & WS_MINIMIZE)
1105 sw = SW_SHOWMINIMIZED;
1107 ShowWindow( hwnd, sw );
1108 if (cs->dwExStyle & WS_EX_MDICHILD)
1110 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1111 /* ShowWindow won't activate child windows */
1112 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1116 /* Call WH_SHELL hook */
1118 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1119 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1121 TRACE("created window %p\n", hwnd);
1126 /***********************************************************************
1127 * CreateWindow (USER.41)
1129 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1130 DWORD style, INT16 x, INT16 y, INT16 width,
1131 INT16 height, HWND16 parent, HMENU16 menu,
1132 HINSTANCE16 instance, LPVOID data )
1134 return CreateWindowEx16( 0, className, windowName, style,
1135 x, y, width, height, parent, menu, instance, data );
1139 /***********************************************************************
1140 * CreateWindowEx (USER.452)
1142 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1143 LPCSTR windowName, DWORD style, INT16 x,
1144 INT16 y, INT16 width, INT16 height,
1145 HWND16 parent, HMENU16 menu,
1146 HINSTANCE16 instance, LPVOID data )
1152 /* Find the class atom */
1154 if (HIWORD(className))
1156 if (!(classAtom = GlobalFindAtomA( className )))
1158 ERR( "bad class name %s\n", debugstr_a(className) );
1164 classAtom = LOWORD(className);
1165 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1167 ERR( "bad atom %x\n", classAtom);
1173 /* Fix the coordinates */
1175 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1176 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1177 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1178 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1180 /* Create the window */
1182 cs.lpCreateParams = data;
1183 cs.hInstance = HINSTANCE_32(instance);
1184 cs.hMenu = HMENU_32(menu);
1185 cs.hwndParent = WIN_Handle32( parent );
1187 cs.lpszName = windowName;
1188 cs.lpszClass = className;
1189 cs.dwExStyle = exStyle;
1191 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1195 /***********************************************************************
1196 * CreateWindowExA (USER32.@)
1198 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1199 LPCSTR windowName, DWORD style, INT x,
1200 INT y, INT width, INT height,
1201 HWND parent, HMENU menu,
1202 HINSTANCE instance, LPVOID data )
1208 /* Find the class atom */
1210 if (HIWORD(className))
1212 if (!(classAtom = GlobalFindAtomA( className )))
1214 ERR( "bad class name %s\n", debugstr_a(className) );
1220 classAtom = LOWORD(className);
1221 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1223 ERR( "bad atom %x\n", classAtom);
1229 /* Create the window */
1231 cs.lpCreateParams = data;
1232 cs.hInstance = instance;
1234 cs.hwndParent = parent;
1240 cs.lpszName = windowName;
1241 cs.lpszClass = className;
1242 cs.dwExStyle = exStyle;
1244 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1248 /***********************************************************************
1249 * CreateWindowExW (USER32.@)
1251 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1252 LPCWSTR windowName, DWORD style, INT x,
1253 INT y, INT width, INT height,
1254 HWND parent, HMENU menu,
1255 HINSTANCE instance, LPVOID data )
1261 /* Find the class atom */
1263 if (HIWORD(className))
1265 if (!(classAtom = GlobalFindAtomW( className )))
1267 ERR( "bad class name %s\n", debugstr_w(className) );
1273 classAtom = LOWORD(className);
1274 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1276 ERR( "bad atom %x\n", classAtom);
1282 /* Create the window */
1284 cs.lpCreateParams = data;
1285 cs.hInstance = instance;
1287 cs.hwndParent = parent;
1293 cs.lpszName = windowName;
1294 cs.lpszClass = className;
1295 cs.dwExStyle = exStyle;
1297 /* Note: we rely on the fact that CREATESTRUCTA and */
1298 /* CREATESTRUCTW have the same layout. */
1299 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1303 /***********************************************************************
1304 * WIN_SendDestroyMsg
1306 static void WIN_SendDestroyMsg( HWND hwnd )
1310 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1312 if (hwnd == info.hwndCaret) DestroyCaret();
1313 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1315 if (USER_Driver.pResetSelectionOwner)
1316 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1319 * Send the WM_DESTROY to the window.
1321 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1324 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1325 * make sure that the window still exists when we come back.
1332 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1334 for (i = 0; pWndArray[i]; i++)
1336 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1338 HeapFree( GetProcessHeap(), 0, pWndArray );
1341 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1345 /***********************************************************************
1346 * DestroyWindow (USER32.@)
1348 BOOL WINAPI DestroyWindow( HWND hwnd )
1352 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1354 SetLastError( ERROR_ACCESS_DENIED );
1358 TRACE("(%p)\n", hwnd);
1362 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1364 if (MENU_IsMenuActive() == hwnd)
1367 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1371 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1372 send_parent_notify( hwnd, WM_DESTROY );
1374 else if (!GetWindow( hwnd, GW_OWNER ))
1376 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1377 /* FIXME: clean up palette - see "Internals" p.352 */
1380 if (!IsWindow(hwnd)) return TRUE;
1382 if (USER_Driver.pResetSelectionOwner)
1383 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1385 /* Hide the window */
1386 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1388 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1390 ShowWindow( hwnd, SW_HIDE );
1392 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1393 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1396 if (!IsWindow(hwnd)) return TRUE;
1398 /* Recursively destroy owned windows */
1405 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1408 for (i = 0; list[i]; i++)
1410 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1411 if (WIN_IsCurrentThread( list[i] ))
1413 DestroyWindow( list[i] );
1417 WIN_SetOwner( list[i], 0 );
1419 HeapFree( GetProcessHeap(), 0, list );
1421 if (!got_one) break;
1425 /* Send destroy messages */
1427 WIN_SendDestroyMsg( hwnd );
1428 if (!IsWindow( hwnd )) return TRUE;
1430 if (GetClipboardOwner() == hwnd)
1431 CLIPBOARD_ReleaseOwner();
1433 /* Destroy the window storage */
1435 WIN_DestroyWindow( hwnd );
1440 /***********************************************************************
1441 * CloseWindow (USER32.@)
1443 BOOL WINAPI CloseWindow( HWND hwnd )
1445 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1446 ShowWindow( hwnd, SW_MINIMIZE );
1451 /***********************************************************************
1452 * OpenIcon (USER32.@)
1454 BOOL WINAPI OpenIcon( HWND hwnd )
1456 if (!IsIconic( hwnd )) return FALSE;
1457 ShowWindow( hwnd, SW_SHOWNORMAL );
1462 /***********************************************************************
1465 * Implementation of FindWindow() and FindWindowEx().
1467 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1472 WCHAR *buffer = NULL;
1474 if (!parent) parent = GetDesktopWindow();
1477 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1478 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1481 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1485 child = WIN_GetFullHandle( child );
1486 while (list[i] && list[i] != child) i++;
1487 if (!list[i]) goto done;
1488 i++; /* start from next window */
1495 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1502 HeapFree( GetProcessHeap(), 0, list );
1503 HeapFree( GetProcessHeap(), 0, buffer );
1509 /***********************************************************************
1510 * FindWindowA (USER32.@)
1512 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1514 HWND ret = FindWindowExA( 0, 0, className, title );
1515 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1520 /***********************************************************************
1521 * FindWindowExA (USER32.@)
1523 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1524 LPCSTR className, LPCSTR title )
1533 /* If the atom doesn't exist, then no class */
1534 /* with this name exists either. */
1535 if (!(atom = GlobalFindAtomA( className )))
1537 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1541 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1543 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1544 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1545 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1546 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1547 HeapFree( GetProcessHeap(), 0, buffer );
1552 /***********************************************************************
1553 * FindWindowExW (USER32.@)
1555 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1556 LPCWSTR className, LPCWSTR title )
1562 /* If the atom doesn't exist, then no class */
1563 /* with this name exists either. */
1564 if (!(atom = GlobalFindAtomW( className )))
1566 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1570 return WIN_FindWindow( parent, child, atom, title );
1574 /***********************************************************************
1575 * FindWindowW (USER32.@)
1577 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1579 return FindWindowExW( 0, 0, className, title );
1583 /**********************************************************************
1584 * GetDesktopWindow (USER32.@)
1586 HWND WINAPI GetDesktopWindow(void)
1588 if (hwndDesktop) return hwndDesktop;
1589 ERR( "Wine init error: either you're trying to use an invalid native USER.EXE config, or some graphics/GUI libraries or DLLs didn't initialize properly. Aborting.\n" );
1595 /*******************************************************************
1596 * EnableWindow (USER32.@)
1598 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1603 if (is_broadcast(hwnd))
1605 SetLastError( ERROR_INVALID_PARAMETER );
1609 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1610 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1614 TRACE("( %p, %d )\n", hwnd, enable);
1616 retvalue = !IsWindowEnabled( hwnd );
1618 if (enable && retvalue)
1620 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1621 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1623 else if (!enable && !retvalue)
1627 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1629 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1631 if (hwnd == GetFocus())
1632 SetFocus( 0 ); /* A disabled window can't have the focus */
1634 capture_wnd = GetCapture();
1635 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1636 ReleaseCapture(); /* A disabled window can't capture the mouse */
1638 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1644 /***********************************************************************
1645 * IsWindowEnabled (USER32.@)
1647 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1649 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1653 /***********************************************************************
1654 * IsWindowUnicode (USER32.@)
1656 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1661 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return FALSE;
1662 if (wndPtr == WND_DESKTOP) return TRUE;
1663 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1664 WIN_ReleasePtr( wndPtr );
1669 /**********************************************************************
1670 * GetWindowWord (USER32.@)
1672 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1677 WND *wndPtr = WIN_GetPtr( hwnd );
1680 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1683 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1685 SERVER_START_REQ( set_window_info )
1688 req->flags = 0; /* don't set anything, just retrieve */
1689 req->extra_offset = offset;
1690 req->extra_size = sizeof(retvalue);
1691 if (!wine_server_call_err( req ))
1692 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1697 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1699 WARN("Invalid offset %d\n", offset );
1700 SetLastError( ERROR_INVALID_INDEX );
1702 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1703 WIN_ReleasePtr( wndPtr );
1709 case GWLP_HWNDPARENT:
1710 return GetWindowLongPtrW( hwnd, offset );
1712 case GWLP_HINSTANCE:
1714 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1716 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1720 WARN("Invalid offset %d\n", offset );
1726 /**********************************************************************
1727 * SetWindowWord (USER32.@)
1729 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1737 case GWLP_HINSTANCE:
1738 case GWLP_HWNDPARENT:
1739 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1743 WARN("Invalid offset %d\n", offset );
1744 SetLastError( ERROR_INVALID_INDEX );
1749 wndPtr = WIN_GetPtr( hwnd );
1750 if (wndPtr == WND_DESKTOP)
1752 SetLastError( ERROR_ACCESS_DENIED );
1755 if (wndPtr == WND_OTHER_PROCESS)
1758 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1759 offset, newval, hwnd );
1764 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1768 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1770 WARN("Invalid offset %d\n", offset );
1771 WIN_ReleasePtr(wndPtr);
1772 SetLastError( ERROR_INVALID_INDEX );
1776 SERVER_START_REQ( set_window_info )
1779 req->flags = SET_WIN_EXTRA;
1780 req->extra_offset = offset;
1781 req->extra_size = sizeof(newval);
1782 memcpy( &req->extra_value, &newval, sizeof(newval) );
1783 if (!wine_server_call_err( req ))
1785 void *ptr = (char *)wndPtr->wExtra + offset;
1786 memcpy( &retval, ptr, sizeof(retval) );
1787 memcpy( ptr, &newval, sizeof(newval) );
1791 WIN_ReleasePtr( wndPtr );
1796 /**********************************************************************
1799 * Helper function for GetWindowLong().
1801 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1803 LONG_PTR retvalue = 0;
1806 if (offset == GWLP_HWNDPARENT)
1808 HWND parent = GetAncestor( hwnd, GA_PARENT );
1809 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1810 return (ULONG_PTR)parent;
1813 if (!(wndPtr = WIN_GetPtr( hwnd )))
1815 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1819 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1821 if (offset == GWLP_WNDPROC)
1823 SetLastError( ERROR_ACCESS_DENIED );
1826 SERVER_START_REQ( set_window_info )
1829 req->flags = 0; /* don't set anything, just retrieve */
1830 req->extra_offset = (offset >= 0) ? offset : -1;
1831 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1832 if (!wine_server_call_err( req ))
1836 case GWL_STYLE: retvalue = reply->old_style; break;
1837 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1838 case GWLP_ID: retvalue = reply->old_id; break;
1839 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1840 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1842 if (offset >= 0) retvalue = reply->old_extra_value;
1843 else SetLastError( ERROR_INVALID_INDEX );
1852 /* now we have a valid wndPtr */
1856 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1859 * Some programs try to access last element from 16 bit
1860 * code using illegal offset value. Hopefully this is
1861 * what those programs really expect.
1863 if (type == WIN_PROC_16 &&
1864 wndPtr->cbWndExtra >= 4 &&
1865 offset == wndPtr->cbWndExtra - sizeof(WORD))
1867 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1869 ERR( "- replaced invalid offset %d with %d\n",
1872 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset2);
1873 WIN_ReleasePtr( wndPtr );
1876 WARN("Invalid offset %d\n", offset );
1877 WIN_ReleasePtr( wndPtr );
1878 SetLastError( ERROR_INVALID_INDEX );
1881 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
1882 /* Special case for dialog window procedure */
1883 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1884 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, type );
1885 WIN_ReleasePtr( wndPtr );
1891 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1892 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1893 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1894 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1895 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type ); break;
1896 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1898 WARN("Unknown offset %d\n", offset );
1899 SetLastError( ERROR_INVALID_INDEX );
1902 WIN_ReleasePtr(wndPtr);
1907 /**********************************************************************
1910 * Helper function for SetWindowLong().
1912 * 0 is the failure code. However, in the case of failure SetLastError
1913 * must be set to distinguish between a 0 return value and a failure.
1915 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval,
1916 WINDOWPROCTYPE type )
1920 LONG_PTR retval = 0;
1923 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1925 if (is_broadcast(hwnd))
1927 SetLastError( ERROR_INVALID_PARAMETER );
1931 if (!(wndPtr = WIN_GetPtr( hwnd )))
1933 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1936 if (wndPtr == WND_DESKTOP)
1938 /* can't change anything on the desktop window */
1939 SetLastError( ERROR_ACCESS_DENIED );
1942 if (wndPtr == WND_OTHER_PROCESS)
1944 if (offset == GWLP_WNDPROC)
1946 SetLastError( ERROR_ACCESS_DENIED );
1949 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1952 /* first some special cases */
1958 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1959 style.styleNew = newval;
1960 WIN_ReleasePtr( wndPtr );
1961 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1962 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1963 newval = style.styleNew;
1965 case GWLP_HWNDPARENT:
1966 if (wndPtr->parent == GetDesktopWindow())
1968 WIN_ReleasePtr( wndPtr );
1969 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1973 WIN_ReleasePtr( wndPtr );
1974 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1977 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type );
1978 wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, type );
1979 WIN_ReleasePtr( wndPtr );
1982 case GWLP_HINSTANCE:
1986 if ((wndPtr->cbWndExtra + sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1988 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1989 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, type );
1990 *ptr = WINPROC_AllocProc( (WNDPROC)newval, type );
1991 WIN_ReleasePtr( wndPtr );
1996 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
1998 WARN("Invalid offset %d\n", offset );
1999 WIN_ReleasePtr( wndPtr );
2000 SetLastError( ERROR_INVALID_INDEX );
2005 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2006 if (*ptr == newval) /* already set to the same value */
2008 WIN_ReleasePtr( wndPtr );
2015 SERVER_START_REQ( set_window_info )
2018 req->extra_offset = -1;
2022 req->flags = SET_WIN_STYLE;
2023 req->style = newval;
2026 req->flags = SET_WIN_EXSTYLE;
2027 req->ex_style = newval;
2030 req->flags = SET_WIN_ID;
2033 case GWLP_HINSTANCE:
2034 req->flags = SET_WIN_INSTANCE;
2035 req->instance = (void *)newval;
2038 req->flags = SET_WIN_USERDATA;
2039 req->user_data = (void *)newval;
2042 req->flags = SET_WIN_EXTRA;
2043 req->extra_offset = offset;
2044 req->extra_size = sizeof(newval);
2045 memcpy( &req->extra_value, &newval, sizeof(newval) );
2047 if ((ok = !wine_server_call_err( req )))
2052 wndPtr->dwStyle = newval;
2053 retval = reply->old_style;
2056 wndPtr->dwExStyle = newval;
2057 retval = reply->old_ex_style;
2060 wndPtr->wIDmenu = newval;
2061 retval = reply->old_id;
2063 case GWLP_HINSTANCE:
2064 wndPtr->hInstance = (HINSTANCE)newval;
2065 retval = (ULONG_PTR)reply->old_instance;
2068 wndPtr->userdata = newval;
2069 retval = (ULONG_PTR)reply->old_user_data;
2073 void *ptr = (char *)wndPtr->wExtra + offset;
2074 memcpy( &retval, ptr, sizeof(retval) );
2075 memcpy( ptr, &newval, sizeof(newval) );
2082 WIN_ReleasePtr( wndPtr );
2086 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2087 USER_Driver.pSetWindowStyle( hwnd, retval );
2089 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2090 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2096 /**********************************************************************
2097 * GetWindowLong (USER.135)
2099 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2101 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2105 /**********************************************************************
2106 * GetWindowLongA (USER32.@)
2108 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2110 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2114 /**********************************************************************
2115 * GetWindowLongW (USER32.@)
2117 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2119 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2123 /**********************************************************************
2124 * SetWindowLong (USER.136)
2126 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2128 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2132 /**********************************************************************
2133 * SetWindowLongA (USER32.@)
2135 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2137 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2141 /**********************************************************************
2142 * SetWindowLongW (USER32.@) Set window attribute
2144 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2145 * value in a window's extra memory.
2147 * The _hwnd_ parameter specifies the window. is the handle to a
2148 * window that has extra memory. The _newval_ parameter contains the
2149 * new attribute or extra memory value. If positive, the _offset_
2150 * parameter is the byte-addressed location in the window's extra
2151 * memory to set. If negative, _offset_ specifies the window
2152 * attribute to set, and should be one of the following values:
2154 * GWL_EXSTYLE The window's extended window style
2156 * GWL_STYLE The window's window style.
2158 * GWLP_WNDPROC Pointer to the window's window procedure.
2160 * GWLP_HINSTANCE The window's pplication instance handle.
2162 * GWLP_ID The window's identifier.
2164 * GWLP_USERDATA The window's user-specified data.
2166 * If the window is a dialog box, the _offset_ parameter can be one of
2167 * the following values:
2169 * DWLP_DLGPROC The address of the window's dialog box procedure.
2171 * DWLP_MSGRESULT The return value of a message
2172 * that the dialog box procedure processed.
2174 * DWLP_USER Application specific information.
2178 * If successful, returns the previous value located at _offset_. Otherwise,
2183 * Extra memory for a window class is specified by a nonzero cbWndExtra
2184 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2185 * time of class creation.
2187 * Using GWL_WNDPROC to set a new window procedure effectively creates
2188 * a window subclass. Use CallWindowProc() in the new windows procedure
2189 * to pass messages to the superclass's window procedure.
2191 * The user data is reserved for use by the application which created
2194 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2195 * instead, call the EnableWindow() function to change the window's
2198 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2199 * SetParent() instead.
2202 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2203 * it sends WM_STYLECHANGING before changing the settings
2204 * and WM_STYLECHANGED afterwards.
2205 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2207 LONG WINAPI SetWindowLongW(
2208 HWND hwnd, /* [in] window to alter */
2209 INT offset, /* [in] offset, in bytes, of location to alter */
2210 LONG newval /* [in] new value of location */
2212 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2216 /*******************************************************************
2217 * GetWindowTextA (USER32.@)
2219 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
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 (WIN_IsCurrentProcess( hwnd ))
2267 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2269 /* when window belongs to other process, don't send a message */
2270 if (nMaxCount <= 0) return 0;
2271 get_server_window_text( hwnd, lpString, nMaxCount );
2272 return strlenW(lpString);
2276 /*******************************************************************
2277 * SetWindowText (USER32.@)
2278 * SetWindowTextA (USER32.@)
2280 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2282 if (is_broadcast(hwnd))
2284 SetLastError( ERROR_INVALID_PARAMETER );
2287 if (!WIN_IsCurrentProcess( hwnd ))
2289 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2290 SetLastError( ERROR_ACCESS_DENIED );
2293 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2297 /*******************************************************************
2298 * SetWindowTextW (USER32.@)
2300 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2302 if (is_broadcast(hwnd))
2304 SetLastError( ERROR_INVALID_PARAMETER );
2307 if (!WIN_IsCurrentProcess( hwnd ))
2309 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2310 SetLastError( ERROR_ACCESS_DENIED );
2313 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2317 /*******************************************************************
2318 * GetWindowTextLengthA (USER32.@)
2320 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2322 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2325 /*******************************************************************
2326 * GetWindowTextLengthW (USER32.@)
2328 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2330 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2334 /*******************************************************************
2335 * IsWindow (USER32.@)
2337 BOOL WINAPI IsWindow( HWND hwnd )
2342 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2343 if (ptr == WND_DESKTOP) return TRUE;
2345 if (ptr != WND_OTHER_PROCESS)
2347 WIN_ReleasePtr( ptr );
2351 /* check other processes */
2352 SERVER_START_REQ( get_window_info )
2355 ret = !wine_server_call_err( req );
2362 /***********************************************************************
2363 * GetWindowThreadProcessId (USER32.@)
2365 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2370 if (!(ptr = WIN_GetPtr( hwnd )))
2372 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2376 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2378 /* got a valid window */
2380 if (process) *process = GetCurrentProcessId();
2381 WIN_ReleasePtr( ptr );
2385 /* check other processes */
2386 SERVER_START_REQ( get_window_info )
2389 if (!wine_server_call_err( req ))
2391 tid = (DWORD)reply->tid;
2392 if (process) *process = (DWORD)reply->pid;
2400 /*****************************************************************
2401 * GetParent (USER32.@)
2403 HWND WINAPI GetParent( HWND hwnd )
2408 if (!(wndPtr = WIN_GetPtr( hwnd )))
2410 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2413 if (wndPtr == WND_DESKTOP) return 0;
2414 if (wndPtr == WND_OTHER_PROCESS)
2416 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2417 if (style & (WS_POPUP | WS_CHILD))
2419 SERVER_START_REQ( get_window_tree )
2422 if (!wine_server_call_err( req ))
2424 if (style & WS_POPUP) retvalue = reply->owner;
2425 else if (style & WS_CHILD) retvalue = reply->parent;
2433 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2434 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2435 WIN_ReleasePtr( wndPtr );
2441 /*****************************************************************
2442 * GetAncestor (USER32.@)
2444 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2447 HWND *list, ret = 0;
2452 if (!(win = WIN_GetPtr( hwnd )))
2454 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2457 if (win == WND_DESKTOP) return 0;
2458 if (win != WND_OTHER_PROCESS)
2461 WIN_ReleasePtr( win );
2463 else /* need to query the server */
2465 SERVER_START_REQ( get_window_tree )
2468 if (!wine_server_call_err( req )) ret = reply->parent;
2475 if (!(list = list_window_parents( hwnd ))) return 0;
2477 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2481 while (list[count]) count++;
2482 ret = list[count - 2]; /* get the one before the desktop */
2484 HeapFree( GetProcessHeap(), 0, list );
2488 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2491 HWND parent = GetParent( ret );
2501 /*****************************************************************
2502 * SetParent (USER32.@)
2504 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2508 if (is_broadcast(hwnd) || is_broadcast(parent))
2510 SetLastError(ERROR_INVALID_PARAMETER);
2514 if (!parent) parent = GetDesktopWindow();
2515 else parent = WIN_GetFullHandle( parent );
2517 if (!IsWindow( parent ))
2519 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2523 /* Some applications try to set a child as a parent */
2524 if (IsChild(hwnd, parent))
2526 SetLastError( ERROR_INVALID_PARAMETER );
2530 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2531 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2533 if (USER_Driver.pSetParent)
2534 return USER_Driver.pSetParent( full_handle, parent );
2540 /*******************************************************************
2541 * IsChild (USER32.@)
2543 BOOL WINAPI IsChild( HWND parent, HWND child )
2545 HWND *list = list_window_parents( child );
2549 if (!list) return FALSE;
2550 parent = WIN_GetFullHandle( parent );
2551 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2552 ret = (list[i] != 0);
2553 HeapFree( GetProcessHeap(), 0, list );
2558 /***********************************************************************
2559 * IsWindowVisible (USER32.@)
2561 BOOL WINAPI IsWindowVisible( HWND hwnd )
2567 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2568 if (!(list = list_window_parents( hwnd ))) return TRUE;
2569 for (i = 0; list[i]; i++)
2570 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2572 HeapFree( GetProcessHeap(), 0, list );
2577 /***********************************************************************
2578 * WIN_IsWindowDrawable
2580 * hwnd is drawable when it is visible, all parents are not
2581 * minimized, and it is itself not minimized unless we are
2582 * trying to draw its default class icon.
2584 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2589 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2591 if (!(style & WS_VISIBLE)) return FALSE;
2592 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2594 if (!(list = list_window_parents( hwnd ))) return TRUE;
2595 for (i = 0; list[i]; i++)
2596 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2599 HeapFree( GetProcessHeap(), 0, list );
2604 /*******************************************************************
2605 * GetTopWindow (USER32.@)
2607 HWND WINAPI GetTopWindow( HWND hwnd )
2609 if (!hwnd) hwnd = GetDesktopWindow();
2610 return GetWindow( hwnd, GW_CHILD );
2614 /*******************************************************************
2615 * GetWindow (USER32.@)
2617 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2621 if (rel == GW_OWNER) /* this one may be available locally */
2623 WND *wndPtr = WIN_GetPtr( hwnd );
2626 SetLastError( ERROR_INVALID_HANDLE );
2629 if (wndPtr == WND_DESKTOP) return 0;
2630 if (wndPtr != WND_OTHER_PROCESS)
2632 retval = wndPtr->owner;
2633 WIN_ReleasePtr( wndPtr );
2636 /* else fall through to server call */
2639 SERVER_START_REQ( get_window_tree )
2642 if (!wine_server_call_err( req ))
2647 retval = reply->first_sibling;
2650 retval = reply->last_sibling;
2653 retval = reply->next_sibling;
2656 retval = reply->prev_sibling;
2659 retval = reply->owner;
2662 retval = reply->first_child;
2672 /*******************************************************************
2673 * ShowOwnedPopups (USER32.@)
2675 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2679 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2681 if (!win_array) return TRUE;
2683 while (win_array[count]) count++;
2684 while (--count >= 0)
2686 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2687 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2688 if (pWnd == WND_OTHER_PROCESS) continue;
2690 if (pWnd->dwStyle & WS_POPUP)
2694 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2696 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2697 WIN_ReleasePtr( pWnd );
2698 /* In Windows, ShowOwnedPopups(TRUE) generates
2699 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2700 * regardless of the state of the owner
2702 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2708 if (pWnd->dwStyle & WS_VISIBLE)
2710 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2711 WIN_ReleasePtr( pWnd );
2712 /* In Windows, ShowOwnedPopups(FALSE) generates
2713 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2714 * regardless of the state of the owner
2716 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2721 WIN_ReleasePtr( pWnd );
2723 HeapFree( GetProcessHeap(), 0, win_array );
2728 /*******************************************************************
2729 * GetLastActivePopup (USER32.@)
2731 HWND WINAPI GetLastActivePopup( HWND hwnd )
2735 SERVER_START_REQ( get_window_info )
2738 if (!wine_server_call_err( req )) retval = reply->last_active;
2745 /*******************************************************************
2748 * Build an array of the children of a given window. The array must be
2749 * freed with HeapFree. Returns NULL when no windows are found.
2751 HWND *WIN_ListChildren( HWND hwnd )
2753 return list_window_children( hwnd, 0, 0 );
2757 /*******************************************************************
2758 * EnumWindows (USER32.@)
2760 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2766 USER_CheckNotLock();
2768 /* We have to build a list of all windows first, to avoid */
2769 /* unpleasant side-effects, for instance if the callback */
2770 /* function changes the Z-order of the windows. */
2772 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2774 /* Now call the callback function for every window */
2776 for (i = 0; list[i]; i++)
2778 /* Make sure that the window still exists */
2779 if (!IsWindow( list[i] )) continue;
2780 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2782 HeapFree( GetProcessHeap(), 0, list );
2787 /**********************************************************************
2788 * EnumThreadWindows (USER32.@)
2790 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2795 USER_CheckNotLock();
2797 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2799 /* Now call the callback function for every window */
2801 for (i = 0; list[i]; i++)
2802 if (!func( list[i], lParam )) break;
2803 HeapFree( GetProcessHeap(), 0, list );
2808 /**********************************************************************
2809 * WIN_EnumChildWindows
2811 * Helper function for EnumChildWindows().
2813 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2818 for ( ; *list; list++)
2820 /* Make sure that the window still exists */
2821 if (!IsWindow( *list )) continue;
2822 /* skip owned windows */
2823 if (GetWindow( *list, GW_OWNER )) continue;
2824 /* Build children list first */
2825 childList = WIN_ListChildren( *list );
2827 ret = func( *list, lParam );
2831 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2832 HeapFree( GetProcessHeap(), 0, childList );
2834 if (!ret) return FALSE;
2840 /**********************************************************************
2841 * EnumChildWindows (USER32.@)
2843 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2847 USER_CheckNotLock();
2849 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2850 WIN_EnumChildWindows( list, func, lParam );
2851 HeapFree( GetProcessHeap(), 0, list );
2856 /*******************************************************************
2857 * AnyPopup (USER.52)
2859 BOOL16 WINAPI AnyPopup16(void)
2865 /*******************************************************************
2866 * AnyPopup (USER32.@)
2868 BOOL WINAPI AnyPopup(void)
2872 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2874 if (!list) return FALSE;
2875 for (i = 0; list[i]; i++)
2877 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2879 retvalue = (list[i] != 0);
2880 HeapFree( GetProcessHeap(), 0, list );
2885 /*******************************************************************
2886 * FlashWindow (USER32.@)
2888 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2892 TRACE("%p\n", hWnd);
2894 if (IsIconic( hWnd ))
2896 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2898 wndPtr = WIN_GetPtr(hWnd);
2899 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2900 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2902 wndPtr->flags |= WIN_NCACTIVATED;
2906 wndPtr->flags &= ~WIN_NCACTIVATED;
2908 WIN_ReleasePtr( wndPtr );
2915 wndPtr = WIN_GetPtr(hWnd);
2916 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2917 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2919 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2920 else wparam = (hWnd == GetForegroundWindow());
2922 WIN_ReleasePtr( wndPtr );
2923 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2928 /*******************************************************************
2929 * FlashWindowEx (USER32.@)
2931 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
2933 FIXME("%p\n", pfwi);
2937 /*******************************************************************
2938 * GetWindowContextHelpId (USER32.@)
2940 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2943 WND *wnd = WIN_GetPtr( hwnd );
2944 if (!wnd || wnd == WND_DESKTOP) return 0;
2945 if (wnd == WND_OTHER_PROCESS)
2947 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2950 retval = wnd->helpContext;
2951 WIN_ReleasePtr( wnd );
2956 /*******************************************************************
2957 * SetWindowContextHelpId (USER32.@)
2959 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2961 WND *wnd = WIN_GetPtr( hwnd );
2962 if (!wnd || wnd == WND_DESKTOP) return FALSE;
2963 if (wnd == WND_OTHER_PROCESS)
2965 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2968 wnd->helpContext = id;
2969 WIN_ReleasePtr( wnd );
2974 /*******************************************************************
2975 * DragDetect (USER32.@)
2977 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2982 rect.left = pt.x - wDragWidth;
2983 rect.right = pt.x + wDragWidth;
2985 rect.top = pt.y - wDragHeight;
2986 rect.bottom = pt.y + wDragHeight;
2992 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
2994 if( msg.message == WM_LBUTTONUP )
2999 if( msg.message == WM_MOUSEMOVE )
3002 tmp.x = LOWORD(msg.lParam);
3003 tmp.y = HIWORD(msg.lParam);
3004 if( !PtInRect( &rect, tmp ))
3016 /******************************************************************************
3017 * GetWindowModuleFileNameA (USER32.@)
3019 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3021 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3022 hwnd, lpszFileName, cchFileNameMax);
3026 /******************************************************************************
3027 * GetWindowModuleFileNameW (USER32.@)
3029 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3031 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3032 hwnd, lpszFileName, cchFileNameMax);
3036 /******************************************************************************
3037 * GetWindowInfo (USER32.@)
3039 * Note: tests show that Windows doesn't check cbSize of the structure.
3041 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3043 if (!pwi) return FALSE;
3044 if (!IsWindow(hwnd)) return FALSE;
3046 GetWindowRect(hwnd, &pwi->rcWindow);
3047 GetClientRect(hwnd, &pwi->rcClient);
3048 /* translate to screen coordinates */
3049 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3051 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3052 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3053 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3055 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3056 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3058 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3059 pwi->wCreatorVersion = 0x0400;
3064 /******************************************************************************
3065 * SwitchDesktop (USER32.@)
3067 * NOTES: Sets the current input or interactive desktop.
3069 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3071 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);