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 = !wine_server_call_err( req ))) handle = reply->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 (!wine_server_call_err( req ))
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 )
162 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
164 SERVER_START_REQ( get_window_children )
168 req->tid = (void *)tid;
169 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
170 if (!wine_server_call( req )) count = reply->count;
173 if (count && count < size)
178 HeapFree( GetProcessHeap(), 0, list );
180 size = count + 1; /* restart with a large enough buffer */
186 /*******************************************************************
189 static void send_parent_notify( HWND hwnd, UINT msg )
191 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
192 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
193 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
194 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
198 /*******************************************************************
199 * get_server_window_text
201 * Retrieve the window text from the server.
203 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
207 SERVER_START_REQ( get_window_text )
210 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
211 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
214 text[len / sizeof(WCHAR)] = 0;
218 /***********************************************************************
221 * Return a pointer to the WND structure if local to the process,
222 * or WND_OTHER_PROCESS is handle may be valid in other process.
223 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
225 WND *WIN_GetPtr( HWND hwnd )
228 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
230 if (index >= NB_USER_HANDLES) return NULL;
233 if ((ptr = user_handles[index]))
235 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
239 else ptr = WND_OTHER_PROCESS;
245 /***********************************************************************
246 * WIN_IsCurrentProcess
248 * Check whether a given window belongs to the current process (and return the full handle).
250 HWND WIN_IsCurrentProcess( HWND hwnd )
255 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
257 WIN_ReleasePtr( ptr );
262 /***********************************************************************
263 * WIN_IsCurrentThread
265 * Check whether a given window belongs to the current thread (and return the full handle).
267 HWND WIN_IsCurrentThread( HWND hwnd )
272 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
274 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
275 WIN_ReleasePtr( ptr );
281 /***********************************************************************
284 * Convert a 16-bit window handle to a full 32-bit handle.
286 HWND WIN_Handle32( HWND16 hwnd16 )
289 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
291 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
292 /* do sign extension for -2 and -3 */
293 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
295 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
297 if (ptr != WND_OTHER_PROCESS)
299 hwnd = ptr->hwndSelf;
300 WIN_ReleasePtr( ptr );
302 else /* may belong to another process */
304 SERVER_START_REQ( get_window_info )
307 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
315 /***********************************************************************
318 * Return a pointer to the WND structure corresponding to a HWND.
320 WND * WIN_FindWndPtr( HWND hwnd )
324 if (!hwnd) return NULL;
326 if ((ptr = WIN_GetPtr( hwnd )))
328 if (ptr != WND_OTHER_PROCESS)
330 /* increment destruction monitoring */
334 if (IsWindow( hwnd )) /* check other processes */
336 ERR( "window %04x belongs to other process\n", hwnd );
337 /* DbgBreakPoint(); */
340 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
345 /***********************************************************************
348 * Release the pointer to the WND structure.
350 void WIN_ReleaseWndPtr(WND *wndPtr)
354 /* Decrement destruction monitoring value */
356 /* Check if it's time to release the memory */
357 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
360 free_window_handle( wndPtr->hwndSelf );
362 else if(wndPtr->irefCount < 0)
364 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
365 ERR("forgot a Lock on %p somewhere\n",wndPtr);
367 /* unlock all WND structures for thread safeness */
372 /***********************************************************************
375 * Remove a window from the siblings linked list.
377 void WIN_UnlinkWindow( HWND hwnd )
379 WIN_LinkWindow( hwnd, 0, 0 );
383 /***********************************************************************
386 * Insert a window into the siblings linked list.
387 * The window is inserted after the specified window, which can also
388 * be specified as HWND_TOP or HWND_BOTTOM.
389 * If parent is 0, window is unlinked from the tree.
391 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
393 WND *wndPtr = WIN_GetPtr( hwnd );
396 if (wndPtr == WND_OTHER_PROCESS)
398 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
402 SERVER_START_REQ( link_window )
405 req->parent = parent;
406 req->previous = hwndInsertAfter;
407 if (!wine_server_call( req ))
409 if (reply->full_parent && reply->full_parent != wndPtr->parent)
411 wndPtr->owner = 0; /* reset owner when changing parent */
412 wndPtr->parent = reply->full_parent;
418 WIN_ReleasePtr( wndPtr );
422 /***********************************************************************
425 * Change the owner of a window.
427 void WIN_SetOwner( HWND hwnd, HWND owner )
429 WND *win = WIN_GetPtr( hwnd );
432 if (win == WND_OTHER_PROCESS)
434 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
437 SERVER_START_REQ( set_window_owner )
441 if (!wine_server_call( req )) win->owner = reply->full_owner;
444 WIN_ReleasePtr( win );
448 /***********************************************************************
451 * Change the style of a window.
453 LONG WIN_SetStyle( HWND hwnd, LONG style )
457 WND *win = WIN_GetPtr( hwnd );
460 if (win == WND_OTHER_PROCESS)
463 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
466 if (style == win->dwStyle)
468 WIN_ReleasePtr( win );
471 SERVER_START_REQ( set_window_info )
474 req->flags = SET_WIN_STYLE;
476 if ((ok = !wine_server_call( req )))
478 ret = reply->old_style;
479 win->dwStyle = style;
483 WIN_ReleasePtr( win );
484 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
489 /***********************************************************************
492 * Change the extended style of a window.
494 LONG WIN_SetExStyle( HWND hwnd, LONG style )
497 WND *win = WIN_GetPtr( hwnd );
500 if (win == WND_OTHER_PROCESS)
503 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
506 if (style == win->dwExStyle)
508 WIN_ReleasePtr( win );
511 SERVER_START_REQ( set_window_info )
514 req->flags = SET_WIN_EXSTYLE;
515 req->ex_style = style;
516 if (!wine_server_call( req ))
518 ret = reply->old_ex_style;
519 win->dwExStyle = style;
523 WIN_ReleasePtr( win );
528 /***********************************************************************
531 * Set the window and client rectangles.
533 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
535 WND *win = WIN_GetPtr( hwnd );
539 if (win == WND_OTHER_PROCESS)
541 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
544 SERVER_START_REQ( set_window_rectangles )
547 req->window.left = rectWindow->left;
548 req->window.top = rectWindow->top;
549 req->window.right = rectWindow->right;
550 req->window.bottom = rectWindow->bottom;
551 req->client.left = rectClient->left;
552 req->client.top = rectClient->top;
553 req->client.right = rectClient->right;
554 req->client.bottom = rectClient->bottom;
555 ret = !wine_server_call( req );
560 win->rectWindow = *rectWindow;
561 win->rectClient = *rectClient;
563 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
564 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
565 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
567 WIN_ReleasePtr( win );
571 /***********************************************************************
574 * Destroy storage associated to a window. "Internals" p.358
576 LRESULT WIN_DestroyWindow( HWND hwnd )
581 TRACE("%04x\n", hwnd );
583 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
585 ERR( "window doesn't belong to current thread\n" );
589 /* free child windows */
590 if ((list = WIN_ListChildren( hwnd )))
593 for (i = 0; list[i]; i++)
595 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
596 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
598 HeapFree( GetProcessHeap(), 0, list );
602 * Clear the update region to make sure no WM_PAINT messages will be
603 * generated for this window while processing the WM_NCDESTROY.
605 RedrawWindow( hwnd, NULL, 0,
606 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
609 * Send the WM_NCDESTROY to the window being destroyed.
611 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
613 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
615 WINPOS_CheckInternalPos( hwnd );
616 if( hwnd == GetCapture()) ReleaseCapture();
618 /* free resources associated with the window */
620 TIMER_RemoveWindowTimers( hwnd );
622 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
623 wndPtr->hmemTaskQ = 0;
625 if (!(wndPtr->dwStyle & WS_CHILD))
627 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
628 if (menu) DestroyMenu( menu );
630 if (wndPtr->hSysMenu)
632 DestroyMenu( wndPtr->hSysMenu );
633 wndPtr->hSysMenu = 0;
635 USER_Driver.pDestroyWindow( hwnd );
636 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
637 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
638 CLASS_RemoveWindow( wndPtr->class );
639 wndPtr->class = NULL;
640 wndPtr->dwMagic = 0; /* Mark it as invalid */
641 WIN_ReleaseWndPtr( wndPtr );
645 /***********************************************************************
646 * WIN_DestroyThreadWindows
648 * Destroy all children of 'wnd' owned by the current thread.
649 * Return TRUE if something was done.
651 void WIN_DestroyThreadWindows( HWND hwnd )
656 if (!(list = WIN_ListChildren( hwnd ))) return;
657 for (i = 0; list[i]; i++)
659 if (WIN_IsCurrentThread( list[i] ))
660 DestroyWindow( list[i] );
662 WIN_DestroyThreadWindows( list[i] );
664 HeapFree( GetProcessHeap(), 0, list );
667 /***********************************************************************
668 * WIN_CreateDesktopWindow
670 * Create the desktop window.
672 BOOL WIN_CreateDesktopWindow(void)
674 struct tagCLASS *class;
683 TRACE("Creating desktop window\n");
685 if (!WINPOS_CreateInternalPosAtom() ||
686 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
687 &wndExtra, &winproc, &clsStyle, &dce )))
690 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
691 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
692 if (!pWndDesktop) return FALSE;
693 hwndDesktop = pWndDesktop->hwndSelf;
695 pWndDesktop->tid = 0; /* nobody owns the desktop */
696 pWndDesktop->parent = 0;
697 pWndDesktop->owner = 0;
698 pWndDesktop->class = class;
699 pWndDesktop->hInstance = 0;
700 pWndDesktop->text = NULL;
701 pWndDesktop->hmemTaskQ = 0;
702 pWndDesktop->hrgnUpdate = 0;
703 pWndDesktop->hwndLastActive = hwndDesktop;
704 pWndDesktop->dwStyle = 0;
705 pWndDesktop->dwExStyle = 0;
706 pWndDesktop->clsStyle = clsStyle;
707 pWndDesktop->dce = NULL;
708 pWndDesktop->pVScroll = NULL;
709 pWndDesktop->pHScroll = NULL;
710 pWndDesktop->wIDmenu = 0;
711 pWndDesktop->helpContext = 0;
712 pWndDesktop->flags = 0;
713 pWndDesktop->hSysMenu = 0;
714 pWndDesktop->userdata = 0;
715 pWndDesktop->winproc = winproc;
716 pWndDesktop->cbWndExtra = wndExtra;
718 cs.lpCreateParams = NULL;
724 cs.cx = GetSystemMetrics( SM_CXSCREEN );
725 cs.cy = GetSystemMetrics( SM_CYSCREEN );
726 cs.style = pWndDesktop->dwStyle;
727 cs.dwExStyle = pWndDesktop->dwExStyle;
729 cs.lpszClass = DESKTOP_CLASS_ATOM;
731 SetRect( &rect, 0, 0, cs.cx, cs.cy );
732 WIN_SetRectangles( hwndDesktop, &rect, &rect );
733 WIN_SetStyle( hwndDesktop, WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
735 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
737 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
738 WIN_ReleaseWndPtr( pWndDesktop );
743 /***********************************************************************
746 * Fix the coordinates - Helper for WIN_CreateWindowEx.
747 * returns default show mode in sw.
748 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
750 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
752 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
753 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
755 if (cs->style & (WS_CHILD | WS_POPUP))
757 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
758 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
760 else /* overlapped window */
764 GetStartupInfoA( &info );
766 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
768 /* Never believe Microsoft's documentation... CreateWindowEx doc says
769 * that if an overlapped window is created with WS_VISIBLE style bit
770 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
771 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
774 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
775 * 2) it does not ignore the y parameter as the docs claim; instead, it
776 * uses it as second parameter to ShowWindow() unless y is either
777 * CW_USEDEFAULT or CW_USEDEFAULT16.
779 * The fact that we didn't do 2) caused bogus windows pop up when wine
780 * was running apps that were using this obscure feature. Example -
781 * calc.exe that comes with Win98 (only Win98, it's different from
782 * the one that comes with Win95 and NT)
784 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
785 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
786 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
789 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
791 if (info.dwFlags & STARTF_USESIZE)
793 cs->cx = info.dwXSize;
794 cs->cy = info.dwYSize;
796 else /* if no other hint from the app, pick 3/4 of the screen real estate */
799 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
800 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
801 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
808 /***********************************************************************
811 static void dump_window_styles( DWORD style, DWORD exstyle )
814 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
815 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
816 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
817 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
818 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
819 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
820 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
821 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
822 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
825 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
826 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
828 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
829 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
830 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
831 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
832 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
833 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
834 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
835 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
837 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
838 #define DUMPED_STYLES \
858 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
863 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
864 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
865 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
866 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
867 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
868 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
869 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
870 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
871 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
872 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
873 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
874 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
875 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
876 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
877 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
878 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
879 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
880 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
882 #define DUMPED_EX_STYLES \
883 (WS_EX_DLGMODALFRAME | \
885 WS_EX_NOPARENTNOTIFY | \
887 WS_EX_ACCEPTFILES | \
888 WS_EX_TRANSPARENT | \
893 WS_EX_CONTEXTHELP | \
896 WS_EX_LEFTSCROLLBAR | \
897 WS_EX_CONTROLPARENT | \
902 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
904 #undef DUMPED_EX_STYLES
908 /***********************************************************************
911 * Implementation of CreateWindowEx().
913 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
914 WINDOWPROCTYPE type )
917 struct tagCLASS *classPtr;
919 HWND hwnd, hwndLinkAfter, parent, owner;
924 BOOL unicode = (type == WIN_PROC_32W);
926 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
927 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
928 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
929 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
930 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
932 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
934 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
935 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
937 /* Find the parent window */
939 parent = GetDesktopWindow();
943 /* Make sure parent is valid */
944 if (!IsWindow( cs->hwndParent ))
946 WARN("Bad parent %04x\n", cs->hwndParent );
949 if (cs->style & WS_CHILD) parent = WIN_GetFullHandle(cs->hwndParent);
950 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
952 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
954 WARN("No parent for child window\n" );
955 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
958 /* Find the window class */
959 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
960 &wndExtra, &winproc, &clsStyle, &dce )))
962 WARN("Bad class '%s'\n", cs->lpszClass );
966 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
968 /* Correct the window style - stage 1
970 * These are patches that appear to affect both the style loaded into the
971 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
973 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
974 * why does the user get to set it?
977 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
978 * tested for WS_POPUP
980 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
981 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
982 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
983 cs->dwExStyle |= WS_EX_WINDOWEDGE;
985 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
987 /* Create the window structure */
989 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
990 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
992 TRACE("out of memory\n" );
995 hwnd = wndPtr->hwndSelf;
997 /* Fill the window structure */
999 wndPtr->tid = GetCurrentThreadId();
1000 wndPtr->owner = owner;
1001 wndPtr->parent = parent;
1002 wndPtr->class = classPtr;
1003 wndPtr->winproc = winproc;
1004 wndPtr->hInstance = cs->hInstance;
1005 wndPtr->text = NULL;
1006 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
1007 wndPtr->hrgnUpdate = 0;
1008 wndPtr->hrgnWnd = 0;
1009 wndPtr->hwndLastActive = hwnd;
1010 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1011 wndPtr->dwExStyle = cs->dwExStyle;
1012 wndPtr->clsStyle = clsStyle;
1013 wndPtr->wIDmenu = 0;
1014 wndPtr->helpContext = 0;
1015 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1016 wndPtr->pVScroll = NULL;
1017 wndPtr->pHScroll = NULL;
1018 wndPtr->userdata = 0;
1019 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1020 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1021 wndPtr->cbWndExtra = wndExtra;
1023 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1025 /* Call the WH_CBT hook */
1027 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
1028 ? HWND_BOTTOM : HWND_TOP;
1030 if (HOOK_IsHooked( WH_CBT ))
1032 CBT_CREATEWNDA cbtc;
1036 cbtc.hwndInsertAfter = hwndLinkAfter;
1037 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND,
1038 (WPARAM)hwnd, (LPARAM)&cbtc)
1039 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND,
1040 (WPARAM)hwnd, (LPARAM)&cbtc);
1043 TRACE("CBT-hook returned 0\n");
1044 free_window_handle( hwnd );
1045 CLASS_RemoveWindow( classPtr );
1046 WIN_ReleaseWndPtr(wndPtr);
1051 /* Correct the window style - stage 2 */
1053 if (!(cs->style & WS_CHILD))
1055 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1056 if (!(cs->style & WS_POPUP))
1058 wndPtr->dwStyle |= WS_CAPTION;
1059 wndPtr->flags |= WIN_NEED_SIZE;
1062 SERVER_START_REQ( set_window_info )
1065 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1066 req->style = wndPtr->dwStyle;
1067 req->ex_style = wndPtr->dwExStyle;
1068 req->instance = (void *)wndPtr->hInstance;
1069 wine_server_call( req );
1073 /* Get class or window DC if needed */
1075 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1076 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1077 else wndPtr->dce = NULL;
1079 /* Set the window menu */
1081 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1083 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1086 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1089 if (HIWORD(cs->hInstance))
1090 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1092 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1094 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1098 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1099 WIN_ReleaseWndPtr( wndPtr );
1101 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1103 WIN_DestroyWindow( hwnd );
1107 /* Notify the parent window only */
1109 send_parent_notify( hwnd, WM_CREATE );
1110 if (!IsWindow( hwnd )) return 0;
1112 if (cs->style & WS_VISIBLE)
1114 /* in case WS_VISIBLE got set in the meantime */
1115 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1116 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1117 WIN_ReleasePtr( wndPtr );
1118 ShowWindow( hwnd, sw );
1121 /* Call WH_SHELL hook */
1123 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1124 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1126 TRACE("created window %04x\n", hwnd);
1131 /***********************************************************************
1132 * CreateWindow (USER.41)
1134 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1135 DWORD style, INT16 x, INT16 y, INT16 width,
1136 INT16 height, HWND16 parent, HMENU16 menu,
1137 HINSTANCE16 instance, LPVOID data )
1139 return CreateWindowEx16( 0, className, windowName, style,
1140 x, y, width, height, parent, menu, instance, data );
1144 /***********************************************************************
1145 * CreateWindowEx (USER.452)
1147 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1148 LPCSTR windowName, DWORD style, INT16 x,
1149 INT16 y, INT16 width, INT16 height,
1150 HWND16 parent, HMENU16 menu,
1151 HINSTANCE16 instance, LPVOID data )
1157 /* Find the class atom */
1159 if (HIWORD(className))
1161 if (!(classAtom = GlobalFindAtomA( className )))
1163 ERR( "bad class name %s\n", debugres_a(className) );
1169 classAtom = LOWORD(className);
1170 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1172 ERR( "bad atom %x\n", classAtom);
1178 /* Fix the coordinates */
1180 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1181 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1182 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1183 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1185 /* Create the window */
1187 cs.lpCreateParams = data;
1188 cs.hInstance = (HINSTANCE)instance;
1189 cs.hMenu = (HMENU)menu;
1190 cs.hwndParent = WIN_Handle32( parent );
1192 cs.lpszName = windowName;
1193 cs.lpszClass = className;
1194 cs.dwExStyle = exStyle;
1196 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1200 /***********************************************************************
1201 * CreateWindowExA (USER32.@)
1203 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1204 LPCSTR windowName, DWORD style, INT x,
1205 INT y, INT width, INT height,
1206 HWND parent, HMENU menu,
1207 HINSTANCE instance, LPVOID data )
1214 instance=GetModuleHandleA(NULL);
1216 if(exStyle & WS_EX_MDICHILD)
1217 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1219 /* Find the class atom */
1221 if (HIWORD(className))
1223 if (!(classAtom = GlobalFindAtomA( className )))
1225 ERR( "bad class name %s\n", debugres_a(className) );
1231 classAtom = LOWORD(className);
1232 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1234 ERR( "bad atom %x\n", classAtom);
1240 /* Create the window */
1242 cs.lpCreateParams = data;
1243 cs.hInstance = instance;
1245 cs.hwndParent = parent;
1251 cs.lpszName = windowName;
1252 cs.lpszClass = className;
1253 cs.dwExStyle = exStyle;
1255 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1259 /***********************************************************************
1260 * CreateWindowExW (USER32.@)
1262 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1263 LPCWSTR windowName, DWORD style, INT x,
1264 INT y, INT width, INT height,
1265 HWND parent, HMENU menu,
1266 HINSTANCE instance, LPVOID data )
1273 instance=GetModuleHandleA(NULL);
1275 if(exStyle & WS_EX_MDICHILD)
1276 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1278 /* Find the class atom */
1280 if (HIWORD(className))
1282 if (!(classAtom = GlobalFindAtomW( className )))
1284 ERR( "bad class name %s\n", debugres_w(className) );
1290 classAtom = LOWORD(className);
1291 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1293 ERR( "bad atom %x\n", classAtom);
1299 /* Create the window */
1301 cs.lpCreateParams = data;
1302 cs.hInstance = instance;
1304 cs.hwndParent = parent;
1310 cs.lpszName = windowName;
1311 cs.lpszClass = className;
1312 cs.dwExStyle = exStyle;
1314 /* Note: we rely on the fact that CREATESTRUCTA and */
1315 /* CREATESTRUCTW have the same layout. */
1316 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1320 /***********************************************************************
1321 * WIN_SendDestroyMsg
1323 static void WIN_SendDestroyMsg( HWND hwnd )
1325 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1326 if (USER_Driver.pResetSelectionOwner)
1327 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1330 * Send the WM_DESTROY to the window.
1332 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1335 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1336 * make sure that the window still exists when we come back.
1343 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1345 /* start from the end (FIXME: is this needed?) */
1346 for (i = 0; pWndArray[i]; i++) ;
1350 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1352 HeapFree( GetProcessHeap(), 0, pWndArray );
1355 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1359 /***********************************************************************
1360 * DestroyWindow (USER32.@)
1362 BOOL WINAPI DestroyWindow( HWND hwnd )
1367 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1369 SetLastError( ERROR_ACCESS_DENIED );
1373 TRACE("(%04x)\n", hwnd);
1375 /* Look whether the focus is within the tree of windows we will
1379 if (h == hwnd || IsChild( hwnd, h ))
1381 HWND parent = GetAncestor( hwnd, GA_PARENT );
1382 if (parent == GetDesktopWindow()) parent = 0;
1388 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1390 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1394 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1395 send_parent_notify( hwnd, WM_DESTROY );
1397 else if (!GetWindow( hwnd, GW_OWNER ))
1399 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1400 /* FIXME: clean up palette - see "Internals" p.352 */
1403 if (!IsWindow(hwnd)) return TRUE;
1405 if (USER_Driver.pResetSelectionOwner)
1406 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1408 /* Hide the window */
1410 ShowWindow( hwnd, SW_HIDE );
1411 if (!IsWindow(hwnd)) return TRUE;
1413 /* Recursively destroy owned windows */
1422 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1425 for (i = 0; list[i]; i++)
1427 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1428 if (WIN_IsCurrentThread( list[i] ))
1430 DestroyWindow( list[i] );
1434 WIN_SetOwner( list[i], 0 );
1436 HeapFree( GetProcessHeap(), 0, list );
1438 if (!got_one) break;
1441 WINPOS_ActivateOtherWindow( hwnd );
1443 if ((owner = GetWindow( hwnd, GW_OWNER )))
1445 WND *ptr = WIN_FindWndPtr( owner );
1448 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1449 WIN_ReleaseWndPtr( ptr );
1454 /* Send destroy messages */
1456 WIN_SendDestroyMsg( hwnd );
1457 if (!IsWindow( hwnd )) return TRUE;
1459 /* Unlink now so we won't bother with the children later on */
1461 WIN_UnlinkWindow( hwnd );
1463 /* Destroy the window storage */
1465 WIN_DestroyWindow( hwnd );
1470 /***********************************************************************
1471 * CloseWindow (USER32.@)
1473 BOOL WINAPI CloseWindow( HWND hwnd )
1475 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1476 ShowWindow( hwnd, SW_MINIMIZE );
1481 /***********************************************************************
1482 * OpenIcon (USER32.@)
1484 BOOL WINAPI OpenIcon( HWND hwnd )
1486 if (!IsIconic( hwnd )) return FALSE;
1487 ShowWindow( hwnd, SW_SHOWNORMAL );
1492 /***********************************************************************
1495 * Implementation of FindWindow() and FindWindowEx().
1497 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1502 WCHAR *buffer = NULL;
1504 if (!parent) parent = GetDesktopWindow();
1507 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1508 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1511 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1515 child = WIN_GetFullHandle( child );
1516 while (list[i] && list[i] != child) i++;
1517 if (!list[i]) goto done;
1518 i++; /* start from next window */
1525 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1532 if (list) HeapFree( GetProcessHeap(), 0, list );
1533 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1539 /***********************************************************************
1540 * FindWindowA (USER32.@)
1542 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1544 HWND ret = FindWindowExA( 0, 0, className, title );
1545 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1550 /***********************************************************************
1551 * FindWindowExA (USER32.@)
1553 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1554 LPCSTR className, LPCSTR title )
1562 /* If the atom doesn't exist, then no class */
1563 /* with this name exists either. */
1564 if (!(atom = GlobalFindAtomA( className )))
1566 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1571 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1572 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1573 HeapFree( GetProcessHeap(), 0, buffer );
1578 /***********************************************************************
1579 * FindWindowExW (USER32.@)
1581 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1582 LPCWSTR className, LPCWSTR title )
1588 /* If the atom doesn't exist, then no class */
1589 /* with this name exists either. */
1590 if (!(atom = GlobalFindAtomW( className )))
1592 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1596 return WIN_FindWindow( parent, child, atom, title );
1600 /***********************************************************************
1601 * FindWindowW (USER32.@)
1603 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1605 return FindWindowExW( 0, 0, className, title );
1609 /**********************************************************************
1610 * GetDesktopWindow (USER32.@)
1612 HWND WINAPI GetDesktopWindow(void)
1614 if (pWndDesktop) return pWndDesktop->hwndSelf;
1615 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" );
1621 /*******************************************************************
1622 * EnableWindow (USER32.@)
1624 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1631 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1632 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1636 TRACE("( %x, %d )\n", hwnd, enable);
1638 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1639 style = wndPtr->dwStyle;
1640 retvalue = ((style & WS_DISABLED) != 0);
1641 WIN_ReleasePtr( wndPtr );
1643 if (enable && retvalue)
1645 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1646 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1648 else if (!enable && !retvalue)
1650 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1652 WIN_SetStyle( hwnd, style | WS_DISABLED );
1654 if (hwnd == GetFocus())
1655 SetFocus( 0 ); /* A disabled window can't have the focus */
1657 if (hwnd == GetCapture())
1658 ReleaseCapture(); /* A disabled window can't capture the mouse */
1660 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1666 /***********************************************************************
1667 * IsWindowEnabled (USER32.@)
1669 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1671 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1675 /***********************************************************************
1676 * IsWindowUnicode (USER32.@)
1678 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1683 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1684 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1685 WIN_ReleaseWndPtr(wndPtr);
1690 /**********************************************************************
1691 * GetWindowWord (USER32.@)
1693 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1698 WND *wndPtr = WIN_GetPtr( hwnd );
1701 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1704 if (wndPtr == WND_OTHER_PROCESS)
1706 if (IsWindow( hwnd ))
1707 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1708 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1711 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1713 WARN("Invalid offset %d\n", offset );
1714 SetLastError( ERROR_INVALID_INDEX );
1716 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1717 WIN_ReleasePtr( wndPtr );
1723 case GWL_HWNDPARENT:
1724 return GetWindowLongW( hwnd, offset );
1728 LONG ret = GetWindowLongW( hwnd, offset );
1730 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1734 WARN("Invalid offset %d\n", offset );
1740 /**********************************************************************
1741 * SetWindowWord (USER32.@)
1743 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1752 case GWL_HWNDPARENT:
1753 return SetWindowLongW( hwnd, offset, (UINT)newval );
1757 WARN("Invalid offset %d\n", offset );
1758 SetLastError( ERROR_INVALID_INDEX );
1763 wndPtr = WIN_GetPtr( hwnd );
1764 if (wndPtr == WND_OTHER_PROCESS)
1767 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1768 offset, newval, hwnd );
1773 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1777 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1779 WARN("Invalid offset %d\n", offset );
1780 WIN_ReleasePtr(wndPtr);
1781 SetLastError( ERROR_INVALID_INDEX );
1784 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1787 WIN_ReleasePtr(wndPtr);
1792 /**********************************************************************
1795 * Helper function for GetWindowLong().
1797 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1802 if (offset == GWL_HWNDPARENT) return (LONG)GetParent( hwnd );
1804 if (!(wndPtr = WIN_GetPtr( hwnd )))
1806 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1810 if (wndPtr == WND_OTHER_PROCESS)
1815 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1816 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1819 if (offset == GWL_WNDPROC)
1821 SetLastError( ERROR_ACCESS_DENIED );
1824 SERVER_START_REQ( set_window_info )
1827 req->flags = 0; /* don't set anything, just retrieve */
1828 if (!wine_server_call_err( req ))
1832 case GWL_STYLE: retvalue = reply->old_style; break;
1833 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1834 case GWL_ID: retvalue = reply->old_id; break;
1835 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1836 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1838 SetLastError( ERROR_INVALID_INDEX );
1847 /* now we have a valid wndPtr */
1851 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1853 WARN("Invalid offset %d\n", offset );
1854 WIN_ReleasePtr( wndPtr );
1855 SetLastError( ERROR_INVALID_INDEX );
1858 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1859 /* Special case for dialog window procedure */
1860 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1861 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1862 WIN_ReleasePtr( wndPtr );
1868 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1869 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1870 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1871 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1872 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1873 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1875 WARN("Unknown offset %d\n", offset );
1876 SetLastError( ERROR_INVALID_INDEX );
1879 WIN_ReleasePtr(wndPtr);
1884 /**********************************************************************
1887 * Helper function for SetWindowLong().
1889 * 0 is the failure code. However, in the case of failure SetLastError
1890 * must be set to distinguish between a 0 return value and a failure.
1892 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1893 WINDOWPROCTYPE type )
1898 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1900 if (!WIN_IsCurrentProcess( hwnd ))
1902 if (offset == GWL_WNDPROC)
1904 SetLastError( ERROR_ACCESS_DENIED );
1907 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1910 wndPtr = WIN_GetPtr( hwnd );
1914 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1915 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1917 WARN("Invalid offset %d\n", offset );
1918 WIN_ReleasePtr( wndPtr );
1919 SetLastError( ERROR_INVALID_INDEX );
1922 /* Special case for dialog window procedure */
1923 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1925 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1926 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1927 type, WIN_PROC_WINDOW );
1928 WIN_ReleasePtr( wndPtr );
1933 WIN_ReleasePtr( wndPtr );
1940 /* first some special cases */
1945 style.styleOld = wndPtr->dwStyle;
1946 style.styleNew = newval;
1947 WIN_ReleasePtr( wndPtr );
1948 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1949 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1950 newval = style.styleNew;
1952 case GWL_HWNDPARENT:
1953 WIN_ReleasePtr( wndPtr );
1954 return (LONG)SetParent( hwnd, (HWND)newval );
1956 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1957 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1958 type, WIN_PROC_WINDOW );
1959 WIN_ReleasePtr( wndPtr );
1966 WIN_ReleasePtr( wndPtr );
1967 WARN("Invalid offset %d\n", offset );
1968 SetLastError( ERROR_INVALID_INDEX );
1972 SERVER_START_REQ( set_window_info )
1978 req->flags = SET_WIN_STYLE;
1979 req->style = newval;
1982 req->flags = SET_WIN_EXSTYLE;
1983 req->ex_style = newval;
1986 req->flags = SET_WIN_ID;
1990 req->flags = SET_WIN_INSTANCE;
1991 req->instance = (void *)newval;
1994 req->flags = SET_WIN_USERDATA;
1995 req->user_data = (void *)newval;
1998 if ((ok = !wine_server_call_err( req )))
2003 wndPtr->dwStyle = newval;
2004 retval = reply->old_style;
2007 wndPtr->dwExStyle = newval;
2008 retval = reply->old_ex_style;
2011 wndPtr->wIDmenu = newval;
2012 retval = reply->old_id;
2015 wndPtr->hInstance = newval;
2016 retval = (HINSTANCE)reply->old_instance;
2019 wndPtr->userdata = newval;
2020 retval = (ULONG_PTR)reply->old_user_data;
2026 WIN_ReleasePtr( wndPtr );
2030 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2031 USER_Driver.pSetWindowStyle( hwnd, retval );
2033 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2034 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2041 /**********************************************************************
2042 * GetWindowLong (USER.135)
2044 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2046 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2050 /**********************************************************************
2051 * GetWindowLongA (USER32.@)
2053 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2055 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2059 /**********************************************************************
2060 * GetWindowLongW (USER32.@)
2062 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2064 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2068 /**********************************************************************
2069 * SetWindowLong (USER.136)
2071 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2073 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2077 /**********************************************************************
2078 * SetWindowLongA (USER32.@)
2080 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2082 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2086 /**********************************************************************
2087 * SetWindowLongW (USER32.@) Set window attribute
2089 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2090 * value in a window's extra memory.
2092 * The _hwnd_ parameter specifies the window. is the handle to a
2093 * window that has extra memory. The _newval_ parameter contains the
2094 * new attribute or extra memory value. If positive, the _offset_
2095 * parameter is the byte-addressed location in the window's extra
2096 * memory to set. If negative, _offset_ specifies the window
2097 * attribute to set, and should be one of the following values:
2099 * GWL_EXSTYLE The window's extended window style
2101 * GWL_STYLE The window's window style.
2103 * GWL_WNDPROC Pointer to the window's window procedure.
2105 * GWL_HINSTANCE The window's pplication instance handle.
2107 * GWL_ID The window's identifier.
2109 * GWL_USERDATA The window's user-specified data.
2111 * If the window is a dialog box, the _offset_ parameter can be one of
2112 * the following values:
2114 * DWL_DLGPROC The address of the window's dialog box procedure.
2116 * DWL_MSGRESULT The return value of a message
2117 * that the dialog box procedure processed.
2119 * DWL_USER Application specific information.
2123 * If successful, returns the previous value located at _offset_. Otherwise,
2128 * Extra memory for a window class is specified by a nonzero cbWndExtra
2129 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2130 * time of class creation.
2132 * Using GWL_WNDPROC to set a new window procedure effectively creates
2133 * a window subclass. Use CallWindowProc() in the new windows procedure
2134 * to pass messages to the superclass's window procedure.
2136 * The user data is reserved for use by the application which created
2139 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2140 * instead, call the EnableWindow() function to change the window's
2143 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2144 * SetParent() instead.
2147 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2148 * it sends WM_STYLECHANGING before changing the settings
2149 * and WM_STYLECHANGED afterwards.
2150 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2152 LONG WINAPI SetWindowLongW(
2153 HWND hwnd, /* [in] window to alter */
2154 INT offset, /* [in] offset, in bytes, of location to alter */
2155 LONG newval /* [in] new value of location */
2157 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2161 /*******************************************************************
2162 * GetWindowTextA (USER32.@)
2164 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2168 if (WIN_IsCurrentProcess( hwnd ))
2169 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2171 /* when window belongs to other process, don't send a message */
2172 if (nMaxCount <= 0) return 0;
2173 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2174 get_server_window_text( hwnd, buffer, nMaxCount );
2175 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2176 lpString[nMaxCount-1] = 0;
2177 HeapFree( GetProcessHeap(), 0, buffer );
2178 return strlen(lpString);
2182 /*******************************************************************
2183 * InternalGetWindowText (USER32.@)
2185 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2189 if (nMaxCount <= 0) return 0;
2190 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2191 if (win != WND_OTHER_PROCESS)
2193 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2194 else lpString[0] = 0;
2195 WIN_ReleasePtr( win );
2199 get_server_window_text( hwnd, lpString, nMaxCount );
2201 return strlenW(lpString);
2205 /*******************************************************************
2206 * GetWindowTextW (USER32.@)
2208 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2210 if (WIN_IsCurrentProcess( hwnd ))
2211 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2213 /* when window belongs to other process, don't send a message */
2214 if (nMaxCount <= 0) return 0;
2215 get_server_window_text( hwnd, lpString, nMaxCount );
2216 return strlenW(lpString);
2220 /*******************************************************************
2221 * SetWindowText (USER32.@)
2222 * SetWindowTextA (USER32.@)
2224 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2226 if (!WIN_IsCurrentProcess( hwnd ))
2228 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2229 SetLastError( ERROR_ACCESS_DENIED );
2232 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2236 /*******************************************************************
2237 * SetWindowTextW (USER32.@)
2239 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2241 if (!WIN_IsCurrentProcess( hwnd ))
2243 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2244 SetLastError( ERROR_ACCESS_DENIED );
2247 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2251 /*******************************************************************
2252 * GetWindowTextLengthA (USER32.@)
2254 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2256 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2259 /*******************************************************************
2260 * GetWindowTextLengthW (USER32.@)
2262 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2264 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2268 /*******************************************************************
2269 * IsWindow (USER32.@)
2271 BOOL WINAPI IsWindow( HWND hwnd )
2276 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2278 if (ptr != WND_OTHER_PROCESS)
2280 WIN_ReleasePtr( ptr );
2284 /* check other processes */
2285 SERVER_START_REQ( get_window_info )
2288 ret = !wine_server_call_err( req );
2295 /***********************************************************************
2296 * GetWindowThreadProcessId (USER32.@)
2298 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2303 if (!(ptr = WIN_GetPtr( hwnd )))
2305 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2309 if (ptr != WND_OTHER_PROCESS)
2311 /* got a valid window */
2313 if (process) *process = GetCurrentProcessId();
2314 WIN_ReleasePtr( ptr );
2318 /* check other processes */
2319 SERVER_START_REQ( get_window_info )
2322 if (!wine_server_call_err( req ))
2324 tid = (DWORD)reply->tid;
2325 if (process) *process = (DWORD)reply->pid;
2333 /*****************************************************************
2334 * GetParent (USER32.@)
2336 HWND WINAPI GetParent( HWND hwnd )
2341 if (!(wndPtr = WIN_GetPtr( hwnd )))
2343 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2346 if (wndPtr == WND_OTHER_PROCESS)
2348 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2349 if (style & (WS_POPUP | WS_CHILD))
2351 SERVER_START_REQ( get_window_tree )
2354 if (!wine_server_call_err( req ))
2356 if (style & WS_CHILD) retvalue = reply->parent;
2357 else retvalue = reply->owner;
2365 if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2366 else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2367 WIN_ReleasePtr( wndPtr );
2373 /*****************************************************************
2374 * GetAncestor (USER32.@)
2376 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2379 HWND *list, ret = 0;
2381 if (type == GA_PARENT)
2383 if (!(win = WIN_GetPtr( hwnd )))
2385 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2388 if (win != WND_OTHER_PROCESS)
2391 WIN_ReleasePtr( win );
2393 else /* need to query the server */
2395 SERVER_START_REQ( get_window_tree )
2398 if (!wine_server_call_err( req )) ret = reply->parent;
2405 if (!(list = WIN_ListParents( hwnd ))) return 0;
2407 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2411 while (list[count]) count++;
2412 ret = list[count - 2]; /* get the one before the desktop */
2414 HeapFree( GetProcessHeap(), 0, list );
2416 if (ret && type == GA_ROOTOWNER)
2420 HWND owner = GetWindow( ret, GW_OWNER );
2429 /*****************************************************************
2430 * SetParent (USER32.@)
2432 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2435 HWND retvalue, full_handle;
2438 if (!parent) parent = GetDesktopWindow();
2439 else parent = WIN_GetFullHandle( parent );
2441 if (!IsWindow( parent ))
2443 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2447 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2448 return SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2452 if (USER_Driver.pSetParent)
2453 return USER_Driver.pSetParent( hwnd, parent );
2455 /* Windows hides the window first, then shows it again
2456 * including the WM_SHOWWINDOW messages and all */
2457 was_visible = ShowWindow( hwnd, SW_HIDE );
2459 if (!IsWindow( parent )) return 0;
2460 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2462 retvalue = wndPtr->parent; /* old parent */
2463 if (parent != retvalue)
2465 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2467 if (parent != GetDesktopWindow()) /* a child window */
2469 if (!(wndPtr->dwStyle & WS_CHILD))
2471 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2472 if (menu) DestroyMenu( menu );
2476 WIN_ReleasePtr( wndPtr );
2478 /* SetParent additionally needs to make hwnd the topmost window
2479 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2480 WM_WINDOWPOSCHANGED notification messages.
2482 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2483 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2484 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2485 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2490 /*******************************************************************
2491 * IsChild (USER32.@)
2493 BOOL WINAPI IsChild( HWND parent, HWND child )
2495 HWND *list = WIN_ListParents( child );
2499 if (!list) return FALSE;
2500 parent = WIN_GetFullHandle( parent );
2501 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2502 ret = (list[i] != 0);
2503 HeapFree( GetProcessHeap(), 0, list );
2508 /***********************************************************************
2509 * IsWindowVisible (USER32.@)
2511 BOOL WINAPI IsWindowVisible( HWND hwnd )
2517 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2518 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2519 for (i = 0; list[i]; i++)
2520 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2522 HeapFree( GetProcessHeap(), 0, list );
2527 /***********************************************************************
2528 * WIN_IsWindowDrawable
2530 * hwnd is drawable when it is visible, all parents are not
2531 * minimized, and it is itself not minimized unless we are
2532 * trying to draw its default class icon.
2534 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2539 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2541 if (!(style & WS_VISIBLE)) return FALSE;
2542 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2544 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2545 for (i = 0; list[i]; i++)
2546 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2549 HeapFree( GetProcessHeap(), 0, list );
2554 /*******************************************************************
2555 * GetTopWindow (USER32.@)
2557 HWND WINAPI GetTopWindow( HWND hwnd )
2559 if (!hwnd) hwnd = GetDesktopWindow();
2560 return GetWindow( hwnd, GW_CHILD );
2564 /*******************************************************************
2565 * GetWindow (USER32.@)
2567 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2571 if (rel == GW_OWNER) /* this one may be available locally */
2573 WND *wndPtr = WIN_GetPtr( hwnd );
2576 SetLastError( ERROR_INVALID_HANDLE );
2579 if (wndPtr != WND_OTHER_PROCESS)
2581 retval = wndPtr->owner;
2582 WIN_ReleasePtr( wndPtr );
2585 /* else fall through to server call */
2588 SERVER_START_REQ( get_window_tree )
2591 if (!wine_server_call_err( req ))
2596 retval = reply->first_sibling;
2599 retval = reply->last_sibling;
2602 retval = reply->next_sibling;
2605 retval = reply->prev_sibling;
2608 retval = reply->owner;
2611 retval = reply->first_child;
2621 /***********************************************************************
2622 * WIN_InternalShowOwnedPopups
2624 * Internal version of ShowOwnedPopups; Wine functions should use this
2625 * to avoid interfering with application calls to ShowOwnedPopups
2626 * and to make sure the application can't prevent showing/hiding.
2628 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2632 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2636 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2638 if (!win_array) return TRUE;
2641 * Show windows Lowest first, Highest last to preserve Z-Order
2643 while (win_array[count]) count++;
2644 while (--count >= 0)
2646 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2647 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2649 if (pWnd->dwStyle & WS_POPUP)
2653 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2654 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2657 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2659 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2660 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2665 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2666 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2667 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2670 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2672 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2673 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2674 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2678 WIN_ReleaseWndPtr( pWnd );
2680 HeapFree( GetProcessHeap(), 0, win_array );
2685 /*******************************************************************
2686 * ShowOwnedPopups (USER32.@)
2688 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2692 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2694 if (!win_array) return TRUE;
2696 while (win_array[count]) count++;
2697 while (--count >= 0)
2699 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2700 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2702 if (pWnd->dwStyle & WS_POPUP)
2706 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2708 /* In Windows, ShowOwnedPopups(TRUE) generates
2709 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2710 * regardless of the state of the owner
2712 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2713 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2718 if (IsWindowVisible(pWnd->hwndSelf))
2720 /* In Windows, ShowOwnedPopups(FALSE) generates
2721 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2722 * regardless of the state of the owner
2724 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2725 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2729 WIN_ReleaseWndPtr( pWnd );
2731 HeapFree( GetProcessHeap(), 0, win_array );
2736 /*******************************************************************
2737 * GetLastActivePopup (USER32.@)
2739 HWND WINAPI GetLastActivePopup( HWND hwnd )
2742 WND *wndPtr =WIN_FindWndPtr(hwnd);
2743 if (!wndPtr) return hwnd;
2744 retval = wndPtr->hwndLastActive;
2745 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2746 WIN_ReleaseWndPtr(wndPtr);
2751 /*******************************************************************
2754 * Build an array of all parents of a given window, starting with
2755 * the immediate parent. The array must be freed with HeapFree.
2756 * Returns NULL if window is a top-level window.
2758 HWND *WIN_ListParents( HWND hwnd )
2761 HWND current, *list;
2762 int pos = 0, size = 16, count = 0;
2764 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2769 if (!(win = WIN_GetPtr( current ))) goto empty;
2770 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2771 list[pos] = win->parent;
2772 WIN_ReleasePtr( win );
2773 if (!(current = list[pos]))
2775 if (!pos) goto empty;
2778 if (++pos == size - 1)
2780 /* need to grow the list */
2781 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2782 if (!new_list) goto empty;
2788 /* at least one parent belongs to another process, have to query the server */
2793 SERVER_START_REQ( get_window_parents )
2796 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2797 if (!wine_server_call( req )) count = reply->count;
2800 if (!count) goto empty;
2806 HeapFree( GetProcessHeap(), 0, list );
2808 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2812 HeapFree( GetProcessHeap(), 0, list );
2817 /*******************************************************************
2820 * Build an array of the children of a given window. The array must be
2821 * freed with HeapFree. Returns NULL when no windows are found.
2823 HWND *WIN_ListChildren( HWND hwnd )
2825 return list_window_children( hwnd, 0, 0 );
2829 /*******************************************************************
2830 * EnumWindows (USER32.@)
2832 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2838 /* We have to build a list of all windows first, to avoid */
2839 /* unpleasant side-effects, for instance if the callback */
2840 /* function changes the Z-order of the windows. */
2842 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2844 /* Now call the callback function for every window */
2846 iWndsLocks = WIN_SuspendWndsLock();
2847 for (i = 0; list[i]; i++)
2849 /* Make sure that the window still exists */
2850 if (!IsWindow( list[i] )) continue;
2851 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2853 WIN_RestoreWndsLock(iWndsLocks);
2854 HeapFree( GetProcessHeap(), 0, list );
2859 /**********************************************************************
2860 * EnumTaskWindows16 (USER.225)
2862 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2865 TDB *tdb = TASK_GetPtr( hTask );
2866 if (!tdb) return FALSE;
2867 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2871 /**********************************************************************
2872 * EnumThreadWindows (USER32.@)
2874 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2879 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2882 /* Now call the callback function for every window */
2884 iWndsLocks = WIN_SuspendWndsLock();
2885 for (i = 0; list[i]; i++)
2886 if (!func( list[i], lParam )) break;
2887 WIN_RestoreWndsLock(iWndsLocks);
2888 HeapFree( GetProcessHeap(), 0, list );
2893 /**********************************************************************
2894 * WIN_EnumChildWindows
2896 * Helper function for EnumChildWindows().
2898 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2903 for ( ; *list; list++)
2905 /* Make sure that the window still exists */
2906 if (!IsWindow( *list )) continue;
2907 /* skip owned windows */
2908 if (GetWindow( *list, GW_OWNER )) continue;
2909 /* Build children list first */
2910 childList = WIN_ListChildren( *list );
2912 ret = func( *list, lParam );
2916 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2917 HeapFree( GetProcessHeap(), 0, childList );
2919 if (!ret) return FALSE;
2925 /**********************************************************************
2926 * EnumChildWindows (USER32.@)
2928 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2933 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2934 iWndsLocks = WIN_SuspendWndsLock();
2935 WIN_EnumChildWindows( list, func, lParam );
2936 WIN_RestoreWndsLock(iWndsLocks);
2937 HeapFree( GetProcessHeap(), 0, list );
2942 /*******************************************************************
2943 * AnyPopup (USER.52)
2945 BOOL16 WINAPI AnyPopup16(void)
2951 /*******************************************************************
2952 * AnyPopup (USER32.@)
2954 BOOL WINAPI AnyPopup(void)
2958 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2960 if (!list) return FALSE;
2961 for (i = 0; list[i]; i++)
2963 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2965 retvalue = (list[i] != 0);
2966 HeapFree( GetProcessHeap(), 0, list );
2971 /*******************************************************************
2972 * FlashWindow (USER32.@)
2974 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2976 WND *wndPtr = WIN_FindWndPtr(hWnd);
2978 TRACE("%04x\n", hWnd);
2980 if (!wndPtr) return FALSE;
2981 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2983 if (wndPtr->dwStyle & WS_MINIMIZE)
2985 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2987 HDC hDC = GetDC(hWnd);
2989 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2990 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2992 ReleaseDC( hWnd, hDC );
2993 wndPtr->flags |= WIN_NCACTIVATED;
2997 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2998 wndPtr->flags &= ~WIN_NCACTIVATED;
3000 WIN_ReleaseWndPtr(wndPtr);
3006 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3007 else wparam = (hWnd == GetActiveWindow());
3009 WIN_ReleaseWndPtr(wndPtr);
3010 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3016 /*******************************************************************
3017 * GetWindowContextHelpId (USER32.@)
3019 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3022 WND *wnd = WIN_FindWndPtr( hwnd );
3024 retval = wnd->helpContext;
3025 WIN_ReleaseWndPtr(wnd);
3030 /*******************************************************************
3031 * SetWindowContextHelpId (USER32.@)
3033 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3035 WND *wnd = WIN_FindWndPtr( hwnd );
3036 if (!wnd) return FALSE;
3037 wnd->helpContext = id;
3038 WIN_ReleaseWndPtr(wnd);
3043 /*******************************************************************
3046 * recursively find a child that contains spDragInfo->pt point
3047 * and send WM_QUERYDROPOBJECT
3049 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3051 BOOL16 wParam, bResult = 0;
3053 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3056 if (!ptrDragInfo) return FALSE;
3058 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3060 GetWindowRect(hQueryWnd,&tempRect);
3062 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3064 if (!IsIconic( hQueryWnd ))
3066 GetClientRect( hQueryWnd, &tempRect );
3067 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3069 if (PtInRect( &tempRect, pt))
3072 HWND *list = WIN_ListChildren( hQueryWnd );
3078 for (i = 0; list[i]; i++)
3080 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3082 GetWindowRect( list[i], &tempRect );
3083 if (PtInRect( &tempRect, pt )) break;
3088 if (IsWindowEnabled( list[i] ))
3089 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
3091 HeapFree( GetProcessHeap(), 0, list );
3093 if(bResult) return bResult;
3099 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3101 ptrDragInfo->hScope = hQueryWnd;
3103 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3104 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3106 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3112 /*******************************************************************
3113 * DragDetect (USER32.@)
3115 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3120 rect.left = pt.x - wDragWidth;
3121 rect.right = pt.x + wDragWidth;
3123 rect.top = pt.y - wDragHeight;
3124 rect.bottom = pt.y + wDragHeight;
3130 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3132 if( msg.message == WM_LBUTTONUP )
3137 if( msg.message == WM_MOUSEMOVE )
3140 tmp.x = LOWORD(msg.lParam);
3141 tmp.y = HIWORD(msg.lParam);
3142 if( !PtInRect( &rect, tmp ))
3154 /******************************************************************************
3155 * DragObject (USER.464)
3157 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3158 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3161 LPDRAGINFO16 lpDragInfo;
3163 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3164 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3165 HCURSOR16 hCurrentCursor = 0;
3166 HWND16 hCurrentWnd = 0;
3168 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3169 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3171 if( !lpDragInfo || !spDragInfo ) return 0L;
3173 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3175 GlobalFree16(hDragInfo);
3181 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3183 GlobalFree16(hDragInfo);
3187 if( hDragCursor == hCursor ) hDragCursor = 0;
3188 else hCursor = hDragCursor;
3190 hOldCursor = SetCursor(hDragCursor);
3193 lpDragInfo->hWnd = hWnd;
3194 lpDragInfo->hScope = 0;
3195 lpDragInfo->wFlags = wObj;
3196 lpDragInfo->hList = szList; /* near pointer! */
3197 lpDragInfo->hOfStruct = hOfStruct;
3205 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3207 *(lpDragInfo+1) = *lpDragInfo;
3209 lpDragInfo->pt.x = msg.pt.x;
3210 lpDragInfo->pt.y = msg.pt.y;
3212 /* update DRAGINFO struct */
3213 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3215 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3216 hCurrentCursor = hCursor;
3219 hCurrentCursor = hBummer;
3220 lpDragInfo->hScope = 0;
3222 if( hCurrentCursor )
3223 SetCursor(hCurrentCursor);
3225 /* send WM_DRAGLOOP */
3226 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3227 (LPARAM) spDragInfo );
3228 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3229 if( hCurrentWnd != lpDragInfo->hScope )
3232 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3233 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3234 HIWORD(spDragInfo)) );
3235 hCurrentWnd = lpDragInfo->hScope;
3237 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3241 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3243 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3246 ShowCursor( FALSE );
3250 SetCursor( hOldCursor );
3251 if (hDragCursor) DestroyCursor( hDragCursor );
3254 if( hCurrentCursor != hBummer )
3255 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3256 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3259 GlobalFree16(hDragInfo);
3261 return (DWORD)(msg.lParam);
3265 /******************************************************************************
3266 * GetWindowModuleFileNameA (USER32.@)
3268 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3270 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3271 hwnd, lpszFileName, cchFileNameMax);
3275 /******************************************************************************
3276 * GetWindowModuleFileNameW (USER32.@)
3278 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3280 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3281 hwnd, lpszFileName, cchFileNameMax);