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"
19 #include "cursoricon.h"
26 #include "stackframe.h"
27 #include "debugtools.h"
29 DEFAULT_DEBUG_CHANNEL(win);
30 DECLARE_DEBUG_CHANNEL(msg);
32 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
34 /**********************************************************************/
37 static WND *pWndDesktop = NULL;
39 static WORD wDragWidth = 4;
40 static WORD wDragHeight= 3;
42 static void *user_handles[NB_USER_HANDLES];
45 extern SYSLEVEL USER_SysLevel; /* FIXME */
47 /***********************************************************************
50 * Suspend the lock on WND structures.
51 * Returns the number of locks suspended
53 int WIN_SuspendWndsLock( void )
55 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
56 int count = isuspendedLocks;
59 _LeaveSysLevel( &USER_SysLevel );
61 return isuspendedLocks;
64 /***********************************************************************
67 * Restore the suspended locks on WND structures
69 void WIN_RestoreWndsLock( int ipreviousLocks )
71 while ( ipreviousLocks-- > 0 )
72 _EnterSysLevel( &USER_SysLevel );
75 /***********************************************************************
76 * create_window_handle
78 * Create a window handle with the server.
80 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
83 user_handle_t handle = 0;
85 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
87 if (!win) return NULL;
91 SERVER_START_REQ( create_window )
96 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
103 HeapFree( GetProcessHeap(), 0, win );
106 index = LOWORD(handle) - FIRST_USER_HANDLE;
107 assert( index < NB_USER_HANDLES );
108 user_handles[index] = win;
109 win->hwndSelf = handle;
110 win->dwMagic = WND_MAGIC;
116 /***********************************************************************
119 * Free a window handle.
121 static WND *free_window_handle( HWND hwnd )
124 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
126 if (index >= NB_USER_HANDLES) return NULL;
128 if ((ptr = user_handles[index]))
130 SERVER_START_REQ( destroy_window )
133 if (!wine_server_call_err( req ))
134 user_handles[index] = NULL;
141 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
146 /*******************************************************************
147 * list_window_children
149 * Build an array of the children of a given window. The array must be
150 * freed with HeapFree. Returns NULL when no windows are found.
152 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
161 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
163 SERVER_START_REQ( get_window_children )
167 req->tid = (void *)tid;
168 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
169 if (!wine_server_call( req )) count = reply->count;
172 if (count && count < size)
177 HeapFree( GetProcessHeap(), 0, list );
179 size = count + 1; /* restart with a large enough buffer */
185 /*******************************************************************
188 static void send_parent_notify( HWND hwnd, UINT msg )
190 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
191 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
192 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
193 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
197 /*******************************************************************
198 * get_server_window_text
200 * Retrieve the window text from the server.
202 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
206 SERVER_START_REQ( get_window_text )
209 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
210 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
213 text[len / sizeof(WCHAR)] = 0;
217 /***********************************************************************
220 * Return a pointer to the WND structure if local to the process,
221 * or WND_OTHER_PROCESS is handle may be valid in other process.
222 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
224 WND *WIN_GetPtr( HWND hwnd )
227 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
229 if (index >= NB_USER_HANDLES) return NULL;
232 if ((ptr = user_handles[index]))
234 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
238 else ptr = WND_OTHER_PROCESS;
244 /***********************************************************************
245 * WIN_IsCurrentProcess
247 * Check whether a given window belongs to the current process (and return the full handle).
249 HWND WIN_IsCurrentProcess( HWND hwnd )
254 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
256 WIN_ReleasePtr( ptr );
261 /***********************************************************************
262 * WIN_IsCurrentThread
264 * Check whether a given window belongs to the current thread (and return the full handle).
266 HWND WIN_IsCurrentThread( HWND hwnd )
271 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
273 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
274 WIN_ReleasePtr( ptr );
280 /***********************************************************************
283 * Convert a 16-bit window handle to a full 32-bit handle.
285 HWND WIN_Handle32( HWND16 hwnd16 )
288 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
290 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
291 /* do sign extension for -2 and -3 */
292 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
294 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
296 if (ptr != WND_OTHER_PROCESS)
298 hwnd = ptr->hwndSelf;
299 WIN_ReleasePtr( ptr );
301 else /* may belong to another process */
303 SERVER_START_REQ( get_window_info )
306 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
314 /***********************************************************************
317 * Return a pointer to the WND structure corresponding to a HWND.
319 WND * WIN_FindWndPtr( HWND hwnd )
323 if (!hwnd) return NULL;
325 if ((ptr = WIN_GetPtr( hwnd )))
327 if (ptr != WND_OTHER_PROCESS)
329 /* increment destruction monitoring */
333 if (IsWindow( hwnd )) /* check other processes */
335 ERR( "window %04x belongs to other process\n", hwnd );
336 /* DbgBreakPoint(); */
339 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
344 /***********************************************************************
347 * Release the pointer to the WND structure.
349 void WIN_ReleaseWndPtr(WND *wndPtr)
353 /* Decrement destruction monitoring value */
355 /* Check if it's time to release the memory */
356 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
359 free_window_handle( wndPtr->hwndSelf );
361 else if(wndPtr->irefCount < 0)
363 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
364 ERR("forgot a Lock on %p somewhere\n",wndPtr);
366 /* unlock all WND structures for thread safeness */
371 /***********************************************************************
374 * Remove a window from the siblings linked list.
376 void WIN_UnlinkWindow( HWND hwnd )
378 WIN_LinkWindow( hwnd, 0, 0 );
382 /***********************************************************************
385 * Insert a window into the siblings linked list.
386 * The window is inserted after the specified window, which can also
387 * be specified as HWND_TOP or HWND_BOTTOM.
388 * If parent is 0, window is unlinked from the tree.
390 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
392 WND *wndPtr = WIN_GetPtr( hwnd );
395 if (wndPtr == WND_OTHER_PROCESS)
397 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
401 SERVER_START_REQ( link_window )
404 req->parent = parent;
405 req->previous = hwndInsertAfter;
406 if (!wine_server_call( req ))
408 if (reply->full_parent && reply->full_parent != wndPtr->parent)
410 wndPtr->owner = 0; /* reset owner when changing parent */
411 wndPtr->parent = reply->full_parent;
417 WIN_ReleasePtr( wndPtr );
421 /***********************************************************************
424 * Change the owner of a window.
426 void WIN_SetOwner( HWND hwnd, HWND owner )
428 WND *win = WIN_GetPtr( hwnd );
431 if (win == WND_OTHER_PROCESS)
433 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
436 SERVER_START_REQ( set_window_owner )
440 if (!wine_server_call( req )) win->owner = reply->full_owner;
443 WIN_ReleasePtr( win );
447 /***********************************************************************
450 * Change the style of a window.
452 LONG WIN_SetStyle( HWND hwnd, LONG style )
456 WND *win = WIN_GetPtr( hwnd );
459 if (win == WND_OTHER_PROCESS)
462 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
465 if (style == win->dwStyle)
467 WIN_ReleasePtr( win );
470 SERVER_START_REQ( set_window_info )
473 req->flags = SET_WIN_STYLE;
475 if ((ok = !wine_server_call( req )))
477 ret = reply->old_style;
478 win->dwStyle = style;
482 WIN_ReleasePtr( win );
483 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
488 /***********************************************************************
491 * Change the extended style of a window.
493 LONG WIN_SetExStyle( HWND hwnd, LONG style )
496 WND *win = WIN_GetPtr( hwnd );
499 if (win == WND_OTHER_PROCESS)
502 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
505 if (style == win->dwExStyle)
507 WIN_ReleasePtr( win );
510 SERVER_START_REQ( set_window_info )
513 req->flags = SET_WIN_EXSTYLE;
514 req->ex_style = style;
515 if (!wine_server_call( req ))
517 ret = reply->old_ex_style;
518 win->dwExStyle = style;
522 WIN_ReleasePtr( win );
527 /***********************************************************************
530 * Set the window and client rectangles.
532 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
534 WND *win = WIN_GetPtr( hwnd );
538 if (win == WND_OTHER_PROCESS)
540 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
543 SERVER_START_REQ( set_window_rectangles )
546 req->window.left = rectWindow->left;
547 req->window.top = rectWindow->top;
548 req->window.right = rectWindow->right;
549 req->window.bottom = rectWindow->bottom;
550 req->client.left = rectClient->left;
551 req->client.top = rectClient->top;
552 req->client.right = rectClient->right;
553 req->client.bottom = rectClient->bottom;
554 ret = !wine_server_call( req );
559 win->rectWindow = *rectWindow;
560 win->rectClient = *rectClient;
562 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
563 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
564 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
566 WIN_ReleasePtr( win );
570 /***********************************************************************
573 * Get the window and client rectangles.
575 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
577 WND *win = WIN_GetPtr( hwnd );
580 if (!win) return FALSE;
581 if (win == WND_OTHER_PROCESS)
583 SERVER_START_REQ( get_window_rectangles )
586 if ((ret = !wine_server_call( req )))
590 rectWindow->left = reply->window.left;
591 rectWindow->top = reply->window.top;
592 rectWindow->right = reply->window.right;
593 rectWindow->bottom = reply->window.bottom;
597 rectClient->left = reply->client.left;
598 rectClient->top = reply->client.top;
599 rectClient->right = reply->client.right;
600 rectClient->bottom = reply->client.bottom;
608 if (rectWindow) *rectWindow = win->rectWindow;
609 if (rectClient) *rectClient = win->rectClient;
610 WIN_ReleasePtr( win );
616 /***********************************************************************
619 * Destroy storage associated to a window. "Internals" p.358
621 LRESULT WIN_DestroyWindow( HWND hwnd )
626 TRACE("%04x\n", hwnd );
628 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
630 ERR( "window doesn't belong to current thread\n" );
634 /* free child windows */
635 if ((list = WIN_ListChildren( hwnd )))
638 for (i = 0; list[i]; i++)
640 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
641 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
643 HeapFree( GetProcessHeap(), 0, list );
647 * Clear the update region to make sure no WM_PAINT messages will be
648 * generated for this window while processing the WM_NCDESTROY.
650 RedrawWindow( hwnd, NULL, 0,
651 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
654 * Send the WM_NCDESTROY to the window being destroyed.
656 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
658 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
660 WINPOS_CheckInternalPos( hwnd );
661 if( hwnd == GetCapture()) ReleaseCapture();
663 /* free resources associated with the window */
665 TIMER_RemoveWindowTimers( hwnd );
667 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
668 wndPtr->hmemTaskQ = 0;
670 if (!(wndPtr->dwStyle & WS_CHILD))
672 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
673 if (menu) DestroyMenu( menu );
675 if (wndPtr->hSysMenu)
677 DestroyMenu( wndPtr->hSysMenu );
678 wndPtr->hSysMenu = 0;
680 USER_Driver.pDestroyWindow( hwnd );
681 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
682 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
683 CLASS_RemoveWindow( wndPtr->class );
684 wndPtr->class = NULL;
685 wndPtr->dwMagic = 0; /* Mark it as invalid */
686 WIN_ReleaseWndPtr( wndPtr );
690 /***********************************************************************
691 * WIN_DestroyThreadWindows
693 * Destroy all children of 'wnd' owned by the current thread.
694 * Return TRUE if something was done.
696 void WIN_DestroyThreadWindows( HWND hwnd )
701 if (!(list = WIN_ListChildren( hwnd ))) return;
702 for (i = 0; list[i]; i++)
704 if (WIN_IsCurrentThread( list[i] ))
705 DestroyWindow( list[i] );
707 WIN_DestroyThreadWindows( list[i] );
709 HeapFree( GetProcessHeap(), 0, list );
712 /***********************************************************************
713 * WIN_CreateDesktopWindow
715 * Create the desktop window.
717 BOOL WIN_CreateDesktopWindow(void)
719 struct tagCLASS *class;
728 TRACE("Creating desktop window\n");
730 if (!WINPOS_CreateInternalPosAtom() ||
731 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
732 &wndExtra, &winproc, &clsStyle, &dce )))
735 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
736 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
737 if (!pWndDesktop) return FALSE;
738 hwndDesktop = pWndDesktop->hwndSelf;
740 pWndDesktop->tid = 0; /* nobody owns the desktop */
741 pWndDesktop->parent = 0;
742 pWndDesktop->owner = 0;
743 pWndDesktop->class = class;
744 pWndDesktop->hInstance = 0;
745 pWndDesktop->text = NULL;
746 pWndDesktop->hmemTaskQ = 0;
747 pWndDesktop->hrgnUpdate = 0;
748 pWndDesktop->hwndLastActive = hwndDesktop;
749 pWndDesktop->dwStyle = 0;
750 pWndDesktop->dwExStyle = 0;
751 pWndDesktop->clsStyle = clsStyle;
752 pWndDesktop->dce = NULL;
753 pWndDesktop->pVScroll = NULL;
754 pWndDesktop->pHScroll = NULL;
755 pWndDesktop->wIDmenu = 0;
756 pWndDesktop->helpContext = 0;
757 pWndDesktop->flags = 0;
758 pWndDesktop->hSysMenu = 0;
759 pWndDesktop->userdata = 0;
760 pWndDesktop->winproc = winproc;
761 pWndDesktop->cbWndExtra = wndExtra;
763 cs.lpCreateParams = NULL;
769 cs.cx = GetSystemMetrics( SM_CXSCREEN );
770 cs.cy = GetSystemMetrics( SM_CYSCREEN );
771 cs.style = pWndDesktop->dwStyle;
772 cs.dwExStyle = pWndDesktop->dwExStyle;
774 cs.lpszClass = DESKTOP_CLASS_ATOM;
776 SetRect( &rect, 0, 0, cs.cx, cs.cy );
777 WIN_SetRectangles( hwndDesktop, &rect, &rect );
778 WIN_SetStyle( hwndDesktop, WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
780 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
782 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
783 WIN_ReleaseWndPtr( pWndDesktop );
788 /***********************************************************************
791 * Fix the coordinates - Helper for WIN_CreateWindowEx.
792 * returns default show mode in sw.
793 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
795 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
797 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
798 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
800 if (cs->style & (WS_CHILD | WS_POPUP))
802 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
803 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
805 else /* overlapped window */
809 GetStartupInfoA( &info );
811 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
813 /* Never believe Microsoft's documentation... CreateWindowEx doc says
814 * that if an overlapped window is created with WS_VISIBLE style bit
815 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
816 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
819 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
820 * 2) it does not ignore the y parameter as the docs claim; instead, it
821 * uses it as second parameter to ShowWindow() unless y is either
822 * CW_USEDEFAULT or CW_USEDEFAULT16.
824 * The fact that we didn't do 2) caused bogus windows pop up when wine
825 * was running apps that were using this obscure feature. Example -
826 * calc.exe that comes with Win98 (only Win98, it's different from
827 * the one that comes with Win95 and NT)
829 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
830 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
831 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
834 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
836 if (info.dwFlags & STARTF_USESIZE)
838 cs->cx = info.dwXSize;
839 cs->cy = info.dwYSize;
841 else /* if no other hint from the app, pick 3/4 of the screen real estate */
844 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
845 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
846 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
853 /* neither x nor cx are default. Check the y values .
854 * In the trace we see Outlook and Outlook Express using
855 * cy set to CW_USEDEFAULT when opening the address book.
857 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
859 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
860 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
861 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
866 /***********************************************************************
869 static void dump_window_styles( DWORD style, DWORD exstyle )
872 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
873 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
874 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
875 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
876 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
877 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
878 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
879 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
880 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
883 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
884 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
886 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
887 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
888 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
889 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
890 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
891 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
892 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
893 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
895 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
896 #define DUMPED_STYLES \
916 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
921 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
922 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
923 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
924 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
925 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
926 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
927 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
928 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
929 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
930 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
931 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
932 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
933 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
934 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
935 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
936 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
937 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
938 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
940 #define DUMPED_EX_STYLES \
941 (WS_EX_DLGMODALFRAME | \
943 WS_EX_NOPARENTNOTIFY | \
945 WS_EX_ACCEPTFILES | \
946 WS_EX_TRANSPARENT | \
951 WS_EX_CONTEXTHELP | \
954 WS_EX_LEFTSCROLLBAR | \
955 WS_EX_CONTROLPARENT | \
960 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
962 #undef DUMPED_EX_STYLES
966 /***********************************************************************
969 * Implementation of CreateWindowEx().
971 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
972 WINDOWPROCTYPE type )
975 struct tagCLASS *classPtr;
977 HWND hwnd, parent, owner;
982 BOOL unicode = (type == WIN_PROC_32W);
984 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
985 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
986 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
987 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
988 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
990 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
992 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
993 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
995 /* Find the parent window */
997 parent = GetDesktopWindow();
1001 /* Make sure parent is valid */
1002 if (!IsWindow( cs->hwndParent ))
1004 WARN("Bad parent %04x\n", cs->hwndParent );
1007 if (cs->style & WS_CHILD) parent = WIN_GetFullHandle(cs->hwndParent);
1008 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
1010 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
1012 WARN("No parent for child window\n" );
1013 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1016 /* Find the window class */
1017 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1018 &wndExtra, &winproc, &clsStyle, &dce )))
1020 WARN("Bad class '%s'\n", cs->lpszClass );
1024 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1026 /* Correct the window style - stage 1
1028 * These are patches that appear to affect both the style loaded into the
1029 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1031 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1032 * why does the user get to set it?
1035 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1036 * tested for WS_POPUP
1038 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1039 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1040 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1041 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1043 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1045 /* Create the window structure */
1047 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1048 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1050 TRACE("out of memory\n" );
1053 hwnd = wndPtr->hwndSelf;
1055 /* Fill the window structure */
1057 wndPtr->tid = GetCurrentThreadId();
1058 wndPtr->owner = owner;
1059 wndPtr->parent = parent;
1060 wndPtr->class = classPtr;
1061 wndPtr->winproc = winproc;
1062 wndPtr->hInstance = cs->hInstance;
1063 wndPtr->text = NULL;
1064 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
1065 wndPtr->hrgnUpdate = 0;
1066 wndPtr->hrgnWnd = 0;
1067 wndPtr->hwndLastActive = hwnd;
1068 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1069 wndPtr->dwExStyle = cs->dwExStyle;
1070 wndPtr->clsStyle = clsStyle;
1071 wndPtr->wIDmenu = 0;
1072 wndPtr->helpContext = 0;
1073 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1074 wndPtr->pVScroll = NULL;
1075 wndPtr->pHScroll = NULL;
1076 wndPtr->userdata = 0;
1077 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1078 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1079 wndPtr->cbWndExtra = wndExtra;
1081 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1083 /* Correct the window style - stage 2 */
1085 if (!(cs->style & WS_CHILD))
1087 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1088 if (!(cs->style & WS_POPUP))
1090 wndPtr->dwStyle |= WS_CAPTION;
1091 wndPtr->flags |= WIN_NEED_SIZE;
1094 SERVER_START_REQ( set_window_info )
1097 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1098 req->style = wndPtr->dwStyle;
1099 req->ex_style = wndPtr->dwExStyle;
1100 req->instance = (void *)wndPtr->hInstance;
1101 wine_server_call( req );
1105 /* Get class or window DC if needed */
1107 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1108 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1109 else wndPtr->dce = NULL;
1111 /* Set the window menu */
1113 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1115 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1118 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1121 if (HIWORD(cs->hInstance))
1122 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1124 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1126 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1130 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1131 WIN_ReleaseWndPtr( wndPtr );
1133 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1135 WIN_DestroyWindow( hwnd );
1139 /* Notify the parent window only */
1141 send_parent_notify( hwnd, WM_CREATE );
1142 if (!IsWindow( hwnd )) return 0;
1144 if (cs->style & WS_VISIBLE)
1146 /* in case WS_VISIBLE got set in the meantime */
1147 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1148 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1149 WIN_ReleasePtr( wndPtr );
1150 ShowWindow( hwnd, sw );
1153 /* Call WH_SHELL hook */
1155 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1156 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1158 TRACE("created window %04x\n", hwnd);
1163 /***********************************************************************
1164 * CreateWindow (USER.41)
1166 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1167 DWORD style, INT16 x, INT16 y, INT16 width,
1168 INT16 height, HWND16 parent, HMENU16 menu,
1169 HINSTANCE16 instance, LPVOID data )
1171 return CreateWindowEx16( 0, className, windowName, style,
1172 x, y, width, height, parent, menu, instance, data );
1176 /***********************************************************************
1177 * CreateWindowEx (USER.452)
1179 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1180 LPCSTR windowName, DWORD style, INT16 x,
1181 INT16 y, INT16 width, INT16 height,
1182 HWND16 parent, HMENU16 menu,
1183 HINSTANCE16 instance, LPVOID data )
1189 /* Find the class atom */
1191 if (HIWORD(className))
1193 if (!(classAtom = GlobalFindAtomA( className )))
1195 ERR( "bad class name %s\n", debugres_a(className) );
1201 classAtom = LOWORD(className);
1202 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1204 ERR( "bad atom %x\n", classAtom);
1210 /* Fix the coordinates */
1212 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1213 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1214 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1215 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1217 /* Create the window */
1219 cs.lpCreateParams = data;
1220 cs.hInstance = (HINSTANCE)instance;
1221 cs.hMenu = (HMENU)menu;
1222 cs.hwndParent = WIN_Handle32( parent );
1224 cs.lpszName = windowName;
1225 cs.lpszClass = className;
1226 cs.dwExStyle = exStyle;
1228 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1232 /***********************************************************************
1233 * CreateWindowExA (USER32.@)
1235 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1236 LPCSTR windowName, DWORD style, INT x,
1237 INT y, INT width, INT height,
1238 HWND parent, HMENU menu,
1239 HINSTANCE instance, LPVOID data )
1246 instance=GetModuleHandleA(NULL);
1248 if(exStyle & WS_EX_MDICHILD)
1249 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1251 /* Find the class atom */
1253 if (HIWORD(className))
1255 if (!(classAtom = GlobalFindAtomA( className )))
1257 ERR( "bad class name %s\n", debugres_a(className) );
1263 classAtom = LOWORD(className);
1264 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1266 ERR( "bad atom %x\n", classAtom);
1272 /* Create the window */
1274 cs.lpCreateParams = data;
1275 cs.hInstance = instance;
1277 cs.hwndParent = parent;
1283 cs.lpszName = windowName;
1284 cs.lpszClass = className;
1285 cs.dwExStyle = exStyle;
1287 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1291 /***********************************************************************
1292 * CreateWindowExW (USER32.@)
1294 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1295 LPCWSTR windowName, DWORD style, INT x,
1296 INT y, INT width, INT height,
1297 HWND parent, HMENU menu,
1298 HINSTANCE instance, LPVOID data )
1305 instance=GetModuleHandleA(NULL);
1307 if(exStyle & WS_EX_MDICHILD)
1308 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1310 /* Find the class atom */
1312 if (HIWORD(className))
1314 if (!(classAtom = GlobalFindAtomW( className )))
1316 ERR( "bad class name %s\n", debugres_w(className) );
1322 classAtom = LOWORD(className);
1323 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1325 ERR( "bad atom %x\n", classAtom);
1331 /* Create the window */
1333 cs.lpCreateParams = data;
1334 cs.hInstance = instance;
1336 cs.hwndParent = parent;
1342 cs.lpszName = windowName;
1343 cs.lpszClass = className;
1344 cs.dwExStyle = exStyle;
1346 /* Note: we rely on the fact that CREATESTRUCTA and */
1347 /* CREATESTRUCTW have the same layout. */
1348 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1352 /***********************************************************************
1353 * WIN_SendDestroyMsg
1355 static void WIN_SendDestroyMsg( HWND hwnd )
1357 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1358 if (USER_Driver.pResetSelectionOwner)
1359 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1362 * Send the WM_DESTROY to the window.
1364 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1367 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1368 * make sure that the window still exists when we come back.
1375 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1377 /* start from the end (FIXME: is this needed?) */
1378 for (i = 0; pWndArray[i]; i++) ;
1382 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1384 HeapFree( GetProcessHeap(), 0, pWndArray );
1387 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1391 /***********************************************************************
1392 * DestroyWindow (USER32.@)
1394 BOOL WINAPI DestroyWindow( HWND hwnd )
1399 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1401 SetLastError( ERROR_ACCESS_DENIED );
1405 TRACE("(%04x)\n", hwnd);
1407 /* Look whether the focus is within the tree of windows we will
1411 if (h == hwnd || IsChild( hwnd, h ))
1413 HWND parent = GetAncestor( hwnd, GA_PARENT );
1414 if (parent == GetDesktopWindow()) parent = 0;
1420 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1422 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1426 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1427 send_parent_notify( hwnd, WM_DESTROY );
1429 else if (!GetWindow( hwnd, GW_OWNER ))
1431 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1432 /* FIXME: clean up palette - see "Internals" p.352 */
1435 if (!IsWindow(hwnd)) return TRUE;
1437 if (USER_Driver.pResetSelectionOwner)
1438 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1440 /* Hide the window */
1442 ShowWindow( hwnd, SW_HIDE );
1443 if (!IsWindow(hwnd)) return TRUE;
1445 /* Recursively destroy owned windows */
1454 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1457 for (i = 0; list[i]; i++)
1459 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1460 if (WIN_IsCurrentThread( list[i] ))
1462 DestroyWindow( list[i] );
1466 WIN_SetOwner( list[i], 0 );
1468 HeapFree( GetProcessHeap(), 0, list );
1470 if (!got_one) break;
1473 WINPOS_ActivateOtherWindow( hwnd );
1475 if ((owner = GetWindow( hwnd, GW_OWNER )))
1477 WND *ptr = WIN_FindWndPtr( owner );
1480 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1481 WIN_ReleaseWndPtr( ptr );
1486 /* Send destroy messages */
1488 WIN_SendDestroyMsg( hwnd );
1489 if (!IsWindow( hwnd )) return TRUE;
1491 /* Unlink now so we won't bother with the children later on */
1493 WIN_UnlinkWindow( hwnd );
1495 /* Destroy the window storage */
1497 WIN_DestroyWindow( hwnd );
1502 /***********************************************************************
1503 * CloseWindow (USER32.@)
1505 BOOL WINAPI CloseWindow( HWND hwnd )
1507 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1508 ShowWindow( hwnd, SW_MINIMIZE );
1513 /***********************************************************************
1514 * OpenIcon (USER32.@)
1516 BOOL WINAPI OpenIcon( HWND hwnd )
1518 if (!IsIconic( hwnd )) return FALSE;
1519 ShowWindow( hwnd, SW_SHOWNORMAL );
1524 /***********************************************************************
1527 * Implementation of FindWindow() and FindWindowEx().
1529 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1534 WCHAR *buffer = NULL;
1536 if (!parent) parent = GetDesktopWindow();
1539 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1540 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1543 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1547 child = WIN_GetFullHandle( child );
1548 while (list[i] && list[i] != child) i++;
1549 if (!list[i]) goto done;
1550 i++; /* start from next window */
1557 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1564 if (list) HeapFree( GetProcessHeap(), 0, list );
1565 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1571 /***********************************************************************
1572 * FindWindowA (USER32.@)
1574 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1576 HWND ret = FindWindowExA( 0, 0, className, title );
1577 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1582 /***********************************************************************
1583 * FindWindowExA (USER32.@)
1585 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1586 LPCSTR className, LPCSTR title )
1595 /* If the atom doesn't exist, then no class */
1596 /* with this name exists either. */
1597 if (!(atom = GlobalFindAtomA( className )))
1599 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1603 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1605 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1606 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1607 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1608 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1609 HeapFree( GetProcessHeap(), 0, buffer );
1614 /***********************************************************************
1615 * FindWindowExW (USER32.@)
1617 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1618 LPCWSTR className, LPCWSTR title )
1624 /* If the atom doesn't exist, then no class */
1625 /* with this name exists either. */
1626 if (!(atom = GlobalFindAtomW( className )))
1628 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1632 return WIN_FindWindow( parent, child, atom, title );
1636 /***********************************************************************
1637 * FindWindowW (USER32.@)
1639 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1641 return FindWindowExW( 0, 0, className, title );
1645 /**********************************************************************
1646 * GetDesktopWindow (USER32.@)
1648 HWND WINAPI GetDesktopWindow(void)
1650 if (pWndDesktop) return pWndDesktop->hwndSelf;
1651 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" );
1657 /*******************************************************************
1658 * EnableWindow (USER32.@)
1660 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1667 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1668 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1672 TRACE("( %x, %d )\n", hwnd, enable);
1674 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1675 style = wndPtr->dwStyle;
1676 retvalue = ((style & WS_DISABLED) != 0);
1677 WIN_ReleasePtr( wndPtr );
1679 if (enable && retvalue)
1681 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1682 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1684 else if (!enable && !retvalue)
1686 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1688 WIN_SetStyle( hwnd, style | WS_DISABLED );
1690 if (hwnd == GetFocus())
1691 SetFocus( 0 ); /* A disabled window can't have the focus */
1693 if (hwnd == GetCapture())
1694 ReleaseCapture(); /* A disabled window can't capture the mouse */
1696 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1702 /***********************************************************************
1703 * IsWindowEnabled (USER32.@)
1705 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1707 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1711 /***********************************************************************
1712 * IsWindowUnicode (USER32.@)
1714 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1719 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1720 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1721 WIN_ReleaseWndPtr(wndPtr);
1726 /**********************************************************************
1727 * GetWindowWord (USER32.@)
1729 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1734 WND *wndPtr = WIN_GetPtr( hwnd );
1737 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1740 if (wndPtr == WND_OTHER_PROCESS)
1742 if (IsWindow( hwnd ))
1743 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1744 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1747 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1749 WARN("Invalid offset %d\n", offset );
1750 SetLastError( ERROR_INVALID_INDEX );
1752 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1753 WIN_ReleasePtr( wndPtr );
1759 case GWL_HWNDPARENT:
1760 return GetWindowLongW( hwnd, offset );
1764 LONG ret = GetWindowLongW( hwnd, offset );
1766 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1770 WARN("Invalid offset %d\n", offset );
1776 /**********************************************************************
1777 * SetWindowWord (USER32.@)
1779 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1788 case GWL_HWNDPARENT:
1789 return SetWindowLongW( hwnd, offset, (UINT)newval );
1793 WARN("Invalid offset %d\n", offset );
1794 SetLastError( ERROR_INVALID_INDEX );
1799 wndPtr = WIN_GetPtr( hwnd );
1800 if (wndPtr == WND_OTHER_PROCESS)
1803 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1804 offset, newval, hwnd );
1809 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1813 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1815 WARN("Invalid offset %d\n", offset );
1816 WIN_ReleasePtr(wndPtr);
1817 SetLastError( ERROR_INVALID_INDEX );
1820 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1823 WIN_ReleasePtr(wndPtr);
1828 /**********************************************************************
1831 * Helper function for GetWindowLong().
1833 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1838 if (offset == GWL_HWNDPARENT) return (LONG)GetParent( hwnd );
1840 if (!(wndPtr = WIN_GetPtr( hwnd )))
1842 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1846 if (wndPtr == WND_OTHER_PROCESS)
1851 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1852 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1855 if (offset == GWL_WNDPROC)
1857 SetLastError( ERROR_ACCESS_DENIED );
1860 SERVER_START_REQ( set_window_info )
1863 req->flags = 0; /* don't set anything, just retrieve */
1864 if (!wine_server_call_err( req ))
1868 case GWL_STYLE: retvalue = reply->old_style; break;
1869 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1870 case GWL_ID: retvalue = reply->old_id; break;
1871 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1872 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1874 SetLastError( ERROR_INVALID_INDEX );
1883 /* now we have a valid wndPtr */
1887 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1890 * Some programs try to access last element from 16 bit
1891 * code using illegal offset value. Hopefully this is
1892 * what those programs really expect.
1894 if (type == WIN_PROC_16 &&
1895 wndPtr->cbWndExtra >= 4 &&
1896 offset == wndPtr->cbWndExtra - sizeof(WORD))
1898 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1900 ERR( "- replaced invalid offset %d with %d\n",
1903 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1904 WIN_ReleasePtr( wndPtr );
1907 WARN("Invalid offset %d\n", offset );
1908 WIN_ReleasePtr( wndPtr );
1909 SetLastError( ERROR_INVALID_INDEX );
1912 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1913 /* Special case for dialog window procedure */
1914 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1915 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1916 WIN_ReleasePtr( wndPtr );
1922 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1923 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1924 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1925 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1926 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1927 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1929 WARN("Unknown offset %d\n", offset );
1930 SetLastError( ERROR_INVALID_INDEX );
1933 WIN_ReleasePtr(wndPtr);
1938 /**********************************************************************
1941 * Helper function for SetWindowLong().
1943 * 0 is the failure code. However, in the case of failure SetLastError
1944 * must be set to distinguish between a 0 return value and a failure.
1946 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1947 WINDOWPROCTYPE type )
1952 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1954 if (!WIN_IsCurrentProcess( hwnd ))
1956 if (offset == GWL_WNDPROC)
1958 SetLastError( ERROR_ACCESS_DENIED );
1961 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1964 wndPtr = WIN_GetPtr( hwnd );
1968 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1969 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1971 WARN("Invalid offset %d\n", offset );
1972 WIN_ReleasePtr( wndPtr );
1973 SetLastError( ERROR_INVALID_INDEX );
1976 /* Special case for dialog window procedure */
1977 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1979 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1980 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1981 type, WIN_PROC_WINDOW );
1982 WIN_ReleasePtr( wndPtr );
1987 WIN_ReleasePtr( wndPtr );
1994 /* first some special cases */
1999 style.styleOld = wndPtr->dwStyle;
2000 style.styleNew = newval;
2001 WIN_ReleasePtr( wndPtr );
2002 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2003 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2004 newval = style.styleNew;
2006 case GWL_HWNDPARENT:
2007 WIN_ReleasePtr( wndPtr );
2008 return (LONG)SetParent( hwnd, (HWND)newval );
2010 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2011 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2012 type, WIN_PROC_WINDOW );
2013 WIN_ReleasePtr( wndPtr );
2020 WIN_ReleasePtr( wndPtr );
2021 WARN("Invalid offset %d\n", offset );
2022 SetLastError( ERROR_INVALID_INDEX );
2026 SERVER_START_REQ( set_window_info )
2032 req->flags = SET_WIN_STYLE;
2033 req->style = newval;
2036 req->flags = SET_WIN_EXSTYLE;
2037 req->ex_style = newval;
2040 req->flags = SET_WIN_ID;
2044 req->flags = SET_WIN_INSTANCE;
2045 req->instance = (void *)newval;
2048 req->flags = SET_WIN_USERDATA;
2049 req->user_data = (void *)newval;
2052 if ((ok = !wine_server_call_err( req )))
2057 wndPtr->dwStyle = newval;
2058 retval = reply->old_style;
2061 wndPtr->dwExStyle = newval;
2062 retval = reply->old_ex_style;
2065 wndPtr->wIDmenu = newval;
2066 retval = reply->old_id;
2069 wndPtr->hInstance = newval;
2070 retval = (HINSTANCE)reply->old_instance;
2073 wndPtr->userdata = newval;
2074 retval = (ULONG_PTR)reply->old_user_data;
2080 WIN_ReleasePtr( wndPtr );
2084 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2085 USER_Driver.pSetWindowStyle( hwnd, retval );
2087 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2088 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2095 /**********************************************************************
2096 * GetWindowLong (USER.135)
2098 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2100 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2104 /**********************************************************************
2105 * GetWindowLongA (USER32.@)
2107 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2109 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2113 /**********************************************************************
2114 * GetWindowLongW (USER32.@)
2116 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2118 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2122 /**********************************************************************
2123 * SetWindowLong (USER.136)
2125 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2127 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2131 /**********************************************************************
2132 * SetWindowLongA (USER32.@)
2134 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2136 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2140 /**********************************************************************
2141 * SetWindowLongW (USER32.@) Set window attribute
2143 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2144 * value in a window's extra memory.
2146 * The _hwnd_ parameter specifies the window. is the handle to a
2147 * window that has extra memory. The _newval_ parameter contains the
2148 * new attribute or extra memory value. If positive, the _offset_
2149 * parameter is the byte-addressed location in the window's extra
2150 * memory to set. If negative, _offset_ specifies the window
2151 * attribute to set, and should be one of the following values:
2153 * GWL_EXSTYLE The window's extended window style
2155 * GWL_STYLE The window's window style.
2157 * GWL_WNDPROC Pointer to the window's window procedure.
2159 * GWL_HINSTANCE The window's pplication instance handle.
2161 * GWL_ID The window's identifier.
2163 * GWL_USERDATA The window's user-specified data.
2165 * If the window is a dialog box, the _offset_ parameter can be one of
2166 * the following values:
2168 * DWL_DLGPROC The address of the window's dialog box procedure.
2170 * DWL_MSGRESULT The return value of a message
2171 * that the dialog box procedure processed.
2173 * DWL_USER Application specific information.
2177 * If successful, returns the previous value located at _offset_. Otherwise,
2182 * Extra memory for a window class is specified by a nonzero cbWndExtra
2183 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2184 * time of class creation.
2186 * Using GWL_WNDPROC to set a new window procedure effectively creates
2187 * a window subclass. Use CallWindowProc() in the new windows procedure
2188 * to pass messages to the superclass's window procedure.
2190 * The user data is reserved for use by the application which created
2193 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2194 * instead, call the EnableWindow() function to change the window's
2197 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2198 * SetParent() instead.
2201 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2202 * it sends WM_STYLECHANGING before changing the settings
2203 * and WM_STYLECHANGED afterwards.
2204 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2206 LONG WINAPI SetWindowLongW(
2207 HWND hwnd, /* [in] window to alter */
2208 INT offset, /* [in] offset, in bytes, of location to alter */
2209 LONG newval /* [in] new value of location */
2211 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2215 /*******************************************************************
2216 * GetWindowTextA (USER32.@)
2218 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2222 if (WIN_IsCurrentProcess( hwnd ))
2223 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2225 /* when window belongs to other process, don't send a message */
2226 if (nMaxCount <= 0) return 0;
2227 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2228 get_server_window_text( hwnd, buffer, nMaxCount );
2229 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2230 lpString[nMaxCount-1] = 0;
2231 HeapFree( GetProcessHeap(), 0, buffer );
2232 return strlen(lpString);
2236 /*******************************************************************
2237 * InternalGetWindowText (USER32.@)
2239 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2243 if (nMaxCount <= 0) return 0;
2244 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2245 if (win != WND_OTHER_PROCESS)
2247 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2248 else lpString[0] = 0;
2249 WIN_ReleasePtr( win );
2253 get_server_window_text( hwnd, lpString, nMaxCount );
2255 return strlenW(lpString);
2259 /*******************************************************************
2260 * GetWindowTextW (USER32.@)
2262 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2264 if (WIN_IsCurrentProcess( hwnd ))
2265 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2267 /* when window belongs to other process, don't send a message */
2268 if (nMaxCount <= 0) return 0;
2269 get_server_window_text( hwnd, lpString, nMaxCount );
2270 return strlenW(lpString);
2274 /*******************************************************************
2275 * SetWindowText (USER32.@)
2276 * SetWindowTextA (USER32.@)
2278 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2280 if (!WIN_IsCurrentProcess( hwnd ))
2282 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2283 SetLastError( ERROR_ACCESS_DENIED );
2286 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2290 /*******************************************************************
2291 * SetWindowTextW (USER32.@)
2293 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2295 if (!WIN_IsCurrentProcess( hwnd ))
2297 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2298 SetLastError( ERROR_ACCESS_DENIED );
2301 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2305 /*******************************************************************
2306 * GetWindowTextLengthA (USER32.@)
2308 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2310 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2313 /*******************************************************************
2314 * GetWindowTextLengthW (USER32.@)
2316 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2318 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2322 /*******************************************************************
2323 * IsWindow (USER32.@)
2325 BOOL WINAPI IsWindow( HWND hwnd )
2330 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2332 if (ptr != WND_OTHER_PROCESS)
2334 WIN_ReleasePtr( ptr );
2338 /* check other processes */
2339 SERVER_START_REQ( get_window_info )
2342 ret = !wine_server_call_err( req );
2349 /***********************************************************************
2350 * GetWindowThreadProcessId (USER32.@)
2352 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2357 if (!(ptr = WIN_GetPtr( hwnd )))
2359 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2363 if (ptr != WND_OTHER_PROCESS)
2365 /* got a valid window */
2367 if (process) *process = GetCurrentProcessId();
2368 WIN_ReleasePtr( ptr );
2372 /* check other processes */
2373 SERVER_START_REQ( get_window_info )
2376 if (!wine_server_call_err( req ))
2378 tid = (DWORD)reply->tid;
2379 if (process) *process = (DWORD)reply->pid;
2387 /*****************************************************************
2388 * GetParent (USER32.@)
2390 HWND WINAPI GetParent( HWND hwnd )
2395 if (!(wndPtr = WIN_GetPtr( hwnd )))
2397 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2400 if (wndPtr == WND_OTHER_PROCESS)
2402 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2403 if (style & (WS_POPUP | WS_CHILD))
2405 SERVER_START_REQ( get_window_tree )
2408 if (!wine_server_call_err( req ))
2410 if (style & WS_CHILD) retvalue = reply->parent;
2411 else retvalue = reply->owner;
2419 if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2420 else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2421 WIN_ReleasePtr( wndPtr );
2427 /*****************************************************************
2428 * GetAncestor (USER32.@)
2430 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2433 HWND *list, ret = 0;
2435 if (type == GA_PARENT)
2437 if (!(win = WIN_GetPtr( hwnd )))
2439 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2442 if (win != WND_OTHER_PROCESS)
2445 WIN_ReleasePtr( win );
2447 else /* need to query the server */
2449 SERVER_START_REQ( get_window_tree )
2452 if (!wine_server_call_err( req )) ret = reply->parent;
2459 if (!(list = WIN_ListParents( hwnd ))) return 0;
2461 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2465 while (list[count]) count++;
2466 ret = list[count - 2]; /* get the one before the desktop */
2468 HeapFree( GetProcessHeap(), 0, list );
2470 if (ret && type == GA_ROOTOWNER)
2474 HWND owner = GetWindow( ret, GW_OWNER );
2483 /*****************************************************************
2484 * SetParent (USER32.@)
2486 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2489 HWND retvalue, full_handle;
2492 if (!parent) parent = GetDesktopWindow();
2493 else parent = WIN_GetFullHandle( parent );
2495 if (!IsWindow( parent ))
2497 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2501 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2502 return SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2506 if (USER_Driver.pSetParent)
2507 return USER_Driver.pSetParent( hwnd, parent );
2509 /* Windows hides the window first, then shows it again
2510 * including the WM_SHOWWINDOW messages and all */
2511 was_visible = ShowWindow( hwnd, SW_HIDE );
2513 if (!IsWindow( parent )) return 0;
2514 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2516 retvalue = wndPtr->parent; /* old parent */
2517 if (parent != retvalue)
2519 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2521 if (parent != GetDesktopWindow()) /* a child window */
2523 if (!(wndPtr->dwStyle & WS_CHILD))
2525 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2526 if (menu) DestroyMenu( menu );
2530 WIN_ReleasePtr( wndPtr );
2532 /* SetParent additionally needs to make hwnd the topmost window
2533 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2534 WM_WINDOWPOSCHANGED notification messages.
2536 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2537 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2538 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2539 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2544 /*******************************************************************
2545 * IsChild (USER32.@)
2547 BOOL WINAPI IsChild( HWND parent, HWND child )
2549 HWND *list = WIN_ListParents( child );
2553 if (!list) return FALSE;
2554 parent = WIN_GetFullHandle( parent );
2555 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2556 ret = (list[i] != 0);
2557 HeapFree( GetProcessHeap(), 0, list );
2562 /***********************************************************************
2563 * IsWindowVisible (USER32.@)
2565 BOOL WINAPI IsWindowVisible( HWND hwnd )
2571 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2572 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2573 for (i = 0; list[i]; i++)
2574 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2576 HeapFree( GetProcessHeap(), 0, list );
2581 /***********************************************************************
2582 * WIN_IsWindowDrawable
2584 * hwnd is drawable when it is visible, all parents are not
2585 * minimized, and it is itself not minimized unless we are
2586 * trying to draw its default class icon.
2588 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2593 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2595 if (!(style & WS_VISIBLE)) return FALSE;
2596 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2598 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2599 for (i = 0; list[i]; i++)
2600 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2603 HeapFree( GetProcessHeap(), 0, list );
2608 /*******************************************************************
2609 * GetTopWindow (USER32.@)
2611 HWND WINAPI GetTopWindow( HWND hwnd )
2613 if (!hwnd) hwnd = GetDesktopWindow();
2614 return GetWindow( hwnd, GW_CHILD );
2618 /*******************************************************************
2619 * GetWindow (USER32.@)
2621 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2625 if (rel == GW_OWNER) /* this one may be available locally */
2627 WND *wndPtr = WIN_GetPtr( hwnd );
2630 SetLastError( ERROR_INVALID_HANDLE );
2633 if (wndPtr != WND_OTHER_PROCESS)
2635 retval = wndPtr->owner;
2636 WIN_ReleasePtr( wndPtr );
2639 /* else fall through to server call */
2642 SERVER_START_REQ( get_window_tree )
2645 if (!wine_server_call_err( req ))
2650 retval = reply->first_sibling;
2653 retval = reply->last_sibling;
2656 retval = reply->next_sibling;
2659 retval = reply->prev_sibling;
2662 retval = reply->owner;
2665 retval = reply->first_child;
2675 /***********************************************************************
2676 * WIN_InternalShowOwnedPopups
2678 * Internal version of ShowOwnedPopups; Wine functions should use this
2679 * to avoid interfering with application calls to ShowOwnedPopups
2680 * and to make sure the application can't prevent showing/hiding.
2682 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2686 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2690 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2692 if (!win_array) return TRUE;
2695 * Show windows Lowest first, Highest last to preserve Z-Order
2697 while (win_array[count]) count++;
2698 while (--count >= 0)
2700 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2701 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2703 if (pWnd->dwStyle & WS_POPUP)
2707 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2708 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2711 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2713 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2714 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2719 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2720 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2721 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2724 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2726 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2727 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2728 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2732 WIN_ReleaseWndPtr( pWnd );
2734 HeapFree( GetProcessHeap(), 0, win_array );
2739 /*******************************************************************
2740 * ShowOwnedPopups (USER32.@)
2742 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2746 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2748 if (!win_array) return TRUE;
2750 while (win_array[count]) count++;
2751 while (--count >= 0)
2753 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2754 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2756 if (pWnd->dwStyle & WS_POPUP)
2760 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2762 /* In Windows, ShowOwnedPopups(TRUE) generates
2763 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2764 * regardless of the state of the owner
2766 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2767 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2772 if (IsWindowVisible(pWnd->hwndSelf))
2774 /* In Windows, ShowOwnedPopups(FALSE) generates
2775 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2776 * regardless of the state of the owner
2778 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2779 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2783 WIN_ReleaseWndPtr( pWnd );
2785 HeapFree( GetProcessHeap(), 0, win_array );
2790 /*******************************************************************
2791 * GetLastActivePopup (USER32.@)
2793 HWND WINAPI GetLastActivePopup( HWND hwnd )
2796 WND *wndPtr =WIN_FindWndPtr(hwnd);
2797 if (!wndPtr) return hwnd;
2798 retval = wndPtr->hwndLastActive;
2799 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2800 WIN_ReleaseWndPtr(wndPtr);
2805 /*******************************************************************
2808 * Build an array of all parents of a given window, starting with
2809 * the immediate parent. The array must be freed with HeapFree.
2810 * Returns NULL if window is a top-level window.
2812 HWND *WIN_ListParents( HWND hwnd )
2815 HWND current, *list;
2816 int pos = 0, size = 16, count = 0;
2818 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2823 if (!(win = WIN_GetPtr( current ))) goto empty;
2824 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2825 list[pos] = win->parent;
2826 WIN_ReleasePtr( win );
2827 if (!(current = list[pos]))
2829 if (!pos) goto empty;
2832 if (++pos == size - 1)
2834 /* need to grow the list */
2835 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2836 if (!new_list) goto empty;
2842 /* at least one parent belongs to another process, have to query the server */
2847 SERVER_START_REQ( get_window_parents )
2850 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2851 if (!wine_server_call( req )) count = reply->count;
2854 if (!count) goto empty;
2860 HeapFree( GetProcessHeap(), 0, list );
2862 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2866 HeapFree( GetProcessHeap(), 0, list );
2871 /*******************************************************************
2874 * Build an array of the children of a given window. The array must be
2875 * freed with HeapFree. Returns NULL when no windows are found.
2877 HWND *WIN_ListChildren( HWND hwnd )
2879 return list_window_children( hwnd, 0, 0 );
2883 /*******************************************************************
2884 * EnumWindows (USER32.@)
2886 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2892 /* We have to build a list of all windows first, to avoid */
2893 /* unpleasant side-effects, for instance if the callback */
2894 /* function changes the Z-order of the windows. */
2896 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2898 /* Now call the callback function for every window */
2900 iWndsLocks = WIN_SuspendWndsLock();
2901 for (i = 0; list[i]; i++)
2903 /* Make sure that the window still exists */
2904 if (!IsWindow( list[i] )) continue;
2905 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2907 WIN_RestoreWndsLock(iWndsLocks);
2908 HeapFree( GetProcessHeap(), 0, list );
2913 /**********************************************************************
2914 * EnumThreadWindows (USER32.@)
2916 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2921 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2924 /* Now call the callback function for every window */
2926 iWndsLocks = WIN_SuspendWndsLock();
2927 for (i = 0; list[i]; i++)
2928 if (!func( list[i], lParam )) break;
2929 WIN_RestoreWndsLock(iWndsLocks);
2930 HeapFree( GetProcessHeap(), 0, list );
2935 /**********************************************************************
2936 * WIN_EnumChildWindows
2938 * Helper function for EnumChildWindows().
2940 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2945 for ( ; *list; list++)
2947 /* Make sure that the window still exists */
2948 if (!IsWindow( *list )) continue;
2949 /* skip owned windows */
2950 if (GetWindow( *list, GW_OWNER )) continue;
2951 /* Build children list first */
2952 childList = WIN_ListChildren( *list );
2954 ret = func( *list, lParam );
2958 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2959 HeapFree( GetProcessHeap(), 0, childList );
2961 if (!ret) return FALSE;
2967 /**********************************************************************
2968 * EnumChildWindows (USER32.@)
2970 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2975 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2976 iWndsLocks = WIN_SuspendWndsLock();
2977 WIN_EnumChildWindows( list, func, lParam );
2978 WIN_RestoreWndsLock(iWndsLocks);
2979 HeapFree( GetProcessHeap(), 0, list );
2984 /*******************************************************************
2985 * AnyPopup (USER.52)
2987 BOOL16 WINAPI AnyPopup16(void)
2993 /*******************************************************************
2994 * AnyPopup (USER32.@)
2996 BOOL WINAPI AnyPopup(void)
3000 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3002 if (!list) return FALSE;
3003 for (i = 0; list[i]; i++)
3005 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3007 retvalue = (list[i] != 0);
3008 HeapFree( GetProcessHeap(), 0, list );
3013 /*******************************************************************
3014 * FlashWindow (USER32.@)
3016 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3018 WND *wndPtr = WIN_FindWndPtr(hWnd);
3020 TRACE("%04x\n", hWnd);
3022 if (!wndPtr) return FALSE;
3023 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3025 if (wndPtr->dwStyle & WS_MINIMIZE)
3027 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3029 HDC hDC = GetDC(hWnd);
3031 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3032 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3034 ReleaseDC( hWnd, hDC );
3035 wndPtr->flags |= WIN_NCACTIVATED;
3039 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3040 wndPtr->flags &= ~WIN_NCACTIVATED;
3042 WIN_ReleaseWndPtr(wndPtr);
3048 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3049 else wparam = (hWnd == GetActiveWindow());
3051 WIN_ReleaseWndPtr(wndPtr);
3052 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3058 /*******************************************************************
3059 * GetWindowContextHelpId (USER32.@)
3061 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3064 WND *wnd = WIN_FindWndPtr( hwnd );
3066 retval = wnd->helpContext;
3067 WIN_ReleaseWndPtr(wnd);
3072 /*******************************************************************
3073 * SetWindowContextHelpId (USER32.@)
3075 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3077 WND *wnd = WIN_FindWndPtr( hwnd );
3078 if (!wnd) return FALSE;
3079 wnd->helpContext = id;
3080 WIN_ReleaseWndPtr(wnd);
3085 /*******************************************************************
3088 * recursively find a child that contains spDragInfo->pt point
3089 * and send WM_QUERYDROPOBJECT
3091 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3093 BOOL16 wParam, bResult = 0;
3095 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3098 if (!ptrDragInfo) return FALSE;
3100 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3102 GetWindowRect(hQueryWnd,&tempRect);
3104 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3106 if (!IsIconic( hQueryWnd ))
3108 GetClientRect( hQueryWnd, &tempRect );
3109 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3111 if (PtInRect( &tempRect, pt))
3114 HWND *list = WIN_ListChildren( hQueryWnd );
3120 for (i = 0; list[i]; i++)
3122 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3124 GetWindowRect( list[i], &tempRect );
3125 if (PtInRect( &tempRect, pt )) break;
3130 if (IsWindowEnabled( list[i] ))
3131 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
3133 HeapFree( GetProcessHeap(), 0, list );
3135 if(bResult) return bResult;
3141 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3143 ptrDragInfo->hScope = hQueryWnd;
3145 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3146 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3148 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3154 /*******************************************************************
3155 * DragDetect (USER32.@)
3157 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3162 rect.left = pt.x - wDragWidth;
3163 rect.right = pt.x + wDragWidth;
3165 rect.top = pt.y - wDragHeight;
3166 rect.bottom = pt.y + wDragHeight;
3172 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3174 if( msg.message == WM_LBUTTONUP )
3179 if( msg.message == WM_MOUSEMOVE )
3182 tmp.x = LOWORD(msg.lParam);
3183 tmp.y = HIWORD(msg.lParam);
3184 if( !PtInRect( &rect, tmp ))
3196 /******************************************************************************
3197 * DragObject (USER.464)
3199 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3200 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3203 LPDRAGINFO16 lpDragInfo;
3205 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3206 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3207 HCURSOR16 hCurrentCursor = 0;
3208 HWND16 hCurrentWnd = 0;
3210 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3211 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3213 if( !lpDragInfo || !spDragInfo ) return 0L;
3215 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3217 GlobalFree16(hDragInfo);
3223 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3225 GlobalFree16(hDragInfo);
3229 if( hDragCursor == hCursor ) hDragCursor = 0;
3230 else hCursor = hDragCursor;
3232 hOldCursor = SetCursor(hDragCursor);
3235 lpDragInfo->hWnd = hWnd;
3236 lpDragInfo->hScope = 0;
3237 lpDragInfo->wFlags = wObj;
3238 lpDragInfo->hList = szList; /* near pointer! */
3239 lpDragInfo->hOfStruct = hOfStruct;
3247 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3249 *(lpDragInfo+1) = *lpDragInfo;
3251 lpDragInfo->pt.x = msg.pt.x;
3252 lpDragInfo->pt.y = msg.pt.y;
3254 /* update DRAGINFO struct */
3255 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3257 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3258 hCurrentCursor = hCursor;
3261 hCurrentCursor = hBummer;
3262 lpDragInfo->hScope = 0;
3264 if( hCurrentCursor )
3265 SetCursor(hCurrentCursor);
3267 /* send WM_DRAGLOOP */
3268 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3269 (LPARAM) spDragInfo );
3270 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3271 if( hCurrentWnd != lpDragInfo->hScope )
3274 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3275 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3276 HIWORD(spDragInfo)) );
3277 hCurrentWnd = lpDragInfo->hScope;
3279 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3283 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3285 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3288 ShowCursor( FALSE );
3292 SetCursor( hOldCursor );
3293 if (hDragCursor) DestroyCursor( hDragCursor );
3296 if( hCurrentCursor != hBummer )
3297 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3298 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3301 GlobalFree16(hDragInfo);
3303 return (DWORD)(msg.lParam);
3307 /******************************************************************************
3308 * GetWindowModuleFileNameA (USER32.@)
3310 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3312 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3313 hwnd, lpszFileName, cchFileNameMax);
3317 /******************************************************************************
3318 * GetWindowModuleFileNameW (USER32.@)
3320 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3322 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3323 hwnd, lpszFileName, cchFileNameMax);