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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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"
37 #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, BOOL unicode )
62 HWND full_parent = 0, full_owner = 0;
63 struct tagCLASS *class = NULL;
64 user_handle_t handle = 0;
67 /* if 16-bit instance, map to module handle */
68 if (instance && !HIWORD(instance))
69 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
71 SERVER_START_REQ( create_window )
76 req->instance = instance;
77 if (!wine_server_call_err( req ))
79 handle = reply->handle;
80 full_parent = reply->parent;
81 full_owner = reply->owner;
82 extra_bytes = reply->extra;
83 class = reply->class_ptr;
90 WARN( "error %ld creating window\n", GetLastError() );
94 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
96 SERVER_START_REQ( destroy_window )
99 wine_server_call( req );
102 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
106 if (!parent) /* if parent is 0 we don't have a desktop window yet */
108 struct user_thread_info *thread_info = get_user_thread_info();
110 assert( !thread_info->desktop );
111 thread_info->desktop = full_parent ? full_parent : handle;
112 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
113 ERR( "failed to create desktop window\n" );
118 index = USER_HANDLE_TO_INDEX(handle);
119 assert( index < NB_USER_HANDLES );
120 user_handles[index] = win;
121 win->hwndSelf = handle;
122 win->parent = full_parent;
123 win->owner = full_owner;
124 win->dwMagic = WND_MAGIC;
126 win->cbWndExtra = extra_bytes;
127 memset( win->wExtra, 0, extra_bytes );
128 CLASS_AddWindow( class, win, unicode );
133 /***********************************************************************
136 * Free a window handle.
138 static WND *free_window_handle( HWND hwnd )
141 WORD index = USER_HANDLE_TO_INDEX(hwnd);
143 if (index >= NB_USER_HANDLES) return NULL;
145 if ((ptr = user_handles[index]))
147 SERVER_START_REQ( destroy_window )
150 if (!wine_server_call_err( req ))
152 user_handles[index] = NULL;
161 HeapFree( GetProcessHeap(), 0, ptr );
166 /*******************************************************************
167 * list_window_children
169 * Build an array of the children of a given window. The array must be
170 * freed with HeapFree. Returns NULL when no windows are found.
172 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
181 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
183 SERVER_START_REQ( get_window_children )
188 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
189 if (!wine_server_call( req )) count = reply->count;
192 if (count && count < size)
197 HeapFree( GetProcessHeap(), 0, list );
199 size = count + 1; /* restart with a large enough buffer */
205 /*******************************************************************
206 * list_window_parents
208 * Build an array of all parents of a given window, starting with
209 * the immediate parent. The array must be freed with HeapFree.
210 * Returns NULL if window is a top-level window.
212 static HWND *list_window_parents( HWND hwnd )
216 int pos = 0, size = 16, count = 0;
218 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
223 if (!(win = WIN_GetPtr( current ))) goto empty;
224 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
225 if (win == WND_DESKTOP)
227 if (!pos) goto empty;
231 list[pos] = current = win->parent;
232 WIN_ReleasePtr( win );
233 if (++pos == size - 1)
235 /* need to grow the list */
236 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
237 if (!new_list) goto empty;
243 /* at least one parent belongs to another process, have to query the server */
248 SERVER_START_REQ( get_window_parents )
251 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
252 if (!wine_server_call( req )) count = reply->count;
255 if (!count) goto empty;
261 HeapFree( GetProcessHeap(), 0, list );
263 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
267 HeapFree( GetProcessHeap(), 0, list );
272 /*******************************************************************
275 static void send_parent_notify( HWND hwnd, UINT msg )
277 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
278 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
280 HWND parent = GetParent(hwnd);
281 if (parent && parent != GetDesktopWindow())
282 SendMessageW( parent, WM_PARENTNOTIFY,
283 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
288 /*******************************************************************
289 * get_server_window_text
291 * Retrieve the window text from the server.
293 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
297 SERVER_START_REQ( get_window_text )
300 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
301 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
304 text[len / sizeof(WCHAR)] = 0;
308 /***********************************************************************
311 * Return a pointer to the WND structure if local to the process,
312 * or WND_OTHER_PROCESS if handle may be valid in other process.
313 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
315 WND *WIN_GetPtr( HWND hwnd )
318 WORD index = USER_HANDLE_TO_INDEX(hwnd);
320 if (index >= NB_USER_HANDLES) return NULL;
323 if ((ptr = user_handles[index]))
325 if (ptr->dwMagic == WND_MAGIC &&
326 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
330 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
332 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
335 else ptr = WND_OTHER_PROCESS;
341 /***********************************************************************
342 * WIN_IsCurrentProcess
344 * Check whether a given window belongs to the current process (and return the full handle).
346 HWND WIN_IsCurrentProcess( HWND hwnd )
351 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
353 WIN_ReleasePtr( ptr );
358 /***********************************************************************
359 * WIN_IsCurrentThread
361 * Check whether a given window belongs to the current thread (and return the full handle).
363 HWND WIN_IsCurrentThread( HWND hwnd )
368 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
369 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
370 WIN_ReleasePtr( ptr );
375 /***********************************************************************
378 * Convert a 16-bit window handle to a full 32-bit handle.
380 HWND WIN_Handle32( HWND16 hwnd16 )
383 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
385 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
386 /* do sign extension for -2 and -3 */
387 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
389 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
391 if (ptr == WND_DESKTOP) return GetDesktopWindow();
393 if (ptr != WND_OTHER_PROCESS)
395 hwnd = ptr->hwndSelf;
396 WIN_ReleasePtr( ptr );
398 else /* may belong to another process */
400 SERVER_START_REQ( get_window_info )
403 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
411 /***********************************************************************
414 * Change the owner of a window.
416 HWND WIN_SetOwner( HWND hwnd, HWND owner )
418 WND *win = WIN_GetPtr( hwnd );
421 if (!win || win == WND_DESKTOP) return 0;
422 if (win == WND_OTHER_PROCESS)
424 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
427 SERVER_START_REQ( set_window_owner )
431 if (!wine_server_call( req ))
433 win->owner = reply->full_owner;
434 ret = reply->prev_owner;
438 WIN_ReleasePtr( win );
443 /***********************************************************************
446 * Change the style of a window.
448 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
451 ULONG new_style, old_style = 0;
452 WND *win = WIN_GetPtr( hwnd );
454 if (!win || win == WND_DESKTOP) return 0;
455 if (win == WND_OTHER_PROCESS)
458 ERR( "cannot set style %lx/%lx on other process window %p\n",
459 set_bits, clear_bits, hwnd );
462 new_style = (win->dwStyle | set_bits) & ~clear_bits;
463 if (new_style == win->dwStyle)
465 WIN_ReleasePtr( win );
468 SERVER_START_REQ( set_window_info )
471 req->flags = SET_WIN_STYLE;
472 req->style = new_style;
473 req->extra_offset = -1;
474 if ((ok = !wine_server_call( req )))
476 old_style = reply->old_style;
477 win->dwStyle = new_style;
481 WIN_ReleasePtr( win );
482 if (ok) USER_Driver->pSetWindowStyle( hwnd, old_style );
487 /***********************************************************************
490 * Get the window and client rectangles.
492 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
494 WND *win = WIN_GetPtr( hwnd );
497 if (!win) return FALSE;
498 if (win == WND_DESKTOP)
501 rect.left = rect.top = 0;
502 rect.right = GetSystemMetrics(SM_CXSCREEN);
503 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
504 if (rectWindow) *rectWindow = rect;
505 if (rectClient) *rectClient = rect;
507 else if (win == WND_OTHER_PROCESS)
509 SERVER_START_REQ( get_window_rectangles )
512 if ((ret = !wine_server_call( req )))
516 rectWindow->left = reply->window.left;
517 rectWindow->top = reply->window.top;
518 rectWindow->right = reply->window.right;
519 rectWindow->bottom = reply->window.bottom;
523 rectClient->left = reply->client.left;
524 rectClient->top = reply->client.top;
525 rectClient->right = reply->client.right;
526 rectClient->bottom = reply->client.bottom;
534 if (rectWindow) *rectWindow = win->rectWindow;
535 if (rectClient) *rectClient = win->rectClient;
536 WIN_ReleasePtr( win );
542 /***********************************************************************
545 * Destroy storage associated to a window. "Internals" p.358
547 LRESULT WIN_DestroyWindow( HWND hwnd )
551 HMENU menu = 0, sys_menu;
553 TRACE("%p\n", hwnd );
555 /* free child windows */
556 if ((list = WIN_ListChildren( hwnd )))
559 for (i = 0; list[i]; i++)
561 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
562 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
564 HeapFree( GetProcessHeap(), 0, list );
567 /* Unlink now so we won't bother with the children later on */
568 SERVER_START_REQ( set_parent )
572 wine_server_call( req );
577 * Send the WM_NCDESTROY to the window being destroyed.
579 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
581 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
583 WINPOS_CheckInternalPos( hwnd );
585 /* free resources associated with the window */
587 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
588 if (!(wndPtr->dwStyle & WS_CHILD)) menu = (HMENU)wndPtr->wIDmenu;
589 sys_menu = wndPtr->hSysMenu;
590 WIN_ReleasePtr( wndPtr );
592 if (menu) DestroyMenu( menu );
593 if (sys_menu) DestroyMenu( sys_menu );
595 USER_Driver->pDestroyWindow( hwnd );
597 free_window_handle( hwnd );
601 /***********************************************************************
602 * WIN_DestroyThreadWindows
604 * Destroy all children of 'wnd' owned by the current thread.
605 * Return TRUE if something was done.
607 void WIN_DestroyThreadWindows( HWND hwnd )
612 if (!(list = WIN_ListChildren( hwnd ))) return;
613 for (i = 0; list[i]; i++)
615 if (WIN_IsCurrentThread( list[i] ))
616 DestroyWindow( list[i] );
618 WIN_DestroyThreadWindows( list[i] );
620 HeapFree( GetProcessHeap(), 0, list );
624 /***********************************************************************
627 * Fix the coordinates - Helper for WIN_CreateWindowEx.
628 * returns default show mode in sw.
629 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
631 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
635 if (cs->dwExStyle & WS_EX_MDICHILD)
639 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
640 if (!(cs->style & WS_POPUP)) cs->hMenu = (HMENU)id;
642 TRACE("MDI child id %04x\n", id);
645 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
646 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
648 if (cs->style & (WS_CHILD | WS_POPUP))
650 if (cs->dwExStyle & WS_EX_MDICHILD)
652 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
657 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
659 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
664 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
666 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
670 else /* overlapped window */
674 GetStartupInfoW( &info );
676 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
678 /* Never believe Microsoft's documentation... CreateWindowEx doc says
679 * that if an overlapped window is created with WS_VISIBLE style bit
680 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
681 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
684 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
685 * 2) it does not ignore the y parameter as the docs claim; instead, it
686 * uses it as second parameter to ShowWindow() unless y is either
687 * CW_USEDEFAULT or CW_USEDEFAULT16.
689 * The fact that we didn't do 2) caused bogus windows pop up when wine
690 * was running apps that were using this obscure feature. Example -
691 * calc.exe that comes with Win98 (only Win98, it's different from
692 * the one that comes with Win95 and NT)
694 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
695 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
696 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
699 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
701 if (info.dwFlags & STARTF_USESIZE)
703 cs->cx = info.dwXSize;
704 cs->cy = info.dwYSize;
706 else /* if no other hint from the app, pick 3/4 of the screen real estate */
709 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
710 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
711 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
714 /* Handle case where only the cy values is set to default */
715 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
718 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
719 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
725 /* neither x nor cx are default. Check the y values .
726 * In the trace we see Outlook and Outlook Express using
727 * cy set to CW_USEDEFAULT when opening the address book.
729 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
731 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
732 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
733 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
738 /***********************************************************************
741 static void dump_window_styles( DWORD style, DWORD exstyle )
744 if(style & WS_POPUP) TRACE(" WS_POPUP");
745 if(style & WS_CHILD) TRACE(" WS_CHILD");
746 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
747 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
748 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
749 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
750 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
751 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
752 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
755 if(style & WS_BORDER) TRACE(" WS_BORDER");
756 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
758 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
759 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
760 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
761 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
762 if (style & WS_CHILD)
764 if(style & WS_GROUP) TRACE(" WS_GROUP");
765 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
769 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
770 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
773 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
774 #define DUMPED_STYLES \
794 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
799 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
800 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
801 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
802 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
803 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
804 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
805 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
806 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
807 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
808 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
809 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
810 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
811 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
812 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
813 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
814 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
815 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
816 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
818 #define DUMPED_EX_STYLES \
819 (WS_EX_DLGMODALFRAME | \
821 WS_EX_NOPARENTNOTIFY | \
823 WS_EX_ACCEPTFILES | \
824 WS_EX_TRANSPARENT | \
829 WS_EX_CONTEXTHELP | \
832 WS_EX_LEFTSCROLLBAR | \
833 WS_EX_CONTROLPARENT | \
838 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
840 #undef DUMPED_EX_STYLES
844 /***********************************************************************
847 * Implementation of CreateWindowEx().
849 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, UINT flags )
853 HWND hwnd, parent, owner, top_child = 0;
854 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
855 MDICREATESTRUCTA mdi_cs;
857 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
858 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
859 unicode ? debugstr_w((LPCWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
860 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
861 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
862 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
864 /* Fix the styles for MDI children */
865 if (cs->dwExStyle & WS_EX_MDICHILD)
869 wndPtr = WIN_GetPtr(cs->hwndParent);
870 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
872 flags = wndPtr->flags;
873 WIN_ReleasePtr(wndPtr);
876 if (!(flags & WIN_ISMDICLIENT))
878 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
882 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
883 * MDICREATESTRUCT members have the originally passed values.
885 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
886 * have the same layout.
888 mdi_cs.szClass = cs->lpszClass;
889 mdi_cs.szTitle = cs->lpszName;
890 mdi_cs.hOwner = cs->hInstance;
895 mdi_cs.style = cs->style;
896 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
898 cs->lpCreateParams = (LPVOID)&mdi_cs;
900 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
902 if (cs->style & WS_POPUP)
904 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
907 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
911 cs->style &= ~WS_POPUP;
912 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
913 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
916 top_child = GetWindow(cs->hwndParent, GW_CHILD);
920 /* Restore current maximized child */
921 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
923 TRACE("Restoring current maximized child %p\n", top_child);
924 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
925 ShowWindow(top_child, SW_RESTORE);
926 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
931 /* Find the parent window */
933 parent = cs->hwndParent;
936 if (cs->hwndParent == HWND_MESSAGE)
938 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
939 * message window (style: WS_POPUP|WS_DISABLED)
941 FIXME("Parent is HWND_MESSAGE\n");
942 parent = GetDesktopWindow();
944 else if (cs->hwndParent)
946 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
948 parent = GetDesktopWindow();
949 owner = cs->hwndParent;
954 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
956 WARN("No parent for child window\n" );
957 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
959 if (classAtom != LOWORD(DESKTOP_CLASS_ATOM)) /* are we creating the desktop itself? */
960 parent = GetDesktopWindow();
963 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
965 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
966 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
967 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
968 cs->dwExStyle |= WS_EX_WINDOWEDGE;
970 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
972 /* Create the window structure */
974 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, unicode )))
976 hwnd = wndPtr->hwndSelf;
978 /* Fill the window structure */
980 wndPtr->tid = GetCurrentThreadId();
981 wndPtr->hInstance = cs->hInstance;
983 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
984 wndPtr->dwExStyle = cs->dwExStyle;
986 wndPtr->helpContext = 0;
987 wndPtr->pVScroll = NULL;
988 wndPtr->pHScroll = NULL;
989 wndPtr->userdata = 0;
991 wndPtr->hIconSmall = 0;
992 wndPtr->hSysMenu = 0;
993 wndPtr->flags |= (flags & WIN_ISWIN32);
995 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
998 * Correct the window styles.
1000 * It affects only the style loaded into the WIN structure.
1003 if (!(wndPtr->dwStyle & WS_CHILD))
1005 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1006 if (!(wndPtr->dwStyle & WS_POPUP))
1007 wndPtr->dwStyle |= WS_CAPTION;
1011 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1012 * why does the user get to set it?
1015 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1016 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1017 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1019 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1021 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1022 wndPtr->flags |= WIN_NEED_SIZE;
1024 SERVER_START_REQ( set_window_info )
1027 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1028 req->style = wndPtr->dwStyle;
1029 req->ex_style = wndPtr->dwExStyle;
1030 req->instance = (void *)wndPtr->hInstance;
1031 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1032 req->extra_offset = -1;
1033 wine_server_call( req );
1037 /* Set the window menu */
1039 if (!(wndPtr->dwStyle & WS_CHILD))
1043 if (!MENU_SetMenu(hwnd, cs->hMenu))
1045 WIN_ReleasePtr( wndPtr );
1046 free_window_handle( hwnd );
1052 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1055 if (!cs->hInstance || HIWORD(cs->hInstance))
1056 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1058 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1060 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1064 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1065 WIN_ReleasePtr( wndPtr );
1067 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1069 WIN_DestroyWindow( hwnd );
1073 /* Notify the parent window only */
1075 send_parent_notify( hwnd, WM_CREATE );
1076 if (!IsWindow( hwnd )) return 0;
1078 if (cs->style & WS_VISIBLE)
1080 if (cs->style & WS_MAXIMIZE)
1082 else if (cs->style & WS_MINIMIZE)
1083 sw = SW_SHOWMINIMIZED;
1085 ShowWindow( hwnd, sw );
1086 if (cs->dwExStyle & WS_EX_MDICHILD)
1088 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1089 /* ShowWindow won't activate child windows */
1090 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1094 /* Call WH_SHELL hook */
1096 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1097 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1099 TRACE("created window %p\n", hwnd);
1104 /***********************************************************************
1105 * CreateWindow (USER.41)
1107 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1108 DWORD style, INT16 x, INT16 y, INT16 width,
1109 INT16 height, HWND16 parent, HMENU16 menu,
1110 HINSTANCE16 instance, LPVOID data )
1112 return CreateWindowEx16( 0, className, windowName, style,
1113 x, y, width, height, parent, menu, instance, data );
1117 /***********************************************************************
1118 * CreateWindowEx (USER.452)
1120 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1121 LPCSTR windowName, DWORD style, INT16 x,
1122 INT16 y, INT16 width, INT16 height,
1123 HWND16 parent, HMENU16 menu,
1124 HINSTANCE16 instance, LPVOID data )
1130 /* Find the class atom */
1132 if (HIWORD(className))
1134 if (!(classAtom = GlobalFindAtomA( className )))
1136 ERR( "bad class name %s\n", debugstr_a(className) );
1142 classAtom = LOWORD(className);
1143 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1145 ERR( "bad atom %x\n", classAtom);
1151 /* Fix the coordinates */
1153 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1154 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1155 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1156 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1158 /* Create the window */
1160 cs.lpCreateParams = data;
1161 cs.hInstance = HINSTANCE_32(instance);
1162 cs.hMenu = HMENU_32(menu);
1163 cs.hwndParent = WIN_Handle32( parent );
1165 cs.lpszName = windowName;
1166 cs.lpszClass = className;
1167 cs.dwExStyle = exStyle;
1169 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, 0 ));
1173 /***********************************************************************
1174 * CreateWindowExA (USER32.@)
1176 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1177 LPCSTR windowName, DWORD style, INT x,
1178 INT y, INT width, INT height,
1179 HWND parent, HMENU menu,
1180 HINSTANCE instance, LPVOID data )
1186 /* Find the class atom */
1188 if (HIWORD(className))
1190 if (!(classAtom = GlobalFindAtomA( className )))
1192 ERR( "bad class name %s\n", debugstr_a(className) );
1198 classAtom = LOWORD(className);
1199 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1201 ERR( "bad atom %x\n", classAtom);
1207 /* Create the window */
1209 cs.lpCreateParams = data;
1210 cs.hInstance = instance;
1212 cs.hwndParent = parent;
1218 cs.lpszName = windowName;
1219 cs.lpszClass = className;
1220 cs.dwExStyle = exStyle;
1222 return WIN_CreateWindowEx( &cs, classAtom, WIN_ISWIN32 );
1226 /***********************************************************************
1227 * CreateWindowExW (USER32.@)
1229 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1230 LPCWSTR windowName, DWORD style, INT x,
1231 INT y, INT width, INT height,
1232 HWND parent, HMENU menu,
1233 HINSTANCE instance, LPVOID data )
1239 /* Find the class atom */
1241 if (HIWORD(className))
1243 if (!(classAtom = GlobalFindAtomW( className )))
1245 ERR( "bad class name %s\n", debugstr_w(className) );
1251 classAtom = LOWORD(className);
1252 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1254 ERR( "bad atom %x\n", classAtom);
1260 /* Create the window */
1262 cs.lpCreateParams = data;
1263 cs.hInstance = instance;
1265 cs.hwndParent = parent;
1271 cs.lpszName = windowName;
1272 cs.lpszClass = className;
1273 cs.dwExStyle = exStyle;
1275 /* Note: we rely on the fact that CREATESTRUCTA and */
1276 /* CREATESTRUCTW have the same layout. */
1277 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_ISWIN32 | WIN_ISUNICODE );
1281 /***********************************************************************
1282 * WIN_SendDestroyMsg
1284 static void WIN_SendDestroyMsg( HWND hwnd )
1288 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1290 if (hwnd == info.hwndCaret) DestroyCaret();
1291 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1295 * Send the WM_DESTROY to the window.
1297 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1300 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1301 * make sure that the window still exists when we come back.
1308 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1310 for (i = 0; pWndArray[i]; i++)
1312 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1314 HeapFree( GetProcessHeap(), 0, pWndArray );
1317 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1321 /***********************************************************************
1322 * DestroyWindow (USER32.@)
1324 BOOL WINAPI DestroyWindow( HWND hwnd )
1328 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1330 SetLastError( ERROR_ACCESS_DENIED );
1334 TRACE("(%p)\n", hwnd);
1338 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1340 if (MENU_IsMenuActive() == hwnd)
1343 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1347 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1348 send_parent_notify( hwnd, WM_DESTROY );
1350 else if (!GetWindow( hwnd, GW_OWNER ))
1352 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1353 /* FIXME: clean up palette - see "Internals" p.352 */
1356 if (!IsWindow(hwnd)) return TRUE;
1358 /* Hide the window */
1359 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1361 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1363 ShowWindow( hwnd, SW_HIDE );
1365 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1366 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1369 if (!IsWindow(hwnd)) return TRUE;
1371 /* Recursively destroy owned windows */
1378 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1381 for (i = 0; list[i]; i++)
1383 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1384 if (WIN_IsCurrentThread( list[i] ))
1386 DestroyWindow( list[i] );
1390 WIN_SetOwner( list[i], 0 );
1392 HeapFree( GetProcessHeap(), 0, list );
1394 if (!got_one) break;
1398 /* Send destroy messages */
1400 WIN_SendDestroyMsg( hwnd );
1401 if (!IsWindow( hwnd )) return TRUE;
1403 if (GetClipboardOwner() == hwnd)
1404 CLIPBOARD_ReleaseOwner();
1406 /* Destroy the window storage */
1408 WIN_DestroyWindow( hwnd );
1413 /***********************************************************************
1414 * CloseWindow (USER32.@)
1416 BOOL WINAPI CloseWindow( HWND hwnd )
1418 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1419 ShowWindow( hwnd, SW_MINIMIZE );
1424 /***********************************************************************
1425 * OpenIcon (USER32.@)
1427 BOOL WINAPI OpenIcon( HWND hwnd )
1429 if (!IsIconic( hwnd )) return FALSE;
1430 ShowWindow( hwnd, SW_SHOWNORMAL );
1435 /***********************************************************************
1438 * Implementation of FindWindow() and FindWindowEx().
1440 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1445 WCHAR *buffer = NULL;
1447 if (!parent) parent = GetDesktopWindow();
1450 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1451 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1454 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1458 child = WIN_GetFullHandle( child );
1459 while (list[i] && list[i] != child) i++;
1460 if (!list[i]) goto done;
1461 i++; /* start from next window */
1468 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1475 HeapFree( GetProcessHeap(), 0, list );
1476 HeapFree( GetProcessHeap(), 0, buffer );
1482 /***********************************************************************
1483 * FindWindowA (USER32.@)
1485 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1487 HWND ret = FindWindowExA( 0, 0, className, title );
1488 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1493 /***********************************************************************
1494 * FindWindowExA (USER32.@)
1496 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1497 LPCSTR className, LPCSTR title )
1506 /* If the atom doesn't exist, then no class */
1507 /* with this name exists either. */
1508 if (!(atom = GlobalFindAtomA( className )))
1510 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1514 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1516 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1517 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1518 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1519 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1520 HeapFree( GetProcessHeap(), 0, buffer );
1525 /***********************************************************************
1526 * FindWindowExW (USER32.@)
1528 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1529 LPCWSTR className, LPCWSTR title )
1535 /* If the atom doesn't exist, then no class */
1536 /* with this name exists either. */
1537 if (!(atom = GlobalFindAtomW( className )))
1539 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1543 return WIN_FindWindow( parent, child, atom, title );
1547 /***********************************************************************
1548 * FindWindowW (USER32.@)
1550 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1552 return FindWindowExW( 0, 0, className, title );
1556 /**********************************************************************
1557 * GetDesktopWindow (USER32.@)
1559 HWND WINAPI GetDesktopWindow(void)
1561 struct user_thread_info *thread_info = get_user_thread_info();
1563 if (thread_info->desktop) return thread_info->desktop;
1565 SERVER_START_REQ( get_desktop_window )
1568 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1572 if (!thread_info->desktop)
1575 PROCESS_INFORMATION pi;
1576 WCHAR command_line[] = {'e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1578 memset( &si, 0, sizeof(si) );
1580 if (CreateProcessW( NULL, command_line, NULL, NULL, FALSE, DETACHED_PROCESS,
1581 NULL, NULL, &si, &pi ))
1583 TRACE( "started explorer pid %04lx tid %04lx\n", pi.dwProcessId, pi.dwThreadId );
1584 WaitForInputIdle( pi.hProcess, 10000 );
1585 CloseHandle( pi.hThread );
1586 CloseHandle( pi.hProcess );
1589 else WARN( "failed to start explorer, err %ld\n", GetLastError() );
1591 SERVER_START_REQ( get_desktop_window )
1594 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1599 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1600 ERR( "failed to create desktop window\n" );
1602 return thread_info->desktop;
1606 /*******************************************************************
1607 * EnableWindow (USER32.@)
1609 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1614 if (is_broadcast(hwnd))
1616 SetLastError( ERROR_INVALID_PARAMETER );
1620 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1621 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1625 TRACE("( %p, %d )\n", hwnd, enable);
1627 retvalue = !IsWindowEnabled( hwnd );
1629 if (enable && retvalue)
1631 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1632 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1634 else if (!enable && !retvalue)
1638 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1640 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1642 if (hwnd == GetFocus())
1643 SetFocus( 0 ); /* A disabled window can't have the focus */
1645 capture_wnd = GetCapture();
1646 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1647 ReleaseCapture(); /* A disabled window can't capture the mouse */
1649 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1655 /***********************************************************************
1656 * IsWindowEnabled (USER32.@)
1658 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1660 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1664 /***********************************************************************
1665 * IsWindowUnicode (USER32.@)
1667 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1670 BOOL retvalue = FALSE;
1672 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1674 if (wndPtr == WND_DESKTOP) return TRUE;
1676 if (wndPtr != WND_OTHER_PROCESS)
1678 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1679 WIN_ReleasePtr( wndPtr );
1683 SERVER_START_REQ( get_window_info )
1686 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1694 /**********************************************************************
1695 * GetWindowWord (USER32.@)
1697 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1702 WND *wndPtr = WIN_GetPtr( hwnd );
1705 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1708 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1710 SERVER_START_REQ( set_window_info )
1713 req->flags = 0; /* don't set anything, just retrieve */
1714 req->extra_offset = offset;
1715 req->extra_size = sizeof(retvalue);
1716 if (!wine_server_call_err( req ))
1717 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1722 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1724 WARN("Invalid offset %d\n", offset );
1725 SetLastError( ERROR_INVALID_INDEX );
1727 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1728 WIN_ReleasePtr( wndPtr );
1734 case GWLP_HWNDPARENT:
1735 return GetWindowLongPtrW( hwnd, offset );
1737 case GWLP_HINSTANCE:
1739 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1741 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1745 WARN("Invalid offset %d\n", offset );
1751 /**********************************************************************
1752 * SetWindowWord (USER32.@)
1754 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1762 case GWLP_HINSTANCE:
1763 case GWLP_HWNDPARENT:
1764 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1768 WARN("Invalid offset %d\n", offset );
1769 SetLastError( ERROR_INVALID_INDEX );
1774 wndPtr = WIN_GetPtr( hwnd );
1775 if (wndPtr == WND_DESKTOP)
1777 SetLastError( ERROR_ACCESS_DENIED );
1780 if (wndPtr == WND_OTHER_PROCESS)
1783 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1784 offset, newval, hwnd );
1789 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1793 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1795 WARN("Invalid offset %d\n", offset );
1796 WIN_ReleasePtr(wndPtr);
1797 SetLastError( ERROR_INVALID_INDEX );
1801 SERVER_START_REQ( set_window_info )
1804 req->flags = SET_WIN_EXTRA;
1805 req->extra_offset = offset;
1806 req->extra_size = sizeof(newval);
1807 memcpy( &req->extra_value, &newval, sizeof(newval) );
1808 if (!wine_server_call_err( req ))
1810 void *ptr = (char *)wndPtr->wExtra + offset;
1811 memcpy( &retval, ptr, sizeof(retval) );
1812 memcpy( ptr, &newval, sizeof(newval) );
1816 WIN_ReleasePtr( wndPtr );
1821 /**********************************************************************
1824 * Helper function for GetWindowLong().
1826 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, BOOL unicode )
1828 LONG_PTR retvalue = 0;
1831 if (offset == GWLP_HWNDPARENT)
1833 HWND parent = GetAncestor( hwnd, GA_PARENT );
1834 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1835 return (ULONG_PTR)parent;
1838 if (!(wndPtr = WIN_GetPtr( hwnd )))
1840 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1844 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1846 if (offset == GWLP_WNDPROC)
1848 SetLastError( ERROR_ACCESS_DENIED );
1851 SERVER_START_REQ( set_window_info )
1854 req->flags = 0; /* don't set anything, just retrieve */
1855 req->extra_offset = (offset >= 0) ? offset : -1;
1856 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1857 if (!wine_server_call_err( req ))
1861 case GWL_STYLE: retvalue = reply->old_style; break;
1862 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1863 case GWLP_ID: retvalue = reply->old_id; break;
1864 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1865 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1867 if (offset >= 0) retvalue = reply->old_extra_value;
1868 else SetLastError( ERROR_INVALID_INDEX );
1877 /* now we have a valid wndPtr */
1881 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1883 WARN("Invalid offset %d\n", offset );
1884 WIN_ReleasePtr( wndPtr );
1885 SetLastError( ERROR_INVALID_INDEX );
1888 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
1889 /* Special case for dialog window procedure */
1890 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1891 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1892 WIN_ReleasePtr( wndPtr );
1898 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1899 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1900 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1901 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1902 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode ); break;
1903 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1905 WARN("Unknown offset %d\n", offset );
1906 SetLastError( ERROR_INVALID_INDEX );
1909 WIN_ReleasePtr(wndPtr);
1914 /**********************************************************************
1917 * Helper function for SetWindowLong().
1919 * 0 is the failure code. However, in the case of failure SetLastError
1920 * must be set to distinguish between a 0 return value and a failure.
1922 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval, BOOL unicode )
1926 LONG_PTR retval = 0;
1929 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1931 if (is_broadcast(hwnd))
1933 SetLastError( ERROR_INVALID_PARAMETER );
1937 if (!(wndPtr = WIN_GetPtr( hwnd )))
1939 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1942 if (wndPtr == WND_DESKTOP)
1944 /* can't change anything on the desktop window */
1945 SetLastError( ERROR_ACCESS_DENIED );
1948 if (wndPtr == WND_OTHER_PROCESS)
1950 if (offset == GWLP_WNDPROC)
1952 SetLastError( ERROR_ACCESS_DENIED );
1955 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1958 /* first some special cases */
1964 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1965 style.styleNew = newval;
1966 WIN_ReleasePtr( wndPtr );
1967 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1968 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1969 newval = style.styleNew;
1971 case GWLP_HWNDPARENT:
1972 if (wndPtr->parent == GetDesktopWindow())
1974 WIN_ReleasePtr( wndPtr );
1975 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1979 WIN_ReleasePtr( wndPtr );
1980 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1984 UINT old_flags = wndPtr->flags;
1985 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1986 if (unicode) wndPtr->winproc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1987 else wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1988 if (WINPROC_IsUnicode( wndPtr->winproc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1989 else wndPtr->flags &= ~WIN_ISUNICODE;
1990 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1992 WIN_ReleasePtr( wndPtr );
1995 /* update is_unicode flag on the server side */
1999 case GWLP_HINSTANCE:
2003 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2005 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2006 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
2007 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2008 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2009 WIN_ReleasePtr( wndPtr );
2014 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
2016 WARN("Invalid offset %d\n", offset );
2017 WIN_ReleasePtr( wndPtr );
2018 SetLastError( ERROR_INVALID_INDEX );
2023 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2024 if (*ptr == newval) /* already set to the same value */
2026 WIN_ReleasePtr( wndPtr );
2033 SERVER_START_REQ( set_window_info )
2036 req->extra_offset = -1;
2040 req->flags = SET_WIN_STYLE;
2041 req->style = newval;
2044 req->flags = SET_WIN_EXSTYLE;
2045 req->ex_style = newval;
2048 req->flags = SET_WIN_ID;
2051 case GWLP_HINSTANCE:
2052 req->flags = SET_WIN_INSTANCE;
2053 req->instance = (void *)newval;
2056 req->flags = SET_WIN_UNICODE;
2057 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2060 req->flags = SET_WIN_USERDATA;
2061 req->user_data = (void *)newval;
2064 req->flags = SET_WIN_EXTRA;
2065 req->extra_offset = offset;
2066 req->extra_size = sizeof(newval);
2067 memcpy( &req->extra_value, &newval, sizeof(newval) );
2069 if ((ok = !wine_server_call_err( req )))
2074 wndPtr->dwStyle = newval;
2075 retval = reply->old_style;
2078 wndPtr->dwExStyle = newval;
2079 retval = reply->old_ex_style;
2082 wndPtr->wIDmenu = newval;
2083 retval = reply->old_id;
2085 case GWLP_HINSTANCE:
2086 wndPtr->hInstance = (HINSTANCE)newval;
2087 retval = (ULONG_PTR)reply->old_instance;
2092 wndPtr->userdata = newval;
2093 retval = (ULONG_PTR)reply->old_user_data;
2097 void *ptr = (char *)wndPtr->wExtra + offset;
2098 memcpy( &retval, ptr, sizeof(retval) );
2099 memcpy( ptr, &newval, sizeof(newval) );
2106 WIN_ReleasePtr( wndPtr );
2110 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2112 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2113 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2119 /**********************************************************************
2120 * GetWindowLong (USER.135)
2122 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2126 BOOL is_winproc = (offset == GWLP_WNDPROC);
2130 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2132 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2135 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2137 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2140 * Some programs try to access last element from 16 bit
2141 * code using illegal offset value. Hopefully this is
2142 * what those programs really expect.
2144 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2146 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2147 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2152 WARN("Invalid offset %d\n", offset );
2153 WIN_ReleasePtr( wndPtr );
2154 SetLastError( ERROR_INVALID_INDEX );
2158 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2159 WIN_ReleasePtr( wndPtr );
2162 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2163 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2168 /**********************************************************************
2169 * GetWindowLongA (USER32.@)
2171 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2173 return WIN_GetWindowLong( hwnd, offset, FALSE );
2177 /**********************************************************************
2178 * GetWindowLongW (USER32.@)
2180 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2182 return WIN_GetWindowLong( hwnd, offset, TRUE );
2186 /**********************************************************************
2187 * SetWindowLong (USER.136)
2189 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2192 BOOL is_winproc = (offset == GWLP_WNDPROC);
2194 if (offset == DWLP_DLGPROC)
2196 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2198 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2201 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2203 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2204 (wndPtr->flags & WIN_ISDIALOG));
2205 WIN_ReleasePtr( wndPtr );
2211 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2212 WNDPROC old_proc = (WNDPROC)SetWindowLongA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2213 return (LONG)WINPROC_GetProc16( (WNDPROC)old_proc, FALSE );
2215 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2219 /**********************************************************************
2220 * SetWindowLongA (USER32.@)
2222 * See SetWindowLongW.
2224 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2226 return WIN_SetWindowLong( hwnd, offset, newval, FALSE );
2230 /**********************************************************************
2231 * SetWindowLongW (USER32.@) Set window attribute
2233 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2234 * value in a window's extra memory.
2236 * The _hwnd_ parameter specifies the window. is the handle to a
2237 * window that has extra memory. The _newval_ parameter contains the
2238 * new attribute or extra memory value. If positive, the _offset_
2239 * parameter is the byte-addressed location in the window's extra
2240 * memory to set. If negative, _offset_ specifies the window
2241 * attribute to set, and should be one of the following values:
2243 * GWL_EXSTYLE The window's extended window style
2245 * GWL_STYLE The window's window style.
2247 * GWLP_WNDPROC Pointer to the window's window procedure.
2249 * GWLP_HINSTANCE The window's pplication instance handle.
2251 * GWLP_ID The window's identifier.
2253 * GWLP_USERDATA The window's user-specified data.
2255 * If the window is a dialog box, the _offset_ parameter can be one of
2256 * the following values:
2258 * DWLP_DLGPROC The address of the window's dialog box procedure.
2260 * DWLP_MSGRESULT The return value of a message
2261 * that the dialog box procedure processed.
2263 * DWLP_USER Application specific information.
2267 * If successful, returns the previous value located at _offset_. Otherwise,
2272 * Extra memory for a window class is specified by a nonzero cbWndExtra
2273 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2274 * time of class creation.
2276 * Using GWL_WNDPROC to set a new window procedure effectively creates
2277 * a window subclass. Use CallWindowProc() in the new windows procedure
2278 * to pass messages to the superclass's window procedure.
2280 * The user data is reserved for use by the application which created
2283 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2284 * instead, call the EnableWindow() function to change the window's
2287 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2288 * SetParent() instead.
2291 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2292 * it sends WM_STYLECHANGING before changing the settings
2293 * and WM_STYLECHANGED afterwards.
2294 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2296 LONG WINAPI SetWindowLongW(
2297 HWND hwnd, /* [in] window to alter */
2298 INT offset, /* [in] offset, in bytes, of location to alter */
2299 LONG newval /* [in] new value of location */
2301 return WIN_SetWindowLong( hwnd, offset, newval, TRUE );
2305 /*******************************************************************
2306 * GetWindowTextA (USER32.@)
2308 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2312 if (!lpString) return 0;
2314 if (WIN_IsCurrentProcess( hwnd ))
2315 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2317 /* when window belongs to other process, don't send a message */
2318 if (nMaxCount <= 0) return 0;
2319 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2320 get_server_window_text( hwnd, buffer, nMaxCount );
2321 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2322 lpString[nMaxCount-1] = 0;
2323 HeapFree( GetProcessHeap(), 0, buffer );
2324 return strlen(lpString);
2328 /*******************************************************************
2329 * InternalGetWindowText (USER32.@)
2331 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2335 if (nMaxCount <= 0) return 0;
2336 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2337 if (win == WND_DESKTOP) lpString[0] = 0;
2338 else if (win != WND_OTHER_PROCESS)
2340 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2341 else lpString[0] = 0;
2342 WIN_ReleasePtr( win );
2346 get_server_window_text( hwnd, lpString, nMaxCount );
2348 return strlenW(lpString);
2352 /*******************************************************************
2353 * GetWindowTextW (USER32.@)
2355 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2357 if (!lpString) return 0;
2359 if (WIN_IsCurrentProcess( hwnd ))
2360 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2362 /* when window belongs to other process, don't send a message */
2363 if (nMaxCount <= 0) return 0;
2364 get_server_window_text( hwnd, lpString, nMaxCount );
2365 return strlenW(lpString);
2369 /*******************************************************************
2370 * SetWindowTextA (USER32.@)
2371 * SetWindowText (USER32.@)
2373 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2375 if (is_broadcast(hwnd))
2377 SetLastError( ERROR_INVALID_PARAMETER );
2380 if (!WIN_IsCurrentProcess( hwnd ))
2381 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2382 debugstr_a(lpString), hwnd );
2383 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2387 /*******************************************************************
2388 * SetWindowTextW (USER32.@)
2390 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2392 if (is_broadcast(hwnd))
2394 SetLastError( ERROR_INVALID_PARAMETER );
2397 if (!WIN_IsCurrentProcess( hwnd ))
2398 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2399 debugstr_w(lpString), hwnd );
2400 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2404 /*******************************************************************
2405 * GetWindowTextLengthA (USER32.@)
2407 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2409 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2412 /*******************************************************************
2413 * GetWindowTextLengthW (USER32.@)
2415 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2417 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2421 /*******************************************************************
2422 * IsWindow (USER32.@)
2424 BOOL WINAPI IsWindow( HWND hwnd )
2429 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2430 if (ptr == WND_DESKTOP) return TRUE;
2432 if (ptr != WND_OTHER_PROCESS)
2434 WIN_ReleasePtr( ptr );
2438 /* check other processes */
2439 SERVER_START_REQ( get_window_info )
2442 ret = !wine_server_call_err( req );
2449 /***********************************************************************
2450 * GetWindowThreadProcessId (USER32.@)
2452 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2457 if (!(ptr = WIN_GetPtr( hwnd )))
2459 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2463 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2465 /* got a valid window */
2467 if (process) *process = GetCurrentProcessId();
2468 WIN_ReleasePtr( ptr );
2472 /* check other processes */
2473 SERVER_START_REQ( get_window_info )
2476 if (!wine_server_call_err( req ))
2478 tid = (DWORD)reply->tid;
2479 if (process) *process = (DWORD)reply->pid;
2487 /*****************************************************************
2488 * GetParent (USER32.@)
2490 HWND WINAPI GetParent( HWND hwnd )
2495 if (!(wndPtr = WIN_GetPtr( hwnd )))
2497 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2500 if (wndPtr == WND_DESKTOP) return 0;
2501 if (wndPtr == WND_OTHER_PROCESS)
2503 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2504 if (style & (WS_POPUP | WS_CHILD))
2506 SERVER_START_REQ( get_window_tree )
2509 if (!wine_server_call_err( req ))
2511 if (style & WS_POPUP) retvalue = reply->owner;
2512 else if (style & WS_CHILD) retvalue = reply->parent;
2520 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2521 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2522 WIN_ReleasePtr( wndPtr );
2528 /*****************************************************************
2529 * GetAncestor (USER32.@)
2531 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2534 HWND *list, ret = 0;
2539 if (!(win = WIN_GetPtr( hwnd )))
2541 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2544 if (win == WND_DESKTOP) return 0;
2545 if (win != WND_OTHER_PROCESS)
2548 WIN_ReleasePtr( win );
2550 else /* need to query the server */
2552 SERVER_START_REQ( get_window_tree )
2555 if (!wine_server_call_err( req )) ret = reply->parent;
2562 if (!(list = list_window_parents( hwnd ))) return 0;
2564 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2568 while (list[count]) count++;
2569 ret = list[count - 2]; /* get the one before the desktop */
2571 HeapFree( GetProcessHeap(), 0, list );
2575 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2578 HWND parent = GetParent( ret );
2588 /*****************************************************************
2589 * SetParent (USER32.@)
2591 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2595 if (is_broadcast(hwnd) || is_broadcast(parent))
2597 SetLastError(ERROR_INVALID_PARAMETER);
2601 if (!parent) parent = GetDesktopWindow();
2602 else parent = WIN_GetFullHandle( parent );
2604 if (!IsWindow( parent ))
2606 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2610 /* Some applications try to set a child as a parent */
2611 if (IsChild(hwnd, parent))
2613 SetLastError( ERROR_INVALID_PARAMETER );
2617 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2618 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2620 return USER_Driver->pSetParent( full_handle, parent );
2624 /*******************************************************************
2625 * IsChild (USER32.@)
2627 BOOL WINAPI IsChild( HWND parent, HWND child )
2629 HWND *list = list_window_parents( child );
2633 if (!list) return FALSE;
2634 parent = WIN_GetFullHandle( parent );
2635 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2636 ret = (list[i] != 0);
2637 HeapFree( GetProcessHeap(), 0, list );
2642 /***********************************************************************
2643 * IsWindowVisible (USER32.@)
2645 BOOL WINAPI IsWindowVisible( HWND hwnd )
2651 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2652 if (!(list = list_window_parents( hwnd ))) return TRUE;
2653 for (i = 0; list[i]; i++)
2654 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2656 HeapFree( GetProcessHeap(), 0, list );
2661 /***********************************************************************
2662 * WIN_IsWindowDrawable
2664 * hwnd is drawable when it is visible, all parents are not
2665 * minimized, and it is itself not minimized unless we are
2666 * trying to draw its default class icon.
2668 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2673 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2675 if (!(style & WS_VISIBLE)) return FALSE;
2676 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2678 if (!(list = list_window_parents( hwnd ))) return TRUE;
2679 for (i = 0; list[i]; i++)
2680 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2683 HeapFree( GetProcessHeap(), 0, list );
2688 /*******************************************************************
2689 * GetTopWindow (USER32.@)
2691 HWND WINAPI GetTopWindow( HWND hwnd )
2693 if (!hwnd) hwnd = GetDesktopWindow();
2694 return GetWindow( hwnd, GW_CHILD );
2698 /*******************************************************************
2699 * GetWindow (USER32.@)
2701 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2705 if (rel == GW_OWNER) /* this one may be available locally */
2707 WND *wndPtr = WIN_GetPtr( hwnd );
2710 SetLastError( ERROR_INVALID_HANDLE );
2713 if (wndPtr == WND_DESKTOP) return 0;
2714 if (wndPtr != WND_OTHER_PROCESS)
2716 retval = wndPtr->owner;
2717 WIN_ReleasePtr( wndPtr );
2720 /* else fall through to server call */
2723 SERVER_START_REQ( get_window_tree )
2726 if (!wine_server_call_err( req ))
2731 retval = reply->first_sibling;
2734 retval = reply->last_sibling;
2737 retval = reply->next_sibling;
2740 retval = reply->prev_sibling;
2743 retval = reply->owner;
2746 retval = reply->first_child;
2756 /*******************************************************************
2757 * ShowOwnedPopups (USER32.@)
2759 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2763 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2765 if (!win_array) return TRUE;
2767 while (win_array[count]) count++;
2768 while (--count >= 0)
2770 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2771 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2772 if (pWnd == WND_OTHER_PROCESS) continue;
2775 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2777 WIN_ReleasePtr( pWnd );
2778 /* In Windows, ShowOwnedPopups(TRUE) generates
2779 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2780 * regardless of the state of the owner
2782 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2788 if (pWnd->dwStyle & WS_VISIBLE)
2790 WIN_ReleasePtr( pWnd );
2791 /* In Windows, ShowOwnedPopups(FALSE) generates
2792 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2793 * regardless of the state of the owner
2795 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2799 WIN_ReleasePtr( pWnd );
2801 HeapFree( GetProcessHeap(), 0, win_array );
2806 /*******************************************************************
2807 * GetLastActivePopup (USER32.@)
2809 HWND WINAPI GetLastActivePopup( HWND hwnd )
2813 SERVER_START_REQ( get_window_info )
2816 if (!wine_server_call_err( req )) retval = reply->last_active;
2823 /*******************************************************************
2826 * Build an array of the children of a given window. The array must be
2827 * freed with HeapFree. Returns NULL when no windows are found.
2829 HWND *WIN_ListChildren( HWND hwnd )
2831 return list_window_children( hwnd, 0, 0 );
2835 /*******************************************************************
2836 * EnumWindows (USER32.@)
2838 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2844 USER_CheckNotLock();
2846 /* We have to build a list of all windows first, to avoid */
2847 /* unpleasant side-effects, for instance if the callback */
2848 /* function changes the Z-order of the windows. */
2850 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2852 /* Now call the callback function for every window */
2854 for (i = 0; list[i]; i++)
2856 /* Make sure that the window still exists */
2857 if (!IsWindow( list[i] )) continue;
2858 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2860 HeapFree( GetProcessHeap(), 0, list );
2865 /**********************************************************************
2866 * EnumThreadWindows (USER32.@)
2868 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2873 USER_CheckNotLock();
2875 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2877 /* Now call the callback function for every window */
2879 for (i = 0; list[i]; i++)
2880 if (!func( list[i], lParam )) break;
2881 HeapFree( GetProcessHeap(), 0, list );
2886 /**********************************************************************
2887 * WIN_EnumChildWindows
2889 * Helper function for EnumChildWindows().
2891 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2896 for ( ; *list; list++)
2898 /* Make sure that the window still exists */
2899 if (!IsWindow( *list )) continue;
2900 /* Build children list first */
2901 childList = WIN_ListChildren( *list );
2903 ret = func( *list, lParam );
2907 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2908 HeapFree( GetProcessHeap(), 0, childList );
2910 if (!ret) return FALSE;
2916 /**********************************************************************
2917 * EnumChildWindows (USER32.@)
2919 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2924 USER_CheckNotLock();
2926 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2927 ret = WIN_EnumChildWindows( list, func, lParam );
2928 HeapFree( GetProcessHeap(), 0, list );
2933 /*******************************************************************
2934 * AnyPopup (USER.52)
2936 BOOL16 WINAPI AnyPopup16(void)
2942 /*******************************************************************
2943 * AnyPopup (USER32.@)
2945 BOOL WINAPI AnyPopup(void)
2949 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2951 if (!list) return FALSE;
2952 for (i = 0; list[i]; i++)
2954 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2956 retvalue = (list[i] != 0);
2957 HeapFree( GetProcessHeap(), 0, list );
2962 /*******************************************************************
2963 * FlashWindow (USER32.@)
2965 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2969 TRACE("%p\n", hWnd);
2971 if (IsIconic( hWnd ))
2973 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2975 wndPtr = WIN_GetPtr(hWnd);
2976 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2977 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2979 wndPtr->flags |= WIN_NCACTIVATED;
2983 wndPtr->flags &= ~WIN_NCACTIVATED;
2985 WIN_ReleasePtr( wndPtr );
2992 wndPtr = WIN_GetPtr(hWnd);
2993 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2994 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2996 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2997 else wparam = (hWnd == GetForegroundWindow());
2999 WIN_ReleasePtr( wndPtr );
3000 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3005 /*******************************************************************
3006 * FlashWindowEx (USER32.@)
3008 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3010 FIXME("%p\n", pfwi);
3014 /*******************************************************************
3015 * GetWindowContextHelpId (USER32.@)
3017 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3020 WND *wnd = WIN_GetPtr( hwnd );
3021 if (!wnd || wnd == WND_DESKTOP) return 0;
3022 if (wnd == WND_OTHER_PROCESS)
3024 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3027 retval = wnd->helpContext;
3028 WIN_ReleasePtr( wnd );
3033 /*******************************************************************
3034 * SetWindowContextHelpId (USER32.@)
3036 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3038 WND *wnd = WIN_GetPtr( hwnd );
3039 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3040 if (wnd == WND_OTHER_PROCESS)
3042 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3045 wnd->helpContext = id;
3046 WIN_ReleasePtr( wnd );
3051 /*******************************************************************
3052 * DragDetect (USER32.@)
3054 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3058 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3059 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3061 rect.left = pt.x - wDragWidth;
3062 rect.right = pt.x + wDragWidth;
3064 rect.top = pt.y - wDragHeight;
3065 rect.bottom = pt.y + wDragHeight;
3071 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3073 if( msg.message == WM_LBUTTONUP )
3078 if( msg.message == WM_MOUSEMOVE )
3081 tmp.x = LOWORD(msg.lParam);
3082 tmp.y = HIWORD(msg.lParam);
3083 if( !PtInRect( &rect, tmp ))
3095 /******************************************************************************
3096 * GetWindowModuleFileNameA (USER32.@)
3098 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3100 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3101 hwnd, lpszFileName, cchFileNameMax);
3105 /******************************************************************************
3106 * GetWindowModuleFileNameW (USER32.@)
3108 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3110 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3111 hwnd, lpszFileName, cchFileNameMax);
3115 /******************************************************************************
3116 * GetWindowInfo (USER32.@)
3118 * Note: tests show that Windows doesn't check cbSize of the structure.
3120 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3122 if (!pwi) return FALSE;
3123 if (!IsWindow(hwnd)) return FALSE;
3125 GetWindowRect(hwnd, &pwi->rcWindow);
3126 GetClientRect(hwnd, &pwi->rcClient);
3127 /* translate to screen coordinates */
3128 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3130 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3131 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3132 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3134 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3135 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3137 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3138 pwi->wCreatorVersion = 0x0400;
3143 /******************************************************************************
3144 * SwitchDesktop (USER32.@)
3146 * NOTES: Sets the current input or interactive desktop.
3148 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3150 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3154 /*****************************************************************************
3155 * SetLayeredWindowAttributes (USER32.@)
3157 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3158 BYTE bAlpha, DWORD dwFlags )
3160 FIXME("(%p,0x%.8lx,%d,%ld): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3164 /*****************************************************************************
3165 * UpdateLayeredWindow (USER32.@)
3167 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3168 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3171 FIXME("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%ld): stub!\n",
3172 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3176 /* 64bit versions */
3178 #ifdef GetWindowLongPtrW
3179 #undef GetWindowLongPtrW
3182 #ifdef GetWindowLongPtrA
3183 #undef GetWindowLongPtrA
3186 #ifdef SetWindowLongPtrW
3187 #undef SetWindowLongPtrW
3190 #ifdef SetWindowLongPtrA
3191 #undef SetWindowLongPtrA
3194 /*****************************************************************************
3195 * GetWindowLongPtrW (USER32.@)
3197 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3203 /*****************************************************************************
3204 * GetWindowLongPtrA (USER32.@)
3206 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3212 /*****************************************************************************
3213 * SetWindowLongPtrW (USER32.@)
3215 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3221 /*****************************************************************************
3222 * SetWindowLongPtrA (USER32.@)
3224 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )