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"
39 #include "cursoricon.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(win);
46 WINE_DECLARE_DEBUG_CHANNEL(msg);
48 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
49 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
51 /**********************************************************************/
54 static WND *pWndDesktop = NULL;
56 static WORD wDragWidth = 4;
57 static WORD wDragHeight= 3;
59 static void *user_handles[NB_USER_HANDLES];
61 /***********************************************************************
62 * create_window_handle
64 * Create a window handle with the server.
66 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
67 HINSTANCE instance, WINDOWPROCTYPE type )
71 struct tagCLASS *class = NULL;
72 user_handle_t handle = 0;
75 /* if 16-bit instance, map to module handle */
76 if (instance && !HIWORD(instance))
77 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
79 SERVER_START_REQ( create_window )
84 req->instance = instance;
85 if (!wine_server_call_err( req ))
87 handle = reply->handle;
88 extra_bytes = reply->extra;
89 class = reply->class_ptr;
96 WARN( "error %ld creating window\n", GetLastError() );
100 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
102 SERVER_START_REQ( destroy_window )
104 req->handle = handle;
105 wine_server_call( req );
108 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
114 index = USER_HANDLE_TO_INDEX(handle);
115 assert( index < NB_USER_HANDLES );
116 user_handles[index] = win;
117 win->hwndSelf = handle;
118 win->dwMagic = WND_MAGIC;
120 win->cbWndExtra = extra_bytes;
121 memset( win->wExtra, 0, extra_bytes );
122 CLASS_AddWindow( class, win, type );
127 /***********************************************************************
130 * Free a window handle.
132 static WND *free_window_handle( HWND hwnd )
135 WORD index = USER_HANDLE_TO_INDEX(hwnd);
137 if (index >= NB_USER_HANDLES) return NULL;
139 if ((ptr = user_handles[index]))
141 SERVER_START_REQ( destroy_window )
144 if (!wine_server_call_err( req ))
145 user_handles[index] = NULL;
152 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
157 /*******************************************************************
158 * list_window_children
160 * Build an array of the children of a given window. The array must be
161 * freed with HeapFree. Returns NULL when no windows are found.
163 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
172 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
174 SERVER_START_REQ( get_window_children )
179 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
180 if (!wine_server_call( req )) count = reply->count;
183 if (count && count < size)
188 HeapFree( GetProcessHeap(), 0, list );
190 size = count + 1; /* restart with a large enough buffer */
196 /*******************************************************************
199 static void send_parent_notify( HWND hwnd, UINT msg )
201 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
202 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
203 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
204 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
208 /*******************************************************************
209 * get_server_window_text
211 * Retrieve the window text from the server.
213 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
217 SERVER_START_REQ( get_window_text )
220 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
221 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
224 text[len / sizeof(WCHAR)] = 0;
228 /***********************************************************************
231 * Return a pointer to the WND structure if local to the process,
232 * or WND_OTHER_PROCESS if handle may be valid in other process.
233 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
235 WND *WIN_GetPtr( HWND hwnd )
238 WORD index = USER_HANDLE_TO_INDEX(hwnd);
240 if (index >= NB_USER_HANDLES) return NULL;
243 if ((ptr = user_handles[index]))
245 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
249 else ptr = WND_OTHER_PROCESS;
255 /***********************************************************************
256 * WIN_IsCurrentProcess
258 * Check whether a given window belongs to the current process (and return the full handle).
260 HWND WIN_IsCurrentProcess( HWND hwnd )
265 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
267 WIN_ReleasePtr( ptr );
272 /***********************************************************************
273 * WIN_IsCurrentThread
275 * Check whether a given window belongs to the current thread (and return the full handle).
277 HWND WIN_IsCurrentThread( HWND hwnd )
282 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
284 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
285 WIN_ReleasePtr( ptr );
291 /***********************************************************************
294 * Convert a 16-bit window handle to a full 32-bit handle.
296 HWND WIN_Handle32( HWND16 hwnd16 )
299 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
301 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
302 /* do sign extension for -2 and -3 */
303 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
305 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
307 if (ptr != WND_OTHER_PROCESS)
309 hwnd = ptr->hwndSelf;
310 WIN_ReleasePtr( ptr );
312 else /* may belong to another process */
314 SERVER_START_REQ( get_window_info )
317 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
325 /***********************************************************************
328 * Return a pointer to the WND structure corresponding to a HWND.
330 WND * WIN_FindWndPtr( HWND hwnd )
334 if (!hwnd) return NULL;
336 if ((ptr = WIN_GetPtr( hwnd )))
338 if (ptr != WND_OTHER_PROCESS)
340 /* increment destruction monitoring */
344 if (IsWindow( hwnd )) /* check other processes */
346 ERR( "window %p belongs to other process\n", hwnd );
347 /* DbgBreakPoint(); */
350 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
355 /***********************************************************************
358 * Release the pointer to the WND structure.
360 void WIN_ReleaseWndPtr(WND *wndPtr)
364 /* Decrement destruction monitoring value */
366 /* Check if it's time to release the memory */
367 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
370 free_window_handle( wndPtr->hwndSelf );
372 else if(wndPtr->irefCount < 0)
374 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
375 ERR("forgot a Lock on %p somewhere\n",wndPtr);
377 /* unlock all WND structures for thread safeness */
382 /***********************************************************************
385 * Remove a window from the siblings linked list.
387 void WIN_UnlinkWindow( HWND hwnd )
389 WIN_LinkWindow( hwnd, 0, 0 );
393 /***********************************************************************
396 * Insert a window into the siblings linked list.
397 * The window is inserted after the specified window, which can also
398 * be specified as HWND_TOP or HWND_BOTTOM.
399 * If parent is 0, window is unlinked from the tree.
401 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
403 WND *wndPtr = WIN_GetPtr( hwnd );
406 if (wndPtr == WND_OTHER_PROCESS)
408 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
412 SERVER_START_REQ( link_window )
415 req->parent = parent;
416 req->previous = hwndInsertAfter;
417 if (!wine_server_call( req ))
419 if (reply->full_parent) wndPtr->parent = reply->full_parent;
424 WIN_ReleasePtr( wndPtr );
428 /***********************************************************************
431 * Change the owner of a window.
433 HWND WIN_SetOwner( HWND hwnd, HWND owner )
435 WND *win = WIN_GetPtr( hwnd );
439 if (win == WND_OTHER_PROCESS)
441 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
444 SERVER_START_REQ( set_window_owner )
448 if (!wine_server_call( req ))
450 win->owner = reply->full_owner;
451 ret = reply->prev_owner;
455 WIN_ReleasePtr( win );
460 /***********************************************************************
463 * Change the style of a window.
465 LONG WIN_SetStyle( HWND hwnd, LONG style )
469 WND *win = WIN_GetPtr( hwnd );
472 if (win == WND_OTHER_PROCESS)
475 ERR( "cannot set style %lx on other process window %p\n", style, hwnd );
478 if (style == win->dwStyle)
480 WIN_ReleasePtr( win );
483 SERVER_START_REQ( set_window_info )
486 req->flags = SET_WIN_STYLE;
488 req->extra_offset = -1;
489 if ((ok = !wine_server_call( req )))
491 ret = reply->old_style;
492 win->dwStyle = style;
496 WIN_ReleasePtr( win );
497 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
502 /***********************************************************************
505 * Change the extended style of a window.
507 LONG WIN_SetExStyle( HWND hwnd, LONG style )
510 WND *win = WIN_GetPtr( hwnd );
513 if (win == WND_OTHER_PROCESS)
516 ERR( "cannot set exstyle %lx on other process window %p\n", style, hwnd );
519 if (style == win->dwExStyle)
521 WIN_ReleasePtr( win );
524 SERVER_START_REQ( set_window_info )
527 req->flags = SET_WIN_EXSTYLE;
528 req->ex_style = style;
529 req->extra_offset = -1;
530 if (!wine_server_call( req ))
532 ret = reply->old_ex_style;
533 win->dwExStyle = style;
537 WIN_ReleasePtr( win );
542 /***********************************************************************
545 * Set the window and client rectangles.
547 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
549 WND *win = WIN_GetPtr( hwnd );
553 if (win == WND_OTHER_PROCESS)
555 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd );
558 SERVER_START_REQ( set_window_rectangles )
561 req->window.left = rectWindow->left;
562 req->window.top = rectWindow->top;
563 req->window.right = rectWindow->right;
564 req->window.bottom = rectWindow->bottom;
565 req->client.left = rectClient->left;
566 req->client.top = rectClient->top;
567 req->client.right = rectClient->right;
568 req->client.bottom = rectClient->bottom;
569 ret = !wine_server_call( req );
574 win->rectWindow = *rectWindow;
575 win->rectClient = *rectClient;
577 TRACE( "win %p window (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n", hwnd,
578 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
579 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
581 WIN_ReleasePtr( win );
585 /***********************************************************************
588 * Get the window and client rectangles.
590 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
592 WND *win = WIN_GetPtr( hwnd );
595 if (!win) return FALSE;
596 if (win == WND_OTHER_PROCESS)
598 SERVER_START_REQ( get_window_rectangles )
601 if ((ret = !wine_server_call( req )))
605 rectWindow->left = reply->window.left;
606 rectWindow->top = reply->window.top;
607 rectWindow->right = reply->window.right;
608 rectWindow->bottom = reply->window.bottom;
612 rectClient->left = reply->client.left;
613 rectClient->top = reply->client.top;
614 rectClient->right = reply->client.right;
615 rectClient->bottom = reply->client.bottom;
623 if (rectWindow) *rectWindow = win->rectWindow;
624 if (rectClient) *rectClient = win->rectClient;
625 WIN_ReleasePtr( win );
631 /***********************************************************************
634 * Destroy storage associated to a window. "Internals" p.358
636 LRESULT WIN_DestroyWindow( HWND hwnd )
641 TRACE("%p\n", hwnd );
643 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
645 ERR( "window doesn't belong to current thread\n" );
649 /* free child windows */
650 if ((list = WIN_ListChildren( hwnd )))
653 for (i = 0; list[i]; i++)
655 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
656 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
658 HeapFree( GetProcessHeap(), 0, list );
662 * Clear the update region to make sure no WM_PAINT messages will be
663 * generated for this window while processing the WM_NCDESTROY.
665 RedrawWindow( hwnd, NULL, 0,
666 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
669 * Send the WM_NCDESTROY to the window being destroyed.
671 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
673 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
675 WINPOS_CheckInternalPos( hwnd );
676 if( hwnd == GetCapture()) ReleaseCapture();
678 /* free resources associated with the window */
680 TIMER_RemoveWindowTimers( hwnd );
682 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
684 if (!(wndPtr->dwStyle & WS_CHILD))
686 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
687 if (menu) DestroyMenu( menu );
689 if (wndPtr->hSysMenu)
691 DestroyMenu( wndPtr->hSysMenu );
692 wndPtr->hSysMenu = 0;
694 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
695 USER_Driver.pDestroyWindow( hwnd );
696 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
697 wndPtr->class = NULL;
698 wndPtr->dwMagic = 0; /* Mark it as invalid */
699 WIN_ReleaseWndPtr( wndPtr );
703 /***********************************************************************
704 * WIN_DestroyThreadWindows
706 * Destroy all children of 'wnd' owned by the current thread.
707 * Return TRUE if something was done.
709 void WIN_DestroyThreadWindows( HWND hwnd )
714 if (!(list = WIN_ListChildren( hwnd ))) return;
715 for (i = 0; list[i]; i++)
717 if (WIN_IsCurrentThread( list[i] ))
718 DestroyWindow( list[i] );
720 WIN_DestroyThreadWindows( list[i] );
722 HeapFree( GetProcessHeap(), 0, list );
725 /***********************************************************************
726 * WIN_CreateDesktopWindow
728 * Create the desktop window.
730 BOOL WIN_CreateDesktopWindow(void)
736 TRACE("Creating desktop window\n");
738 if (!WINPOS_CreateInternalPosAtom()) return FALSE;
740 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W );
741 if (!pWndDesktop) return FALSE;
742 hwndDesktop = pWndDesktop->hwndSelf;
744 pWndDesktop->tid = 0; /* nobody owns the desktop */
745 pWndDesktop->parent = 0;
746 pWndDesktop->owner = 0;
747 pWndDesktop->text = NULL;
748 pWndDesktop->hrgnUpdate = 0;
749 pWndDesktop->pVScroll = NULL;
750 pWndDesktop->pHScroll = NULL;
751 pWndDesktop->helpContext = 0;
752 pWndDesktop->flags = 0;
753 pWndDesktop->hSysMenu = 0;
755 cs.lpCreateParams = NULL;
761 cs.cx = GetSystemMetrics( SM_CXSCREEN );
762 cs.cy = GetSystemMetrics( SM_CYSCREEN );
763 cs.style = pWndDesktop->dwStyle;
764 cs.dwExStyle = pWndDesktop->dwExStyle;
766 cs.lpszClass = DESKTOP_CLASS_ATOM;
768 SetRect( &rect, 0, 0, cs.cx, cs.cy );
769 WIN_SetRectangles( hwndDesktop, &rect, &rect );
771 SERVER_START_REQ( set_window_info )
773 req->handle = hwndDesktop;
774 req->flags = 0; /* don't set anything, just retrieve */
775 req->extra_offset = -1;
776 wine_server_call( req );
777 pWndDesktop->dwStyle = reply->old_style;
778 pWndDesktop->dwExStyle = reply->old_ex_style;
779 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
780 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
781 pWndDesktop->wIDmenu = reply->old_id;
785 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
787 WIN_ReleaseWndPtr( pWndDesktop );
791 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
792 WIN_ReleaseWndPtr( pWndDesktop );
797 /***********************************************************************
800 * Fix the coordinates - Helper for WIN_CreateWindowEx.
801 * returns default show mode in sw.
802 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
804 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
806 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
807 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
809 if (cs->style & (WS_CHILD | WS_POPUP))
811 if (cs->dwExStyle & WS_EX_MDICHILD)
815 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0);
817 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
822 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
824 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
829 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
831 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
835 else /* overlapped window */
839 GetStartupInfoA( &info );
841 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
843 /* Never believe Microsoft's documentation... CreateWindowEx doc says
844 * that if an overlapped window is created with WS_VISIBLE style bit
845 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
846 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
849 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
850 * 2) it does not ignore the y parameter as the docs claim; instead, it
851 * uses it as second parameter to ShowWindow() unless y is either
852 * CW_USEDEFAULT or CW_USEDEFAULT16.
854 * The fact that we didn't do 2) caused bogus windows pop up when wine
855 * was running apps that were using this obscure feature. Example -
856 * calc.exe that comes with Win98 (only Win98, it's different from
857 * the one that comes with Win95 and NT)
859 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
860 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
861 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
864 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
866 if (info.dwFlags & STARTF_USESIZE)
868 cs->cx = info.dwXSize;
869 cs->cy = info.dwYSize;
871 else /* if no other hint from the app, pick 3/4 of the screen real estate */
874 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
875 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
876 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
883 /* neither x nor cx are default. Check the y values .
884 * In the trace we see Outlook and Outlook Express using
885 * cy set to CW_USEDEFAULT when opening the address book.
887 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
889 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
890 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
891 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
896 /***********************************************************************
899 static void dump_window_styles( DWORD style, DWORD exstyle )
902 if(style & WS_POPUP) TRACE(" WS_POPUP");
903 if(style & WS_CHILD) TRACE(" WS_CHILD");
904 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
905 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
906 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
907 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
908 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
909 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
910 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
913 if(style & WS_BORDER) TRACE(" WS_BORDER");
914 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
916 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
917 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
918 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
919 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
920 if(style & WS_GROUP) TRACE(" WS_GROUP");
921 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
922 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
923 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
925 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
926 #define DUMPED_STYLES \
946 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
951 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
952 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
953 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
954 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
955 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
956 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
957 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
958 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
959 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
960 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
961 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
962 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
963 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
964 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
965 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
966 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
967 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
968 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
970 #define DUMPED_EX_STYLES \
971 (WS_EX_DLGMODALFRAME | \
973 WS_EX_NOPARENTNOTIFY | \
975 WS_EX_ACCEPTFILES | \
976 WS_EX_TRANSPARENT | \
981 WS_EX_CONTEXTHELP | \
984 WS_EX_LEFTSCROLLBAR | \
985 WS_EX_CONTROLPARENT | \
990 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
992 #undef DUMPED_EX_STYLES
996 /***********************************************************************
999 * Implementation of CreateWindowEx().
1001 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
1002 WINDOWPROCTYPE type )
1006 HWND hwnd, parent, owner, top_child = 0;
1007 BOOL unicode = (type == WIN_PROC_32W);
1009 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
1010 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1011 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1012 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1013 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1015 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1017 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1018 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1020 /* Fix the styles for MDI children */
1021 if (cs->dwExStyle & WS_EX_MDICHILD)
1023 MDICREATESTRUCTA mdi_cs;
1026 wndPtr = WIN_GetPtr(cs->hwndParent);
1027 if (wndPtr && wndPtr != WND_OTHER_PROCESS)
1029 flags = wndPtr->flags;
1030 WIN_ReleasePtr(wndPtr);
1033 if (!(flags & WIN_ISMDICLIENT))
1035 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
1039 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
1040 * MDICREATESTRUCT members have the originally passed values.
1042 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
1043 * have the same layout.
1045 mdi_cs.szClass = cs->lpszClass;
1046 mdi_cs.szTitle = cs->lpszName;
1047 mdi_cs.hOwner = cs->hInstance;
1052 mdi_cs.style = cs->style;
1053 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
1055 cs->lpCreateParams = (LPVOID)&mdi_cs;
1057 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1059 if (cs->style & WS_POPUP)
1061 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
1064 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
1068 cs->style &= ~WS_POPUP;
1069 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1070 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1073 top_child = GetWindow(cs->hwndParent, GW_CHILD);
1076 /* Find the parent window */
1078 parent = GetDesktopWindow();
1081 if (cs->hwndParent == HWND_MESSAGE)
1083 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1084 * message window (style: WS_POPUP|WS_DISABLED)
1086 FIXME("Parent is HWND_MESSAGE\n");
1088 else if (cs->hwndParent)
1090 /* Make sure parent is valid */
1091 if (!IsWindow( cs->hwndParent ))
1093 WARN("Bad parent %p\n", cs->hwndParent );
1096 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1097 parent = WIN_GetFullHandle(cs->hwndParent);
1099 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1101 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1103 WARN("No parent for child window\n" );
1104 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1107 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1109 /* Correct the window styles.
1111 * It affects both the style loaded into the WIN structure and
1112 * passed in the CREATESTRUCT to the WM_[NC]CREATE.
1114 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1115 * why does the user get to set it?
1118 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1119 * tested for WS_POPUP
1121 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1122 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1123 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1124 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1126 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1128 if (!(cs->style & WS_CHILD))
1130 cs->style |= WS_CLIPSIBLINGS;
1131 if (!(cs->style & WS_POPUP))
1132 cs->style |= WS_CAPTION;
1135 /* Create the window structure */
1137 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
1139 TRACE("out of memory\n" );
1142 hwnd = wndPtr->hwndSelf;
1144 /* Fill the window structure */
1146 wndPtr->tid = GetCurrentThreadId();
1147 wndPtr->owner = owner;
1148 wndPtr->parent = parent;
1149 wndPtr->hInstance = cs->hInstance;
1150 wndPtr->text = NULL;
1151 wndPtr->hrgnUpdate = 0;
1152 wndPtr->hrgnWnd = 0;
1153 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1154 wndPtr->dwExStyle = cs->dwExStyle;
1155 wndPtr->wIDmenu = 0;
1156 wndPtr->helpContext = 0;
1157 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1158 wndPtr->pVScroll = NULL;
1159 wndPtr->pHScroll = NULL;
1160 wndPtr->userdata = 0;
1162 wndPtr->hIconSmall = 0;
1163 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1165 if (!(cs->style & (WS_CHILD | WS_POPUP)))
1166 wndPtr->flags |= WIN_NEED_SIZE;
1168 SERVER_START_REQ( set_window_info )
1171 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1172 req->style = wndPtr->dwStyle;
1173 req->ex_style = wndPtr->dwExStyle;
1174 req->instance = (void *)wndPtr->hInstance;
1175 req->extra_offset = -1;
1176 wine_server_call( req );
1180 /* Get class or window DC if needed */
1182 if (wndPtr->clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1184 /* Set the window menu */
1186 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1187 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1189 if (cs->hMenu) MENU_SetMenu(hwnd, cs->hMenu);
1192 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1195 if (HIWORD(cs->hInstance))
1196 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1198 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1200 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1204 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1205 WIN_ReleaseWndPtr( wndPtr );
1207 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1209 WIN_DestroyWindow( hwnd );
1213 /* Notify the parent window only */
1215 send_parent_notify( hwnd, WM_CREATE );
1216 if (!IsWindow( hwnd )) return 0;
1218 if (cs->dwExStyle & WS_EX_MDICHILD)
1222 /* Restore current maximized child */
1223 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1225 TRACE("Restoring current maximized child %p\n", top_child);
1226 ShowWindow(top_child, SW_SHOWNOACTIVATE);
1230 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1233 if (cs->style & WS_VISIBLE)
1234 ShowWindow( hwnd, sw );
1236 /* Call WH_SHELL hook */
1238 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1239 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1241 TRACE("created window %p\n", hwnd);
1246 /***********************************************************************
1247 * CreateWindow (USER.41)
1249 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1250 DWORD style, INT16 x, INT16 y, INT16 width,
1251 INT16 height, HWND16 parent, HMENU16 menu,
1252 HINSTANCE16 instance, LPVOID data )
1254 return CreateWindowEx16( 0, className, windowName, style,
1255 x, y, width, height, parent, menu, instance, data );
1259 /***********************************************************************
1260 * CreateWindowEx (USER.452)
1262 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1263 LPCSTR windowName, DWORD style, INT16 x,
1264 INT16 y, INT16 width, INT16 height,
1265 HWND16 parent, HMENU16 menu,
1266 HINSTANCE16 instance, LPVOID data )
1272 /* Find the class atom */
1274 if (HIWORD(className))
1276 if (!(classAtom = GlobalFindAtomA( className )))
1278 ERR( "bad class name %s\n", debugstr_a(className) );
1284 classAtom = LOWORD(className);
1285 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1287 ERR( "bad atom %x\n", classAtom);
1293 /* Fix the coordinates */
1295 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1296 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1297 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1298 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1300 /* Create the window */
1302 cs.lpCreateParams = data;
1303 cs.hInstance = HINSTANCE_32(instance);
1304 cs.hMenu = HMENU_32(menu);
1305 cs.hwndParent = WIN_Handle32( parent );
1307 cs.lpszName = windowName;
1308 cs.lpszClass = className;
1309 cs.dwExStyle = exStyle;
1311 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1315 /***********************************************************************
1316 * CreateWindowExA (USER32.@)
1318 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1319 LPCSTR windowName, DWORD style, INT x,
1320 INT y, INT width, INT height,
1321 HWND parent, HMENU menu,
1322 HINSTANCE instance, LPVOID data )
1328 /* Find the class atom */
1330 if (HIWORD(className))
1332 if (!(classAtom = GlobalFindAtomA( className )))
1334 ERR( "bad class name %s\n", debugstr_a(className) );
1340 classAtom = LOWORD(className);
1341 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1343 ERR( "bad atom %x\n", classAtom);
1349 /* Create the window */
1351 cs.lpCreateParams = data;
1352 cs.hInstance = instance;
1354 cs.hwndParent = parent;
1360 cs.lpszName = windowName;
1361 cs.lpszClass = className;
1362 cs.dwExStyle = exStyle;
1364 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1368 /***********************************************************************
1369 * CreateWindowExW (USER32.@)
1371 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1372 LPCWSTR windowName, DWORD style, INT x,
1373 INT y, INT width, INT height,
1374 HWND parent, HMENU menu,
1375 HINSTANCE instance, LPVOID data )
1381 /* Find the class atom */
1383 if (HIWORD(className))
1385 if (!(classAtom = GlobalFindAtomW( className )))
1387 ERR( "bad class name %s\n", debugstr_w(className) );
1393 classAtom = LOWORD(className);
1394 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1396 ERR( "bad atom %x\n", classAtom);
1402 /* Create the window */
1404 cs.lpCreateParams = data;
1405 cs.hInstance = instance;
1407 cs.hwndParent = parent;
1413 cs.lpszName = windowName;
1414 cs.lpszClass = className;
1415 cs.dwExStyle = exStyle;
1417 /* Note: we rely on the fact that CREATESTRUCTA and */
1418 /* CREATESTRUCTW have the same layout. */
1419 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1423 /***********************************************************************
1424 * WIN_SendDestroyMsg
1426 static void WIN_SendDestroyMsg( HWND hwnd )
1430 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1432 if (hwnd == info.hwndCaret) DestroyCaret();
1433 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1435 if (USER_Driver.pResetSelectionOwner)
1436 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1439 * Send the WM_DESTROY to the window.
1441 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1444 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1445 * make sure that the window still exists when we come back.
1452 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1454 /* start from the end (FIXME: is this needed?) */
1455 for (i = 0; pWndArray[i]; i++) ;
1459 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1461 HeapFree( GetProcessHeap(), 0, pWndArray );
1464 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1468 /***********************************************************************
1469 * DestroyWindow (USER32.@)
1471 BOOL WINAPI DestroyWindow( HWND hwnd )
1475 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1477 SetLastError( ERROR_ACCESS_DENIED );
1481 TRACE("(%p)\n", hwnd);
1483 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1484 SendMessageW(GetAncestor(hwnd, GA_PARENT), WM_MDIREFRESHMENU, 0, 0);
1488 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1490 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1494 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1495 send_parent_notify( hwnd, WM_DESTROY );
1497 else if (!GetWindow( hwnd, GW_OWNER ))
1499 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1500 /* FIXME: clean up palette - see "Internals" p.352 */
1503 if (!IsWindow(hwnd)) return TRUE;
1505 if (USER_Driver.pResetSelectionOwner)
1506 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1508 /* Hide the window */
1510 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1512 ShowWindow( hwnd, SW_HIDE );
1514 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1515 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1517 if (!IsWindow(hwnd)) return TRUE;
1519 /* Recursively destroy owned windows */
1526 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1529 for (i = 0; list[i]; i++)
1531 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1532 if (WIN_IsCurrentThread( list[i] ))
1534 DestroyWindow( list[i] );
1538 WIN_SetOwner( list[i], 0 );
1540 HeapFree( GetProcessHeap(), 0, list );
1542 if (!got_one) break;
1546 /* Send destroy messages */
1548 WIN_SendDestroyMsg( hwnd );
1549 if (!IsWindow( hwnd )) return TRUE;
1551 if (GetClipboardOwner() == hwnd)
1552 CLIPBOARD_ReleaseOwner();
1554 /* Unlink now so we won't bother with the children later on */
1556 WIN_UnlinkWindow( hwnd );
1558 /* Destroy the window storage */
1560 WIN_DestroyWindow( hwnd );
1565 /***********************************************************************
1566 * CloseWindow (USER32.@)
1568 BOOL WINAPI CloseWindow( HWND hwnd )
1570 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1571 ShowWindow( hwnd, SW_MINIMIZE );
1576 /***********************************************************************
1577 * OpenIcon (USER32.@)
1579 BOOL WINAPI OpenIcon( HWND hwnd )
1581 if (!IsIconic( hwnd )) return FALSE;
1582 ShowWindow( hwnd, SW_SHOWNORMAL );
1587 /***********************************************************************
1590 * Implementation of FindWindow() and FindWindowEx().
1592 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1597 WCHAR *buffer = NULL;
1599 if (!parent) parent = GetDesktopWindow();
1602 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1603 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1606 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1610 child = WIN_GetFullHandle( child );
1611 while (list[i] && list[i] != child) i++;
1612 if (!list[i]) goto done;
1613 i++; /* start from next window */
1620 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1627 if (list) HeapFree( GetProcessHeap(), 0, list );
1628 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1634 /***********************************************************************
1635 * FindWindowA (USER32.@)
1637 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1639 HWND ret = FindWindowExA( 0, 0, className, title );
1640 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1645 /***********************************************************************
1646 * FindWindowExA (USER32.@)
1648 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1649 LPCSTR className, LPCSTR title )
1658 /* If the atom doesn't exist, then no class */
1659 /* with this name exists either. */
1660 if (!(atom = GlobalFindAtomA( className )))
1662 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1666 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1668 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1669 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1670 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1671 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1672 HeapFree( GetProcessHeap(), 0, buffer );
1677 /***********************************************************************
1678 * FindWindowExW (USER32.@)
1680 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1681 LPCWSTR className, LPCWSTR title )
1687 /* If the atom doesn't exist, then no class */
1688 /* with this name exists either. */
1689 if (!(atom = GlobalFindAtomW( className )))
1691 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1695 return WIN_FindWindow( parent, child, atom, title );
1699 /***********************************************************************
1700 * FindWindowW (USER32.@)
1702 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1704 return FindWindowExW( 0, 0, className, title );
1708 /**********************************************************************
1709 * GetDesktopWindow (USER32.@)
1711 HWND WINAPI GetDesktopWindow(void)
1713 if (pWndDesktop) return pWndDesktop->hwndSelf;
1714 ERR( "Wine init error: either you're trying to use an invalid native USER.EXE config, or some graphics/GUI libraries or DLLs didn't initialize properly. Aborting.\n" );
1720 /*******************************************************************
1721 * EnableWindow (USER32.@)
1723 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1730 if (is_broadcast(hwnd))
1732 SetLastError( ERROR_INVALID_PARAMETER );
1736 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1737 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1741 TRACE("( %p, %d )\n", hwnd, enable);
1743 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1744 style = wndPtr->dwStyle;
1745 retvalue = ((style & WS_DISABLED) != 0);
1746 WIN_ReleasePtr( wndPtr );
1748 if (enable && retvalue)
1750 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1751 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1753 else if (!enable && !retvalue)
1757 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1759 WIN_SetStyle( hwnd, style | WS_DISABLED );
1761 if (hwnd == GetFocus())
1762 SetFocus( 0 ); /* A disabled window can't have the focus */
1764 capture_wnd = GetCapture();
1765 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1766 ReleaseCapture(); /* A disabled window can't capture the mouse */
1768 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1774 /***********************************************************************
1775 * IsWindowEnabled (USER32.@)
1777 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1779 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1783 /***********************************************************************
1784 * IsWindowUnicode (USER32.@)
1786 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1791 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1792 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1793 WIN_ReleaseWndPtr(wndPtr);
1798 /**********************************************************************
1799 * GetWindowWord (USER32.@)
1801 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1806 WND *wndPtr = WIN_GetPtr( hwnd );
1809 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1812 if (wndPtr == WND_OTHER_PROCESS)
1814 SERVER_START_REQ( set_window_info )
1817 req->flags = 0; /* don't set anything, just retrieve */
1818 req->extra_offset = offset;
1819 req->extra_size = sizeof(retvalue);
1820 if (!wine_server_call_err( req ))
1821 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1826 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1828 WARN("Invalid offset %d\n", offset );
1829 SetLastError( ERROR_INVALID_INDEX );
1831 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1832 WIN_ReleasePtr( wndPtr );
1838 case GWL_HWNDPARENT:
1839 return GetWindowLongW( hwnd, offset );
1843 LONG ret = GetWindowLongW( hwnd, offset );
1845 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1849 WARN("Invalid offset %d\n", offset );
1855 /**********************************************************************
1856 * SetWindowWord (USER32.@)
1858 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1867 case GWL_HWNDPARENT:
1868 return SetWindowLongW( hwnd, offset, (UINT)newval );
1872 WARN("Invalid offset %d\n", offset );
1873 SetLastError( ERROR_INVALID_INDEX );
1878 wndPtr = WIN_GetPtr( hwnd );
1879 if (wndPtr == WND_OTHER_PROCESS)
1882 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1883 offset, newval, hwnd );
1888 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1892 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1894 WARN("Invalid offset %d\n", offset );
1895 WIN_ReleasePtr(wndPtr);
1896 SetLastError( ERROR_INVALID_INDEX );
1900 SERVER_START_REQ( set_window_info )
1903 req->flags = SET_WIN_EXTRA;
1904 req->extra_offset = offset;
1905 req->extra_size = sizeof(newval);
1906 memcpy( &req->extra_value, &newval, sizeof(newval) );
1907 if (!wine_server_call_err( req ))
1909 void *ptr = (char *)wndPtr->wExtra + offset;
1910 memcpy( &retval, ptr, sizeof(retval) );
1911 memcpy( ptr, &newval, sizeof(newval) );
1915 WIN_ReleasePtr( wndPtr );
1920 /**********************************************************************
1923 * Helper function for GetWindowLong().
1925 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1930 if (offset == GWL_HWNDPARENT)
1932 HWND parent = GetAncestor( hwnd, GA_PARENT );
1933 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1934 return (LONG)parent;
1937 if (!(wndPtr = WIN_GetPtr( hwnd )))
1939 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1943 if (wndPtr == WND_OTHER_PROCESS)
1945 if (offset == GWL_WNDPROC)
1947 SetLastError( ERROR_ACCESS_DENIED );
1950 SERVER_START_REQ( set_window_info )
1953 req->flags = 0; /* don't set anything, just retrieve */
1954 req->extra_offset = (offset >= 0) ? offset : -1;
1955 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1956 if (!wine_server_call_err( req ))
1960 case GWL_STYLE: retvalue = reply->old_style; break;
1961 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1962 case GWL_ID: retvalue = reply->old_id; break;
1963 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1964 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1966 if (offset >= 0) retvalue = reply->old_extra_value;
1967 else SetLastError( ERROR_INVALID_INDEX );
1976 /* now we have a valid wndPtr */
1980 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1983 * Some programs try to access last element from 16 bit
1984 * code using illegal offset value. Hopefully this is
1985 * what those programs really expect.
1987 if (type == WIN_PROC_16 &&
1988 wndPtr->cbWndExtra >= 4 &&
1989 offset == wndPtr->cbWndExtra - sizeof(WORD))
1991 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1993 ERR( "- replaced invalid offset %d with %d\n",
1996 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1997 WIN_ReleasePtr( wndPtr );
2000 WARN("Invalid offset %d\n", offset );
2001 WIN_ReleasePtr( wndPtr );
2002 SetLastError( ERROR_INVALID_INDEX );
2005 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
2006 /* Special case for dialog window procedure */
2007 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2008 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
2009 WIN_ReleasePtr( wndPtr );
2015 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
2016 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
2017 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
2018 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
2019 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
2020 case GWL_HINSTANCE: retvalue = (LONG)wndPtr->hInstance; break;
2022 WARN("Unknown offset %d\n", offset );
2023 SetLastError( ERROR_INVALID_INDEX );
2026 WIN_ReleasePtr(wndPtr);
2031 /**********************************************************************
2034 * Helper function for SetWindowLong().
2036 * 0 is the failure code. However, in the case of failure SetLastError
2037 * must be set to distinguish between a 0 return value and a failure.
2039 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
2040 WINDOWPROCTYPE type )
2047 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
2049 if (is_broadcast(hwnd))
2051 SetLastError( ERROR_INVALID_PARAMETER );
2054 if (!WIN_IsCurrentProcess( hwnd ))
2056 if (offset == GWL_WNDPROC)
2058 SetLastError( ERROR_ACCESS_DENIED );
2061 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2064 wndPtr = WIN_GetPtr( hwnd );
2065 if (wndPtr->hwndSelf == GetDesktopWindow())
2067 /* can't change anything on the desktop window */
2068 WIN_ReleasePtr( wndPtr );
2069 SetLastError( ERROR_ACCESS_DENIED );
2073 /* first some special cases */
2079 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2080 style.styleNew = newval;
2081 WIN_ReleasePtr( wndPtr );
2082 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2083 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2084 newval = style.styleNew;
2086 case GWL_HWNDPARENT:
2087 if (wndPtr->parent == GetDesktopWindow())
2089 WIN_ReleasePtr( wndPtr );
2090 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2094 WIN_ReleasePtr( wndPtr );
2095 return (LONG)SetParent( hwnd, (HWND)newval );
2098 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2099 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2100 WIN_ReleasePtr( wndPtr );
2107 if ((wndPtr->cbWndExtra + sizeof(LONG) >= DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2109 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWL_DLGPROC);
2110 retval = (LONG)WINPROC_GetProc( *ptr, type );
2111 WINPROC_SetProc( ptr, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2112 WIN_ReleasePtr( wndPtr );
2117 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2119 WARN("Invalid offset %d\n", offset );
2120 WIN_ReleasePtr( wndPtr );
2121 SetLastError( ERROR_INVALID_INDEX );
2126 LONG *ptr = (LONG *)((char *)wndPtr->wExtra + offset);
2127 if (*ptr == newval) /* already set to the same value */
2129 WIN_ReleasePtr( wndPtr );
2136 SERVER_START_REQ( set_window_info )
2139 req->extra_offset = -1;
2143 req->flags = SET_WIN_STYLE;
2144 req->style = newval;
2147 req->flags = SET_WIN_EXSTYLE;
2148 req->ex_style = newval;
2151 req->flags = SET_WIN_ID;
2155 req->flags = SET_WIN_INSTANCE;
2156 req->instance = (void *)newval;
2159 req->flags = SET_WIN_USERDATA;
2160 req->user_data = (void *)newval;
2163 req->flags = SET_WIN_EXTRA;
2164 req->extra_offset = offset;
2165 req->extra_size = sizeof(newval);
2166 memcpy( &req->extra_value, &newval, sizeof(newval) );
2168 if ((ok = !wine_server_call_err( req )))
2173 wndPtr->dwStyle = newval;
2174 retval = reply->old_style;
2177 wndPtr->dwExStyle = newval;
2178 retval = reply->old_ex_style;
2181 wndPtr->wIDmenu = newval;
2182 retval = reply->old_id;
2185 wndPtr->hInstance = (HINSTANCE)newval;
2186 retval = (ULONG_PTR)reply->old_instance;
2189 wndPtr->userdata = newval;
2190 retval = (ULONG_PTR)reply->old_user_data;
2194 void *ptr = (char *)wndPtr->wExtra + offset;
2195 memcpy( &retval, ptr, sizeof(retval) );
2196 memcpy( ptr, &newval, sizeof(newval) );
2203 WIN_ReleasePtr( wndPtr );
2207 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2208 USER_Driver.pSetWindowStyle( hwnd, retval );
2210 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2211 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2217 /**********************************************************************
2218 * GetWindowLong (USER.135)
2220 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2222 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2226 /**********************************************************************
2227 * GetWindowLongA (USER32.@)
2229 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2231 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2235 /**********************************************************************
2236 * GetWindowLongW (USER32.@)
2238 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2240 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2244 /**********************************************************************
2245 * SetWindowLong (USER.136)
2247 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2249 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2253 /**********************************************************************
2254 * SetWindowLongA (USER32.@)
2256 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2258 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2262 /**********************************************************************
2263 * SetWindowLongW (USER32.@) Set window attribute
2265 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2266 * value in a window's extra memory.
2268 * The _hwnd_ parameter specifies the window. is the handle to a
2269 * window that has extra memory. The _newval_ parameter contains the
2270 * new attribute or extra memory value. If positive, the _offset_
2271 * parameter is the byte-addressed location in the window's extra
2272 * memory to set. If negative, _offset_ specifies the window
2273 * attribute to set, and should be one of the following values:
2275 * GWL_EXSTYLE The window's extended window style
2277 * GWL_STYLE The window's window style.
2279 * GWL_WNDPROC Pointer to the window's window procedure.
2281 * GWL_HINSTANCE The window's pplication instance handle.
2283 * GWL_ID The window's identifier.
2285 * GWL_USERDATA The window's user-specified data.
2287 * If the window is a dialog box, the _offset_ parameter can be one of
2288 * the following values:
2290 * DWL_DLGPROC The address of the window's dialog box procedure.
2292 * DWL_MSGRESULT The return value of a message
2293 * that the dialog box procedure processed.
2295 * DWL_USER Application specific information.
2299 * If successful, returns the previous value located at _offset_. Otherwise,
2304 * Extra memory for a window class is specified by a nonzero cbWndExtra
2305 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2306 * time of class creation.
2308 * Using GWL_WNDPROC to set a new window procedure effectively creates
2309 * a window subclass. Use CallWindowProc() in the new windows procedure
2310 * to pass messages to the superclass's window procedure.
2312 * The user data is reserved for use by the application which created
2315 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2316 * instead, call the EnableWindow() function to change the window's
2319 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2320 * SetParent() instead.
2323 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2324 * it sends WM_STYLECHANGING before changing the settings
2325 * and WM_STYLECHANGED afterwards.
2326 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2328 LONG WINAPI SetWindowLongW(
2329 HWND hwnd, /* [in] window to alter */
2330 INT offset, /* [in] offset, in bytes, of location to alter */
2331 LONG newval /* [in] new value of location */
2333 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2337 /*******************************************************************
2338 * GetWindowTextA (USER32.@)
2340 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2344 if (WIN_IsCurrentProcess( hwnd ))
2345 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2347 /* when window belongs to other process, don't send a message */
2348 if (nMaxCount <= 0) return 0;
2349 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2350 get_server_window_text( hwnd, buffer, nMaxCount );
2351 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2352 lpString[nMaxCount-1] = 0;
2353 HeapFree( GetProcessHeap(), 0, buffer );
2354 return strlen(lpString);
2358 /*******************************************************************
2359 * InternalGetWindowText (USER32.@)
2361 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2365 if (nMaxCount <= 0) return 0;
2366 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2367 if (win != WND_OTHER_PROCESS)
2369 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2370 else lpString[0] = 0;
2371 WIN_ReleasePtr( win );
2375 get_server_window_text( hwnd, lpString, nMaxCount );
2377 return strlenW(lpString);
2381 /*******************************************************************
2382 * GetWindowTextW (USER32.@)
2384 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2386 if (WIN_IsCurrentProcess( hwnd ))
2387 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2389 /* when window belongs to other process, don't send a message */
2390 if (nMaxCount <= 0) return 0;
2391 get_server_window_text( hwnd, lpString, nMaxCount );
2392 return strlenW(lpString);
2396 /*******************************************************************
2397 * SetWindowText (USER32.@)
2398 * SetWindowTextA (USER32.@)
2400 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2402 if (is_broadcast(hwnd))
2404 SetLastError( ERROR_INVALID_PARAMETER );
2407 if (!WIN_IsCurrentProcess( hwnd ))
2409 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2410 SetLastError( ERROR_ACCESS_DENIED );
2413 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2417 /*******************************************************************
2418 * SetWindowTextW (USER32.@)
2420 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2422 if (is_broadcast(hwnd))
2424 SetLastError( ERROR_INVALID_PARAMETER );
2427 if (!WIN_IsCurrentProcess( hwnd ))
2429 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2430 SetLastError( ERROR_ACCESS_DENIED );
2433 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2437 /*******************************************************************
2438 * GetWindowTextLengthA (USER32.@)
2440 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2442 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2445 /*******************************************************************
2446 * GetWindowTextLengthW (USER32.@)
2448 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2450 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2454 /*******************************************************************
2455 * IsWindow (USER32.@)
2457 BOOL WINAPI IsWindow( HWND hwnd )
2462 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2464 if (ptr != WND_OTHER_PROCESS)
2466 WIN_ReleasePtr( ptr );
2470 /* check other processes */
2471 SERVER_START_REQ( get_window_info )
2474 ret = !wine_server_call_err( req );
2481 /***********************************************************************
2482 * GetWindowThreadProcessId (USER32.@)
2484 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2489 if (!(ptr = WIN_GetPtr( hwnd )))
2491 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2495 if (ptr != WND_OTHER_PROCESS)
2497 /* got a valid window */
2499 if (process) *process = GetCurrentProcessId();
2500 WIN_ReleasePtr( ptr );
2504 /* check other processes */
2505 SERVER_START_REQ( get_window_info )
2508 if (!wine_server_call_err( req ))
2510 tid = (DWORD)reply->tid;
2511 if (process) *process = (DWORD)reply->pid;
2519 /*****************************************************************
2520 * GetParent (USER32.@)
2522 HWND WINAPI GetParent( HWND hwnd )
2527 if (!(wndPtr = WIN_GetPtr( hwnd )))
2529 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2532 if (wndPtr == WND_OTHER_PROCESS)
2534 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2535 if (style & (WS_POPUP | WS_CHILD))
2537 SERVER_START_REQ( get_window_tree )
2540 if (!wine_server_call_err( req ))
2542 if (style & WS_POPUP) retvalue = reply->owner;
2543 else if (style & WS_CHILD) retvalue = reply->parent;
2551 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2552 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2553 WIN_ReleasePtr( wndPtr );
2559 /*****************************************************************
2560 * GetAncestor (USER32.@)
2562 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2565 HWND *list, ret = 0;
2570 if (!(win = WIN_GetPtr( hwnd )))
2572 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2575 if (win != WND_OTHER_PROCESS)
2578 WIN_ReleasePtr( win );
2580 else /* need to query the server */
2582 SERVER_START_REQ( get_window_tree )
2585 if (!wine_server_call_err( req )) ret = reply->parent;
2592 if (!(list = WIN_ListParents( hwnd ))) return 0;
2594 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2598 while (list[count]) count++;
2599 ret = list[count - 2]; /* get the one before the desktop */
2601 HeapFree( GetProcessHeap(), 0, list );
2605 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2608 HWND parent = GetParent( ret );
2618 /*****************************************************************
2619 * SetParent (USER32.@)
2621 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2624 HWND retvalue, full_handle;
2627 if (is_broadcast(hwnd) || is_broadcast(parent))
2629 SetLastError(ERROR_INVALID_PARAMETER);
2633 if (!parent) parent = GetDesktopWindow();
2634 else parent = WIN_GetFullHandle( parent );
2636 if (!IsWindow( parent ))
2638 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2642 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2643 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2647 if (USER_Driver.pSetParent)
2648 return USER_Driver.pSetParent( hwnd, parent );
2650 /* Windows hides the window first, then shows it again
2651 * including the WM_SHOWWINDOW messages and all */
2652 was_visible = ShowWindow( hwnd, SW_HIDE );
2654 if (!IsWindow( parent )) return 0;
2655 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2657 retvalue = wndPtr->parent; /* old parent */
2658 if (parent != retvalue)
2660 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2662 if (parent != GetDesktopWindow()) /* a child window */
2664 if (!(wndPtr->dwStyle & WS_CHILD))
2666 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2667 if (menu) DestroyMenu( menu );
2671 WIN_ReleasePtr( wndPtr );
2673 /* SetParent additionally needs to make hwnd the topmost window
2674 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2675 WM_WINDOWPOSCHANGED notification messages.
2677 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2678 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2679 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2680 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2685 /*******************************************************************
2686 * IsChild (USER32.@)
2688 BOOL WINAPI IsChild( HWND parent, HWND child )
2690 HWND *list = WIN_ListParents( child );
2694 if (!list) return FALSE;
2695 parent = WIN_GetFullHandle( parent );
2696 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2697 ret = (list[i] != 0);
2698 HeapFree( GetProcessHeap(), 0, list );
2703 /***********************************************************************
2704 * IsWindowVisible (USER32.@)
2706 BOOL WINAPI IsWindowVisible( HWND hwnd )
2712 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2713 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2714 for (i = 0; list[i]; i++)
2715 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2717 HeapFree( GetProcessHeap(), 0, list );
2722 /***********************************************************************
2723 * WIN_IsWindowDrawable
2725 * hwnd is drawable when it is visible, all parents are not
2726 * minimized, and it is itself not minimized unless we are
2727 * trying to draw its default class icon.
2729 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2734 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2736 if (!(style & WS_VISIBLE)) return FALSE;
2737 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2739 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2740 for (i = 0; list[i]; i++)
2741 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2744 HeapFree( GetProcessHeap(), 0, list );
2749 /*******************************************************************
2750 * GetTopWindow (USER32.@)
2752 HWND WINAPI GetTopWindow( HWND hwnd )
2754 if (!hwnd) hwnd = GetDesktopWindow();
2755 return GetWindow( hwnd, GW_CHILD );
2759 /*******************************************************************
2760 * GetWindow (USER32.@)
2762 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2766 if (rel == GW_OWNER) /* this one may be available locally */
2768 WND *wndPtr = WIN_GetPtr( hwnd );
2771 SetLastError( ERROR_INVALID_HANDLE );
2774 if (wndPtr != WND_OTHER_PROCESS)
2776 retval = wndPtr->owner;
2777 WIN_ReleasePtr( wndPtr );
2780 /* else fall through to server call */
2783 SERVER_START_REQ( get_window_tree )
2786 if (!wine_server_call_err( req ))
2791 retval = reply->first_sibling;
2794 retval = reply->last_sibling;
2797 retval = reply->next_sibling;
2800 retval = reply->prev_sibling;
2803 retval = reply->owner;
2806 retval = reply->first_child;
2816 /***********************************************************************
2817 * WIN_InternalShowOwnedPopups
2819 * Internal version of ShowOwnedPopups; Wine functions should use this
2820 * to avoid interfering with application calls to ShowOwnedPopups
2821 * and to make sure the application can't prevent showing/hiding.
2823 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2827 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2831 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2833 if (!win_array) return TRUE;
2836 * Show windows Lowest first, Highest last to preserve Z-Order
2838 while (win_array[count]) count++;
2839 while (--count >= 0)
2841 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2842 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2844 if (pWnd->dwStyle & WS_POPUP)
2848 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2849 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2852 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2854 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2855 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2860 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2861 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2862 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2865 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2867 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2868 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2869 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2873 WIN_ReleaseWndPtr( pWnd );
2875 HeapFree( GetProcessHeap(), 0, win_array );
2880 /*******************************************************************
2881 * ShowOwnedPopups (USER32.@)
2883 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2887 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2889 if (!win_array) return TRUE;
2891 while (win_array[count]) count++;
2892 while (--count >= 0)
2894 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2895 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2897 if (pWnd->dwStyle & WS_POPUP)
2901 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2903 /* In Windows, ShowOwnedPopups(TRUE) generates
2904 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2905 * regardless of the state of the owner
2907 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2908 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2913 if (IsWindowVisible(pWnd->hwndSelf))
2915 /* In Windows, ShowOwnedPopups(FALSE) generates
2916 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2917 * regardless of the state of the owner
2919 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2920 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2924 WIN_ReleaseWndPtr( pWnd );
2926 HeapFree( GetProcessHeap(), 0, win_array );
2931 /*******************************************************************
2932 * GetLastActivePopup (USER32.@)
2934 HWND WINAPI GetLastActivePopup( HWND hwnd )
2938 SERVER_START_REQ( get_window_info )
2941 if (!wine_server_call_err( req )) retval = reply->last_active;
2948 /*******************************************************************
2951 * Build an array of all parents of a given window, starting with
2952 * the immediate parent. The array must be freed with HeapFree.
2953 * Returns NULL if window is a top-level window.
2955 HWND *WIN_ListParents( HWND hwnd )
2958 HWND current, *list;
2959 int pos = 0, size = 16, count = 0;
2961 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2966 if (!(win = WIN_GetPtr( current ))) goto empty;
2967 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2968 list[pos] = win->parent;
2969 WIN_ReleasePtr( win );
2970 if (!(current = list[pos]))
2972 if (!pos) goto empty;
2975 if (++pos == size - 1)
2977 /* need to grow the list */
2978 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2979 if (!new_list) goto empty;
2985 /* at least one parent belongs to another process, have to query the server */
2990 SERVER_START_REQ( get_window_parents )
2993 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2994 if (!wine_server_call( req )) count = reply->count;
2997 if (!count) goto empty;
3003 HeapFree( GetProcessHeap(), 0, list );
3005 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
3009 HeapFree( GetProcessHeap(), 0, list );
3014 /*******************************************************************
3017 * Build an array of the children of a given window. The array must be
3018 * freed with HeapFree. Returns NULL when no windows are found.
3020 HWND *WIN_ListChildren( HWND hwnd )
3022 return list_window_children( hwnd, 0, 0 );
3026 /*******************************************************************
3027 * EnumWindows (USER32.@)
3029 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
3035 /* We have to build a list of all windows first, to avoid */
3036 /* unpleasant side-effects, for instance if the callback */
3037 /* function changes the Z-order of the windows. */
3039 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
3041 /* Now call the callback function for every window */
3043 iWndsLocks = WIN_SuspendWndsLock();
3044 for (i = 0; list[i]; i++)
3046 /* Make sure that the window still exists */
3047 if (!IsWindow( list[i] )) continue;
3048 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
3050 WIN_RestoreWndsLock(iWndsLocks);
3051 HeapFree( GetProcessHeap(), 0, list );
3056 /**********************************************************************
3057 * EnumThreadWindows (USER32.@)
3059 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
3064 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
3066 /* Now call the callback function for every window */
3068 iWndsLocks = WIN_SuspendWndsLock();
3069 for (i = 0; list[i]; i++)
3070 if (!func( list[i], lParam )) break;
3071 WIN_RestoreWndsLock(iWndsLocks);
3072 HeapFree( GetProcessHeap(), 0, list );
3077 /**********************************************************************
3078 * WIN_EnumChildWindows
3080 * Helper function for EnumChildWindows().
3082 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3087 for ( ; *list; list++)
3089 /* Make sure that the window still exists */
3090 if (!IsWindow( *list )) continue;
3091 /* skip owned windows */
3092 if (GetWindow( *list, GW_OWNER )) continue;
3093 /* Build children list first */
3094 childList = WIN_ListChildren( *list );
3096 ret = func( *list, lParam );
3100 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3101 HeapFree( GetProcessHeap(), 0, childList );
3103 if (!ret) return FALSE;
3109 /**********************************************************************
3110 * EnumChildWindows (USER32.@)
3112 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3117 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3118 iWndsLocks = WIN_SuspendWndsLock();
3119 WIN_EnumChildWindows( list, func, lParam );
3120 WIN_RestoreWndsLock(iWndsLocks);
3121 HeapFree( GetProcessHeap(), 0, list );
3126 /*******************************************************************
3127 * AnyPopup (USER.52)
3129 BOOL16 WINAPI AnyPopup16(void)
3135 /*******************************************************************
3136 * AnyPopup (USER32.@)
3138 BOOL WINAPI AnyPopup(void)
3142 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3144 if (!list) return FALSE;
3145 for (i = 0; list[i]; i++)
3147 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3149 retvalue = (list[i] != 0);
3150 HeapFree( GetProcessHeap(), 0, list );
3155 /*******************************************************************
3156 * FlashWindow (USER32.@)
3158 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3160 WND *wndPtr = WIN_FindWndPtr(hWnd);
3162 TRACE("%p\n", hWnd);
3164 if (!wndPtr) return FALSE;
3165 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3167 if (wndPtr->dwStyle & WS_MINIMIZE)
3169 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3171 HDC hDC = GetDC(hWnd);
3173 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3174 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3176 ReleaseDC( hWnd, hDC );
3177 wndPtr->flags |= WIN_NCACTIVATED;
3181 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3182 wndPtr->flags &= ~WIN_NCACTIVATED;
3184 WIN_ReleaseWndPtr(wndPtr);
3190 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3191 else wparam = (hWnd == GetForegroundWindow());
3193 WIN_ReleaseWndPtr(wndPtr);
3194 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3199 /*******************************************************************
3200 * FlashWindowEx (USER32.@)
3202 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3204 FIXME("%p\n", pfwi);
3208 /*******************************************************************
3209 * GetWindowContextHelpId (USER32.@)
3211 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3214 WND *wnd = WIN_FindWndPtr( hwnd );
3216 retval = wnd->helpContext;
3217 WIN_ReleaseWndPtr(wnd);
3222 /*******************************************************************
3223 * SetWindowContextHelpId (USER32.@)
3225 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3227 WND *wnd = WIN_FindWndPtr( hwnd );
3228 if (!wnd) return FALSE;
3229 wnd->helpContext = id;
3230 WIN_ReleaseWndPtr(wnd);
3235 /*******************************************************************
3236 * DragDetect (USER32.@)
3238 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3243 rect.left = pt.x - wDragWidth;
3244 rect.right = pt.x + wDragWidth;
3246 rect.top = pt.y - wDragHeight;
3247 rect.bottom = pt.y + wDragHeight;
3253 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3255 if( msg.message == WM_LBUTTONUP )
3260 if( msg.message == WM_MOUSEMOVE )
3263 tmp.x = LOWORD(msg.lParam);
3264 tmp.y = HIWORD(msg.lParam);
3265 if( !PtInRect( &rect, tmp ))
3277 /******************************************************************************
3278 * GetWindowModuleFileNameA (USER32.@)
3280 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3282 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3283 hwnd, lpszFileName, cchFileNameMax);
3287 /******************************************************************************
3288 * GetWindowModuleFileNameW (USER32.@)
3290 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3292 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3293 hwnd, lpszFileName, cchFileNameMax);
3297 /******************************************************************************
3298 * GetWindowInfo (USER32.@)
3300 * Note: tests show that Windows doesn't check cbSize of the structure.
3302 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3304 if (!pwi) return FALSE;
3305 if (!IsWindow(hwnd)) return FALSE;
3307 GetWindowRect(hwnd, &pwi->rcWindow);
3308 GetClientRect(hwnd, &pwi->rcClient);
3309 /* translate to screen coordinates */
3310 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3312 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3313 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3314 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3316 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3317 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3319 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3320 pwi->wCreatorVersion = 0x0400;