2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
36 #include "user_private.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(win);
44 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
45 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
47 /**********************************************************************/
50 static void *user_handles[NB_USER_HANDLES];
52 /***********************************************************************
53 * create_window_handle
55 * Create a window handle with the server.
57 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
58 HINSTANCE instance, WINDOWPROCTYPE type )
62 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;
125 win->cbWndExtra = extra_bytes;
126 memset( win->wExtra, 0, extra_bytes );
127 CLASS_AddWindow( class, win, type );
132 /***********************************************************************
135 * Free a window handle.
137 static WND *free_window_handle( HWND hwnd )
140 WORD index = USER_HANDLE_TO_INDEX(hwnd);
142 if (index >= NB_USER_HANDLES) return NULL;
144 if ((ptr = user_handles[index]))
146 SERVER_START_REQ( destroy_window )
149 if (!wine_server_call_err( req ))
151 user_handles[index] = NULL;
160 HeapFree( GetProcessHeap(), 0, ptr );
165 /*******************************************************************
166 * list_window_children
168 * Build an array of the children of a given window. The array must be
169 * freed with HeapFree. Returns NULL when no windows are found.
171 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
180 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
182 SERVER_START_REQ( get_window_children )
187 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
188 if (!wine_server_call( req )) count = reply->count;
191 if (count && count < size)
196 HeapFree( GetProcessHeap(), 0, list );
198 size = count + 1; /* restart with a large enough buffer */
204 /*******************************************************************
205 * list_window_parents
207 * Build an array of all parents of a given window, starting with
208 * the immediate parent. The array must be freed with HeapFree.
209 * Returns NULL if window is a top-level window.
211 static HWND *list_window_parents( HWND hwnd )
215 int pos = 0, size = 16, count = 0;
217 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
222 if (!(win = WIN_GetPtr( current ))) goto empty;
223 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
224 if (win == WND_DESKTOP)
226 if (!pos) goto empty;
230 list[pos] = current = win->parent;
231 WIN_ReleasePtr( win );
232 if (++pos == size - 1)
234 /* need to grow the list */
235 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
236 if (!new_list) goto empty;
242 /* at least one parent belongs to another process, have to query the server */
247 SERVER_START_REQ( get_window_parents )
250 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
251 if (!wine_server_call( req )) count = reply->count;
254 if (!count) goto empty;
260 HeapFree( GetProcessHeap(), 0, list );
262 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
266 HeapFree( GetProcessHeap(), 0, list );
271 /*******************************************************************
274 static void send_parent_notify( HWND hwnd, UINT msg )
276 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
277 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
279 HWND parent = GetParent(hwnd);
280 if (parent && parent != GetDesktopWindow())
281 SendMessageW( parent, WM_PARENTNOTIFY,
282 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
287 /*******************************************************************
288 * get_server_window_text
290 * Retrieve the window text from the server.
292 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
296 SERVER_START_REQ( get_window_text )
299 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
300 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
303 text[len / sizeof(WCHAR)] = 0;
307 /***********************************************************************
310 * Return a pointer to the WND structure if local to the process,
311 * or WND_OTHER_PROCESS if handle may be valid in other process.
312 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
314 WND *WIN_GetPtr( HWND hwnd )
317 WORD index = USER_HANDLE_TO_INDEX(hwnd);
319 if (index >= NB_USER_HANDLES) return NULL;
322 if ((ptr = user_handles[index]))
324 if (ptr->dwMagic == WND_MAGIC &&
325 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
329 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
331 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
334 else ptr = WND_OTHER_PROCESS;
340 /***********************************************************************
341 * WIN_IsCurrentProcess
343 * Check whether a given window belongs to the current process (and return the full handle).
345 HWND WIN_IsCurrentProcess( HWND hwnd )
350 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
352 WIN_ReleasePtr( ptr );
357 /***********************************************************************
358 * WIN_IsCurrentThread
360 * Check whether a given window belongs to the current thread (and return the full handle).
362 HWND WIN_IsCurrentThread( HWND hwnd )
367 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
368 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
369 WIN_ReleasePtr( ptr );
374 /***********************************************************************
377 * Convert a 16-bit window handle to a full 32-bit handle.
379 HWND WIN_Handle32( HWND16 hwnd16 )
382 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
384 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
385 /* do sign extension for -2 and -3 */
386 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
388 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
390 if (ptr == WND_DESKTOP) return GetDesktopWindow();
392 if (ptr != WND_OTHER_PROCESS)
394 hwnd = ptr->hwndSelf;
395 WIN_ReleasePtr( ptr );
397 else /* may belong to another process */
399 SERVER_START_REQ( get_window_info )
402 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
410 /***********************************************************************
413 * Change the owner of a window.
415 HWND WIN_SetOwner( HWND hwnd, HWND owner )
417 WND *win = WIN_GetPtr( hwnd );
420 if (!win || win == WND_DESKTOP) return 0;
421 if (win == WND_OTHER_PROCESS)
423 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
426 SERVER_START_REQ( set_window_owner )
430 if (!wine_server_call( req ))
432 win->owner = reply->full_owner;
433 ret = reply->prev_owner;
437 WIN_ReleasePtr( win );
442 /***********************************************************************
445 * Change the style of a window.
447 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
450 ULONG new_style, old_style = 0;
451 WND *win = WIN_GetPtr( hwnd );
453 if (!win || win == WND_DESKTOP) return 0;
454 if (win == WND_OTHER_PROCESS)
457 ERR( "cannot set style %lx/%lx on other process window %p\n",
458 set_bits, clear_bits, hwnd );
461 new_style = (win->dwStyle | set_bits) & ~clear_bits;
462 if (new_style == win->dwStyle)
464 WIN_ReleasePtr( win );
467 SERVER_START_REQ( set_window_info )
470 req->flags = SET_WIN_STYLE;
471 req->style = new_style;
472 req->extra_offset = -1;
473 if ((ok = !wine_server_call( req )))
475 old_style = reply->old_style;
476 win->dwStyle = new_style;
480 WIN_ReleasePtr( win );
481 if (ok) USER_Driver->pSetWindowStyle( hwnd, old_style );
486 /***********************************************************************
489 * Get the window and client rectangles.
491 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
493 WND *win = WIN_GetPtr( hwnd );
496 if (!win) return FALSE;
497 if (win == WND_DESKTOP)
500 rect.left = rect.top = 0;
501 rect.right = GetSystemMetrics(SM_CXSCREEN);
502 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
503 if (rectWindow) *rectWindow = rect;
504 if (rectClient) *rectClient = rect;
506 else if (win == WND_OTHER_PROCESS)
508 SERVER_START_REQ( get_window_rectangles )
511 if ((ret = !wine_server_call( req )))
515 rectWindow->left = reply->window.left;
516 rectWindow->top = reply->window.top;
517 rectWindow->right = reply->window.right;
518 rectWindow->bottom = reply->window.bottom;
522 rectClient->left = reply->client.left;
523 rectClient->top = reply->client.top;
524 rectClient->right = reply->client.right;
525 rectClient->bottom = reply->client.bottom;
533 if (rectWindow) *rectWindow = win->rectWindow;
534 if (rectClient) *rectClient = win->rectClient;
535 WIN_ReleasePtr( win );
541 /***********************************************************************
544 * Destroy storage associated to a window. "Internals" p.358
546 LRESULT WIN_DestroyWindow( HWND hwnd )
550 HMENU menu = 0, sys_menu;
552 TRACE("%p\n", hwnd );
554 /* free child windows */
555 if ((list = WIN_ListChildren( hwnd )))
558 for (i = 0; list[i]; i++)
560 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
561 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
563 HeapFree( GetProcessHeap(), 0, list );
566 /* Unlink now so we won't bother with the children later on */
567 SERVER_START_REQ( set_parent )
571 wine_server_call( req );
576 * Send the WM_NCDESTROY to the window being destroyed.
578 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
580 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
582 WINPOS_CheckInternalPos( hwnd );
584 /* free resources associated with the window */
586 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
587 if (!(wndPtr->dwStyle & WS_CHILD)) menu = (HMENU)wndPtr->wIDmenu;
588 sys_menu = wndPtr->hSysMenu;
589 WIN_ReleasePtr( wndPtr );
591 if (menu) DestroyMenu( menu );
592 if (sys_menu) DestroyMenu( sys_menu );
594 USER_Driver->pDestroyWindow( hwnd );
596 free_window_handle( hwnd );
600 /***********************************************************************
601 * WIN_DestroyThreadWindows
603 * Destroy all children of 'wnd' owned by the current thread.
604 * Return TRUE if something was done.
606 void WIN_DestroyThreadWindows( HWND hwnd )
611 if (!(list = WIN_ListChildren( hwnd ))) return;
612 for (i = 0; list[i]; i++)
614 if (WIN_IsCurrentThread( list[i] ))
615 DestroyWindow( list[i] );
617 WIN_DestroyThreadWindows( list[i] );
619 HeapFree( GetProcessHeap(), 0, list );
623 /***********************************************************************
626 * Fix the coordinates - Helper for WIN_CreateWindowEx.
627 * returns default show mode in sw.
628 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
630 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
634 if (cs->dwExStyle & WS_EX_MDICHILD)
638 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
639 if (!(cs->style & WS_POPUP)) cs->hMenu = (HMENU)id;
641 TRACE("MDI child id %04x\n", id);
644 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
645 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
647 if (cs->style & (WS_CHILD | WS_POPUP))
649 if (cs->dwExStyle & WS_EX_MDICHILD)
651 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
656 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
658 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
663 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
665 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
669 else /* overlapped window */
673 GetStartupInfoW( &info );
675 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
677 /* Never believe Microsoft's documentation... CreateWindowEx doc says
678 * that if an overlapped window is created with WS_VISIBLE style bit
679 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
680 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
683 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
684 * 2) it does not ignore the y parameter as the docs claim; instead, it
685 * uses it as second parameter to ShowWindow() unless y is either
686 * CW_USEDEFAULT or CW_USEDEFAULT16.
688 * The fact that we didn't do 2) caused bogus windows pop up when wine
689 * was running apps that were using this obscure feature. Example -
690 * calc.exe that comes with Win98 (only Win98, it's different from
691 * the one that comes with Win95 and NT)
693 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
694 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
695 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
698 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
700 if (info.dwFlags & STARTF_USESIZE)
702 cs->cx = info.dwXSize;
703 cs->cy = info.dwYSize;
705 else /* if no other hint from the app, pick 3/4 of the screen real estate */
708 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
709 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
710 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
713 /* Handle case where only the cy values is set to default */
714 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
717 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
718 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
724 /* neither x nor cx are default. Check the y values .
725 * In the trace we see Outlook and Outlook Express using
726 * cy set to CW_USEDEFAULT when opening the address book.
728 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
730 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
731 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
732 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
737 /***********************************************************************
740 static void dump_window_styles( DWORD style, DWORD exstyle )
743 if(style & WS_POPUP) TRACE(" WS_POPUP");
744 if(style & WS_CHILD) TRACE(" WS_CHILD");
745 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
746 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
747 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
748 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
749 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
750 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
751 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
754 if(style & WS_BORDER) TRACE(" WS_BORDER");
755 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
757 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
758 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
759 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
760 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
761 if (style & WS_CHILD)
763 if(style & WS_GROUP) TRACE(" WS_GROUP");
764 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
768 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
769 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
772 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
773 #define DUMPED_STYLES \
793 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
798 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
799 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
800 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
801 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
802 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
803 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
804 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
805 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
806 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
807 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
808 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
809 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
810 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
811 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
812 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
813 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
814 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
815 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
817 #define DUMPED_EX_STYLES \
818 (WS_EX_DLGMODALFRAME | \
820 WS_EX_NOPARENTNOTIFY | \
822 WS_EX_ACCEPTFILES | \
823 WS_EX_TRANSPARENT | \
828 WS_EX_CONTEXTHELP | \
831 WS_EX_LEFTSCROLLBAR | \
832 WS_EX_CONTROLPARENT | \
837 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
839 #undef DUMPED_EX_STYLES
843 /***********************************************************************
846 * Implementation of CreateWindowEx().
848 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
849 WINDOWPROCTYPE type )
853 HWND hwnd, parent, owner, top_child = 0;
854 BOOL unicode = (type == WIN_PROC_32W);
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 (type == WIN_PROC_32W) ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
859 (type == WIN_PROC_32W) ? 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 );
863 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
865 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
866 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
868 /* Fix the styles for MDI children */
869 if (cs->dwExStyle & WS_EX_MDICHILD)
873 wndPtr = WIN_GetPtr(cs->hwndParent);
874 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
876 flags = wndPtr->flags;
877 WIN_ReleasePtr(wndPtr);
880 if (!(flags & WIN_ISMDICLIENT))
882 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
886 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
887 * MDICREATESTRUCT members have the originally passed values.
889 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
890 * have the same layout.
892 mdi_cs.szClass = cs->lpszClass;
893 mdi_cs.szTitle = cs->lpszName;
894 mdi_cs.hOwner = cs->hInstance;
899 mdi_cs.style = cs->style;
900 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
902 cs->lpCreateParams = (LPVOID)&mdi_cs;
904 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
906 if (cs->style & WS_POPUP)
908 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
911 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
915 cs->style &= ~WS_POPUP;
916 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
917 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
920 top_child = GetWindow(cs->hwndParent, GW_CHILD);
924 /* Restore current maximized child */
925 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
927 TRACE("Restoring current maximized child %p\n", top_child);
928 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
929 ShowWindow(top_child, SW_RESTORE);
930 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
935 /* Find the parent window */
937 parent = cs->hwndParent;
940 if (cs->hwndParent == HWND_MESSAGE)
942 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
943 * message window (style: WS_POPUP|WS_DISABLED)
945 FIXME("Parent is HWND_MESSAGE\n");
946 parent = GetDesktopWindow();
948 else if (cs->hwndParent)
950 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
952 parent = GetDesktopWindow();
953 owner = cs->hwndParent;
958 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
960 WARN("No parent for child window\n" );
961 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
963 if (classAtom != LOWORD(DESKTOP_CLASS_ATOM)) /* are we creating the desktop itself? */
964 parent = GetDesktopWindow();
967 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
969 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
970 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
971 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
972 cs->dwExStyle |= WS_EX_WINDOWEDGE;
974 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
976 /* Create the window structure */
978 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
980 hwnd = wndPtr->hwndSelf;
982 /* Fill the window structure */
984 wndPtr->tid = GetCurrentThreadId();
985 wndPtr->hInstance = cs->hInstance;
987 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
988 wndPtr->dwExStyle = cs->dwExStyle;
990 wndPtr->helpContext = 0;
991 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
992 wndPtr->pVScroll = NULL;
993 wndPtr->pHScroll = NULL;
994 wndPtr->userdata = 0;
996 wndPtr->hIconSmall = 0;
997 wndPtr->hSysMenu = 0;
999 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1002 * Correct the window styles.
1004 * It affects only the style loaded into the WIN structure.
1007 if (!(wndPtr->dwStyle & WS_CHILD))
1009 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1010 if (!(wndPtr->dwStyle & WS_POPUP))
1011 wndPtr->dwStyle |= WS_CAPTION;
1015 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1016 * why does the user get to set it?
1019 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1020 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1021 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1023 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1025 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1026 wndPtr->flags |= WIN_NEED_SIZE;
1028 SERVER_START_REQ( set_window_info )
1031 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1032 req->style = wndPtr->dwStyle;
1033 req->ex_style = wndPtr->dwExStyle;
1034 req->instance = (void *)wndPtr->hInstance;
1035 req->is_unicode = (type == WIN_PROC_32W);
1036 req->extra_offset = -1;
1037 wine_server_call( req );
1041 /* Set the window menu */
1043 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1044 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1048 if (!MENU_SetMenu(hwnd, cs->hMenu))
1050 WIN_ReleasePtr( wndPtr );
1051 free_window_handle( hwnd );
1057 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1060 if (!cs->hInstance || HIWORD(cs->hInstance))
1061 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1063 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1065 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1069 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1070 WIN_ReleasePtr( wndPtr );
1072 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1074 WIN_DestroyWindow( hwnd );
1078 /* Notify the parent window only */
1080 send_parent_notify( hwnd, WM_CREATE );
1081 if (!IsWindow( hwnd )) return 0;
1083 if (cs->style & WS_VISIBLE)
1085 if (cs->style & WS_MAXIMIZE)
1087 else if (cs->style & WS_MINIMIZE)
1088 sw = SW_SHOWMINIMIZED;
1090 ShowWindow( hwnd, sw );
1091 if (cs->dwExStyle & WS_EX_MDICHILD)
1093 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1094 /* ShowWindow won't activate child windows */
1095 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1099 /* Call WH_SHELL hook */
1101 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1102 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1104 TRACE("created window %p\n", hwnd);
1109 /***********************************************************************
1110 * CreateWindow (USER.41)
1112 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1113 DWORD style, INT16 x, INT16 y, INT16 width,
1114 INT16 height, HWND16 parent, HMENU16 menu,
1115 HINSTANCE16 instance, LPVOID data )
1117 return CreateWindowEx16( 0, className, windowName, style,
1118 x, y, width, height, parent, menu, instance, data );
1122 /***********************************************************************
1123 * CreateWindowEx (USER.452)
1125 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1126 LPCSTR windowName, DWORD style, INT16 x,
1127 INT16 y, INT16 width, INT16 height,
1128 HWND16 parent, HMENU16 menu,
1129 HINSTANCE16 instance, LPVOID data )
1135 /* Find the class atom */
1137 if (HIWORD(className))
1139 if (!(classAtom = GlobalFindAtomA( className )))
1141 ERR( "bad class name %s\n", debugstr_a(className) );
1147 classAtom = LOWORD(className);
1148 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1150 ERR( "bad atom %x\n", classAtom);
1156 /* Fix the coordinates */
1158 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1159 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1160 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1161 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1163 /* Create the window */
1165 cs.lpCreateParams = data;
1166 cs.hInstance = HINSTANCE_32(instance);
1167 cs.hMenu = HMENU_32(menu);
1168 cs.hwndParent = WIN_Handle32( parent );
1170 cs.lpszName = windowName;
1171 cs.lpszClass = className;
1172 cs.dwExStyle = exStyle;
1174 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1178 /***********************************************************************
1179 * CreateWindowExA (USER32.@)
1181 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1182 LPCSTR windowName, DWORD style, INT x,
1183 INT y, INT width, INT height,
1184 HWND parent, HMENU menu,
1185 HINSTANCE instance, LPVOID data )
1191 /* Find the class atom */
1193 if (HIWORD(className))
1195 if (!(classAtom = GlobalFindAtomA( className )))
1197 ERR( "bad class name %s\n", debugstr_a(className) );
1203 classAtom = LOWORD(className);
1204 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1206 ERR( "bad atom %x\n", classAtom);
1212 /* Create the window */
1214 cs.lpCreateParams = data;
1215 cs.hInstance = instance;
1217 cs.hwndParent = parent;
1223 cs.lpszName = windowName;
1224 cs.lpszClass = className;
1225 cs.dwExStyle = exStyle;
1227 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1231 /***********************************************************************
1232 * CreateWindowExW (USER32.@)
1234 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1235 LPCWSTR windowName, DWORD style, INT x,
1236 INT y, INT width, INT height,
1237 HWND parent, HMENU menu,
1238 HINSTANCE instance, LPVOID data )
1244 /* Find the class atom */
1246 if (HIWORD(className))
1248 if (!(classAtom = GlobalFindAtomW( className )))
1250 ERR( "bad class name %s\n", debugstr_w(className) );
1256 classAtom = LOWORD(className);
1257 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1259 ERR( "bad atom %x\n", classAtom);
1265 /* Create the window */
1267 cs.lpCreateParams = data;
1268 cs.hInstance = instance;
1270 cs.hwndParent = parent;
1276 cs.lpszName = windowName;
1277 cs.lpszClass = className;
1278 cs.dwExStyle = exStyle;
1280 /* Note: we rely on the fact that CREATESTRUCTA and */
1281 /* CREATESTRUCTW have the same layout. */
1282 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1286 /***********************************************************************
1287 * WIN_SendDestroyMsg
1289 static void WIN_SendDestroyMsg( HWND hwnd )
1293 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1295 if (hwnd == info.hwndCaret) DestroyCaret();
1296 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1298 USER_Driver->pResetSelectionOwner( hwnd, TRUE );
1301 * Send the WM_DESTROY to the window.
1303 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1306 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1307 * make sure that the window still exists when we come back.
1314 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1316 for (i = 0; pWndArray[i]; i++)
1318 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1320 HeapFree( GetProcessHeap(), 0, pWndArray );
1323 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1327 /***********************************************************************
1328 * DestroyWindow (USER32.@)
1330 BOOL WINAPI DestroyWindow( HWND hwnd )
1334 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1336 SetLastError( ERROR_ACCESS_DENIED );
1340 TRACE("(%p)\n", hwnd);
1344 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1346 if (MENU_IsMenuActive() == hwnd)
1349 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1353 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1354 send_parent_notify( hwnd, WM_DESTROY );
1356 else if (!GetWindow( hwnd, GW_OWNER ))
1358 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1359 /* FIXME: clean up palette - see "Internals" p.352 */
1362 if (!IsWindow(hwnd)) return TRUE;
1364 USER_Driver->pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1366 /* Hide the window */
1367 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1369 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1371 ShowWindow( hwnd, SW_HIDE );
1373 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1374 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1377 if (!IsWindow(hwnd)) return TRUE;
1379 /* Recursively destroy owned windows */
1386 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1389 for (i = 0; list[i]; i++)
1391 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1392 if (WIN_IsCurrentThread( list[i] ))
1394 DestroyWindow( list[i] );
1398 WIN_SetOwner( list[i], 0 );
1400 HeapFree( GetProcessHeap(), 0, list );
1402 if (!got_one) break;
1406 /* Send destroy messages */
1408 WIN_SendDestroyMsg( hwnd );
1409 if (!IsWindow( hwnd )) return TRUE;
1411 if (GetClipboardOwner() == hwnd)
1412 CLIPBOARD_ReleaseOwner();
1414 /* Destroy the window storage */
1416 WIN_DestroyWindow( hwnd );
1421 /***********************************************************************
1422 * CloseWindow (USER32.@)
1424 BOOL WINAPI CloseWindow( HWND hwnd )
1426 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1427 ShowWindow( hwnd, SW_MINIMIZE );
1432 /***********************************************************************
1433 * OpenIcon (USER32.@)
1435 BOOL WINAPI OpenIcon( HWND hwnd )
1437 if (!IsIconic( hwnd )) return FALSE;
1438 ShowWindow( hwnd, SW_SHOWNORMAL );
1443 /***********************************************************************
1446 * Implementation of FindWindow() and FindWindowEx().
1448 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1453 WCHAR *buffer = NULL;
1455 if (!parent) parent = GetDesktopWindow();
1458 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1459 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1462 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1466 child = WIN_GetFullHandle( child );
1467 while (list[i] && list[i] != child) i++;
1468 if (!list[i]) goto done;
1469 i++; /* start from next window */
1476 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1483 HeapFree( GetProcessHeap(), 0, list );
1484 HeapFree( GetProcessHeap(), 0, buffer );
1490 /***********************************************************************
1491 * FindWindowA (USER32.@)
1493 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1495 HWND ret = FindWindowExA( 0, 0, className, title );
1496 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1501 /***********************************************************************
1502 * FindWindowExA (USER32.@)
1504 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1505 LPCSTR className, LPCSTR title )
1514 /* If the atom doesn't exist, then no class */
1515 /* with this name exists either. */
1516 if (!(atom = GlobalFindAtomA( className )))
1518 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1522 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1524 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1525 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1526 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1527 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1528 HeapFree( GetProcessHeap(), 0, buffer );
1533 /***********************************************************************
1534 * FindWindowExW (USER32.@)
1536 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1537 LPCWSTR className, LPCWSTR title )
1543 /* If the atom doesn't exist, then no class */
1544 /* with this name exists either. */
1545 if (!(atom = GlobalFindAtomW( className )))
1547 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1551 return WIN_FindWindow( parent, child, atom, title );
1555 /***********************************************************************
1556 * FindWindowW (USER32.@)
1558 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1560 return FindWindowExW( 0, 0, className, title );
1564 /**********************************************************************
1565 * GetDesktopWindow (USER32.@)
1567 HWND WINAPI GetDesktopWindow(void)
1569 struct user_thread_info *thread_info = get_user_thread_info();
1571 if (thread_info->desktop) return thread_info->desktop;
1573 SERVER_START_REQ( get_desktop_window )
1576 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1580 if (!thread_info->desktop)
1583 PROCESS_INFORMATION pi;
1584 WCHAR command_line[] = {'e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1586 memset( &si, 0, sizeof(si) );
1588 if (CreateProcessW( NULL, command_line, NULL, NULL, FALSE, DETACHED_PROCESS,
1589 NULL, NULL, &si, &pi ))
1591 TRACE( "started explorer pid %04lx tid %04lx\n", pi.dwProcessId, pi.dwThreadId );
1592 WaitForInputIdle( pi.hProcess, 10000 );
1593 CloseHandle( pi.hThread );
1594 CloseHandle( pi.hProcess );
1597 else WARN( "failed to start explorer, err %ld\n", GetLastError() );
1599 SERVER_START_REQ( get_desktop_window )
1602 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1607 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1608 ERR( "failed to create desktop window\n" );
1610 return thread_info->desktop;
1614 /*******************************************************************
1615 * EnableWindow (USER32.@)
1617 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1622 if (is_broadcast(hwnd))
1624 SetLastError( ERROR_INVALID_PARAMETER );
1628 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1629 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1633 TRACE("( %p, %d )\n", hwnd, enable);
1635 retvalue = !IsWindowEnabled( hwnd );
1637 if (enable && retvalue)
1639 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1640 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1642 else if (!enable && !retvalue)
1646 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1648 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1650 if (hwnd == GetFocus())
1651 SetFocus( 0 ); /* A disabled window can't have the focus */
1653 capture_wnd = GetCapture();
1654 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1655 ReleaseCapture(); /* A disabled window can't capture the mouse */
1657 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1663 /***********************************************************************
1664 * IsWindowEnabled (USER32.@)
1666 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1668 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1672 /***********************************************************************
1673 * IsWindowUnicode (USER32.@)
1675 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1678 BOOL retvalue = FALSE;
1680 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1682 if (wndPtr == WND_DESKTOP) return TRUE;
1684 if (wndPtr != WND_OTHER_PROCESS)
1686 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1687 WIN_ReleasePtr( wndPtr );
1691 SERVER_START_REQ( get_window_info )
1694 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1702 /**********************************************************************
1703 * GetWindowWord (USER32.@)
1705 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1710 WND *wndPtr = WIN_GetPtr( hwnd );
1713 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1716 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1718 SERVER_START_REQ( set_window_info )
1721 req->flags = 0; /* don't set anything, just retrieve */
1722 req->extra_offset = offset;
1723 req->extra_size = sizeof(retvalue);
1724 if (!wine_server_call_err( req ))
1725 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1730 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1732 WARN("Invalid offset %d\n", offset );
1733 SetLastError( ERROR_INVALID_INDEX );
1735 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1736 WIN_ReleasePtr( wndPtr );
1742 case GWLP_HWNDPARENT:
1743 return GetWindowLongPtrW( hwnd, offset );
1745 case GWLP_HINSTANCE:
1747 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1749 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1753 WARN("Invalid offset %d\n", offset );
1759 /**********************************************************************
1760 * SetWindowWord (USER32.@)
1762 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1770 case GWLP_HINSTANCE:
1771 case GWLP_HWNDPARENT:
1772 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1776 WARN("Invalid offset %d\n", offset );
1777 SetLastError( ERROR_INVALID_INDEX );
1782 wndPtr = WIN_GetPtr( hwnd );
1783 if (wndPtr == WND_DESKTOP)
1785 SetLastError( ERROR_ACCESS_DENIED );
1788 if (wndPtr == WND_OTHER_PROCESS)
1791 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1792 offset, newval, hwnd );
1797 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1801 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1803 WARN("Invalid offset %d\n", offset );
1804 WIN_ReleasePtr(wndPtr);
1805 SetLastError( ERROR_INVALID_INDEX );
1809 SERVER_START_REQ( set_window_info )
1812 req->flags = SET_WIN_EXTRA;
1813 req->extra_offset = offset;
1814 req->extra_size = sizeof(newval);
1815 memcpy( &req->extra_value, &newval, sizeof(newval) );
1816 if (!wine_server_call_err( req ))
1818 void *ptr = (char *)wndPtr->wExtra + offset;
1819 memcpy( &retval, ptr, sizeof(retval) );
1820 memcpy( ptr, &newval, sizeof(newval) );
1824 WIN_ReleasePtr( wndPtr );
1829 /**********************************************************************
1832 * Helper function for GetWindowLong().
1834 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1836 LONG_PTR retvalue = 0;
1839 if (offset == GWLP_HWNDPARENT)
1841 HWND parent = GetAncestor( hwnd, GA_PARENT );
1842 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1843 return (ULONG_PTR)parent;
1846 if (!(wndPtr = WIN_GetPtr( hwnd )))
1848 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1852 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1854 if (offset == GWLP_WNDPROC)
1856 SetLastError( ERROR_ACCESS_DENIED );
1859 SERVER_START_REQ( set_window_info )
1862 req->flags = 0; /* don't set anything, just retrieve */
1863 req->extra_offset = (offset >= 0) ? offset : -1;
1864 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1865 if (!wine_server_call_err( req ))
1869 case GWL_STYLE: retvalue = reply->old_style; break;
1870 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1871 case GWLP_ID: retvalue = reply->old_id; break;
1872 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1873 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1875 if (offset >= 0) retvalue = reply->old_extra_value;
1876 else SetLastError( ERROR_INVALID_INDEX );
1885 /* now we have a valid wndPtr */
1889 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1892 * Some programs try to access last element from 16 bit
1893 * code using illegal offset value. Hopefully this is
1894 * what those programs really expect.
1896 if (type == WIN_PROC_16 &&
1897 wndPtr->cbWndExtra >= 4 &&
1898 offset == wndPtr->cbWndExtra - sizeof(WORD))
1900 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1902 ERR( "- replaced invalid offset %d with %d\n",
1905 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset2);
1906 WIN_ReleasePtr( wndPtr );
1909 WARN("Invalid offset %d\n", offset );
1910 WIN_ReleasePtr( wndPtr );
1911 SetLastError( ERROR_INVALID_INDEX );
1914 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
1915 /* Special case for dialog window procedure */
1916 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1917 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, type );
1918 WIN_ReleasePtr( wndPtr );
1924 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1925 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1926 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1927 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1928 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type ); break;
1929 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1931 WARN("Unknown offset %d\n", offset );
1932 SetLastError( ERROR_INVALID_INDEX );
1935 WIN_ReleasePtr(wndPtr);
1940 /**********************************************************************
1943 * Helper function for SetWindowLong().
1945 * 0 is the failure code. However, in the case of failure SetLastError
1946 * must be set to distinguish between a 0 return value and a failure.
1948 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval,
1949 WINDOWPROCTYPE type )
1953 LONG_PTR retval = 0;
1956 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1958 if (is_broadcast(hwnd))
1960 SetLastError( ERROR_INVALID_PARAMETER );
1964 if (!(wndPtr = WIN_GetPtr( hwnd )))
1966 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1969 if (wndPtr == WND_DESKTOP)
1971 /* can't change anything on the desktop window */
1972 SetLastError( ERROR_ACCESS_DENIED );
1975 if (wndPtr == WND_OTHER_PROCESS)
1977 if (offset == GWLP_WNDPROC)
1979 SetLastError( ERROR_ACCESS_DENIED );
1982 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1985 /* first some special cases */
1991 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1992 style.styleNew = newval;
1993 WIN_ReleasePtr( wndPtr );
1994 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1995 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1996 newval = style.styleNew;
1998 case GWLP_HWNDPARENT:
1999 if (wndPtr->parent == GetDesktopWindow())
2001 WIN_ReleasePtr( wndPtr );
2002 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2006 WIN_ReleasePtr( wndPtr );
2007 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2011 WINDOWPROCTYPE old_type = WINPROC_GetProcType( wndPtr->winproc );
2012 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type );
2013 wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, type );
2014 if (old_type == type)
2016 WIN_ReleasePtr( wndPtr );
2019 /* update is_unicode flag on the server side */
2023 case GWLP_HINSTANCE:
2027 if ((wndPtr->cbWndExtra + sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2029 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2030 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, type );
2031 *ptr = WINPROC_AllocProc( (WNDPROC)newval, type );
2032 WIN_ReleasePtr( wndPtr );
2037 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
2039 WARN("Invalid offset %d\n", offset );
2040 WIN_ReleasePtr( wndPtr );
2041 SetLastError( ERROR_INVALID_INDEX );
2046 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2047 if (*ptr == newval) /* already set to the same value */
2049 WIN_ReleasePtr( wndPtr );
2056 SERVER_START_REQ( set_window_info )
2059 req->extra_offset = -1;
2063 req->flags = SET_WIN_STYLE;
2064 req->style = newval;
2067 req->flags = SET_WIN_EXSTYLE;
2068 req->ex_style = newval;
2071 req->flags = SET_WIN_ID;
2074 case GWLP_HINSTANCE:
2075 req->flags = SET_WIN_INSTANCE;
2076 req->instance = (void *)newval;
2079 req->flags = SET_WIN_UNICODE;
2080 req->is_unicode = (type == WIN_PROC_32W);
2083 req->flags = SET_WIN_USERDATA;
2084 req->user_data = (void *)newval;
2087 req->flags = SET_WIN_EXTRA;
2088 req->extra_offset = offset;
2089 req->extra_size = sizeof(newval);
2090 memcpy( &req->extra_value, &newval, sizeof(newval) );
2092 if ((ok = !wine_server_call_err( req )))
2097 wndPtr->dwStyle = newval;
2098 retval = reply->old_style;
2101 wndPtr->dwExStyle = newval;
2102 retval = reply->old_ex_style;
2105 wndPtr->wIDmenu = newval;
2106 retval = reply->old_id;
2108 case GWLP_HINSTANCE:
2109 wndPtr->hInstance = (HINSTANCE)newval;
2110 retval = (ULONG_PTR)reply->old_instance;
2115 wndPtr->userdata = newval;
2116 retval = (ULONG_PTR)reply->old_user_data;
2120 void *ptr = (char *)wndPtr->wExtra + offset;
2121 memcpy( &retval, ptr, sizeof(retval) );
2122 memcpy( ptr, &newval, sizeof(newval) );
2129 WIN_ReleasePtr( wndPtr );
2133 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2135 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2136 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2142 /**********************************************************************
2143 * GetWindowLong (USER.135)
2145 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2147 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2151 /**********************************************************************
2152 * GetWindowLongA (USER32.@)
2154 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2156 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2160 /**********************************************************************
2161 * GetWindowLongW (USER32.@)
2163 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2165 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2169 /**********************************************************************
2170 * SetWindowLong (USER.136)
2172 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2174 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2178 /**********************************************************************
2179 * SetWindowLongA (USER32.@)
2181 * See SetWindowLongW.
2183 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2185 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2189 /**********************************************************************
2190 * SetWindowLongW (USER32.@) Set window attribute
2192 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2193 * value in a window's extra memory.
2195 * The _hwnd_ parameter specifies the window. is the handle to a
2196 * window that has extra memory. The _newval_ parameter contains the
2197 * new attribute or extra memory value. If positive, the _offset_
2198 * parameter is the byte-addressed location in the window's extra
2199 * memory to set. If negative, _offset_ specifies the window
2200 * attribute to set, and should be one of the following values:
2202 * GWL_EXSTYLE The window's extended window style
2204 * GWL_STYLE The window's window style.
2206 * GWLP_WNDPROC Pointer to the window's window procedure.
2208 * GWLP_HINSTANCE The window's pplication instance handle.
2210 * GWLP_ID The window's identifier.
2212 * GWLP_USERDATA The window's user-specified data.
2214 * If the window is a dialog box, the _offset_ parameter can be one of
2215 * the following values:
2217 * DWLP_DLGPROC The address of the window's dialog box procedure.
2219 * DWLP_MSGRESULT The return value of a message
2220 * that the dialog box procedure processed.
2222 * DWLP_USER Application specific information.
2226 * If successful, returns the previous value located at _offset_. Otherwise,
2231 * Extra memory for a window class is specified by a nonzero cbWndExtra
2232 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2233 * time of class creation.
2235 * Using GWL_WNDPROC to set a new window procedure effectively creates
2236 * a window subclass. Use CallWindowProc() in the new windows procedure
2237 * to pass messages to the superclass's window procedure.
2239 * The user data is reserved for use by the application which created
2242 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2243 * instead, call the EnableWindow() function to change the window's
2246 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2247 * SetParent() instead.
2250 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2251 * it sends WM_STYLECHANGING before changing the settings
2252 * and WM_STYLECHANGED afterwards.
2253 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2255 LONG WINAPI SetWindowLongW(
2256 HWND hwnd, /* [in] window to alter */
2257 INT offset, /* [in] offset, in bytes, of location to alter */
2258 LONG newval /* [in] new value of location */
2260 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2264 /*******************************************************************
2265 * GetWindowTextA (USER32.@)
2267 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2271 if (!lpString) return 0;
2273 if (WIN_IsCurrentProcess( hwnd ))
2274 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2276 /* when window belongs to other process, don't send a message */
2277 if (nMaxCount <= 0) return 0;
2278 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2279 get_server_window_text( hwnd, buffer, nMaxCount );
2280 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2281 lpString[nMaxCount-1] = 0;
2282 HeapFree( GetProcessHeap(), 0, buffer );
2283 return strlen(lpString);
2287 /*******************************************************************
2288 * InternalGetWindowText (USER32.@)
2290 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2294 if (nMaxCount <= 0) return 0;
2295 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2296 if (win == WND_DESKTOP) lpString[0] = 0;
2297 else if (win != WND_OTHER_PROCESS)
2299 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2300 else lpString[0] = 0;
2301 WIN_ReleasePtr( win );
2305 get_server_window_text( hwnd, lpString, nMaxCount );
2307 return strlenW(lpString);
2311 /*******************************************************************
2312 * GetWindowTextW (USER32.@)
2314 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2316 if (!lpString) return 0;
2318 if (WIN_IsCurrentProcess( hwnd ))
2319 return (INT)SendMessageW( 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 get_server_window_text( hwnd, lpString, nMaxCount );
2324 return strlenW(lpString);
2328 /*******************************************************************
2329 * SetWindowTextA (USER32.@)
2330 * SetWindowText (USER32.@)
2332 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2334 if (is_broadcast(hwnd))
2336 SetLastError( ERROR_INVALID_PARAMETER );
2339 if (!WIN_IsCurrentProcess( hwnd ))
2340 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2341 debugstr_a(lpString), hwnd );
2342 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2346 /*******************************************************************
2347 * SetWindowTextW (USER32.@)
2349 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2351 if (is_broadcast(hwnd))
2353 SetLastError( ERROR_INVALID_PARAMETER );
2356 if (!WIN_IsCurrentProcess( hwnd ))
2357 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2358 debugstr_w(lpString), hwnd );
2359 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2363 /*******************************************************************
2364 * GetWindowTextLengthA (USER32.@)
2366 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2368 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2371 /*******************************************************************
2372 * GetWindowTextLengthW (USER32.@)
2374 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2376 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2380 /*******************************************************************
2381 * IsWindow (USER32.@)
2383 BOOL WINAPI IsWindow( HWND hwnd )
2388 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2389 if (ptr == WND_DESKTOP) return TRUE;
2391 if (ptr != WND_OTHER_PROCESS)
2393 WIN_ReleasePtr( ptr );
2397 /* check other processes */
2398 SERVER_START_REQ( get_window_info )
2401 ret = !wine_server_call_err( req );
2408 /***********************************************************************
2409 * GetWindowThreadProcessId (USER32.@)
2411 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2416 if (!(ptr = WIN_GetPtr( hwnd )))
2418 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2422 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2424 /* got a valid window */
2426 if (process) *process = GetCurrentProcessId();
2427 WIN_ReleasePtr( ptr );
2431 /* check other processes */
2432 SERVER_START_REQ( get_window_info )
2435 if (!wine_server_call_err( req ))
2437 tid = (DWORD)reply->tid;
2438 if (process) *process = (DWORD)reply->pid;
2446 /*****************************************************************
2447 * GetParent (USER32.@)
2449 HWND WINAPI GetParent( HWND hwnd )
2454 if (!(wndPtr = WIN_GetPtr( hwnd )))
2456 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2459 if (wndPtr == WND_DESKTOP) return 0;
2460 if (wndPtr == WND_OTHER_PROCESS)
2462 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2463 if (style & (WS_POPUP | WS_CHILD))
2465 SERVER_START_REQ( get_window_tree )
2468 if (!wine_server_call_err( req ))
2470 if (style & WS_POPUP) retvalue = reply->owner;
2471 else if (style & WS_CHILD) retvalue = reply->parent;
2479 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2480 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2481 WIN_ReleasePtr( wndPtr );
2487 /*****************************************************************
2488 * GetAncestor (USER32.@)
2490 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2493 HWND *list, ret = 0;
2498 if (!(win = WIN_GetPtr( hwnd )))
2500 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2503 if (win == WND_DESKTOP) return 0;
2504 if (win != WND_OTHER_PROCESS)
2507 WIN_ReleasePtr( win );
2509 else /* need to query the server */
2511 SERVER_START_REQ( get_window_tree )
2514 if (!wine_server_call_err( req )) ret = reply->parent;
2521 if (!(list = list_window_parents( hwnd ))) return 0;
2523 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2527 while (list[count]) count++;
2528 ret = list[count - 2]; /* get the one before the desktop */
2530 HeapFree( GetProcessHeap(), 0, list );
2534 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2537 HWND parent = GetParent( ret );
2547 /*****************************************************************
2548 * SetParent (USER32.@)
2550 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2554 if (is_broadcast(hwnd) || is_broadcast(parent))
2556 SetLastError(ERROR_INVALID_PARAMETER);
2560 if (!parent) parent = GetDesktopWindow();
2561 else parent = WIN_GetFullHandle( parent );
2563 if (!IsWindow( parent ))
2565 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2569 /* Some applications try to set a child as a parent */
2570 if (IsChild(hwnd, parent))
2572 SetLastError( ERROR_INVALID_PARAMETER );
2576 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2577 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2579 return USER_Driver->pSetParent( full_handle, parent );
2583 /*******************************************************************
2584 * IsChild (USER32.@)
2586 BOOL WINAPI IsChild( HWND parent, HWND child )
2588 HWND *list = list_window_parents( child );
2592 if (!list) return FALSE;
2593 parent = WIN_GetFullHandle( parent );
2594 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2595 ret = (list[i] != 0);
2596 HeapFree( GetProcessHeap(), 0, list );
2601 /***********************************************************************
2602 * IsWindowVisible (USER32.@)
2604 BOOL WINAPI IsWindowVisible( HWND hwnd )
2610 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2611 if (!(list = list_window_parents( hwnd ))) return TRUE;
2612 for (i = 0; list[i]; i++)
2613 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2615 HeapFree( GetProcessHeap(), 0, list );
2620 /***********************************************************************
2621 * WIN_IsWindowDrawable
2623 * hwnd is drawable when it is visible, all parents are not
2624 * minimized, and it is itself not minimized unless we are
2625 * trying to draw its default class icon.
2627 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2632 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2634 if (!(style & WS_VISIBLE)) return FALSE;
2635 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2637 if (!(list = list_window_parents( hwnd ))) return TRUE;
2638 for (i = 0; list[i]; i++)
2639 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2642 HeapFree( GetProcessHeap(), 0, list );
2647 /*******************************************************************
2648 * GetTopWindow (USER32.@)
2650 HWND WINAPI GetTopWindow( HWND hwnd )
2652 if (!hwnd) hwnd = GetDesktopWindow();
2653 return GetWindow( hwnd, GW_CHILD );
2657 /*******************************************************************
2658 * GetWindow (USER32.@)
2660 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2664 if (rel == GW_OWNER) /* this one may be available locally */
2666 WND *wndPtr = WIN_GetPtr( hwnd );
2669 SetLastError( ERROR_INVALID_HANDLE );
2672 if (wndPtr == WND_DESKTOP) return 0;
2673 if (wndPtr != WND_OTHER_PROCESS)
2675 retval = wndPtr->owner;
2676 WIN_ReleasePtr( wndPtr );
2679 /* else fall through to server call */
2682 SERVER_START_REQ( get_window_tree )
2685 if (!wine_server_call_err( req ))
2690 retval = reply->first_sibling;
2693 retval = reply->last_sibling;
2696 retval = reply->next_sibling;
2699 retval = reply->prev_sibling;
2702 retval = reply->owner;
2705 retval = reply->first_child;
2715 /*******************************************************************
2716 * ShowOwnedPopups (USER32.@)
2718 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2722 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2724 if (!win_array) return TRUE;
2726 while (win_array[count]) count++;
2727 while (--count >= 0)
2729 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2730 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2731 if (pWnd == WND_OTHER_PROCESS) continue;
2734 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2736 WIN_ReleasePtr( pWnd );
2737 /* In Windows, ShowOwnedPopups(TRUE) generates
2738 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2739 * regardless of the state of the owner
2741 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2747 if (pWnd->dwStyle & WS_VISIBLE)
2749 WIN_ReleasePtr( pWnd );
2750 /* In Windows, ShowOwnedPopups(FALSE) generates
2751 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2752 * regardless of the state of the owner
2754 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2758 WIN_ReleasePtr( pWnd );
2760 HeapFree( GetProcessHeap(), 0, win_array );
2765 /*******************************************************************
2766 * GetLastActivePopup (USER32.@)
2768 HWND WINAPI GetLastActivePopup( HWND hwnd )
2772 SERVER_START_REQ( get_window_info )
2775 if (!wine_server_call_err( req )) retval = reply->last_active;
2782 /*******************************************************************
2785 * Build an array of the children of a given window. The array must be
2786 * freed with HeapFree. Returns NULL when no windows are found.
2788 HWND *WIN_ListChildren( HWND hwnd )
2790 return list_window_children( hwnd, 0, 0 );
2794 /*******************************************************************
2795 * EnumWindows (USER32.@)
2797 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2803 USER_CheckNotLock();
2805 /* We have to build a list of all windows first, to avoid */
2806 /* unpleasant side-effects, for instance if the callback */
2807 /* function changes the Z-order of the windows. */
2809 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2811 /* Now call the callback function for every window */
2813 for (i = 0; list[i]; i++)
2815 /* Make sure that the window still exists */
2816 if (!IsWindow( list[i] )) continue;
2817 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2819 HeapFree( GetProcessHeap(), 0, list );
2824 /**********************************************************************
2825 * EnumThreadWindows (USER32.@)
2827 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2832 USER_CheckNotLock();
2834 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2836 /* Now call the callback function for every window */
2838 for (i = 0; list[i]; i++)
2839 if (!func( list[i], lParam )) break;
2840 HeapFree( GetProcessHeap(), 0, list );
2845 /**********************************************************************
2846 * WIN_EnumChildWindows
2848 * Helper function for EnumChildWindows().
2850 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2855 for ( ; *list; list++)
2857 /* Make sure that the window still exists */
2858 if (!IsWindow( *list )) continue;
2859 /* Build children list first */
2860 childList = WIN_ListChildren( *list );
2862 ret = func( *list, lParam );
2866 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2867 HeapFree( GetProcessHeap(), 0, childList );
2869 if (!ret) return FALSE;
2875 /**********************************************************************
2876 * EnumChildWindows (USER32.@)
2878 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2883 USER_CheckNotLock();
2885 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2886 ret = WIN_EnumChildWindows( list, func, lParam );
2887 HeapFree( GetProcessHeap(), 0, list );
2892 /*******************************************************************
2893 * AnyPopup (USER.52)
2895 BOOL16 WINAPI AnyPopup16(void)
2901 /*******************************************************************
2902 * AnyPopup (USER32.@)
2904 BOOL WINAPI AnyPopup(void)
2908 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2910 if (!list) return FALSE;
2911 for (i = 0; list[i]; i++)
2913 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2915 retvalue = (list[i] != 0);
2916 HeapFree( GetProcessHeap(), 0, list );
2921 /*******************************************************************
2922 * FlashWindow (USER32.@)
2924 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2928 TRACE("%p\n", hWnd);
2930 if (IsIconic( hWnd ))
2932 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2934 wndPtr = WIN_GetPtr(hWnd);
2935 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2936 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2938 wndPtr->flags |= WIN_NCACTIVATED;
2942 wndPtr->flags &= ~WIN_NCACTIVATED;
2944 WIN_ReleasePtr( wndPtr );
2951 wndPtr = WIN_GetPtr(hWnd);
2952 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2953 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2955 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2956 else wparam = (hWnd == GetForegroundWindow());
2958 WIN_ReleasePtr( wndPtr );
2959 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2964 /*******************************************************************
2965 * FlashWindowEx (USER32.@)
2967 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
2969 FIXME("%p\n", pfwi);
2973 /*******************************************************************
2974 * GetWindowContextHelpId (USER32.@)
2976 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2979 WND *wnd = WIN_GetPtr( hwnd );
2980 if (!wnd || wnd == WND_DESKTOP) return 0;
2981 if (wnd == WND_OTHER_PROCESS)
2983 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2986 retval = wnd->helpContext;
2987 WIN_ReleasePtr( wnd );
2992 /*******************************************************************
2993 * SetWindowContextHelpId (USER32.@)
2995 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2997 WND *wnd = WIN_GetPtr( hwnd );
2998 if (!wnd || wnd == WND_DESKTOP) return FALSE;
2999 if (wnd == WND_OTHER_PROCESS)
3001 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3004 wnd->helpContext = id;
3005 WIN_ReleasePtr( wnd );
3010 /*******************************************************************
3011 * DragDetect (USER32.@)
3013 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3017 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3018 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3020 rect.left = pt.x - wDragWidth;
3021 rect.right = pt.x + wDragWidth;
3023 rect.top = pt.y - wDragHeight;
3024 rect.bottom = pt.y + wDragHeight;
3030 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3032 if( msg.message == WM_LBUTTONUP )
3037 if( msg.message == WM_MOUSEMOVE )
3040 tmp.x = LOWORD(msg.lParam);
3041 tmp.y = HIWORD(msg.lParam);
3042 if( !PtInRect( &rect, tmp ))
3054 /******************************************************************************
3055 * GetWindowModuleFileNameA (USER32.@)
3057 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3059 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3060 hwnd, lpszFileName, cchFileNameMax);
3064 /******************************************************************************
3065 * GetWindowModuleFileNameW (USER32.@)
3067 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3069 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3070 hwnd, lpszFileName, cchFileNameMax);
3074 /******************************************************************************
3075 * GetWindowInfo (USER32.@)
3077 * Note: tests show that Windows doesn't check cbSize of the structure.
3079 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3081 if (!pwi) return FALSE;
3082 if (!IsWindow(hwnd)) return FALSE;
3084 GetWindowRect(hwnd, &pwi->rcWindow);
3085 GetClientRect(hwnd, &pwi->rcClient);
3086 /* translate to screen coordinates */
3087 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3089 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3090 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3091 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3093 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3094 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3096 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3097 pwi->wCreatorVersion = 0x0400;
3102 /******************************************************************************
3103 * SwitchDesktop (USER32.@)
3105 * NOTES: Sets the current input or interactive desktop.
3107 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3109 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3113 /*****************************************************************************
3114 * SetLayeredWindowAttributes (USER32.@)
3116 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3117 BYTE bAlpha, DWORD dwFlags )
3119 FIXME("(%p,0x%.8lx,%d,%ld): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3123 /*****************************************************************************
3124 * UpdateLayeredWindow (USER32.@)
3126 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3127 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3130 FIXME("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%ld): stub!\n",
3131 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);