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( "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" );
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 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1855 /* Special case for dialog window procedure */
1856 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1857 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1858 WIN_ReleasePtr( wndPtr );
1864 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1865 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1866 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1867 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1868 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1869 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1871 WARN("Unknown offset %d\n", offset );
1872 SetLastError( ERROR_INVALID_INDEX );
1875 WIN_ReleasePtr(wndPtr);
1880 /**********************************************************************
1883 * Helper function for SetWindowLong().
1885 * 0 is the failure code. However, in the case of failure SetLastError
1886 * must be set to distinguish between a 0 return value and a failure.
1888 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1889 WINDOWPROCTYPE type )
1894 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1896 if (!WIN_IsCurrentProcess( hwnd ))
1898 if (offset == GWL_WNDPROC)
1900 SetLastError( ERROR_ACCESS_DENIED );
1903 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1906 wndPtr = WIN_GetPtr( hwnd );
1910 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1911 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1913 WARN("Invalid offset %d\n", offset );
1914 WIN_ReleasePtr( wndPtr );
1915 SetLastError( ERROR_INVALID_INDEX );
1918 /* Special case for dialog window procedure */
1919 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1921 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1922 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1923 type, WIN_PROC_WINDOW );
1924 WIN_ReleasePtr( wndPtr );
1929 WIN_ReleasePtr( wndPtr );
1936 /* first some special cases */
1941 style.styleOld = wndPtr->dwStyle;
1942 style.styleNew = newval;
1943 WIN_ReleasePtr( wndPtr );
1944 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1945 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1946 newval = style.styleNew;
1948 case GWL_HWNDPARENT:
1949 WIN_ReleasePtr( wndPtr );
1950 return (LONG)SetParent( hwnd, (HWND)newval );
1952 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1953 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1954 type, WIN_PROC_WINDOW );
1955 WIN_ReleasePtr( wndPtr );
1962 WIN_ReleasePtr( wndPtr );
1963 WARN("Invalid offset %d\n", offset );
1964 SetLastError( ERROR_INVALID_INDEX );
1968 SERVER_START_REQ( set_window_info )
1974 req->flags = SET_WIN_STYLE;
1975 req->style = newval;
1978 req->flags = SET_WIN_EXSTYLE;
1979 req->ex_style = newval;
1982 req->flags = SET_WIN_ID;
1986 req->flags = SET_WIN_INSTANCE;
1987 req->instance = (void *)newval;
1990 req->flags = SET_WIN_USERDATA;
1991 req->user_data = (void *)newval;
1994 if ((ok = !SERVER_CALL_ERR()))
1999 wndPtr->dwStyle = newval;
2000 retval = req->old_style;
2003 wndPtr->dwExStyle = newval;
2004 retval = req->old_ex_style;
2007 wndPtr->wIDmenu = newval;
2008 retval = req->old_id;
2011 wndPtr->hInstance = newval;
2012 retval = (HINSTANCE)req->old_instance;
2015 wndPtr->userdata = newval;
2016 retval = (ULONG_PTR)req->old_user_data;
2022 WIN_ReleasePtr( wndPtr );
2026 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2027 USER_Driver.pSetWindowStyle( hwnd, retval );
2029 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2030 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2037 /**********************************************************************
2038 * GetWindowLong (USER.135)
2040 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2042 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2046 /**********************************************************************
2047 * GetWindowLongA (USER32.@)
2049 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2051 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2055 /**********************************************************************
2056 * GetWindowLongW (USER32.@)
2058 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2060 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2064 /**********************************************************************
2065 * SetWindowLong (USER.136)
2067 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2069 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2073 /**********************************************************************
2074 * SetWindowLongA (USER32.@)
2076 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2078 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2082 /**********************************************************************
2083 * SetWindowLongW (USER32.@) Set window attribute
2085 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2086 * value in a window's extra memory.
2088 * The _hwnd_ parameter specifies the window. is the handle to a
2089 * window that has extra memory. The _newval_ parameter contains the
2090 * new attribute or extra memory value. If positive, the _offset_
2091 * parameter is the byte-addressed location in the window's extra
2092 * memory to set. If negative, _offset_ specifies the window
2093 * attribute to set, and should be one of the following values:
2095 * GWL_EXSTYLE The window's extended window style
2097 * GWL_STYLE The window's window style.
2099 * GWL_WNDPROC Pointer to the window's window procedure.
2101 * GWL_HINSTANCE The window's pplication instance handle.
2103 * GWL_ID The window's identifier.
2105 * GWL_USERDATA The window's user-specified data.
2107 * If the window is a dialog box, the _offset_ parameter can be one of
2108 * the following values:
2110 * DWL_DLGPROC The address of the window's dialog box procedure.
2112 * DWL_MSGRESULT The return value of a message
2113 * that the dialog box procedure processed.
2115 * DWL_USER Application specific information.
2119 * If successful, returns the previous value located at _offset_. Otherwise,
2124 * Extra memory for a window class is specified by a nonzero cbWndExtra
2125 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2126 * time of class creation.
2128 * Using GWL_WNDPROC to set a new window procedure effectively creates
2129 * a window subclass. Use CallWindowProc() in the new windows procedure
2130 * to pass messages to the superclass's window procedure.
2132 * The user data is reserved for use by the application which created
2135 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2136 * instead, call the EnableWindow() function to change the window's
2139 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2140 * SetParent() instead.
2143 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2144 * it sends WM_STYLECHANGING before changing the settings
2145 * and WM_STYLECHANGED afterwards.
2146 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2148 LONG WINAPI SetWindowLongW(
2149 HWND hwnd, /* [in] window to alter */
2150 INT offset, /* [in] offset, in bytes, of location to alter */
2151 LONG newval /* [in] new value of location */
2153 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2157 /*******************************************************************
2158 * GetWindowTextA (USER32.@)
2160 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2164 if (WIN_IsCurrentProcess( hwnd ))
2165 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2167 /* when window belongs to other process, don't send a message */
2168 if (nMaxCount <= 0) return 0;
2169 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2170 get_server_window_text( hwnd, buffer, nMaxCount );
2171 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2172 lpString[nMaxCount-1] = 0;
2173 HeapFree( GetProcessHeap(), 0, buffer );
2174 return strlen(lpString);
2178 /*******************************************************************
2179 * InternalGetWindowText (USER32.@)
2181 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2185 if (nMaxCount <= 0) return 0;
2186 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2187 if (win != WND_OTHER_PROCESS)
2189 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2190 else lpString[0] = 0;
2191 WIN_ReleasePtr( win );
2195 get_server_window_text( hwnd, lpString, nMaxCount );
2197 return strlenW(lpString);
2201 /*******************************************************************
2202 * GetWindowTextW (USER32.@)
2204 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2206 if (WIN_IsCurrentProcess( hwnd ))
2207 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2209 /* when window belongs to other process, don't send a message */
2210 if (nMaxCount <= 0) return 0;
2211 get_server_window_text( hwnd, lpString, nMaxCount );
2212 return strlenW(lpString);
2216 /*******************************************************************
2217 * SetWindowText (USER32.@)
2218 * SetWindowTextA (USER32.@)
2220 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2222 if (!WIN_IsCurrentProcess( hwnd ))
2224 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2225 SetLastError( ERROR_ACCESS_DENIED );
2228 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2232 /*******************************************************************
2233 * SetWindowTextW (USER32.@)
2235 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2237 if (!WIN_IsCurrentProcess( hwnd ))
2239 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2240 SetLastError( ERROR_ACCESS_DENIED );
2243 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2247 /*******************************************************************
2248 * GetWindowTextLengthA (USER32.@)
2250 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2252 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2255 /*******************************************************************
2256 * GetWindowTextLengthW (USER32.@)
2258 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2260 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2264 /*******************************************************************
2265 * IsWindow (USER32.@)
2267 BOOL WINAPI IsWindow( HWND hwnd )
2272 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2274 if (ptr != WND_OTHER_PROCESS)
2276 WIN_ReleasePtr( ptr );
2280 /* check other processes */
2281 SERVER_START_REQ( get_window_info )
2284 ret = !SERVER_CALL_ERR();
2291 /***********************************************************************
2292 * GetWindowThreadProcessId (USER32.@)
2294 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2299 if (!(ptr = WIN_GetPtr( hwnd )))
2301 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2305 if (ptr != WND_OTHER_PROCESS)
2307 /* got a valid window */
2309 if (process) *process = GetCurrentProcessId();
2310 WIN_ReleasePtr( ptr );
2314 /* check other processes */
2315 SERVER_START_REQ( get_window_info )
2318 if (!SERVER_CALL_ERR())
2320 tid = (DWORD)req->tid;
2321 if (process) *process = (DWORD)req->pid;
2329 /*****************************************************************
2330 * GetParent (USER32.@)
2332 HWND WINAPI GetParent( HWND hwnd )
2337 if (!(wndPtr = WIN_GetPtr( hwnd )))
2339 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2342 if (wndPtr == WND_OTHER_PROCESS)
2344 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2345 if (style & (WS_POPUP | WS_CHILD))
2347 SERVER_START_REQ( get_window_tree )
2350 if (!SERVER_CALL_ERR())
2352 if (style & WS_CHILD) retvalue = req->parent;
2353 else retvalue = req->owner;
2361 if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2362 else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2363 WIN_ReleasePtr( wndPtr );
2369 /*****************************************************************
2370 * GetAncestor (USER32.@)
2372 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2380 if (!(win = WIN_GetPtr( hwnd )))
2382 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2385 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2387 WIN_ReleasePtr( win );
2388 if (type == GA_PARENT) return ret;
2389 if (!ret || ret == GetDesktopWindow())
2391 ret = hwnd; /* if ret is the desktop, hwnd is the root ancestor */
2394 hwnd = ret; /* restart with parent as hwnd */
2397 size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE;
2399 SERVER_START_VAR_REQ( get_window_parents, size )
2404 user_handle_t *data = server_data_ptr(req);
2405 int count = server_data_size(req) / sizeof(*data);
2415 if (count > 1) ret = data[count - 2]; /* get the one before the desktop */
2416 else ret = WIN_GetFullHandle( hwnd );
2425 if (ret && type == GA_ROOTOWNER)
2429 HWND owner = GetWindow( ret, GW_OWNER );
2438 /*****************************************************************
2439 * SetParent (USER32.@)
2441 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2444 HWND retvalue, full_handle;
2447 if (!parent) parent = GetDesktopWindow();
2448 else parent = WIN_GetFullHandle( parent );
2450 if (!IsWindow( parent ))
2452 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2456 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2457 return SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2461 if (USER_Driver.pSetParent)
2462 return USER_Driver.pSetParent( hwnd, parent );
2464 /* Windows hides the window first, then shows it again
2465 * including the WM_SHOWWINDOW messages and all */
2466 was_visible = ShowWindow( hwnd, SW_HIDE );
2468 if (!IsWindow( parent )) return 0;
2469 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2471 retvalue = wndPtr->parent; /* old parent */
2472 if (parent != retvalue)
2474 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2476 if (parent != GetDesktopWindow()) /* a child window */
2478 if (!(wndPtr->dwStyle & WS_CHILD))
2480 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2481 if (menu) DestroyMenu( menu );
2485 WIN_ReleasePtr( wndPtr );
2487 /* SetParent additionally needs to make hwnd the topmost window
2488 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2489 WM_WINDOWPOSCHANGED notification messages.
2491 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2492 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2493 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2494 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2499 /*******************************************************************
2500 * IsChild (USER32.@)
2502 BOOL WINAPI IsChild( HWND parent, HWND child )
2504 HWND *list = WIN_ListParents( child );
2508 if (!list) return FALSE;
2509 parent = WIN_GetFullHandle( parent );
2510 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2511 ret = (list[i] != 0);
2512 HeapFree( GetProcessHeap(), 0, list );
2517 /***********************************************************************
2518 * IsWindowVisible (USER32.@)
2520 BOOL WINAPI IsWindowVisible( HWND hwnd )
2526 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2527 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2528 for (i = 0; list[i]; i++)
2529 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2531 HeapFree( GetProcessHeap(), 0, list );
2536 /***********************************************************************
2537 * WIN_IsWindowDrawable
2539 * hwnd is drawable when it is visible, all parents are not
2540 * minimized, and it is itself not minimized unless we are
2541 * trying to draw its default class icon.
2543 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2548 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2550 if (!(style & WS_VISIBLE)) return FALSE;
2551 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2553 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2554 for (i = 0; list[i]; i++)
2555 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2558 HeapFree( GetProcessHeap(), 0, list );
2563 /*******************************************************************
2564 * GetTopWindow (USER32.@)
2566 HWND WINAPI GetTopWindow( HWND hwnd )
2568 if (!hwnd) hwnd = GetDesktopWindow();
2569 return GetWindow( hwnd, GW_CHILD );
2573 /*******************************************************************
2574 * GetWindow (USER32.@)
2576 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2580 if (rel == GW_OWNER) /* this one may be available locally */
2582 WND *wndPtr = WIN_GetPtr( hwnd );
2585 SetLastError( ERROR_INVALID_HANDLE );
2588 if (wndPtr != WND_OTHER_PROCESS)
2590 retval = wndPtr->owner;
2591 WIN_ReleasePtr( wndPtr );
2594 /* else fall through to server call */
2597 SERVER_START_REQ( get_window_tree )
2600 if (!SERVER_CALL_ERR())
2605 retval = req->first_sibling;
2608 retval = req->last_sibling;
2611 retval = req->next_sibling;
2614 retval = req->prev_sibling;
2617 retval = req->owner;
2620 retval = req->first_child;
2630 /***********************************************************************
2631 * WIN_InternalShowOwnedPopups
2633 * Internal version of ShowOwnedPopups; Wine functions should use this
2634 * to avoid interfering with application calls to ShowOwnedPopups
2635 * and to make sure the application can't prevent showing/hiding.
2637 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2641 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2645 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2647 if (!win_array) return TRUE;
2650 * Show windows Lowest first, Highest last to preserve Z-Order
2652 while (win_array[count]) count++;
2653 while (--count >= 0)
2655 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2656 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2658 if (pWnd->dwStyle & WS_POPUP)
2662 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2663 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2666 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2668 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2669 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2674 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2675 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2676 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2679 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2681 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2682 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2683 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2687 WIN_ReleaseWndPtr( pWnd );
2689 HeapFree( GetProcessHeap(), 0, win_array );
2694 /*******************************************************************
2695 * ShowOwnedPopups (USER32.@)
2697 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2701 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2703 if (!win_array) return TRUE;
2705 while (win_array[count]) count++;
2706 while (--count >= 0)
2708 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2709 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2711 if (pWnd->dwStyle & WS_POPUP)
2715 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2717 /* In Windows, ShowOwnedPopups(TRUE) generates
2718 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2719 * regardless of the state of the owner
2721 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2722 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2727 if (IsWindowVisible(pWnd->hwndSelf))
2729 /* In Windows, ShowOwnedPopups(FALSE) generates
2730 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2731 * regardless of the state of the owner
2733 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2734 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2738 WIN_ReleaseWndPtr( pWnd );
2740 HeapFree( GetProcessHeap(), 0, win_array );
2745 /*******************************************************************
2746 * GetLastActivePopup (USER32.@)
2748 HWND WINAPI GetLastActivePopup( HWND hwnd )
2751 WND *wndPtr =WIN_FindWndPtr(hwnd);
2752 if (!wndPtr) return hwnd;
2753 retval = wndPtr->hwndLastActive;
2754 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2755 WIN_ReleaseWndPtr(wndPtr);
2760 /*******************************************************************
2763 * Build an array of all parents of a given window, starting with
2764 * the immediate parent. The array must be freed with HeapFree.
2765 * Returns NULL if window is a top-level window.
2767 HWND *WIN_ListParents( HWND hwnd )
2770 HWND current, *list;
2771 int pos = 0, size = 16, count = 0;
2773 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2778 if (!(win = WIN_GetPtr( current ))) goto empty;
2779 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2780 list[pos] = win->parent;
2781 WIN_ReleasePtr( win );
2782 if (!(current = list[pos]))
2784 if (!pos) goto empty;
2787 if (++pos == size - 1)
2789 /* need to grow the list */
2790 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2791 if (!new_list) goto empty;
2797 /* at least one parent belongs to another process, have to query the server */
2798 SERVER_START_VAR_REQ( get_window_parents, REQUEST_MAX_VAR_SIZE )
2803 user_handle_t *data = server_data_ptr(req);
2804 count = server_data_size(req) / sizeof(*data);
2807 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0,
2808 list, (count + 1) * sizeof(HWND) );
2812 for (pos = 0; pos < count; pos++) list[pos] = data[pos];
2820 if (count) return list;
2823 HeapFree( GetProcessHeap(), 0, list );
2828 /*******************************************************************
2831 * Build an array of the children of a given window. The array must be
2832 * freed with HeapFree. Returns NULL when no windows are found.
2834 HWND *WIN_ListChildren( HWND hwnd )
2836 return list_window_children( hwnd, 0, 0 );
2840 /*******************************************************************
2841 * EnumWindows (USER32.@)
2843 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2849 /* We have to build a list of all windows first, to avoid */
2850 /* unpleasant side-effects, for instance if the callback */
2851 /* function changes the Z-order of the windows. */
2853 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2855 /* Now call the callback function for every window */
2857 iWndsLocks = WIN_SuspendWndsLock();
2858 for (i = 0; list[i]; i++)
2860 /* Make sure that the window still exists */
2861 if (!IsWindow( list[i] )) continue;
2862 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2864 WIN_RestoreWndsLock(iWndsLocks);
2865 HeapFree( GetProcessHeap(), 0, list );
2870 /**********************************************************************
2871 * EnumTaskWindows16 (USER.225)
2873 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2876 TDB *tdb = TASK_GetPtr( hTask );
2877 if (!tdb) return FALSE;
2878 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2882 /**********************************************************************
2883 * EnumThreadWindows (USER32.@)
2885 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2890 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2893 /* Now call the callback function for every window */
2895 iWndsLocks = WIN_SuspendWndsLock();
2896 for (i = 0; list[i]; i++)
2897 if (!func( list[i], lParam )) break;
2898 WIN_RestoreWndsLock(iWndsLocks);
2899 HeapFree( GetProcessHeap(), 0, list );
2904 /**********************************************************************
2905 * WIN_EnumChildWindows
2907 * Helper function for EnumChildWindows().
2909 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2914 for ( ; *list; list++)
2916 /* Make sure that the window still exists */
2917 if (!IsWindow( *list )) continue;
2918 /* skip owned windows */
2919 if (GetWindow( *list, GW_OWNER )) continue;
2920 /* Build children list first */
2921 childList = WIN_ListChildren( *list );
2923 ret = func( *list, lParam );
2927 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2928 HeapFree( GetProcessHeap(), 0, childList );
2930 if (!ret) return FALSE;
2936 /**********************************************************************
2937 * EnumChildWindows (USER32.@)
2939 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2944 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2945 iWndsLocks = WIN_SuspendWndsLock();
2946 WIN_EnumChildWindows( list, func, lParam );
2947 WIN_RestoreWndsLock(iWndsLocks);
2948 HeapFree( GetProcessHeap(), 0, list );
2953 /*******************************************************************
2954 * AnyPopup (USER.52)
2956 BOOL16 WINAPI AnyPopup16(void)
2962 /*******************************************************************
2963 * AnyPopup (USER32.@)
2965 BOOL WINAPI AnyPopup(void)
2969 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2971 if (!list) return FALSE;
2972 for (i = 0; list[i]; i++)
2974 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2976 retvalue = (list[i] != 0);
2977 HeapFree( GetProcessHeap(), 0, list );
2982 /*******************************************************************
2983 * FlashWindow (USER32.@)
2985 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2987 WND *wndPtr = WIN_FindWndPtr(hWnd);
2989 TRACE("%04x\n", hWnd);
2991 if (!wndPtr) return FALSE;
2992 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2994 if (wndPtr->dwStyle & WS_MINIMIZE)
2996 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2998 HDC hDC = GetDC(hWnd);
3000 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3001 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3003 ReleaseDC( hWnd, hDC );
3004 wndPtr->flags |= WIN_NCACTIVATED;
3008 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3009 wndPtr->flags &= ~WIN_NCACTIVATED;
3011 WIN_ReleaseWndPtr(wndPtr);
3017 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3018 else wparam = (hWnd == GetActiveWindow());
3020 WIN_ReleaseWndPtr(wndPtr);
3021 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3027 /*******************************************************************
3028 * GetWindowContextHelpId (USER32.@)
3030 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3033 WND *wnd = WIN_FindWndPtr( hwnd );
3035 retval = wnd->helpContext;
3036 WIN_ReleaseWndPtr(wnd);
3041 /*******************************************************************
3042 * SetWindowContextHelpId (USER32.@)
3044 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3046 WND *wnd = WIN_FindWndPtr( hwnd );
3047 if (!wnd) return FALSE;
3048 wnd->helpContext = id;
3049 WIN_ReleaseWndPtr(wnd);
3054 /*******************************************************************
3057 * recursively find a child that contains spDragInfo->pt point
3058 * and send WM_QUERYDROPOBJECT
3060 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3062 BOOL16 wParam, bResult = 0;
3064 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3067 if (!ptrDragInfo) return FALSE;
3069 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3071 GetWindowRect(hQueryWnd,&tempRect);
3073 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3075 if (!IsIconic( hQueryWnd ))
3077 GetClientRect( hQueryWnd, &tempRect );
3078 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3080 if (PtInRect( &tempRect, pt))
3083 HWND *list = WIN_ListChildren( hQueryWnd );
3089 for (i = 0; list[i]; i++)
3091 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3093 GetWindowRect( list[i], &tempRect );
3094 if (PtInRect( &tempRect, pt )) break;
3099 if (IsWindowEnabled( list[i] ))
3100 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
3102 HeapFree( GetProcessHeap(), 0, list );
3104 if(bResult) return bResult;
3110 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3112 ptrDragInfo->hScope = hQueryWnd;
3114 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3115 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3117 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3123 /*******************************************************************
3124 * DragDetect (USER32.@)
3126 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3131 rect.left = pt.x - wDragWidth;
3132 rect.right = pt.x + wDragWidth;
3134 rect.top = pt.y - wDragHeight;
3135 rect.bottom = pt.y + wDragHeight;
3141 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3143 if( msg.message == WM_LBUTTONUP )
3148 if( msg.message == WM_MOUSEMOVE )
3151 tmp.x = LOWORD(msg.lParam);
3152 tmp.y = HIWORD(msg.lParam);
3153 if( !PtInRect( &rect, tmp ))
3165 /******************************************************************************
3166 * DragObject (USER.464)
3168 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3169 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3172 LPDRAGINFO16 lpDragInfo;
3174 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3175 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3176 HCURSOR16 hCurrentCursor = 0;
3177 HWND16 hCurrentWnd = 0;
3179 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3180 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3182 if( !lpDragInfo || !spDragInfo ) return 0L;
3184 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3186 GlobalFree16(hDragInfo);
3192 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3194 GlobalFree16(hDragInfo);
3198 if( hDragCursor == hCursor ) hDragCursor = 0;
3199 else hCursor = hDragCursor;
3201 hOldCursor = SetCursor(hDragCursor);
3204 lpDragInfo->hWnd = hWnd;
3205 lpDragInfo->hScope = 0;
3206 lpDragInfo->wFlags = wObj;
3207 lpDragInfo->hList = szList; /* near pointer! */
3208 lpDragInfo->hOfStruct = hOfStruct;
3216 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3218 *(lpDragInfo+1) = *lpDragInfo;
3220 lpDragInfo->pt.x = msg.pt.x;
3221 lpDragInfo->pt.y = msg.pt.y;
3223 /* update DRAGINFO struct */
3224 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3226 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3227 hCurrentCursor = hCursor;
3230 hCurrentCursor = hBummer;
3231 lpDragInfo->hScope = 0;
3233 if( hCurrentCursor )
3234 SetCursor(hCurrentCursor);
3236 /* send WM_DRAGLOOP */
3237 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3238 (LPARAM) spDragInfo );
3239 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3240 if( hCurrentWnd != lpDragInfo->hScope )
3243 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3244 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3245 HIWORD(spDragInfo)) );
3246 hCurrentWnd = lpDragInfo->hScope;
3248 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3252 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3254 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3257 ShowCursor( FALSE );
3261 SetCursor( hOldCursor );
3262 if (hDragCursor) DestroyCursor( hDragCursor );
3265 if( hCurrentCursor != hBummer )
3266 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3267 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3270 GlobalFree16(hDragInfo);
3272 return (DWORD)(msg.lParam);
3276 /******************************************************************************
3277 * GetWindowModuleFileNameA (USER32.@)
3279 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3281 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3282 hwnd, lpszFileName, cchFileNameMax);
3286 /******************************************************************************
3287 * GetWindowModuleFileNameW (USER32.@)
3289 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3291 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3292 hwnd, lpszFileName, cchFileNameMax);