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"
36 #include "user_private.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(win);
44 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
45 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
47 /**********************************************************************/
50 static void *user_handles[NB_USER_HANDLES];
52 /***********************************************************************
53 * create_window_handle
55 * Create a window handle with the server.
57 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
58 HINSTANCE instance, 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_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1040 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1044 if (!MENU_SetMenu(hwnd, cs->hMenu))
1046 WIN_ReleasePtr( wndPtr );
1047 free_window_handle( hwnd );
1053 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1056 if (!cs->hInstance || HIWORD(cs->hInstance))
1057 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1059 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1061 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1065 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1066 WIN_ReleasePtr( wndPtr );
1068 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1070 WIN_DestroyWindow( hwnd );
1074 /* Notify the parent window only */
1076 send_parent_notify( hwnd, WM_CREATE );
1077 if (!IsWindow( hwnd )) return 0;
1079 if (cs->style & WS_VISIBLE)
1081 if (cs->style & WS_MAXIMIZE)
1083 else if (cs->style & WS_MINIMIZE)
1084 sw = SW_SHOWMINIMIZED;
1086 ShowWindow( hwnd, sw );
1087 if (cs->dwExStyle & WS_EX_MDICHILD)
1089 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1090 /* ShowWindow won't activate child windows */
1091 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1095 /* Call WH_SHELL hook */
1097 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1098 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1100 TRACE("created window %p\n", hwnd);
1105 /***********************************************************************
1106 * CreateWindow (USER.41)
1108 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1109 DWORD style, INT16 x, INT16 y, INT16 width,
1110 INT16 height, HWND16 parent, HMENU16 menu,
1111 HINSTANCE16 instance, LPVOID data )
1113 return CreateWindowEx16( 0, className, windowName, style,
1114 x, y, width, height, parent, menu, instance, data );
1118 /***********************************************************************
1119 * CreateWindowEx (USER.452)
1121 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1122 LPCSTR windowName, DWORD style, INT16 x,
1123 INT16 y, INT16 width, INT16 height,
1124 HWND16 parent, HMENU16 menu,
1125 HINSTANCE16 instance, LPVOID data )
1131 /* Find the class atom */
1133 if (HIWORD(className))
1135 if (!(classAtom = GlobalFindAtomA( className )))
1137 ERR( "bad class name %s\n", debugstr_a(className) );
1143 classAtom = LOWORD(className);
1144 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1146 ERR( "bad atom %x\n", classAtom);
1152 /* Fix the coordinates */
1154 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1155 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1156 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1157 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1159 /* Create the window */
1161 cs.lpCreateParams = data;
1162 cs.hInstance = HINSTANCE_32(instance);
1163 cs.hMenu = HMENU_32(menu);
1164 cs.hwndParent = WIN_Handle32( parent );
1166 cs.lpszName = windowName;
1167 cs.lpszClass = className;
1168 cs.dwExStyle = exStyle;
1170 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, 0 ));
1174 /***********************************************************************
1175 * CreateWindowExA (USER32.@)
1177 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1178 LPCSTR windowName, DWORD style, INT x,
1179 INT y, INT width, INT height,
1180 HWND parent, HMENU menu,
1181 HINSTANCE instance, LPVOID data )
1187 /* Find the class atom */
1189 if (HIWORD(className))
1191 if (!(classAtom = GlobalFindAtomA( className )))
1193 ERR( "bad class name %s\n", debugstr_a(className) );
1199 classAtom = LOWORD(className);
1200 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1202 ERR( "bad atom %x\n", classAtom);
1208 /* Create the window */
1210 cs.lpCreateParams = data;
1211 cs.hInstance = instance;
1213 cs.hwndParent = parent;
1219 cs.lpszName = windowName;
1220 cs.lpszClass = className;
1221 cs.dwExStyle = exStyle;
1223 return WIN_CreateWindowEx( &cs, classAtom, WIN_ISWIN32 );
1227 /***********************************************************************
1228 * CreateWindowExW (USER32.@)
1230 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1231 LPCWSTR windowName, DWORD style, INT x,
1232 INT y, INT width, INT height,
1233 HWND parent, HMENU menu,
1234 HINSTANCE instance, LPVOID data )
1240 /* Find the class atom */
1242 if (HIWORD(className))
1244 if (!(classAtom = GlobalFindAtomW( className )))
1246 ERR( "bad class name %s\n", debugstr_w(className) );
1252 classAtom = LOWORD(className);
1253 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1255 ERR( "bad atom %x\n", classAtom);
1261 /* Create the window */
1263 cs.lpCreateParams = data;
1264 cs.hInstance = instance;
1266 cs.hwndParent = parent;
1272 cs.lpszName = windowName;
1273 cs.lpszClass = className;
1274 cs.dwExStyle = exStyle;
1276 /* Note: we rely on the fact that CREATESTRUCTA and */
1277 /* CREATESTRUCTW have the same layout. */
1278 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_ISWIN32 | WIN_ISUNICODE );
1282 /***********************************************************************
1283 * WIN_SendDestroyMsg
1285 static void WIN_SendDestroyMsg( HWND hwnd )
1289 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1291 if (hwnd == info.hwndCaret) DestroyCaret();
1292 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1294 USER_Driver->pResetSelectionOwner( hwnd, TRUE );
1297 * Send the WM_DESTROY to the window.
1299 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1302 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1303 * make sure that the window still exists when we come back.
1310 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1312 for (i = 0; pWndArray[i]; i++)
1314 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1316 HeapFree( GetProcessHeap(), 0, pWndArray );
1319 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1323 /***********************************************************************
1324 * DestroyWindow (USER32.@)
1326 BOOL WINAPI DestroyWindow( HWND hwnd )
1330 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1332 SetLastError( ERROR_ACCESS_DENIED );
1336 TRACE("(%p)\n", hwnd);
1340 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1342 if (MENU_IsMenuActive() == hwnd)
1345 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1349 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1350 send_parent_notify( hwnd, WM_DESTROY );
1352 else if (!GetWindow( hwnd, GW_OWNER ))
1354 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1355 /* FIXME: clean up palette - see "Internals" p.352 */
1358 if (!IsWindow(hwnd)) return TRUE;
1360 USER_Driver->pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1362 /* Hide the window */
1363 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1365 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1367 ShowWindow( hwnd, SW_HIDE );
1369 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1370 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1373 if (!IsWindow(hwnd)) return TRUE;
1375 /* Recursively destroy owned windows */
1382 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1385 for (i = 0; list[i]; i++)
1387 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1388 if (WIN_IsCurrentThread( list[i] ))
1390 DestroyWindow( list[i] );
1394 WIN_SetOwner( list[i], 0 );
1396 HeapFree( GetProcessHeap(), 0, list );
1398 if (!got_one) break;
1402 /* Send destroy messages */
1404 WIN_SendDestroyMsg( hwnd );
1405 if (!IsWindow( hwnd )) return TRUE;
1407 if (GetClipboardOwner() == hwnd)
1408 CLIPBOARD_ReleaseOwner();
1410 /* Destroy the window storage */
1412 WIN_DestroyWindow( hwnd );
1417 /***********************************************************************
1418 * CloseWindow (USER32.@)
1420 BOOL WINAPI CloseWindow( HWND hwnd )
1422 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1423 ShowWindow( hwnd, SW_MINIMIZE );
1428 /***********************************************************************
1429 * OpenIcon (USER32.@)
1431 BOOL WINAPI OpenIcon( HWND hwnd )
1433 if (!IsIconic( hwnd )) return FALSE;
1434 ShowWindow( hwnd, SW_SHOWNORMAL );
1439 /***********************************************************************
1442 * Implementation of FindWindow() and FindWindowEx().
1444 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1449 WCHAR *buffer = NULL;
1451 if (!parent) parent = GetDesktopWindow();
1454 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1455 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1458 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1462 child = WIN_GetFullHandle( child );
1463 while (list[i] && list[i] != child) i++;
1464 if (!list[i]) goto done;
1465 i++; /* start from next window */
1472 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1479 HeapFree( GetProcessHeap(), 0, list );
1480 HeapFree( GetProcessHeap(), 0, buffer );
1486 /***********************************************************************
1487 * FindWindowA (USER32.@)
1489 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1491 HWND ret = FindWindowExA( 0, 0, className, title );
1492 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1497 /***********************************************************************
1498 * FindWindowExA (USER32.@)
1500 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1501 LPCSTR className, LPCSTR title )
1510 /* If the atom doesn't exist, then no class */
1511 /* with this name exists either. */
1512 if (!(atom = GlobalFindAtomA( className )))
1514 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1518 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1520 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1521 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1522 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1523 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1524 HeapFree( GetProcessHeap(), 0, buffer );
1529 /***********************************************************************
1530 * FindWindowExW (USER32.@)
1532 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1533 LPCWSTR className, LPCWSTR title )
1539 /* If the atom doesn't exist, then no class */
1540 /* with this name exists either. */
1541 if (!(atom = GlobalFindAtomW( className )))
1543 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1547 return WIN_FindWindow( parent, child, atom, title );
1551 /***********************************************************************
1552 * FindWindowW (USER32.@)
1554 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1556 return FindWindowExW( 0, 0, className, title );
1560 /**********************************************************************
1561 * GetDesktopWindow (USER32.@)
1563 HWND WINAPI GetDesktopWindow(void)
1565 struct user_thread_info *thread_info = get_user_thread_info();
1567 if (thread_info->desktop) return thread_info->desktop;
1569 SERVER_START_REQ( get_desktop_window )
1572 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1576 if (!thread_info->desktop)
1579 PROCESS_INFORMATION pi;
1580 WCHAR command_line[] = {'e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1582 memset( &si, 0, sizeof(si) );
1584 if (CreateProcessW( NULL, command_line, NULL, NULL, FALSE, DETACHED_PROCESS,
1585 NULL, NULL, &si, &pi ))
1587 TRACE( "started explorer pid %04lx tid %04lx\n", pi.dwProcessId, pi.dwThreadId );
1588 WaitForInputIdle( pi.hProcess, 10000 );
1589 CloseHandle( pi.hThread );
1590 CloseHandle( pi.hProcess );
1593 else WARN( "failed to start explorer, err %ld\n", GetLastError() );
1595 SERVER_START_REQ( get_desktop_window )
1598 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1603 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1604 ERR( "failed to create desktop window\n" );
1606 return thread_info->desktop;
1610 /*******************************************************************
1611 * EnableWindow (USER32.@)
1613 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1618 if (is_broadcast(hwnd))
1620 SetLastError( ERROR_INVALID_PARAMETER );
1624 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1625 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1629 TRACE("( %p, %d )\n", hwnd, enable);
1631 retvalue = !IsWindowEnabled( hwnd );
1633 if (enable && retvalue)
1635 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1636 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1638 else if (!enable && !retvalue)
1642 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1644 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1646 if (hwnd == GetFocus())
1647 SetFocus( 0 ); /* A disabled window can't have the focus */
1649 capture_wnd = GetCapture();
1650 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1651 ReleaseCapture(); /* A disabled window can't capture the mouse */
1653 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1659 /***********************************************************************
1660 * IsWindowEnabled (USER32.@)
1662 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1664 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1668 /***********************************************************************
1669 * IsWindowUnicode (USER32.@)
1671 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1674 BOOL retvalue = FALSE;
1676 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1678 if (wndPtr == WND_DESKTOP) return TRUE;
1680 if (wndPtr != WND_OTHER_PROCESS)
1682 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1683 WIN_ReleasePtr( wndPtr );
1687 SERVER_START_REQ( get_window_info )
1690 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1698 /**********************************************************************
1699 * GetWindowWord (USER32.@)
1701 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1706 WND *wndPtr = WIN_GetPtr( hwnd );
1709 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1712 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1714 SERVER_START_REQ( set_window_info )
1717 req->flags = 0; /* don't set anything, just retrieve */
1718 req->extra_offset = offset;
1719 req->extra_size = sizeof(retvalue);
1720 if (!wine_server_call_err( req ))
1721 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1726 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1728 WARN("Invalid offset %d\n", offset );
1729 SetLastError( ERROR_INVALID_INDEX );
1731 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1732 WIN_ReleasePtr( wndPtr );
1738 case GWLP_HWNDPARENT:
1739 return GetWindowLongPtrW( hwnd, offset );
1741 case GWLP_HINSTANCE:
1743 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1745 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1749 WARN("Invalid offset %d\n", offset );
1755 /**********************************************************************
1756 * SetWindowWord (USER32.@)
1758 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1766 case GWLP_HINSTANCE:
1767 case GWLP_HWNDPARENT:
1768 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1772 WARN("Invalid offset %d\n", offset );
1773 SetLastError( ERROR_INVALID_INDEX );
1778 wndPtr = WIN_GetPtr( hwnd );
1779 if (wndPtr == WND_DESKTOP)
1781 SetLastError( ERROR_ACCESS_DENIED );
1784 if (wndPtr == WND_OTHER_PROCESS)
1787 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1788 offset, newval, hwnd );
1793 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1797 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1799 WARN("Invalid offset %d\n", offset );
1800 WIN_ReleasePtr(wndPtr);
1801 SetLastError( ERROR_INVALID_INDEX );
1805 SERVER_START_REQ( set_window_info )
1808 req->flags = SET_WIN_EXTRA;
1809 req->extra_offset = offset;
1810 req->extra_size = sizeof(newval);
1811 memcpy( &req->extra_value, &newval, sizeof(newval) );
1812 if (!wine_server_call_err( req ))
1814 void *ptr = (char *)wndPtr->wExtra + offset;
1815 memcpy( &retval, ptr, sizeof(retval) );
1816 memcpy( ptr, &newval, sizeof(newval) );
1820 WIN_ReleasePtr( wndPtr );
1825 /**********************************************************************
1828 * Helper function for GetWindowLong().
1830 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, BOOL unicode )
1832 LONG_PTR retvalue = 0;
1835 if (offset == GWLP_HWNDPARENT)
1837 HWND parent = GetAncestor( hwnd, GA_PARENT );
1838 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1839 return (ULONG_PTR)parent;
1842 if (!(wndPtr = WIN_GetPtr( hwnd )))
1844 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1848 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1850 if (offset == GWLP_WNDPROC)
1852 SetLastError( ERROR_ACCESS_DENIED );
1855 SERVER_START_REQ( set_window_info )
1858 req->flags = 0; /* don't set anything, just retrieve */
1859 req->extra_offset = (offset >= 0) ? offset : -1;
1860 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1861 if (!wine_server_call_err( req ))
1865 case GWL_STYLE: retvalue = reply->old_style; break;
1866 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1867 case GWLP_ID: retvalue = reply->old_id; break;
1868 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1869 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1871 if (offset >= 0) retvalue = reply->old_extra_value;
1872 else SetLastError( ERROR_INVALID_INDEX );
1881 /* now we have a valid wndPtr */
1885 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1887 WARN("Invalid offset %d\n", offset );
1888 WIN_ReleasePtr( wndPtr );
1889 SetLastError( ERROR_INVALID_INDEX );
1892 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
1893 /* Special case for dialog window procedure */
1894 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1895 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1896 WIN_ReleasePtr( wndPtr );
1902 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1903 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1904 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1905 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1906 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode ); break;
1907 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1909 WARN("Unknown offset %d\n", offset );
1910 SetLastError( ERROR_INVALID_INDEX );
1913 WIN_ReleasePtr(wndPtr);
1918 /**********************************************************************
1921 * Helper function for SetWindowLong().
1923 * 0 is the failure code. However, in the case of failure SetLastError
1924 * must be set to distinguish between a 0 return value and a failure.
1926 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval, BOOL unicode )
1930 LONG_PTR retval = 0;
1933 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1935 if (is_broadcast(hwnd))
1937 SetLastError( ERROR_INVALID_PARAMETER );
1941 if (!(wndPtr = WIN_GetPtr( hwnd )))
1943 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1946 if (wndPtr == WND_DESKTOP)
1948 /* can't change anything on the desktop window */
1949 SetLastError( ERROR_ACCESS_DENIED );
1952 if (wndPtr == WND_OTHER_PROCESS)
1954 if (offset == GWLP_WNDPROC)
1956 SetLastError( ERROR_ACCESS_DENIED );
1959 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1962 /* first some special cases */
1968 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1969 style.styleNew = newval;
1970 WIN_ReleasePtr( wndPtr );
1971 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1972 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1973 newval = style.styleNew;
1975 case GWLP_HWNDPARENT:
1976 if (wndPtr->parent == GetDesktopWindow())
1978 WIN_ReleasePtr( wndPtr );
1979 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1983 WIN_ReleasePtr( wndPtr );
1984 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1988 UINT old_flags = wndPtr->flags;
1989 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1990 if (unicode) wndPtr->winproc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1991 else wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1992 if (WINPROC_IsUnicode( wndPtr->winproc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1993 else wndPtr->flags &= ~WIN_ISUNICODE;
1994 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1996 WIN_ReleasePtr( wndPtr );
1999 /* update is_unicode flag on the server side */
2003 case GWLP_HINSTANCE:
2007 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2009 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2010 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
2011 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2012 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2013 WIN_ReleasePtr( wndPtr );
2018 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
2020 WARN("Invalid offset %d\n", offset );
2021 WIN_ReleasePtr( wndPtr );
2022 SetLastError( ERROR_INVALID_INDEX );
2027 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2028 if (*ptr == newval) /* already set to the same value */
2030 WIN_ReleasePtr( wndPtr );
2037 SERVER_START_REQ( set_window_info )
2040 req->extra_offset = -1;
2044 req->flags = SET_WIN_STYLE;
2045 req->style = newval;
2048 req->flags = SET_WIN_EXSTYLE;
2049 req->ex_style = newval;
2052 req->flags = SET_WIN_ID;
2055 case GWLP_HINSTANCE:
2056 req->flags = SET_WIN_INSTANCE;
2057 req->instance = (void *)newval;
2060 req->flags = SET_WIN_UNICODE;
2061 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2064 req->flags = SET_WIN_USERDATA;
2065 req->user_data = (void *)newval;
2068 req->flags = SET_WIN_EXTRA;
2069 req->extra_offset = offset;
2070 req->extra_size = sizeof(newval);
2071 memcpy( &req->extra_value, &newval, sizeof(newval) );
2073 if ((ok = !wine_server_call_err( req )))
2078 wndPtr->dwStyle = newval;
2079 retval = reply->old_style;
2082 wndPtr->dwExStyle = newval;
2083 retval = reply->old_ex_style;
2086 wndPtr->wIDmenu = newval;
2087 retval = reply->old_id;
2089 case GWLP_HINSTANCE:
2090 wndPtr->hInstance = (HINSTANCE)newval;
2091 retval = (ULONG_PTR)reply->old_instance;
2096 wndPtr->userdata = newval;
2097 retval = (ULONG_PTR)reply->old_user_data;
2101 void *ptr = (char *)wndPtr->wExtra + offset;
2102 memcpy( &retval, ptr, sizeof(retval) );
2103 memcpy( ptr, &newval, sizeof(newval) );
2110 WIN_ReleasePtr( wndPtr );
2114 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2116 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2117 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2123 /**********************************************************************
2124 * GetWindowLong (USER.135)
2126 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2130 BOOL is_winproc = (offset == GWLP_WNDPROC);
2134 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2136 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2139 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2141 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2144 * Some programs try to access last element from 16 bit
2145 * code using illegal offset value. Hopefully this is
2146 * what those programs really expect.
2148 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2150 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2151 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2156 WARN("Invalid offset %d\n", offset );
2157 WIN_ReleasePtr( wndPtr );
2158 SetLastError( ERROR_INVALID_INDEX );
2162 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2163 WIN_ReleasePtr( wndPtr );
2166 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2167 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2172 /**********************************************************************
2173 * GetWindowLongA (USER32.@)
2175 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2177 return WIN_GetWindowLong( hwnd, offset, FALSE );
2181 /**********************************************************************
2182 * GetWindowLongW (USER32.@)
2184 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2186 return WIN_GetWindowLong( hwnd, offset, TRUE );
2190 /**********************************************************************
2191 * SetWindowLong (USER.136)
2193 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2196 BOOL is_winproc = (offset == GWLP_WNDPROC);
2198 if (offset == DWLP_DLGPROC)
2200 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2202 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2205 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2207 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2208 (wndPtr->flags & WIN_ISDIALOG));
2209 WIN_ReleasePtr( wndPtr );
2215 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2216 WNDPROC old_proc = (WNDPROC)SetWindowLongA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2217 return (LONG)WINPROC_GetProc16( (WNDPROC)old_proc, FALSE );
2219 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2223 /**********************************************************************
2224 * SetWindowLongA (USER32.@)
2226 * See SetWindowLongW.
2228 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2230 return WIN_SetWindowLong( hwnd, offset, newval, FALSE );
2234 /**********************************************************************
2235 * SetWindowLongW (USER32.@) Set window attribute
2237 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2238 * value in a window's extra memory.
2240 * The _hwnd_ parameter specifies the window. is the handle to a
2241 * window that has extra memory. The _newval_ parameter contains the
2242 * new attribute or extra memory value. If positive, the _offset_
2243 * parameter is the byte-addressed location in the window's extra
2244 * memory to set. If negative, _offset_ specifies the window
2245 * attribute to set, and should be one of the following values:
2247 * GWL_EXSTYLE The window's extended window style
2249 * GWL_STYLE The window's window style.
2251 * GWLP_WNDPROC Pointer to the window's window procedure.
2253 * GWLP_HINSTANCE The window's pplication instance handle.
2255 * GWLP_ID The window's identifier.
2257 * GWLP_USERDATA The window's user-specified data.
2259 * If the window is a dialog box, the _offset_ parameter can be one of
2260 * the following values:
2262 * DWLP_DLGPROC The address of the window's dialog box procedure.
2264 * DWLP_MSGRESULT The return value of a message
2265 * that the dialog box procedure processed.
2267 * DWLP_USER Application specific information.
2271 * If successful, returns the previous value located at _offset_. Otherwise,
2276 * Extra memory for a window class is specified by a nonzero cbWndExtra
2277 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2278 * time of class creation.
2280 * Using GWL_WNDPROC to set a new window procedure effectively creates
2281 * a window subclass. Use CallWindowProc() in the new windows procedure
2282 * to pass messages to the superclass's window procedure.
2284 * The user data is reserved for use by the application which created
2287 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2288 * instead, call the EnableWindow() function to change the window's
2291 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2292 * SetParent() instead.
2295 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2296 * it sends WM_STYLECHANGING before changing the settings
2297 * and WM_STYLECHANGED afterwards.
2298 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2300 LONG WINAPI SetWindowLongW(
2301 HWND hwnd, /* [in] window to alter */
2302 INT offset, /* [in] offset, in bytes, of location to alter */
2303 LONG newval /* [in] new value of location */
2305 return WIN_SetWindowLong( hwnd, offset, newval, TRUE );
2309 /*******************************************************************
2310 * GetWindowTextA (USER32.@)
2312 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2316 if (!lpString) return 0;
2318 if (WIN_IsCurrentProcess( hwnd ))
2319 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2321 /* when window belongs to other process, don't send a message */
2322 if (nMaxCount <= 0) return 0;
2323 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2324 get_server_window_text( hwnd, buffer, nMaxCount );
2325 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2326 lpString[nMaxCount-1] = 0;
2327 HeapFree( GetProcessHeap(), 0, buffer );
2328 return strlen(lpString);
2332 /*******************************************************************
2333 * InternalGetWindowText (USER32.@)
2335 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2339 if (nMaxCount <= 0) return 0;
2340 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2341 if (win == WND_DESKTOP) lpString[0] = 0;
2342 else if (win != WND_OTHER_PROCESS)
2344 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2345 else lpString[0] = 0;
2346 WIN_ReleasePtr( win );
2350 get_server_window_text( hwnd, lpString, nMaxCount );
2352 return strlenW(lpString);
2356 /*******************************************************************
2357 * GetWindowTextW (USER32.@)
2359 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2361 if (!lpString) return 0;
2363 if (WIN_IsCurrentProcess( hwnd ))
2364 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2366 /* when window belongs to other process, don't send a message */
2367 if (nMaxCount <= 0) return 0;
2368 get_server_window_text( hwnd, lpString, nMaxCount );
2369 return strlenW(lpString);
2373 /*******************************************************************
2374 * SetWindowTextA (USER32.@)
2375 * SetWindowText (USER32.@)
2377 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2379 if (is_broadcast(hwnd))
2381 SetLastError( ERROR_INVALID_PARAMETER );
2384 if (!WIN_IsCurrentProcess( hwnd ))
2385 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2386 debugstr_a(lpString), hwnd );
2387 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2391 /*******************************************************************
2392 * SetWindowTextW (USER32.@)
2394 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2396 if (is_broadcast(hwnd))
2398 SetLastError( ERROR_INVALID_PARAMETER );
2401 if (!WIN_IsCurrentProcess( hwnd ))
2402 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2403 debugstr_w(lpString), hwnd );
2404 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2408 /*******************************************************************
2409 * GetWindowTextLengthA (USER32.@)
2411 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2413 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2416 /*******************************************************************
2417 * GetWindowTextLengthW (USER32.@)
2419 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2421 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2425 /*******************************************************************
2426 * IsWindow (USER32.@)
2428 BOOL WINAPI IsWindow( HWND hwnd )
2433 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2434 if (ptr == WND_DESKTOP) return TRUE;
2436 if (ptr != WND_OTHER_PROCESS)
2438 WIN_ReleasePtr( ptr );
2442 /* check other processes */
2443 SERVER_START_REQ( get_window_info )
2446 ret = !wine_server_call_err( req );
2453 /***********************************************************************
2454 * GetWindowThreadProcessId (USER32.@)
2456 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2461 if (!(ptr = WIN_GetPtr( hwnd )))
2463 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2467 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2469 /* got a valid window */
2471 if (process) *process = GetCurrentProcessId();
2472 WIN_ReleasePtr( ptr );
2476 /* check other processes */
2477 SERVER_START_REQ( get_window_info )
2480 if (!wine_server_call_err( req ))
2482 tid = (DWORD)reply->tid;
2483 if (process) *process = (DWORD)reply->pid;
2491 /*****************************************************************
2492 * GetParent (USER32.@)
2494 HWND WINAPI GetParent( HWND hwnd )
2499 if (!(wndPtr = WIN_GetPtr( hwnd )))
2501 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2504 if (wndPtr == WND_DESKTOP) return 0;
2505 if (wndPtr == WND_OTHER_PROCESS)
2507 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2508 if (style & (WS_POPUP | WS_CHILD))
2510 SERVER_START_REQ( get_window_tree )
2513 if (!wine_server_call_err( req ))
2515 if (style & WS_POPUP) retvalue = reply->owner;
2516 else if (style & WS_CHILD) retvalue = reply->parent;
2524 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2525 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2526 WIN_ReleasePtr( wndPtr );
2532 /*****************************************************************
2533 * GetAncestor (USER32.@)
2535 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2538 HWND *list, ret = 0;
2543 if (!(win = WIN_GetPtr( hwnd )))
2545 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2548 if (win == WND_DESKTOP) return 0;
2549 if (win != WND_OTHER_PROCESS)
2552 WIN_ReleasePtr( win );
2554 else /* need to query the server */
2556 SERVER_START_REQ( get_window_tree )
2559 if (!wine_server_call_err( req )) ret = reply->parent;
2566 if (!(list = list_window_parents( hwnd ))) return 0;
2568 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2572 while (list[count]) count++;
2573 ret = list[count - 2]; /* get the one before the desktop */
2575 HeapFree( GetProcessHeap(), 0, list );
2579 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2582 HWND parent = GetParent( ret );
2592 /*****************************************************************
2593 * SetParent (USER32.@)
2595 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2599 if (is_broadcast(hwnd) || is_broadcast(parent))
2601 SetLastError(ERROR_INVALID_PARAMETER);
2605 if (!parent) parent = GetDesktopWindow();
2606 else parent = WIN_GetFullHandle( parent );
2608 if (!IsWindow( parent ))
2610 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2614 /* Some applications try to set a child as a parent */
2615 if (IsChild(hwnd, parent))
2617 SetLastError( ERROR_INVALID_PARAMETER );
2621 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2622 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2624 return USER_Driver->pSetParent( full_handle, parent );
2628 /*******************************************************************
2629 * IsChild (USER32.@)
2631 BOOL WINAPI IsChild( HWND parent, HWND child )
2633 HWND *list = list_window_parents( child );
2637 if (!list) return FALSE;
2638 parent = WIN_GetFullHandle( parent );
2639 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2640 ret = (list[i] != 0);
2641 HeapFree( GetProcessHeap(), 0, list );
2646 /***********************************************************************
2647 * IsWindowVisible (USER32.@)
2649 BOOL WINAPI IsWindowVisible( HWND hwnd )
2655 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2656 if (!(list = list_window_parents( hwnd ))) return TRUE;
2657 for (i = 0; list[i]; i++)
2658 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2660 HeapFree( GetProcessHeap(), 0, list );
2665 /***********************************************************************
2666 * WIN_IsWindowDrawable
2668 * hwnd is drawable when it is visible, all parents are not
2669 * minimized, and it is itself not minimized unless we are
2670 * trying to draw its default class icon.
2672 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2677 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2679 if (!(style & WS_VISIBLE)) return FALSE;
2680 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2682 if (!(list = list_window_parents( hwnd ))) return TRUE;
2683 for (i = 0; list[i]; i++)
2684 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2687 HeapFree( GetProcessHeap(), 0, list );
2692 /*******************************************************************
2693 * GetTopWindow (USER32.@)
2695 HWND WINAPI GetTopWindow( HWND hwnd )
2697 if (!hwnd) hwnd = GetDesktopWindow();
2698 return GetWindow( hwnd, GW_CHILD );
2702 /*******************************************************************
2703 * GetWindow (USER32.@)
2705 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2709 if (rel == GW_OWNER) /* this one may be available locally */
2711 WND *wndPtr = WIN_GetPtr( hwnd );
2714 SetLastError( ERROR_INVALID_HANDLE );
2717 if (wndPtr == WND_DESKTOP) return 0;
2718 if (wndPtr != WND_OTHER_PROCESS)
2720 retval = wndPtr->owner;
2721 WIN_ReleasePtr( wndPtr );
2724 /* else fall through to server call */
2727 SERVER_START_REQ( get_window_tree )
2730 if (!wine_server_call_err( req ))
2735 retval = reply->first_sibling;
2738 retval = reply->last_sibling;
2741 retval = reply->next_sibling;
2744 retval = reply->prev_sibling;
2747 retval = reply->owner;
2750 retval = reply->first_child;
2760 /*******************************************************************
2761 * ShowOwnedPopups (USER32.@)
2763 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2767 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2769 if (!win_array) return TRUE;
2771 while (win_array[count]) count++;
2772 while (--count >= 0)
2774 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2775 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2776 if (pWnd == WND_OTHER_PROCESS) continue;
2779 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2781 WIN_ReleasePtr( pWnd );
2782 /* In Windows, ShowOwnedPopups(TRUE) generates
2783 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2784 * regardless of the state of the owner
2786 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2792 if (pWnd->dwStyle & WS_VISIBLE)
2794 WIN_ReleasePtr( pWnd );
2795 /* In Windows, ShowOwnedPopups(FALSE) generates
2796 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2797 * regardless of the state of the owner
2799 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2803 WIN_ReleasePtr( pWnd );
2805 HeapFree( GetProcessHeap(), 0, win_array );
2810 /*******************************************************************
2811 * GetLastActivePopup (USER32.@)
2813 HWND WINAPI GetLastActivePopup( HWND hwnd )
2817 SERVER_START_REQ( get_window_info )
2820 if (!wine_server_call_err( req )) retval = reply->last_active;
2827 /*******************************************************************
2830 * Build an array of the children of a given window. The array must be
2831 * freed with HeapFree. Returns NULL when no windows are found.
2833 HWND *WIN_ListChildren( HWND hwnd )
2835 return list_window_children( hwnd, 0, 0 );
2839 /*******************************************************************
2840 * EnumWindows (USER32.@)
2842 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2848 USER_CheckNotLock();
2850 /* We have to build a list of all windows first, to avoid */
2851 /* unpleasant side-effects, for instance if the callback */
2852 /* function changes the Z-order of the windows. */
2854 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2856 /* Now call the callback function for every window */
2858 for (i = 0; list[i]; i++)
2860 /* Make sure that the window still exists */
2861 if (!IsWindow( list[i] )) continue;
2862 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2864 HeapFree( GetProcessHeap(), 0, list );
2869 /**********************************************************************
2870 * EnumThreadWindows (USER32.@)
2872 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2877 USER_CheckNotLock();
2879 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2881 /* Now call the callback function for every window */
2883 for (i = 0; list[i]; i++)
2884 if (!func( list[i], lParam )) break;
2885 HeapFree( GetProcessHeap(), 0, list );
2890 /**********************************************************************
2891 * WIN_EnumChildWindows
2893 * Helper function for EnumChildWindows().
2895 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2900 for ( ; *list; list++)
2902 /* Make sure that the window still exists */
2903 if (!IsWindow( *list )) continue;
2904 /* Build children list first */
2905 childList = WIN_ListChildren( *list );
2907 ret = func( *list, lParam );
2911 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2912 HeapFree( GetProcessHeap(), 0, childList );
2914 if (!ret) return FALSE;
2920 /**********************************************************************
2921 * EnumChildWindows (USER32.@)
2923 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2928 USER_CheckNotLock();
2930 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2931 ret = WIN_EnumChildWindows( list, func, lParam );
2932 HeapFree( GetProcessHeap(), 0, list );
2937 /*******************************************************************
2938 * AnyPopup (USER.52)
2940 BOOL16 WINAPI AnyPopup16(void)
2946 /*******************************************************************
2947 * AnyPopup (USER32.@)
2949 BOOL WINAPI AnyPopup(void)
2953 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2955 if (!list) return FALSE;
2956 for (i = 0; list[i]; i++)
2958 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2960 retvalue = (list[i] != 0);
2961 HeapFree( GetProcessHeap(), 0, list );
2966 /*******************************************************************
2967 * FlashWindow (USER32.@)
2969 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2973 TRACE("%p\n", hWnd);
2975 if (IsIconic( hWnd ))
2977 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2979 wndPtr = WIN_GetPtr(hWnd);
2980 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2981 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2983 wndPtr->flags |= WIN_NCACTIVATED;
2987 wndPtr->flags &= ~WIN_NCACTIVATED;
2989 WIN_ReleasePtr( wndPtr );
2996 wndPtr = WIN_GetPtr(hWnd);
2997 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2998 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3000 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3001 else wparam = (hWnd == GetForegroundWindow());
3003 WIN_ReleasePtr( wndPtr );
3004 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3009 /*******************************************************************
3010 * FlashWindowEx (USER32.@)
3012 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3014 FIXME("%p\n", pfwi);
3018 /*******************************************************************
3019 * GetWindowContextHelpId (USER32.@)
3021 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3024 WND *wnd = WIN_GetPtr( hwnd );
3025 if (!wnd || wnd == WND_DESKTOP) return 0;
3026 if (wnd == WND_OTHER_PROCESS)
3028 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3031 retval = wnd->helpContext;
3032 WIN_ReleasePtr( wnd );
3037 /*******************************************************************
3038 * SetWindowContextHelpId (USER32.@)
3040 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3042 WND *wnd = WIN_GetPtr( hwnd );
3043 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3044 if (wnd == WND_OTHER_PROCESS)
3046 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3049 wnd->helpContext = id;
3050 WIN_ReleasePtr( wnd );
3055 /*******************************************************************
3056 * DragDetect (USER32.@)
3058 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3062 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3063 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3065 rect.left = pt.x - wDragWidth;
3066 rect.right = pt.x + wDragWidth;
3068 rect.top = pt.y - wDragHeight;
3069 rect.bottom = pt.y + wDragHeight;
3075 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3077 if( msg.message == WM_LBUTTONUP )
3082 if( msg.message == WM_MOUSEMOVE )
3085 tmp.x = LOWORD(msg.lParam);
3086 tmp.y = HIWORD(msg.lParam);
3087 if( !PtInRect( &rect, tmp ))
3099 /******************************************************************************
3100 * GetWindowModuleFileNameA (USER32.@)
3102 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3104 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3105 hwnd, lpszFileName, cchFileNameMax);
3109 /******************************************************************************
3110 * GetWindowModuleFileNameW (USER32.@)
3112 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3114 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3115 hwnd, lpszFileName, cchFileNameMax);
3119 /******************************************************************************
3120 * GetWindowInfo (USER32.@)
3122 * Note: tests show that Windows doesn't check cbSize of the structure.
3124 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3126 if (!pwi) return FALSE;
3127 if (!IsWindow(hwnd)) return FALSE;
3129 GetWindowRect(hwnd, &pwi->rcWindow);
3130 GetClientRect(hwnd, &pwi->rcClient);
3131 /* translate to screen coordinates */
3132 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3134 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3135 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3136 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3138 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3139 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3141 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3142 pwi->wCreatorVersion = 0x0400;
3147 /******************************************************************************
3148 * SwitchDesktop (USER32.@)
3150 * NOTES: Sets the current input or interactive desktop.
3152 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3154 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3158 /*****************************************************************************
3159 * SetLayeredWindowAttributes (USER32.@)
3161 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3162 BYTE bAlpha, DWORD dwFlags )
3164 FIXME("(%p,0x%.8lx,%d,%ld): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3168 /*****************************************************************************
3169 * UpdateLayeredWindow (USER32.@)
3171 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3172 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3175 FIXME("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%ld): stub!\n",
3176 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);