2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "wine/server.h"
14 #include "wine/unicode.h"
20 #include "cursoricon.h"
27 #include "stackframe.h"
28 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(win);
31 DECLARE_DEBUG_CHANNEL(msg);
33 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
35 /**********************************************************************/
38 static WND *pWndDesktop = NULL;
40 static WORD wDragWidth = 4;
41 static WORD wDragHeight= 3;
43 static void *user_handles[NB_USER_HANDLES];
46 extern SYSLEVEL USER_SysLevel; /* FIXME */
48 /***********************************************************************
51 * Suspend the lock on WND structures.
52 * Returns the number of locks suspended
54 int WIN_SuspendWndsLock( void )
56 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
57 int count = isuspendedLocks;
60 _LeaveSysLevel( &USER_SysLevel );
62 return isuspendedLocks;
65 /***********************************************************************
68 * Restore the suspended locks on WND structures
70 void WIN_RestoreWndsLock( int ipreviousLocks )
72 while ( ipreviousLocks-- > 0 )
73 _EnterSysLevel( &USER_SysLevel );
76 /***********************************************************************
77 * create_window_handle
79 * Create a window handle with the server.
81 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
84 user_handle_t handle = 0;
86 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
88 if (!win) return NULL;
92 SERVER_START_REQ( create_window )
97 if ((res = !SERVER_CALL_ERR())) handle = req->handle;
104 HeapFree( GetProcessHeap(), 0, win );
107 index = LOWORD(handle) - FIRST_USER_HANDLE;
108 assert( index < NB_USER_HANDLES );
109 user_handles[index] = win;
110 win->hwndSelf = handle;
111 win->dwMagic = WND_MAGIC;
117 /***********************************************************************
120 * Free a window handle.
122 static WND *free_window_handle( HWND hwnd )
125 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
127 if (index >= NB_USER_HANDLES) return NULL;
129 if ((ptr = user_handles[index]))
131 SERVER_START_REQ( destroy_window )
134 if (!SERVER_CALL_ERR())
135 user_handles[index] = NULL;
142 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
147 /*******************************************************************
148 * list_window_children
150 * Build an array of the children of a given window. The array must be
151 * freed with HeapFree. Returns NULL when no windows are found.
153 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
157 SERVER_START_VAR_REQ( get_window_children, REQUEST_MAX_VAR_SIZE )
161 req->tid = (void *)tid;
164 user_handle_t *data = server_data_ptr(req);
165 int i, count = server_data_size(req) / sizeof(*data);
166 if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) ))))
168 for (i = 0; i < count; i++) list[i] = data[i];
178 /*******************************************************************
181 static void send_parent_notify( HWND hwnd, UINT msg )
183 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
184 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
185 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
186 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
190 /*******************************************************************
191 * get_server_window_text
193 * Retrieve the window text from the server.
195 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
197 size_t len = (count - 1) * sizeof(WCHAR);
198 len = min( len, REQUEST_MAX_VAR_SIZE );
199 SERVER_START_VAR_REQ( get_window_text, len )
202 if (!SERVER_CALL_ERR())
204 len = server_data_size(req);
205 memcpy( text, server_data_ptr(req), len );
210 text[len / sizeof(WCHAR)] = 0;
214 /***********************************************************************
217 * Return a pointer to the WND structure if local to the process,
218 * or WND_OTHER_PROCESS is handle may be valid in other process.
219 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
221 WND *WIN_GetPtr( HWND hwnd )
224 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
226 if (index >= NB_USER_HANDLES) return NULL;
229 if ((ptr = user_handles[index]))
231 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
235 else ptr = WND_OTHER_PROCESS;
241 /***********************************************************************
242 * WIN_IsCurrentProcess
244 * Check whether a given window belongs to the current process (and return the full handle).
246 HWND WIN_IsCurrentProcess( HWND hwnd )
251 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
253 WIN_ReleasePtr( ptr );
258 /***********************************************************************
259 * WIN_IsCurrentThread
261 * Check whether a given window belongs to the current thread (and return the full handle).
263 HWND WIN_IsCurrentThread( HWND hwnd )
268 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
270 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
271 WIN_ReleasePtr( ptr );
277 /***********************************************************************
280 * Convert a 16-bit window handle to a full 32-bit handle.
282 HWND WIN_Handle32( HWND16 hwnd16 )
285 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
287 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
288 /* do sign extension for -2 and -3 */
289 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
291 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
293 if (ptr != WND_OTHER_PROCESS)
295 hwnd = ptr->hwndSelf;
296 WIN_ReleasePtr( ptr );
298 else /* may belong to another process */
300 SERVER_START_REQ( get_window_info )
303 if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
311 /***********************************************************************
314 * Return a pointer to the WND structure corresponding to a HWND.
316 WND * WIN_FindWndPtr( HWND hwnd )
320 if (!hwnd) return NULL;
322 if ((ptr = WIN_GetPtr( hwnd )))
324 if (ptr != WND_OTHER_PROCESS)
326 /* increment destruction monitoring */
330 if (IsWindow( hwnd )) /* check other processes */
332 ERR( "window %04x belongs to other process\n", hwnd );
333 /* DbgBreakPoint(); */
336 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
341 /***********************************************************************
344 * Release the pointer to the WND structure.
346 void WIN_ReleaseWndPtr(WND *wndPtr)
350 /* Decrement destruction monitoring value */
352 /* Check if it's time to release the memory */
353 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
356 free_window_handle( wndPtr->hwndSelf );
358 else if(wndPtr->irefCount < 0)
360 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
361 ERR("forgot a Lock on %p somewhere\n",wndPtr);
363 /* unlock all WND structures for thread safeness */
368 /***********************************************************************
371 * Remove a window from the siblings linked list.
373 void WIN_UnlinkWindow( HWND hwnd )
375 WIN_LinkWindow( hwnd, 0, 0 );
379 /***********************************************************************
382 * Insert a window into the siblings linked list.
383 * The window is inserted after the specified window, which can also
384 * be specified as HWND_TOP or HWND_BOTTOM.
385 * If parent is 0, window is unlinked from the tree.
387 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
389 WND *wndPtr = WIN_GetPtr( hwnd );
392 if (wndPtr == WND_OTHER_PROCESS)
394 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
398 SERVER_START_REQ( link_window )
401 req->parent = parent;
402 req->previous = hwndInsertAfter;
405 if (req->full_parent && req->full_parent != wndPtr->parent)
407 wndPtr->owner = 0; /* reset owner when changing parent */
408 wndPtr->parent = req->full_parent;
414 WIN_ReleasePtr( wndPtr );
418 /***********************************************************************
421 * Change the owner of a window.
423 void WIN_SetOwner( HWND hwnd, HWND owner )
425 WND *win = WIN_GetPtr( hwnd );
428 if (win == WND_OTHER_PROCESS)
430 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
433 SERVER_START_REQ( set_window_owner )
437 if (!SERVER_CALL()) win->owner = req->full_owner;
440 WIN_ReleasePtr( win );
444 /***********************************************************************
447 * Change the style of a window.
449 LONG WIN_SetStyle( HWND hwnd, LONG style )
453 WND *win = WIN_GetPtr( hwnd );
456 if (win == WND_OTHER_PROCESS)
459 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
462 if (style == win->dwStyle)
464 WIN_ReleasePtr( win );
467 SERVER_START_REQ( set_window_info )
470 req->flags = SET_WIN_STYLE;
472 if ((ok = !SERVER_CALL()))
474 ret = req->old_style;
475 win->dwStyle = style;
479 WIN_ReleasePtr( win );
480 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
485 /***********************************************************************
488 * Change the extended style of a window.
490 LONG WIN_SetExStyle( HWND hwnd, LONG style )
493 WND *win = WIN_GetPtr( hwnd );
496 if (win == WND_OTHER_PROCESS)
499 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
502 if (style == win->dwExStyle)
504 WIN_ReleasePtr( win );
507 SERVER_START_REQ( set_window_info )
510 req->flags = SET_WIN_EXSTYLE;
511 req->ex_style = style;
514 ret = req->old_ex_style;
515 win->dwExStyle = style;
519 WIN_ReleasePtr( win );
524 /***********************************************************************
527 * Set the window and client rectangles.
529 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
531 WND *win = WIN_GetPtr( hwnd );
535 if (win == WND_OTHER_PROCESS)
537 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
540 SERVER_START_REQ( set_window_rectangles )
543 req->window.left = rectWindow->left;
544 req->window.top = rectWindow->top;
545 req->window.right = rectWindow->right;
546 req->window.bottom = rectWindow->bottom;
547 req->client.left = rectClient->left;
548 req->client.top = rectClient->top;
549 req->client.right = rectClient->right;
550 req->client.bottom = rectClient->bottom;
551 ret = !SERVER_CALL();
556 win->rectWindow = *rectWindow;
557 win->rectClient = *rectClient;
559 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
560 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
561 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
563 WIN_ReleasePtr( win );
567 /***********************************************************************
570 * Destroy storage associated to a window. "Internals" p.358
572 LRESULT WIN_DestroyWindow( HWND hwnd )
577 TRACE("%04x\n", hwnd );
579 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
581 ERR( "window doesn't belong to current thread\n" );
585 /* free child windows */
586 if ((list = WIN_ListChildren( hwnd )))
589 for (i = 0; list[i]; i++)
591 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
592 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
594 HeapFree( GetProcessHeap(), 0, list );
598 * Clear the update region to make sure no WM_PAINT messages will be
599 * generated for this window while processing the WM_NCDESTROY.
601 RedrawWindow( hwnd, NULL, 0,
602 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
605 * Send the WM_NCDESTROY to the window being destroyed.
607 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
609 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
611 WINPOS_CheckInternalPos( hwnd );
612 if( hwnd == GetCapture()) ReleaseCapture();
614 /* free resources associated with the window */
616 TIMER_RemoveWindowTimers( hwnd );
618 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
619 wndPtr->hmemTaskQ = 0;
621 if (!(wndPtr->dwStyle & WS_CHILD))
623 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
624 if (menu) DestroyMenu( menu );
626 if (wndPtr->hSysMenu)
628 DestroyMenu( wndPtr->hSysMenu );
629 wndPtr->hSysMenu = 0;
631 USER_Driver.pDestroyWindow( hwnd );
632 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
633 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
634 CLASS_RemoveWindow( wndPtr->class );
635 wndPtr->class = NULL;
636 wndPtr->dwMagic = 0; /* Mark it as invalid */
637 WIN_ReleaseWndPtr( wndPtr );
641 /***********************************************************************
642 * WIN_DestroyThreadWindows
644 * Destroy all children of 'wnd' owned by the current thread.
645 * Return TRUE if something was done.
647 void WIN_DestroyThreadWindows( HWND hwnd )
652 if (!(list = WIN_ListChildren( hwnd ))) return;
653 for (i = 0; list[i]; i++)
655 if (WIN_IsCurrentThread( list[i] ))
656 DestroyWindow( list[i] );
658 WIN_DestroyThreadWindows( list[i] );
660 HeapFree( GetProcessHeap(), 0, list );
663 /***********************************************************************
664 * WIN_CreateDesktopWindow
666 * Create the desktop window.
668 BOOL WIN_CreateDesktopWindow(void)
670 struct tagCLASS *class;
679 TRACE("Creating desktop window\n");
681 if (!WINPOS_CreateInternalPosAtom() ||
682 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
683 &wndExtra, &winproc, &clsStyle, &dce )))
686 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
687 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
688 if (!pWndDesktop) return FALSE;
689 hwndDesktop = pWndDesktop->hwndSelf;
691 pWndDesktop->tid = 0; /* nobody owns the desktop */
692 pWndDesktop->parent = 0;
693 pWndDesktop->owner = 0;
694 pWndDesktop->class = class;
695 pWndDesktop->hInstance = 0;
696 pWndDesktop->text = NULL;
697 pWndDesktop->hmemTaskQ = 0;
698 pWndDesktop->hrgnUpdate = 0;
699 pWndDesktop->hwndLastActive = hwndDesktop;
700 pWndDesktop->dwStyle = 0;
701 pWndDesktop->dwExStyle = 0;
702 pWndDesktop->clsStyle = clsStyle;
703 pWndDesktop->dce = NULL;
704 pWndDesktop->pVScroll = NULL;
705 pWndDesktop->pHScroll = NULL;
706 pWndDesktop->wIDmenu = 0;
707 pWndDesktop->helpContext = 0;
708 pWndDesktop->flags = 0;
709 pWndDesktop->hSysMenu = 0;
710 pWndDesktop->userdata = 0;
711 pWndDesktop->winproc = winproc;
712 pWndDesktop->cbWndExtra = wndExtra;
714 cs.lpCreateParams = NULL;
720 cs.cx = GetSystemMetrics( SM_CXSCREEN );
721 cs.cy = GetSystemMetrics( SM_CYSCREEN );
722 cs.style = pWndDesktop->dwStyle;
723 cs.dwExStyle = pWndDesktop->dwExStyle;
725 cs.lpszClass = DESKTOP_CLASS_ATOM;
727 SetRect( &rect, 0, 0, cs.cx, cs.cy );
728 WIN_SetRectangles( hwndDesktop, &rect, &rect );
729 WIN_SetStyle( hwndDesktop, WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
731 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
733 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
734 WIN_ReleaseWndPtr( pWndDesktop );
739 /***********************************************************************
742 * Fix the coordinates - Helper for WIN_CreateWindowEx.
743 * returns default show mode in sw.
744 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
746 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
748 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
749 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
751 if (cs->style & (WS_CHILD | WS_POPUP))
753 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
754 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
756 else /* overlapped window */
760 GetStartupInfoA( &info );
762 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
764 /* Never believe Microsoft's documentation... CreateWindowEx doc says
765 * that if an overlapped window is created with WS_VISIBLE style bit
766 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
767 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
770 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
771 * 2) it does not ignore the y parameter as the docs claim; instead, it
772 * uses it as second parameter to ShowWindow() unless y is either
773 * CW_USEDEFAULT or CW_USEDEFAULT16.
775 * The fact that we didn't do 2) caused bogus windows pop up when wine
776 * was running apps that were using this obscure feature. Example -
777 * calc.exe that comes with Win98 (only Win98, it's different from
778 * the one that comes with Win95 and NT)
780 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
781 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
782 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
785 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
787 if (info.dwFlags & STARTF_USESIZE)
789 cs->cx = info.dwXSize;
790 cs->cy = info.dwYSize;
792 else /* if no other hint from the app, pick 3/4 of the screen real estate */
795 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
796 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
797 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
804 /***********************************************************************
807 static void dump_window_styles( DWORD style, DWORD exstyle )
810 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
811 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
812 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
813 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
814 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
815 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
816 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
817 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
818 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
821 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
822 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
824 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
825 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
826 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
827 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
828 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
829 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
830 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
831 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
833 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
834 #define DUMPED_STYLES \
854 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
859 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
860 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
861 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
862 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
863 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
864 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
865 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
866 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
867 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
868 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
869 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
870 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
871 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
872 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
873 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
874 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
875 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
876 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
878 #define DUMPED_EX_STYLES \
879 (WS_EX_DLGMODALFRAME | \
881 WS_EX_NOPARENTNOTIFY | \
883 WS_EX_ACCEPTFILES | \
884 WS_EX_TRANSPARENT | \
889 WS_EX_CONTEXTHELP | \
892 WS_EX_LEFTSCROLLBAR | \
893 WS_EX_CONTROLPARENT | \
898 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
900 #undef DUMPED_EX_STYLES
904 /***********************************************************************
907 * Implementation of CreateWindowEx().
909 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
910 WINDOWPROCTYPE type )
913 struct tagCLASS *classPtr;
915 HWND hwnd, hwndLinkAfter, parent, owner;
920 BOOL unicode = (type == WIN_PROC_32W);
922 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
923 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
924 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
925 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
926 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
928 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
930 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
931 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
933 /* Find the parent window */
935 parent = GetDesktopWindow();
939 /* Make sure parent is valid */
940 if (!IsWindow( cs->hwndParent ))
942 WARN("Bad parent %04x\n", cs->hwndParent );
945 if (cs->style & WS_CHILD) parent = WIN_GetFullHandle(cs->hwndParent);
946 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
948 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
950 WARN("No parent for child window\n" );
951 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
954 /* Find the window class */
955 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
956 &wndExtra, &winproc, &clsStyle, &dce )))
958 WARN("Bad class '%s'\n", cs->lpszClass );
962 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
964 /* Correct the window style - stage 1
966 * These are patches that appear to affect both the style loaded into the
967 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
969 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
970 * why does the user get to set it?
973 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
974 * tested for WS_POPUP
976 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
977 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
978 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
979 cs->dwExStyle |= WS_EX_WINDOWEDGE;
981 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
983 /* Create the window structure */
985 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
986 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
988 TRACE("out of memory\n" );
991 hwnd = wndPtr->hwndSelf;
993 /* Fill the window structure */
995 wndPtr->tid = GetCurrentThreadId();
996 wndPtr->owner = owner;
997 wndPtr->parent = parent;
998 wndPtr->class = classPtr;
999 wndPtr->winproc = winproc;
1000 wndPtr->hInstance = cs->hInstance;
1001 wndPtr->text = NULL;
1002 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
1003 wndPtr->hrgnUpdate = 0;
1004 wndPtr->hrgnWnd = 0;
1005 wndPtr->hwndLastActive = hwnd;
1006 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1007 wndPtr->dwExStyle = cs->dwExStyle;
1008 wndPtr->clsStyle = clsStyle;
1009 wndPtr->wIDmenu = 0;
1010 wndPtr->helpContext = 0;
1011 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1012 wndPtr->pVScroll = NULL;
1013 wndPtr->pHScroll = NULL;
1014 wndPtr->userdata = 0;
1015 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1016 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1017 wndPtr->cbWndExtra = wndExtra;
1019 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1021 /* Call the WH_CBT hook */
1023 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
1024 ? HWND_BOTTOM : HWND_TOP;
1026 if (HOOK_IsHooked( WH_CBT ))
1028 CBT_CREATEWNDA cbtc;
1032 cbtc.hwndInsertAfter = hwndLinkAfter;
1033 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND,
1034 (WPARAM)hwnd, (LPARAM)&cbtc)
1035 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND,
1036 (WPARAM)hwnd, (LPARAM)&cbtc);
1039 TRACE("CBT-hook returned 0\n");
1040 free_window_handle( hwnd );
1041 CLASS_RemoveWindow( classPtr );
1042 WIN_ReleaseWndPtr(wndPtr);
1047 /* Correct the window style - stage 2 */
1049 if (!(cs->style & WS_CHILD))
1051 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1052 if (!(cs->style & WS_POPUP))
1054 wndPtr->dwStyle |= WS_CAPTION;
1055 wndPtr->flags |= WIN_NEED_SIZE;
1058 SERVER_START_REQ( set_window_info )
1061 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1062 req->style = wndPtr->dwStyle;
1063 req->ex_style = wndPtr->dwExStyle;
1064 req->instance = (void *)wndPtr->hInstance;
1069 /* Get class or window DC if needed */
1071 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1072 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1073 else wndPtr->dce = NULL;
1075 /* Set the window menu */
1077 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1079 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1082 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1085 if (HIWORD(cs->hInstance))
1086 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1088 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1090 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1094 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1095 WIN_ReleaseWndPtr( wndPtr );
1097 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1099 WIN_DestroyWindow( hwnd );
1103 /* Notify the parent window only */
1105 send_parent_notify( hwnd, WM_CREATE );
1106 if (!IsWindow( hwnd )) return 0;
1108 if (cs->style & WS_VISIBLE)
1110 /* in case WS_VISIBLE got set in the meantime */
1111 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1112 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1113 WIN_ReleasePtr( wndPtr );
1114 ShowWindow( hwnd, sw );
1117 /* Call WH_SHELL hook */
1119 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1120 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1122 TRACE("created window %04x\n", hwnd);
1127 /***********************************************************************
1128 * CreateWindow (USER.41)
1130 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1131 DWORD style, INT16 x, INT16 y, INT16 width,
1132 INT16 height, HWND16 parent, HMENU16 menu,
1133 HINSTANCE16 instance, LPVOID data )
1135 return CreateWindowEx16( 0, className, windowName, style,
1136 x, y, width, height, parent, menu, instance, data );
1140 /***********************************************************************
1141 * CreateWindowEx (USER.452)
1143 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1144 LPCSTR windowName, DWORD style, INT16 x,
1145 INT16 y, INT16 width, INT16 height,
1146 HWND16 parent, HMENU16 menu,
1147 HINSTANCE16 instance, LPVOID data )
1153 /* Find the class atom */
1155 if (HIWORD(className))
1157 if (!(classAtom = GlobalFindAtomA( className )))
1159 ERR( "bad class name %s\n", debugres_a(className) );
1165 classAtom = LOWORD(className);
1166 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1168 ERR( "bad atom %x\n", classAtom);
1174 /* Fix the coordinates */
1176 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1177 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1178 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1179 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1181 /* Create the window */
1183 cs.lpCreateParams = data;
1184 cs.hInstance = (HINSTANCE)instance;
1185 cs.hMenu = (HMENU)menu;
1186 cs.hwndParent = WIN_Handle32( parent );
1188 cs.lpszName = windowName;
1189 cs.lpszClass = className;
1190 cs.dwExStyle = exStyle;
1192 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1196 /***********************************************************************
1197 * CreateWindowExA (USER32.@)
1199 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1200 LPCSTR windowName, DWORD style, INT x,
1201 INT y, INT width, INT height,
1202 HWND parent, HMENU menu,
1203 HINSTANCE instance, LPVOID data )
1210 instance=GetModuleHandleA(NULL);
1212 if(exStyle & WS_EX_MDICHILD)
1213 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1215 /* Find the class atom */
1217 if (HIWORD(className))
1219 if (!(classAtom = GlobalFindAtomA( className )))
1221 ERR( "bad class name %s\n", debugres_a(className) );
1227 classAtom = LOWORD(className);
1228 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1230 ERR( "bad atom %x\n", classAtom);
1236 /* Create the window */
1238 cs.lpCreateParams = data;
1239 cs.hInstance = instance;
1241 cs.hwndParent = parent;
1247 cs.lpszName = windowName;
1248 cs.lpszClass = className;
1249 cs.dwExStyle = exStyle;
1251 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1255 /***********************************************************************
1256 * CreateWindowExW (USER32.@)
1258 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1259 LPCWSTR windowName, DWORD style, INT x,
1260 INT y, INT width, INT height,
1261 HWND parent, HMENU menu,
1262 HINSTANCE instance, LPVOID data )
1269 instance=GetModuleHandleA(NULL);
1271 if(exStyle & WS_EX_MDICHILD)
1272 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1274 /* Find the class atom */
1276 if (HIWORD(className))
1278 if (!(classAtom = GlobalFindAtomW( className )))
1280 ERR( "bad class name %s\n", debugres_w(className) );
1286 classAtom = LOWORD(className);
1287 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1289 ERR( "bad atom %x\n", classAtom);
1295 /* Create the window */
1297 cs.lpCreateParams = data;
1298 cs.hInstance = instance;
1300 cs.hwndParent = parent;
1306 cs.lpszName = windowName;
1307 cs.lpszClass = className;
1308 cs.dwExStyle = exStyle;
1310 /* Note: we rely on the fact that CREATESTRUCTA and */
1311 /* CREATESTRUCTW have the same layout. */
1312 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1316 /***********************************************************************
1317 * WIN_SendDestroyMsg
1319 static void WIN_SendDestroyMsg( HWND hwnd )
1321 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1322 if (USER_Driver.pResetSelectionOwner)
1323 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1326 * Send the WM_DESTROY to the window.
1328 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1331 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1332 * make sure that the window still exists when we come back.
1339 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1341 /* start from the end (FIXME: is this needed?) */
1342 for (i = 0; pWndArray[i]; i++) ;
1346 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1348 HeapFree( GetProcessHeap(), 0, pWndArray );
1351 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1355 /***********************************************************************
1356 * DestroyWindow (USER32.@)
1358 BOOL WINAPI DestroyWindow( HWND hwnd )
1363 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1365 SetLastError( ERROR_ACCESS_DENIED );
1369 TRACE("(%04x)\n", hwnd);
1371 /* Look whether the focus is within the tree of windows we will
1375 if (h == hwnd || IsChild( hwnd, h ))
1377 HWND parent = GetAncestor( hwnd, GA_PARENT );
1378 if (parent == GetDesktopWindow()) parent = 0;
1384 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1386 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1390 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1391 send_parent_notify( hwnd, WM_DESTROY );
1393 else if (!GetWindow( hwnd, GW_OWNER ))
1395 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1396 /* FIXME: clean up palette - see "Internals" p.352 */
1399 if (!IsWindow(hwnd)) return TRUE;
1401 if (USER_Driver.pResetSelectionOwner)
1402 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1404 /* Hide the window */
1406 ShowWindow( hwnd, SW_HIDE );
1407 if (!IsWindow(hwnd)) return TRUE;
1409 /* Recursively destroy owned windows */
1418 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1421 for (i = 0; list[i]; i++)
1423 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1424 if (WIN_IsCurrentThread( list[i] ))
1426 DestroyWindow( list[i] );
1430 WIN_SetOwner( list[i], 0 );
1432 HeapFree( GetProcessHeap(), 0, list );
1434 if (!got_one) break;
1437 WINPOS_ActivateOtherWindow( hwnd );
1439 if ((owner = GetWindow( hwnd, GW_OWNER )))
1441 WND *ptr = WIN_FindWndPtr( owner );
1444 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1445 WIN_ReleaseWndPtr( ptr );
1450 /* Send destroy messages */
1452 WIN_SendDestroyMsg( hwnd );
1453 if (!IsWindow( hwnd )) return TRUE;
1455 /* Unlink now so we won't bother with the children later on */
1457 WIN_UnlinkWindow( hwnd );
1459 /* Destroy the window storage */
1461 WIN_DestroyWindow( hwnd );
1466 /***********************************************************************
1467 * CloseWindow (USER32.@)
1469 BOOL WINAPI CloseWindow( HWND hwnd )
1471 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1472 ShowWindow( hwnd, SW_MINIMIZE );
1477 /***********************************************************************
1478 * OpenIcon (USER32.@)
1480 BOOL WINAPI OpenIcon( HWND hwnd )
1482 if (!IsIconic( hwnd )) return FALSE;
1483 ShowWindow( hwnd, SW_SHOWNORMAL );
1488 /***********************************************************************
1491 * Implementation of FindWindow() and FindWindowEx().
1493 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1498 WCHAR *buffer = NULL;
1500 if (!parent) parent = GetDesktopWindow();
1503 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1504 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1507 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1511 child = WIN_GetFullHandle( child );
1512 while (list[i] && list[i] != child) i++;
1513 if (!list[i]) goto done;
1514 i++; /* start from next window */
1521 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1528 if (list) HeapFree( GetProcessHeap(), 0, list );
1529 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1535 /***********************************************************************
1536 * FindWindowA (USER32.@)
1538 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1540 HWND ret = FindWindowExA( 0, 0, className, title );
1541 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1546 /***********************************************************************
1547 * FindWindowExA (USER32.@)
1549 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1550 LPCSTR className, LPCSTR title )
1558 /* If the atom doesn't exist, then no class */
1559 /* with this name exists either. */
1560 if (!(atom = GlobalFindAtomA( className )))
1562 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1567 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1568 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1569 HeapFree( GetProcessHeap(), 0, buffer );
1574 /***********************************************************************
1575 * FindWindowExW (USER32.@)
1577 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1578 LPCWSTR className, LPCWSTR title )
1584 /* If the atom doesn't exist, then no class */
1585 /* with this name exists either. */
1586 if (!(atom = GlobalFindAtomW( className )))
1588 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1592 return WIN_FindWindow( parent, child, atom, title );
1596 /***********************************************************************
1597 * FindWindowW (USER32.@)
1599 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1601 return FindWindowExW( 0, 0, className, title );
1605 /**********************************************************************
1606 * GetDesktopWindow (USER32.@)
1608 HWND WINAPI GetDesktopWindow(void)
1610 if (pWndDesktop) return pWndDesktop->hwndSelf;
1611 ERR( "You need the -desktop option when running with native USER\n" );
1617 /*******************************************************************
1618 * EnableWindow (USER32.@)
1620 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1627 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1628 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1632 TRACE("( %x, %d )\n", hwnd, enable);
1634 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1635 style = wndPtr->dwStyle;
1636 retvalue = ((style & WS_DISABLED) != 0);
1637 WIN_ReleasePtr( wndPtr );
1639 if (enable && retvalue)
1641 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1642 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1644 else if (!enable && !retvalue)
1646 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1648 WIN_SetStyle( hwnd, style | WS_DISABLED );
1650 if (hwnd == GetFocus())
1651 SetFocus( 0 ); /* A disabled window can't have the focus */
1653 if (hwnd == GetCapture())
1654 ReleaseCapture(); /* A disabled window can't capture the mouse */
1656 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1662 /***********************************************************************
1663 * IsWindowEnabled (USER32.@)
1665 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1667 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1671 /***********************************************************************
1672 * IsWindowUnicode (USER32.@)
1674 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1679 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1680 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1681 WIN_ReleaseWndPtr(wndPtr);
1686 /**********************************************************************
1687 * GetWindowWord (USER32.@)
1689 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1694 WND *wndPtr = WIN_GetPtr( hwnd );
1697 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1700 if (wndPtr == WND_OTHER_PROCESS)
1702 if (IsWindow( hwnd ))
1703 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1704 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1707 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1709 WARN("Invalid offset %d\n", offset );
1710 SetLastError( ERROR_INVALID_INDEX );
1712 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1713 WIN_ReleasePtr( wndPtr );
1719 case GWL_HWNDPARENT:
1720 return GetWindowLongW( hwnd, offset );
1724 LONG ret = GetWindowLongW( hwnd, offset );
1726 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1730 WARN("Invalid offset %d\n", offset );
1736 /**********************************************************************
1737 * SetWindowWord (USER32.@)
1739 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1748 case GWL_HWNDPARENT:
1749 return SetWindowLongW( hwnd, offset, (UINT)newval );
1753 WARN("Invalid offset %d\n", offset );
1754 SetLastError( ERROR_INVALID_INDEX );
1759 wndPtr = WIN_GetPtr( hwnd );
1760 if (wndPtr == WND_OTHER_PROCESS)
1763 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1764 offset, newval, hwnd );
1769 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1773 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1775 WARN("Invalid offset %d\n", offset );
1776 WIN_ReleasePtr(wndPtr);
1777 SetLastError( ERROR_INVALID_INDEX );
1780 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1783 WIN_ReleasePtr(wndPtr);
1788 /**********************************************************************
1791 * Helper function for GetWindowLong().
1793 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1798 if (offset == GWL_HWNDPARENT) return (LONG)GetParent( hwnd );
1800 if (!(wndPtr = WIN_GetPtr( hwnd )))
1802 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1806 if (wndPtr == WND_OTHER_PROCESS)
1811 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1812 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1815 if (offset == GWL_WNDPROC)
1817 SetLastError( ERROR_ACCESS_DENIED );
1820 SERVER_START_REQ( set_window_info )
1823 req->flags = 0; /* don't set anything, just retrieve */
1824 if (!SERVER_CALL_ERR())
1828 case GWL_STYLE: retvalue = req->style; break;
1829 case GWL_EXSTYLE: retvalue = req->ex_style; break;
1830 case GWL_ID: retvalue = req->id; break;
1831 case GWL_HINSTANCE: retvalue = (ULONG_PTR)req->instance; break;
1832 case GWL_USERDATA: retvalue = (ULONG_PTR)req->user_data; break;
1834 SetLastError( ERROR_INVALID_INDEX );
1843 /* now we have a valid wndPtr */
1847 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1849 WARN("Invalid offset %d\n", offset );
1850 WIN_ReleasePtr( wndPtr );
1851 SetLastError( ERROR_INVALID_INDEX );
1854 /* Special case for dialog window procedure */
1855 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1856 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1858 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1859 WIN_ReleasePtr( wndPtr );
1865 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1866 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1867 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1868 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1869 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1870 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1872 WARN("Unknown offset %d\n", offset );
1873 SetLastError( ERROR_INVALID_INDEX );
1876 WIN_ReleasePtr(wndPtr);
1881 /**********************************************************************
1884 * Helper function for SetWindowLong().
1886 * 0 is the failure code. However, in the case of failure SetLastError
1887 * must be set to distinguish between a 0 return value and a failure.
1889 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1890 WINDOWPROCTYPE type )
1895 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1897 if (!WIN_IsCurrentProcess( hwnd ))
1899 if (offset == GWL_WNDPROC)
1901 SetLastError( ERROR_ACCESS_DENIED );
1904 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1907 wndPtr = WIN_GetPtr( hwnd );
1911 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1912 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1914 WARN("Invalid offset %d\n", offset );
1915 WIN_ReleasePtr( wndPtr );
1916 SetLastError( ERROR_INVALID_INDEX );
1919 /* Special case for dialog window procedure */
1920 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1922 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1923 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1924 type, WIN_PROC_WINDOW );
1925 WIN_ReleasePtr( wndPtr );
1930 WIN_ReleasePtr( wndPtr );
1937 /* first some special cases */
1942 style.styleOld = wndPtr->dwStyle;
1943 style.styleNew = newval;
1944 WIN_ReleasePtr( wndPtr );
1945 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1946 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1947 newval = style.styleNew;
1949 case GWL_HWNDPARENT:
1950 WIN_ReleasePtr( wndPtr );
1951 return (LONG)SetParent( hwnd, (HWND)newval );
1953 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1954 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1955 type, WIN_PROC_WINDOW );
1956 WIN_ReleasePtr( wndPtr );
1963 WIN_ReleasePtr( wndPtr );
1964 WARN("Invalid offset %d\n", offset );
1965 SetLastError( ERROR_INVALID_INDEX );
1969 SERVER_START_REQ( set_window_info )
1975 req->flags = SET_WIN_STYLE;
1976 req->style = newval;
1979 req->flags = SET_WIN_EXSTYLE;
1980 req->ex_style = newval;
1983 req->flags = SET_WIN_ID;
1987 req->flags = SET_WIN_INSTANCE;
1988 req->instance = (void *)newval;
1991 req->flags = SET_WIN_USERDATA;
1992 req->user_data = (void *)newval;
1995 if ((ok = !SERVER_CALL_ERR()))
2000 wndPtr->dwStyle = newval;
2001 retval = req->old_style;
2004 wndPtr->dwExStyle = newval;
2005 retval = req->old_ex_style;
2008 wndPtr->wIDmenu = newval;
2009 retval = req->old_id;
2012 wndPtr->hInstance = newval;
2013 retval = (HINSTANCE)req->old_instance;
2016 wndPtr->userdata = newval;
2017 retval = (ULONG_PTR)req->old_user_data;
2023 WIN_ReleasePtr( wndPtr );
2027 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2028 USER_Driver.pSetWindowStyle( hwnd, retval );
2030 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2031 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2038 /**********************************************************************
2039 * GetWindowLong (USER.135)
2041 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2043 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2047 /**********************************************************************
2048 * GetWindowLongA (USER32.@)
2050 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2052 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2056 /**********************************************************************
2057 * GetWindowLongW (USER32.@)
2059 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2061 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2065 /**********************************************************************
2066 * SetWindowLong (USER.136)
2068 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2070 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2074 /**********************************************************************
2075 * SetWindowLongA (USER32.@)
2077 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2079 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2083 /**********************************************************************
2084 * SetWindowLongW (USER32.@) Set window attribute
2086 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2087 * value in a window's extra memory.
2089 * The _hwnd_ parameter specifies the window. is the handle to a
2090 * window that has extra memory. The _newval_ parameter contains the
2091 * new attribute or extra memory value. If positive, the _offset_
2092 * parameter is the byte-addressed location in the window's extra
2093 * memory to set. If negative, _offset_ specifies the window
2094 * attribute to set, and should be one of the following values:
2096 * GWL_EXSTYLE The window's extended window style
2098 * GWL_STYLE The window's window style.
2100 * GWL_WNDPROC Pointer to the window's window procedure.
2102 * GWL_HINSTANCE The window's pplication instance handle.
2104 * GWL_ID The window's identifier.
2106 * GWL_USERDATA The window's user-specified data.
2108 * If the window is a dialog box, the _offset_ parameter can be one of
2109 * the following values:
2111 * DWL_DLGPROC The address of the window's dialog box procedure.
2113 * DWL_MSGRESULT The return value of a message
2114 * that the dialog box procedure processed.
2116 * DWL_USER Application specific information.
2120 * If successful, returns the previous value located at _offset_. Otherwise,
2125 * Extra memory for a window class is specified by a nonzero cbWndExtra
2126 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2127 * time of class creation.
2129 * Using GWL_WNDPROC to set a new window procedure effectively creates
2130 * a window subclass. Use CallWindowProc() in the new windows procedure
2131 * to pass messages to the superclass's window procedure.
2133 * The user data is reserved for use by the application which created
2136 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2137 * instead, call the EnableWindow() function to change the window's
2140 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2141 * SetParent() instead.
2144 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2145 * it sends WM_STYLECHANGING before changing the settings
2146 * and WM_STYLECHANGED afterwards.
2147 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2149 LONG WINAPI SetWindowLongW(
2150 HWND hwnd, /* [in] window to alter */
2151 INT offset, /* [in] offset, in bytes, of location to alter */
2152 LONG newval /* [in] new value of location */
2154 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2158 /*******************************************************************
2159 * GetWindowTextA (USER32.@)
2161 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2165 if (WIN_IsCurrentProcess( hwnd ))
2166 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2168 /* when window belongs to other process, don't send a message */
2169 if (nMaxCount <= 0) return 0;
2170 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2171 get_server_window_text( hwnd, buffer, nMaxCount );
2172 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2173 lpString[nMaxCount-1] = 0;
2174 HeapFree( GetProcessHeap(), 0, buffer );
2175 return strlen(lpString);
2179 /*******************************************************************
2180 * InternalGetWindowText (USER32.@)
2182 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2186 if (nMaxCount <= 0) return 0;
2187 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2188 if (win != WND_OTHER_PROCESS)
2190 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2191 else lpString[0] = 0;
2192 WIN_ReleasePtr( win );
2196 get_server_window_text( hwnd, lpString, nMaxCount );
2198 return strlenW(lpString);
2202 /*******************************************************************
2203 * GetWindowTextW (USER32.@)
2205 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2207 if (WIN_IsCurrentProcess( hwnd ))
2208 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2210 /* when window belongs to other process, don't send a message */
2211 if (nMaxCount <= 0) return 0;
2212 get_server_window_text( hwnd, lpString, nMaxCount );
2213 return strlenW(lpString);
2217 /*******************************************************************
2218 * SetWindowText (USER32.@)
2219 * SetWindowTextA (USER32.@)
2221 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2223 if (!WIN_IsCurrentProcess( hwnd ))
2225 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2226 SetLastError( ERROR_ACCESS_DENIED );
2229 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2233 /*******************************************************************
2234 * SetWindowTextW (USER32.@)
2236 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2238 if (!WIN_IsCurrentProcess( hwnd ))
2240 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2241 SetLastError( ERROR_ACCESS_DENIED );
2244 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2248 /*******************************************************************
2249 * GetWindowTextLengthA (USER32.@)
2251 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2253 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2256 /*******************************************************************
2257 * GetWindowTextLengthW (USER32.@)
2259 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2261 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2265 /*******************************************************************
2266 * IsWindow (USER32.@)
2268 BOOL WINAPI IsWindow( HWND hwnd )
2273 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2275 if (ptr != WND_OTHER_PROCESS)
2277 WIN_ReleasePtr( ptr );
2281 /* check other processes */
2282 SERVER_START_REQ( get_window_info )
2285 ret = !SERVER_CALL_ERR();
2292 /***********************************************************************
2293 * GetWindowThreadProcessId (USER32.@)
2295 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2300 if (!(ptr = WIN_GetPtr( hwnd )))
2302 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2306 if (ptr != WND_OTHER_PROCESS)
2308 /* got a valid window */
2310 if (process) *process = GetCurrentProcessId();
2311 WIN_ReleasePtr( ptr );
2315 /* check other processes */
2316 SERVER_START_REQ( get_window_info )
2319 if (!SERVER_CALL_ERR())
2321 tid = (DWORD)req->tid;
2322 if (process) *process = (DWORD)req->pid;
2330 /*****************************************************************
2331 * GetParent (USER32.@)
2333 HWND WINAPI GetParent( HWND hwnd )
2338 if (!(wndPtr = WIN_GetPtr( hwnd )))
2340 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2343 if (wndPtr == WND_OTHER_PROCESS)
2345 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2346 if (style & (WS_POPUP | WS_CHILD))
2348 SERVER_START_REQ( get_window_tree )
2351 if (!SERVER_CALL_ERR())
2353 if (style & WS_CHILD) retvalue = req->parent;
2354 else retvalue = req->owner;
2362 if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2363 else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2364 WIN_ReleasePtr( wndPtr );
2370 /*****************************************************************
2371 * GetAncestor (USER32.@)
2373 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2381 if (!(win = WIN_GetPtr( hwnd )))
2383 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2386 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2388 WIN_ReleasePtr( win );
2389 if (type == GA_PARENT) return ret;
2390 if (!ret || ret == GetDesktopWindow())
2392 ret = hwnd; /* if ret is the desktop, hwnd is the root ancestor */
2395 hwnd = ret; /* restart with parent as hwnd */
2398 size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE;
2400 SERVER_START_VAR_REQ( get_window_parents, size )
2405 user_handle_t *data = server_data_ptr(req);
2406 int count = server_data_size(req) / sizeof(*data);
2416 if (count > 1) ret = data[count - 2]; /* get the one before the desktop */
2417 else ret = WIN_GetFullHandle( hwnd );
2426 if (ret && type == GA_ROOTOWNER)
2430 HWND owner = GetWindow( ret, GW_OWNER );
2439 /*****************************************************************
2440 * SetParent (USER32.@)
2442 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2445 HWND retvalue, full_handle;
2448 if (!parent) parent = GetDesktopWindow();
2449 else parent = WIN_GetFullHandle( parent );
2451 if (!IsWindow( parent ))
2453 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2457 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2458 return SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2462 if (USER_Driver.pSetParent)
2463 return USER_Driver.pSetParent( hwnd, parent );
2465 /* Windows hides the window first, then shows it again
2466 * including the WM_SHOWWINDOW messages and all */
2467 was_visible = ShowWindow( hwnd, SW_HIDE );
2469 if (!IsWindow( parent )) return 0;
2470 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2472 retvalue = wndPtr->parent; /* old parent */
2473 if (parent != retvalue)
2475 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2477 if (parent != GetDesktopWindow()) /* a child window */
2479 if (!(wndPtr->dwStyle & WS_CHILD))
2481 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2482 if (menu) DestroyMenu( menu );
2486 WIN_ReleasePtr( wndPtr );
2488 /* SetParent additionally needs to make hwnd the topmost window
2489 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2490 WM_WINDOWPOSCHANGED notification messages.
2492 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2493 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2494 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2495 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2500 /*******************************************************************
2501 * IsChild (USER32.@)
2503 BOOL WINAPI IsChild( HWND parent, HWND child )
2505 HWND *list = WIN_ListParents( child );
2509 if (!list) return FALSE;
2510 parent = WIN_GetFullHandle( parent );
2511 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2512 ret = (list[i] != 0);
2513 HeapFree( GetProcessHeap(), 0, list );
2518 /***********************************************************************
2519 * IsWindowVisible (USER32.@)
2521 BOOL WINAPI IsWindowVisible( HWND hwnd )
2527 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2528 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2529 for (i = 0; list[i]; i++)
2530 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2532 HeapFree( GetProcessHeap(), 0, list );
2537 /***********************************************************************
2538 * WIN_IsWindowDrawable
2540 * hwnd is drawable when it is visible, all parents are not
2541 * minimized, and it is itself not minimized unless we are
2542 * trying to draw its default class icon.
2544 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2549 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2551 if (!(style & WS_VISIBLE)) return FALSE;
2552 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2554 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2555 for (i = 0; list[i]; i++)
2556 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2559 HeapFree( GetProcessHeap(), 0, list );
2564 /*******************************************************************
2565 * GetTopWindow (USER32.@)
2567 HWND WINAPI GetTopWindow( HWND hwnd )
2569 if (!hwnd) hwnd = GetDesktopWindow();
2570 return GetWindow( hwnd, GW_CHILD );
2574 /*******************************************************************
2575 * GetWindow (USER32.@)
2577 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2581 if (rel == GW_OWNER) /* this one may be available locally */
2583 WND *wndPtr = WIN_GetPtr( hwnd );
2586 SetLastError( ERROR_INVALID_HANDLE );
2589 if (wndPtr != WND_OTHER_PROCESS)
2591 retval = wndPtr->owner;
2592 WIN_ReleasePtr( wndPtr );
2595 /* else fall through to server call */
2598 SERVER_START_REQ( get_window_tree )
2601 if (!SERVER_CALL_ERR())
2606 retval = req->first_sibling;
2609 retval = req->last_sibling;
2612 retval = req->next_sibling;
2615 retval = req->prev_sibling;
2618 retval = req->owner;
2621 retval = req->first_child;
2631 /***********************************************************************
2632 * WIN_InternalShowOwnedPopups
2634 * Internal version of ShowOwnedPopups; Wine functions should use this
2635 * to avoid interfering with application calls to ShowOwnedPopups
2636 * and to make sure the application can't prevent showing/hiding.
2638 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2642 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2646 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2648 if (!win_array) return TRUE;
2651 * Show windows Lowest first, Highest last to preserve Z-Order
2653 while (win_array[count]) count++;
2654 while (--count >= 0)
2656 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2657 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2659 if (pWnd->dwStyle & WS_POPUP)
2663 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2664 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2667 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2669 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2670 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2675 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2676 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2677 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2680 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2682 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2683 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2684 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2688 WIN_ReleaseWndPtr( pWnd );
2690 HeapFree( GetProcessHeap(), 0, win_array );
2695 /*******************************************************************
2696 * ShowOwnedPopups (USER32.@)
2698 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2702 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2704 if (!win_array) return TRUE;
2706 while (win_array[count]) count++;
2707 while (--count >= 0)
2709 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2710 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2712 if (pWnd->dwStyle & WS_POPUP)
2716 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2718 /* In Windows, ShowOwnedPopups(TRUE) generates
2719 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2720 * regardless of the state of the owner
2722 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2723 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2728 if (IsWindowVisible(pWnd->hwndSelf))
2730 /* In Windows, ShowOwnedPopups(FALSE) generates
2731 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2732 * regardless of the state of the owner
2734 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2735 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2739 WIN_ReleaseWndPtr( pWnd );
2741 HeapFree( GetProcessHeap(), 0, win_array );
2746 /*******************************************************************
2747 * GetLastActivePopup (USER32.@)
2749 HWND WINAPI GetLastActivePopup( HWND hwnd )
2752 WND *wndPtr =WIN_FindWndPtr(hwnd);
2753 if (!wndPtr) return hwnd;
2754 retval = wndPtr->hwndLastActive;
2755 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2756 WIN_ReleaseWndPtr(wndPtr);
2761 /*******************************************************************
2764 * Build an array of all parents of a given window, starting with
2765 * the immediate parent. The array must be freed with HeapFree.
2766 * Returns NULL if window is a top-level window.
2768 HWND *WIN_ListParents( HWND hwnd )
2771 HWND current, *list;
2772 int pos = 0, size = 16, count = 0;
2774 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2779 if (!(win = WIN_GetPtr( current ))) goto empty;
2780 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2781 list[pos] = win->parent;
2782 WIN_ReleasePtr( win );
2783 if (!(current = list[pos]))
2785 if (!pos) goto empty;
2788 if (++pos == size - 1)
2790 /* need to grow the list */
2791 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2792 if (!new_list) goto empty;
2798 /* at least one parent belongs to another process, have to query the server */
2799 SERVER_START_VAR_REQ( get_window_parents, REQUEST_MAX_VAR_SIZE )
2804 user_handle_t *data = server_data_ptr(req);
2805 count = server_data_size(req) / sizeof(*data);
2808 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0,
2809 list, (count + 1) * sizeof(HWND) );
2813 for (pos = 0; pos < count; pos++) list[pos] = data[pos];
2821 if (count) return list;
2824 HeapFree( GetProcessHeap(), 0, list );
2829 /*******************************************************************
2832 * Build an array of the children of a given window. The array must be
2833 * freed with HeapFree. Returns NULL when no windows are found.
2835 HWND *WIN_ListChildren( HWND hwnd )
2837 return list_window_children( hwnd, 0, 0 );
2841 /*******************************************************************
2842 * EnumWindows (USER32.@)
2844 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2850 /* We have to build a list of all windows first, to avoid */
2851 /* unpleasant side-effects, for instance if the callback */
2852 /* function changes the Z-order of the windows. */
2854 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2856 /* Now call the callback function for every window */
2858 iWndsLocks = WIN_SuspendWndsLock();
2859 for (i = 0; list[i]; i++)
2861 /* Make sure that the window still exists */
2862 if (!IsWindow( list[i] )) continue;
2863 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2865 WIN_RestoreWndsLock(iWndsLocks);
2866 HeapFree( GetProcessHeap(), 0, list );
2871 /**********************************************************************
2872 * EnumTaskWindows16 (USER.225)
2874 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2877 TDB *tdb = TASK_GetPtr( hTask );
2878 if (!tdb) return FALSE;
2879 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2883 /**********************************************************************
2884 * EnumThreadWindows (USER32.@)
2886 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2891 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2894 /* Now call the callback function for every window */
2896 iWndsLocks = WIN_SuspendWndsLock();
2897 for (i = 0; list[i]; i++)
2898 if (!func( list[i], lParam )) break;
2899 WIN_RestoreWndsLock(iWndsLocks);
2900 HeapFree( GetProcessHeap(), 0, list );
2905 /**********************************************************************
2906 * WIN_EnumChildWindows
2908 * Helper function for EnumChildWindows().
2910 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2915 for ( ; *list; list++)
2917 /* Make sure that the window still exists */
2918 if (!IsWindow( *list )) continue;
2919 /* skip owned windows */
2920 if (GetWindow( *list, GW_OWNER )) continue;
2921 /* Build children list first */
2922 childList = WIN_ListChildren( *list );
2924 ret = func( *list, lParam );
2928 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2929 HeapFree( GetProcessHeap(), 0, childList );
2931 if (!ret) return FALSE;
2937 /**********************************************************************
2938 * EnumChildWindows (USER32.@)
2940 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2945 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2946 iWndsLocks = WIN_SuspendWndsLock();
2947 WIN_EnumChildWindows( list, func, lParam );
2948 WIN_RestoreWndsLock(iWndsLocks);
2949 HeapFree( GetProcessHeap(), 0, list );
2954 /*******************************************************************
2955 * AnyPopup (USER.52)
2957 BOOL16 WINAPI AnyPopup16(void)
2963 /*******************************************************************
2964 * AnyPopup (USER32.@)
2966 BOOL WINAPI AnyPopup(void)
2970 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2972 if (!list) return FALSE;
2973 for (i = 0; list[i]; i++)
2975 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2977 retvalue = (list[i] != 0);
2978 HeapFree( GetProcessHeap(), 0, list );
2983 /*******************************************************************
2984 * FlashWindow (USER32.@)
2986 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2988 WND *wndPtr = WIN_FindWndPtr(hWnd);
2990 TRACE("%04x\n", hWnd);
2992 if (!wndPtr) return FALSE;
2993 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2995 if (wndPtr->dwStyle & WS_MINIMIZE)
2997 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2999 HDC hDC = GetDC(hWnd);
3001 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3002 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3004 ReleaseDC( hWnd, hDC );
3005 wndPtr->flags |= WIN_NCACTIVATED;
3009 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3010 wndPtr->flags &= ~WIN_NCACTIVATED;
3012 WIN_ReleaseWndPtr(wndPtr);
3018 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3019 else wparam = (hWnd == GetActiveWindow());
3021 WIN_ReleaseWndPtr(wndPtr);
3022 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3028 /*******************************************************************
3029 * GetWindowContextHelpId (USER32.@)
3031 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3034 WND *wnd = WIN_FindWndPtr( hwnd );
3036 retval = wnd->helpContext;
3037 WIN_ReleaseWndPtr(wnd);
3042 /*******************************************************************
3043 * SetWindowContextHelpId (USER32.@)
3045 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3047 WND *wnd = WIN_FindWndPtr( hwnd );
3048 if (!wnd) return FALSE;
3049 wnd->helpContext = id;
3050 WIN_ReleaseWndPtr(wnd);
3055 /*******************************************************************
3058 * recursively find a child that contains spDragInfo->pt point
3059 * and send WM_QUERYDROPOBJECT
3061 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3063 BOOL16 wParam, bResult = 0;
3065 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3068 if (!ptrDragInfo) return FALSE;
3070 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3072 GetWindowRect(hQueryWnd,&tempRect);
3074 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3076 if (!IsIconic( hQueryWnd ))
3078 GetClientRect( hQueryWnd, &tempRect );
3079 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3081 if (PtInRect( &tempRect, pt))
3084 HWND *list = WIN_ListChildren( hQueryWnd );
3090 for (i = 0; list[i]; i++)
3092 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3094 GetWindowRect( list[i], &tempRect );
3095 if (PtInRect( &tempRect, pt )) break;
3100 if (IsWindowEnabled( list[i] ))
3101 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
3103 HeapFree( GetProcessHeap(), 0, list );
3105 if(bResult) return bResult;
3111 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3113 ptrDragInfo->hScope = hQueryWnd;
3115 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3116 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3118 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3124 /*******************************************************************
3125 * DragDetect (USER32.@)
3127 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3132 rect.left = pt.x - wDragWidth;
3133 rect.right = pt.x + wDragWidth;
3135 rect.top = pt.y - wDragHeight;
3136 rect.bottom = pt.y + wDragHeight;
3142 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3144 if( msg.message == WM_LBUTTONUP )
3149 if( msg.message == WM_MOUSEMOVE )
3152 tmp.x = LOWORD(msg.lParam);
3153 tmp.y = HIWORD(msg.lParam);
3154 if( !PtInRect( &rect, tmp ))
3166 /******************************************************************************
3167 * DragObject (USER.464)
3169 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3170 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3173 LPDRAGINFO16 lpDragInfo;
3175 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3176 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3177 HCURSOR16 hCurrentCursor = 0;
3178 HWND16 hCurrentWnd = 0;
3180 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3181 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3183 if( !lpDragInfo || !spDragInfo ) return 0L;
3185 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3187 GlobalFree16(hDragInfo);
3193 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3195 GlobalFree16(hDragInfo);
3199 if( hDragCursor == hCursor ) hDragCursor = 0;
3200 else hCursor = hDragCursor;
3202 hOldCursor = SetCursor(hDragCursor);
3205 lpDragInfo->hWnd = hWnd;
3206 lpDragInfo->hScope = 0;
3207 lpDragInfo->wFlags = wObj;
3208 lpDragInfo->hList = szList; /* near pointer! */
3209 lpDragInfo->hOfStruct = hOfStruct;
3217 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3219 *(lpDragInfo+1) = *lpDragInfo;
3221 lpDragInfo->pt.x = msg.pt.x;
3222 lpDragInfo->pt.y = msg.pt.y;
3224 /* update DRAGINFO struct */
3225 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3227 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3228 hCurrentCursor = hCursor;
3231 hCurrentCursor = hBummer;
3232 lpDragInfo->hScope = 0;
3234 if( hCurrentCursor )
3235 SetCursor(hCurrentCursor);
3237 /* send WM_DRAGLOOP */
3238 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3239 (LPARAM) spDragInfo );
3240 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3241 if( hCurrentWnd != lpDragInfo->hScope )
3244 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3245 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3246 HIWORD(spDragInfo)) );
3247 hCurrentWnd = lpDragInfo->hScope;
3249 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3253 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3255 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3258 ShowCursor( FALSE );
3262 SetCursor( hOldCursor );
3263 if (hDragCursor) DestroyCursor( hDragCursor );
3266 if( hCurrentCursor != hBummer )
3267 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3268 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3271 GlobalFree16(hDragInfo);
3273 return (DWORD)(msg.lParam);
3277 /******************************************************************************
3278 * GetWindowModuleFileNameA (USER32.@)
3280 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3282 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3283 hwnd, lpszFileName, cchFileNameMax);
3287 /******************************************************************************
3288 * GetWindowModuleFileNameW (USER32.@)
3290 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3292 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3293 hwnd, lpszFileName, cchFileNameMax);