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 /***********************************************************************
856 static void dump_window_styles( DWORD style, DWORD exstyle )
859 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
860 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
861 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
862 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
863 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
864 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
865 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
866 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
867 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
870 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
871 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
873 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
874 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
875 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
876 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
877 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
878 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
879 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
880 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
882 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
883 #define DUMPED_STYLES \
903 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
908 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
909 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
910 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
911 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
912 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
913 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
914 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
915 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
916 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
917 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
918 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
919 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
920 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
921 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
922 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
923 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
924 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
925 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
927 #define DUMPED_EX_STYLES \
928 (WS_EX_DLGMODALFRAME | \
930 WS_EX_NOPARENTNOTIFY | \
932 WS_EX_ACCEPTFILES | \
933 WS_EX_TRANSPARENT | \
938 WS_EX_CONTEXTHELP | \
941 WS_EX_LEFTSCROLLBAR | \
942 WS_EX_CONTROLPARENT | \
947 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
949 #undef DUMPED_EX_STYLES
953 /***********************************************************************
956 * Implementation of CreateWindowEx().
958 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
959 WINDOWPROCTYPE type )
962 struct tagCLASS *classPtr;
964 HWND hwnd, parent, owner;
969 BOOL unicode = (type == WIN_PROC_32W);
971 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
972 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
973 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
974 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
975 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
977 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
979 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
980 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
982 /* Find the parent window */
984 parent = GetDesktopWindow();
988 /* Make sure parent is valid */
989 if (!IsWindow( cs->hwndParent ))
991 WARN("Bad parent %04x\n", cs->hwndParent );
994 if (cs->style & WS_CHILD) parent = WIN_GetFullHandle(cs->hwndParent);
995 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
997 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
999 WARN("No parent for child window\n" );
1000 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1003 /* Find the window class */
1004 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1005 &wndExtra, &winproc, &clsStyle, &dce )))
1007 WARN("Bad class '%s'\n", cs->lpszClass );
1011 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1013 /* Correct the window style - stage 1
1015 * These are patches that appear to affect both the style loaded into the
1016 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1018 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1019 * why does the user get to set it?
1022 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1023 * tested for WS_POPUP
1025 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1026 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1027 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1028 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1030 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1032 /* Create the window structure */
1034 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1035 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1037 TRACE("out of memory\n" );
1040 hwnd = wndPtr->hwndSelf;
1042 /* Fill the window structure */
1044 wndPtr->tid = GetCurrentThreadId();
1045 wndPtr->owner = owner;
1046 wndPtr->parent = parent;
1047 wndPtr->class = classPtr;
1048 wndPtr->winproc = winproc;
1049 wndPtr->hInstance = cs->hInstance;
1050 wndPtr->text = NULL;
1051 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
1052 wndPtr->hrgnUpdate = 0;
1053 wndPtr->hrgnWnd = 0;
1054 wndPtr->hwndLastActive = hwnd;
1055 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1056 wndPtr->dwExStyle = cs->dwExStyle;
1057 wndPtr->clsStyle = clsStyle;
1058 wndPtr->wIDmenu = 0;
1059 wndPtr->helpContext = 0;
1060 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1061 wndPtr->pVScroll = NULL;
1062 wndPtr->pHScroll = NULL;
1063 wndPtr->userdata = 0;
1064 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1065 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1066 wndPtr->cbWndExtra = wndExtra;
1068 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1070 /* Correct the window style - stage 2 */
1072 if (!(cs->style & WS_CHILD))
1074 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1075 if (!(cs->style & WS_POPUP))
1077 wndPtr->dwStyle |= WS_CAPTION;
1078 wndPtr->flags |= WIN_NEED_SIZE;
1081 SERVER_START_REQ( set_window_info )
1084 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1085 req->style = wndPtr->dwStyle;
1086 req->ex_style = wndPtr->dwExStyle;
1087 req->instance = (void *)wndPtr->hInstance;
1088 wine_server_call( req );
1092 /* Get class or window DC if needed */
1094 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1095 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1096 else wndPtr->dce = NULL;
1098 /* Set the window menu */
1100 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1102 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1105 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1108 if (HIWORD(cs->hInstance))
1109 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1111 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1113 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1117 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1118 WIN_ReleaseWndPtr( wndPtr );
1120 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1122 WIN_DestroyWindow( hwnd );
1126 /* Notify the parent window only */
1128 send_parent_notify( hwnd, WM_CREATE );
1129 if (!IsWindow( hwnd )) return 0;
1131 if (cs->style & WS_VISIBLE)
1133 /* in case WS_VISIBLE got set in the meantime */
1134 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1135 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1136 WIN_ReleasePtr( wndPtr );
1137 ShowWindow( hwnd, sw );
1140 /* Call WH_SHELL hook */
1142 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1143 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1145 TRACE("created window %04x\n", hwnd);
1150 /***********************************************************************
1151 * CreateWindow (USER.41)
1153 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1154 DWORD style, INT16 x, INT16 y, INT16 width,
1155 INT16 height, HWND16 parent, HMENU16 menu,
1156 HINSTANCE16 instance, LPVOID data )
1158 return CreateWindowEx16( 0, className, windowName, style,
1159 x, y, width, height, parent, menu, instance, data );
1163 /***********************************************************************
1164 * CreateWindowEx (USER.452)
1166 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1167 LPCSTR windowName, DWORD style, INT16 x,
1168 INT16 y, INT16 width, INT16 height,
1169 HWND16 parent, HMENU16 menu,
1170 HINSTANCE16 instance, LPVOID data )
1176 /* Find the class atom */
1178 if (HIWORD(className))
1180 if (!(classAtom = GlobalFindAtomA( className )))
1182 ERR( "bad class name %s\n", debugres_a(className) );
1188 classAtom = LOWORD(className);
1189 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1191 ERR( "bad atom %x\n", classAtom);
1197 /* Fix the coordinates */
1199 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1200 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1201 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1202 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1204 /* Create the window */
1206 cs.lpCreateParams = data;
1207 cs.hInstance = (HINSTANCE)instance;
1208 cs.hMenu = (HMENU)menu;
1209 cs.hwndParent = WIN_Handle32( parent );
1211 cs.lpszName = windowName;
1212 cs.lpszClass = className;
1213 cs.dwExStyle = exStyle;
1215 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1219 /***********************************************************************
1220 * CreateWindowExA (USER32.@)
1222 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1223 LPCSTR windowName, DWORD style, INT x,
1224 INT y, INT width, INT height,
1225 HWND parent, HMENU menu,
1226 HINSTANCE instance, LPVOID data )
1233 instance=GetModuleHandleA(NULL);
1235 if(exStyle & WS_EX_MDICHILD)
1236 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1238 /* Find the class atom */
1240 if (HIWORD(className))
1242 if (!(classAtom = GlobalFindAtomA( className )))
1244 ERR( "bad class name %s\n", debugres_a(className) );
1250 classAtom = LOWORD(className);
1251 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1253 ERR( "bad atom %x\n", classAtom);
1259 /* Create the window */
1261 cs.lpCreateParams = data;
1262 cs.hInstance = instance;
1264 cs.hwndParent = parent;
1270 cs.lpszName = windowName;
1271 cs.lpszClass = className;
1272 cs.dwExStyle = exStyle;
1274 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1278 /***********************************************************************
1279 * CreateWindowExW (USER32.@)
1281 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1282 LPCWSTR windowName, DWORD style, INT x,
1283 INT y, INT width, INT height,
1284 HWND parent, HMENU menu,
1285 HINSTANCE instance, LPVOID data )
1292 instance=GetModuleHandleA(NULL);
1294 if(exStyle & WS_EX_MDICHILD)
1295 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1297 /* Find the class atom */
1299 if (HIWORD(className))
1301 if (!(classAtom = GlobalFindAtomW( className )))
1303 ERR( "bad class name %s\n", debugres_w(className) );
1309 classAtom = LOWORD(className);
1310 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1312 ERR( "bad atom %x\n", classAtom);
1318 /* Create the window */
1320 cs.lpCreateParams = data;
1321 cs.hInstance = instance;
1323 cs.hwndParent = parent;
1329 cs.lpszName = windowName;
1330 cs.lpszClass = className;
1331 cs.dwExStyle = exStyle;
1333 /* Note: we rely on the fact that CREATESTRUCTA and */
1334 /* CREATESTRUCTW have the same layout. */
1335 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1339 /***********************************************************************
1340 * WIN_SendDestroyMsg
1342 static void WIN_SendDestroyMsg( HWND hwnd )
1344 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1345 if (USER_Driver.pResetSelectionOwner)
1346 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1349 * Send the WM_DESTROY to the window.
1351 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1354 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1355 * make sure that the window still exists when we come back.
1362 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1364 /* start from the end (FIXME: is this needed?) */
1365 for (i = 0; pWndArray[i]; i++) ;
1369 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1371 HeapFree( GetProcessHeap(), 0, pWndArray );
1374 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1378 /***********************************************************************
1379 * DestroyWindow (USER32.@)
1381 BOOL WINAPI DestroyWindow( HWND hwnd )
1386 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1388 SetLastError( ERROR_ACCESS_DENIED );
1392 TRACE("(%04x)\n", hwnd);
1394 /* Look whether the focus is within the tree of windows we will
1398 if (h == hwnd || IsChild( hwnd, h ))
1400 HWND parent = GetAncestor( hwnd, GA_PARENT );
1401 if (parent == GetDesktopWindow()) parent = 0;
1407 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1409 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1413 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1414 send_parent_notify( hwnd, WM_DESTROY );
1416 else if (!GetWindow( hwnd, GW_OWNER ))
1418 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1419 /* FIXME: clean up palette - see "Internals" p.352 */
1422 if (!IsWindow(hwnd)) return TRUE;
1424 if (USER_Driver.pResetSelectionOwner)
1425 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1427 /* Hide the window */
1429 ShowWindow( hwnd, SW_HIDE );
1430 if (!IsWindow(hwnd)) return TRUE;
1432 /* Recursively destroy owned windows */
1441 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1444 for (i = 0; list[i]; i++)
1446 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1447 if (WIN_IsCurrentThread( list[i] ))
1449 DestroyWindow( list[i] );
1453 WIN_SetOwner( list[i], 0 );
1455 HeapFree( GetProcessHeap(), 0, list );
1457 if (!got_one) break;
1460 WINPOS_ActivateOtherWindow( hwnd );
1462 if ((owner = GetWindow( hwnd, GW_OWNER )))
1464 WND *ptr = WIN_FindWndPtr( owner );
1467 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1468 WIN_ReleaseWndPtr( ptr );
1473 /* Send destroy messages */
1475 WIN_SendDestroyMsg( hwnd );
1476 if (!IsWindow( hwnd )) return TRUE;
1478 /* Unlink now so we won't bother with the children later on */
1480 WIN_UnlinkWindow( hwnd );
1482 /* Destroy the window storage */
1484 WIN_DestroyWindow( hwnd );
1489 /***********************************************************************
1490 * CloseWindow (USER32.@)
1492 BOOL WINAPI CloseWindow( HWND hwnd )
1494 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1495 ShowWindow( hwnd, SW_MINIMIZE );
1500 /***********************************************************************
1501 * OpenIcon (USER32.@)
1503 BOOL WINAPI OpenIcon( HWND hwnd )
1505 if (!IsIconic( hwnd )) return FALSE;
1506 ShowWindow( hwnd, SW_SHOWNORMAL );
1511 /***********************************************************************
1514 * Implementation of FindWindow() and FindWindowEx().
1516 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1521 WCHAR *buffer = NULL;
1523 if (!parent) parent = GetDesktopWindow();
1526 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1527 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1530 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1534 child = WIN_GetFullHandle( child );
1535 while (list[i] && list[i] != child) i++;
1536 if (!list[i]) goto done;
1537 i++; /* start from next window */
1544 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1551 if (list) HeapFree( GetProcessHeap(), 0, list );
1552 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1558 /***********************************************************************
1559 * FindWindowA (USER32.@)
1561 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1563 HWND ret = FindWindowExA( 0, 0, className, title );
1564 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1569 /***********************************************************************
1570 * FindWindowExA (USER32.@)
1572 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1573 LPCSTR className, LPCSTR title )
1582 /* If the atom doesn't exist, then no class */
1583 /* with this name exists either. */
1584 if (!(atom = GlobalFindAtomA( className )))
1586 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1590 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1592 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1593 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1594 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1595 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1596 HeapFree( GetProcessHeap(), 0, buffer );
1601 /***********************************************************************
1602 * FindWindowExW (USER32.@)
1604 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1605 LPCWSTR className, LPCWSTR title )
1611 /* If the atom doesn't exist, then no class */
1612 /* with this name exists either. */
1613 if (!(atom = GlobalFindAtomW( className )))
1615 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1619 return WIN_FindWindow( parent, child, atom, title );
1623 /***********************************************************************
1624 * FindWindowW (USER32.@)
1626 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1628 return FindWindowExW( 0, 0, className, title );
1632 /**********************************************************************
1633 * GetDesktopWindow (USER32.@)
1635 HWND WINAPI GetDesktopWindow(void)
1637 if (pWndDesktop) return pWndDesktop->hwndSelf;
1638 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" );
1644 /*******************************************************************
1645 * EnableWindow (USER32.@)
1647 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1654 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1655 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1659 TRACE("( %x, %d )\n", hwnd, enable);
1661 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1662 style = wndPtr->dwStyle;
1663 retvalue = ((style & WS_DISABLED) != 0);
1664 WIN_ReleasePtr( wndPtr );
1666 if (enable && retvalue)
1668 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1669 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1671 else if (!enable && !retvalue)
1673 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1675 WIN_SetStyle( hwnd, style | WS_DISABLED );
1677 if (hwnd == GetFocus())
1678 SetFocus( 0 ); /* A disabled window can't have the focus */
1680 if (hwnd == GetCapture())
1681 ReleaseCapture(); /* A disabled window can't capture the mouse */
1683 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1689 /***********************************************************************
1690 * IsWindowEnabled (USER32.@)
1692 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1694 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1698 /***********************************************************************
1699 * IsWindowUnicode (USER32.@)
1701 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1706 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1707 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1708 WIN_ReleaseWndPtr(wndPtr);
1713 /**********************************************************************
1714 * GetWindowWord (USER32.@)
1716 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1721 WND *wndPtr = WIN_GetPtr( hwnd );
1724 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1727 if (wndPtr == WND_OTHER_PROCESS)
1729 if (IsWindow( hwnd ))
1730 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1731 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1734 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1736 WARN("Invalid offset %d\n", offset );
1737 SetLastError( ERROR_INVALID_INDEX );
1739 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1740 WIN_ReleasePtr( wndPtr );
1746 case GWL_HWNDPARENT:
1747 return GetWindowLongW( hwnd, offset );
1751 LONG ret = GetWindowLongW( hwnd, offset );
1753 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1757 WARN("Invalid offset %d\n", offset );
1763 /**********************************************************************
1764 * SetWindowWord (USER32.@)
1766 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1775 case GWL_HWNDPARENT:
1776 return SetWindowLongW( hwnd, offset, (UINT)newval );
1780 WARN("Invalid offset %d\n", offset );
1781 SetLastError( ERROR_INVALID_INDEX );
1786 wndPtr = WIN_GetPtr( hwnd );
1787 if (wndPtr == WND_OTHER_PROCESS)
1790 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1791 offset, newval, hwnd );
1796 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1800 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1802 WARN("Invalid offset %d\n", offset );
1803 WIN_ReleasePtr(wndPtr);
1804 SetLastError( ERROR_INVALID_INDEX );
1807 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1810 WIN_ReleasePtr(wndPtr);
1815 /**********************************************************************
1818 * Helper function for GetWindowLong().
1820 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1825 if (offset == GWL_HWNDPARENT) return (LONG)GetParent( hwnd );
1827 if (!(wndPtr = WIN_GetPtr( hwnd )))
1829 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1833 if (wndPtr == WND_OTHER_PROCESS)
1838 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1839 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1842 if (offset == GWL_WNDPROC)
1844 SetLastError( ERROR_ACCESS_DENIED );
1847 SERVER_START_REQ( set_window_info )
1850 req->flags = 0; /* don't set anything, just retrieve */
1851 if (!wine_server_call_err( req ))
1855 case GWL_STYLE: retvalue = reply->old_style; break;
1856 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1857 case GWL_ID: retvalue = reply->old_id; break;
1858 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1859 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1861 SetLastError( ERROR_INVALID_INDEX );
1870 /* now we have a valid wndPtr */
1874 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1877 * Some programs try to access last element from 16 bit
1878 * code using illegal offset value. Hopefully this is
1879 * what those programs really expect.
1881 if (type == WIN_PROC_16 &&
1882 wndPtr->cbWndExtra >= 4 &&
1883 offset == wndPtr->cbWndExtra - sizeof(WORD))
1885 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1887 ERR( "- replaced invalid offset %d with %d\n",
1890 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1891 WIN_ReleasePtr( wndPtr );
1894 WARN("Invalid offset %d\n", offset );
1895 WIN_ReleasePtr( wndPtr );
1896 SetLastError( ERROR_INVALID_INDEX );
1899 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1900 /* Special case for dialog window procedure */
1901 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1902 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1903 WIN_ReleasePtr( wndPtr );
1909 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1910 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1911 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1912 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1913 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1914 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1916 WARN("Unknown offset %d\n", offset );
1917 SetLastError( ERROR_INVALID_INDEX );
1920 WIN_ReleasePtr(wndPtr);
1925 /**********************************************************************
1928 * Helper function for SetWindowLong().
1930 * 0 is the failure code. However, in the case of failure SetLastError
1931 * must be set to distinguish between a 0 return value and a failure.
1933 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1934 WINDOWPROCTYPE type )
1939 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1941 if (!WIN_IsCurrentProcess( hwnd ))
1943 if (offset == GWL_WNDPROC)
1945 SetLastError( ERROR_ACCESS_DENIED );
1948 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1951 wndPtr = WIN_GetPtr( hwnd );
1955 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1956 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1958 WARN("Invalid offset %d\n", offset );
1959 WIN_ReleasePtr( wndPtr );
1960 SetLastError( ERROR_INVALID_INDEX );
1963 /* Special case for dialog window procedure */
1964 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1966 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1967 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1968 type, WIN_PROC_WINDOW );
1969 WIN_ReleasePtr( wndPtr );
1974 WIN_ReleasePtr( wndPtr );
1981 /* first some special cases */
1986 style.styleOld = wndPtr->dwStyle;
1987 style.styleNew = newval;
1988 WIN_ReleasePtr( wndPtr );
1989 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1990 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1991 newval = style.styleNew;
1993 case GWL_HWNDPARENT:
1994 WIN_ReleasePtr( wndPtr );
1995 return (LONG)SetParent( hwnd, (HWND)newval );
1997 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1998 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1999 type, WIN_PROC_WINDOW );
2000 WIN_ReleasePtr( wndPtr );
2007 WIN_ReleasePtr( wndPtr );
2008 WARN("Invalid offset %d\n", offset );
2009 SetLastError( ERROR_INVALID_INDEX );
2013 SERVER_START_REQ( set_window_info )
2019 req->flags = SET_WIN_STYLE;
2020 req->style = newval;
2023 req->flags = SET_WIN_EXSTYLE;
2024 req->ex_style = newval;
2027 req->flags = SET_WIN_ID;
2031 req->flags = SET_WIN_INSTANCE;
2032 req->instance = (void *)newval;
2035 req->flags = SET_WIN_USERDATA;
2036 req->user_data = (void *)newval;
2039 if ((ok = !wine_server_call_err( req )))
2044 wndPtr->dwStyle = newval;
2045 retval = reply->old_style;
2048 wndPtr->dwExStyle = newval;
2049 retval = reply->old_ex_style;
2052 wndPtr->wIDmenu = newval;
2053 retval = reply->old_id;
2056 wndPtr->hInstance = newval;
2057 retval = (HINSTANCE)reply->old_instance;
2060 wndPtr->userdata = newval;
2061 retval = (ULONG_PTR)reply->old_user_data;
2067 WIN_ReleasePtr( wndPtr );
2071 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2072 USER_Driver.pSetWindowStyle( hwnd, retval );
2074 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2075 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2082 /**********************************************************************
2083 * GetWindowLong (USER.135)
2085 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2087 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2091 /**********************************************************************
2092 * GetWindowLongA (USER32.@)
2094 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2096 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2100 /**********************************************************************
2101 * GetWindowLongW (USER32.@)
2103 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2105 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2109 /**********************************************************************
2110 * SetWindowLong (USER.136)
2112 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2114 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2118 /**********************************************************************
2119 * SetWindowLongA (USER32.@)
2121 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2123 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2127 /**********************************************************************
2128 * SetWindowLongW (USER32.@) Set window attribute
2130 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2131 * value in a window's extra memory.
2133 * The _hwnd_ parameter specifies the window. is the handle to a
2134 * window that has extra memory. The _newval_ parameter contains the
2135 * new attribute or extra memory value. If positive, the _offset_
2136 * parameter is the byte-addressed location in the window's extra
2137 * memory to set. If negative, _offset_ specifies the window
2138 * attribute to set, and should be one of the following values:
2140 * GWL_EXSTYLE The window's extended window style
2142 * GWL_STYLE The window's window style.
2144 * GWL_WNDPROC Pointer to the window's window procedure.
2146 * GWL_HINSTANCE The window's pplication instance handle.
2148 * GWL_ID The window's identifier.
2150 * GWL_USERDATA The window's user-specified data.
2152 * If the window is a dialog box, the _offset_ parameter can be one of
2153 * the following values:
2155 * DWL_DLGPROC The address of the window's dialog box procedure.
2157 * DWL_MSGRESULT The return value of a message
2158 * that the dialog box procedure processed.
2160 * DWL_USER Application specific information.
2164 * If successful, returns the previous value located at _offset_. Otherwise,
2169 * Extra memory for a window class is specified by a nonzero cbWndExtra
2170 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2171 * time of class creation.
2173 * Using GWL_WNDPROC to set a new window procedure effectively creates
2174 * a window subclass. Use CallWindowProc() in the new windows procedure
2175 * to pass messages to the superclass's window procedure.
2177 * The user data is reserved for use by the application which created
2180 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2181 * instead, call the EnableWindow() function to change the window's
2184 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2185 * SetParent() instead.
2188 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2189 * it sends WM_STYLECHANGING before changing the settings
2190 * and WM_STYLECHANGED afterwards.
2191 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2193 LONG WINAPI SetWindowLongW(
2194 HWND hwnd, /* [in] window to alter */
2195 INT offset, /* [in] offset, in bytes, of location to alter */
2196 LONG newval /* [in] new value of location */
2198 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2202 /*******************************************************************
2203 * GetWindowTextA (USER32.@)
2205 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2209 if (WIN_IsCurrentProcess( hwnd ))
2210 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2212 /* when window belongs to other process, don't send a message */
2213 if (nMaxCount <= 0) return 0;
2214 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2215 get_server_window_text( hwnd, buffer, nMaxCount );
2216 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2217 lpString[nMaxCount-1] = 0;
2218 HeapFree( GetProcessHeap(), 0, buffer );
2219 return strlen(lpString);
2223 /*******************************************************************
2224 * InternalGetWindowText (USER32.@)
2226 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2230 if (nMaxCount <= 0) return 0;
2231 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2232 if (win != WND_OTHER_PROCESS)
2234 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2235 else lpString[0] = 0;
2236 WIN_ReleasePtr( win );
2240 get_server_window_text( hwnd, lpString, nMaxCount );
2242 return strlenW(lpString);
2246 /*******************************************************************
2247 * GetWindowTextW (USER32.@)
2249 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2251 if (WIN_IsCurrentProcess( hwnd ))
2252 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2254 /* when window belongs to other process, don't send a message */
2255 if (nMaxCount <= 0) return 0;
2256 get_server_window_text( hwnd, lpString, nMaxCount );
2257 return strlenW(lpString);
2261 /*******************************************************************
2262 * SetWindowText (USER32.@)
2263 * SetWindowTextA (USER32.@)
2265 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2267 if (!WIN_IsCurrentProcess( hwnd ))
2269 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2270 SetLastError( ERROR_ACCESS_DENIED );
2273 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2277 /*******************************************************************
2278 * SetWindowTextW (USER32.@)
2280 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2282 if (!WIN_IsCurrentProcess( hwnd ))
2284 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2285 SetLastError( ERROR_ACCESS_DENIED );
2288 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2292 /*******************************************************************
2293 * GetWindowTextLengthA (USER32.@)
2295 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2297 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2300 /*******************************************************************
2301 * GetWindowTextLengthW (USER32.@)
2303 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2305 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2309 /*******************************************************************
2310 * IsWindow (USER32.@)
2312 BOOL WINAPI IsWindow( HWND hwnd )
2317 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2319 if (ptr != WND_OTHER_PROCESS)
2321 WIN_ReleasePtr( ptr );
2325 /* check other processes */
2326 SERVER_START_REQ( get_window_info )
2329 ret = !wine_server_call_err( req );
2336 /***********************************************************************
2337 * GetWindowThreadProcessId (USER32.@)
2339 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2344 if (!(ptr = WIN_GetPtr( hwnd )))
2346 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2350 if (ptr != WND_OTHER_PROCESS)
2352 /* got a valid window */
2354 if (process) *process = GetCurrentProcessId();
2355 WIN_ReleasePtr( ptr );
2359 /* check other processes */
2360 SERVER_START_REQ( get_window_info )
2363 if (!wine_server_call_err( req ))
2365 tid = (DWORD)reply->tid;
2366 if (process) *process = (DWORD)reply->pid;
2374 /*****************************************************************
2375 * GetParent (USER32.@)
2377 HWND WINAPI GetParent( HWND hwnd )
2382 if (!(wndPtr = WIN_GetPtr( hwnd )))
2384 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2387 if (wndPtr == WND_OTHER_PROCESS)
2389 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2390 if (style & (WS_POPUP | WS_CHILD))
2392 SERVER_START_REQ( get_window_tree )
2395 if (!wine_server_call_err( req ))
2397 if (style & WS_CHILD) retvalue = reply->parent;
2398 else retvalue = reply->owner;
2406 if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2407 else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2408 WIN_ReleasePtr( wndPtr );
2414 /*****************************************************************
2415 * GetAncestor (USER32.@)
2417 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2420 HWND *list, ret = 0;
2422 if (type == GA_PARENT)
2424 if (!(win = WIN_GetPtr( hwnd )))
2426 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2429 if (win != WND_OTHER_PROCESS)
2432 WIN_ReleasePtr( win );
2434 else /* need to query the server */
2436 SERVER_START_REQ( get_window_tree )
2439 if (!wine_server_call_err( req )) ret = reply->parent;
2446 if (!(list = WIN_ListParents( hwnd ))) return 0;
2448 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2452 while (list[count]) count++;
2453 ret = list[count - 2]; /* get the one before the desktop */
2455 HeapFree( GetProcessHeap(), 0, list );
2457 if (ret && type == GA_ROOTOWNER)
2461 HWND owner = GetWindow( ret, GW_OWNER );
2470 /*****************************************************************
2471 * SetParent (USER32.@)
2473 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2476 HWND retvalue, full_handle;
2479 if (!parent) parent = GetDesktopWindow();
2480 else parent = WIN_GetFullHandle( parent );
2482 if (!IsWindow( parent ))
2484 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2488 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2489 return SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2493 if (USER_Driver.pSetParent)
2494 return USER_Driver.pSetParent( hwnd, parent );
2496 /* Windows hides the window first, then shows it again
2497 * including the WM_SHOWWINDOW messages and all */
2498 was_visible = ShowWindow( hwnd, SW_HIDE );
2500 if (!IsWindow( parent )) return 0;
2501 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2503 retvalue = wndPtr->parent; /* old parent */
2504 if (parent != retvalue)
2506 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2508 if (parent != GetDesktopWindow()) /* a child window */
2510 if (!(wndPtr->dwStyle & WS_CHILD))
2512 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2513 if (menu) DestroyMenu( menu );
2517 WIN_ReleasePtr( wndPtr );
2519 /* SetParent additionally needs to make hwnd the topmost window
2520 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2521 WM_WINDOWPOSCHANGED notification messages.
2523 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2524 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2525 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2526 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2531 /*******************************************************************
2532 * IsChild (USER32.@)
2534 BOOL WINAPI IsChild( HWND parent, HWND child )
2536 HWND *list = WIN_ListParents( child );
2540 if (!list) return FALSE;
2541 parent = WIN_GetFullHandle( parent );
2542 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2543 ret = (list[i] != 0);
2544 HeapFree( GetProcessHeap(), 0, list );
2549 /***********************************************************************
2550 * IsWindowVisible (USER32.@)
2552 BOOL WINAPI IsWindowVisible( HWND hwnd )
2558 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2559 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2560 for (i = 0; list[i]; i++)
2561 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2563 HeapFree( GetProcessHeap(), 0, list );
2568 /***********************************************************************
2569 * WIN_IsWindowDrawable
2571 * hwnd is drawable when it is visible, all parents are not
2572 * minimized, and it is itself not minimized unless we are
2573 * trying to draw its default class icon.
2575 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2580 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2582 if (!(style & WS_VISIBLE)) return FALSE;
2583 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2585 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2586 for (i = 0; list[i]; i++)
2587 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2590 HeapFree( GetProcessHeap(), 0, list );
2595 /*******************************************************************
2596 * GetTopWindow (USER32.@)
2598 HWND WINAPI GetTopWindow( HWND hwnd )
2600 if (!hwnd) hwnd = GetDesktopWindow();
2601 return GetWindow( hwnd, GW_CHILD );
2605 /*******************************************************************
2606 * GetWindow (USER32.@)
2608 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2612 if (rel == GW_OWNER) /* this one may be available locally */
2614 WND *wndPtr = WIN_GetPtr( hwnd );
2617 SetLastError( ERROR_INVALID_HANDLE );
2620 if (wndPtr != WND_OTHER_PROCESS)
2622 retval = wndPtr->owner;
2623 WIN_ReleasePtr( wndPtr );
2626 /* else fall through to server call */
2629 SERVER_START_REQ( get_window_tree )
2632 if (!wine_server_call_err( req ))
2637 retval = reply->first_sibling;
2640 retval = reply->last_sibling;
2643 retval = reply->next_sibling;
2646 retval = reply->prev_sibling;
2649 retval = reply->owner;
2652 retval = reply->first_child;
2662 /***********************************************************************
2663 * WIN_InternalShowOwnedPopups
2665 * Internal version of ShowOwnedPopups; Wine functions should use this
2666 * to avoid interfering with application calls to ShowOwnedPopups
2667 * and to make sure the application can't prevent showing/hiding.
2669 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2673 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2677 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2679 if (!win_array) return TRUE;
2682 * Show windows Lowest first, Highest last to preserve Z-Order
2684 while (win_array[count]) count++;
2685 while (--count >= 0)
2687 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2688 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2690 if (pWnd->dwStyle & WS_POPUP)
2694 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2695 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2698 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2700 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2701 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2706 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2707 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2708 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2711 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2713 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2714 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2715 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2719 WIN_ReleaseWndPtr( pWnd );
2721 HeapFree( GetProcessHeap(), 0, win_array );
2726 /*******************************************************************
2727 * ShowOwnedPopups (USER32.@)
2729 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2733 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2735 if (!win_array) return TRUE;
2737 while (win_array[count]) count++;
2738 while (--count >= 0)
2740 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2741 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2743 if (pWnd->dwStyle & WS_POPUP)
2747 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2749 /* In Windows, ShowOwnedPopups(TRUE) generates
2750 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2751 * regardless of the state of the owner
2753 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2754 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2759 if (IsWindowVisible(pWnd->hwndSelf))
2761 /* In Windows, ShowOwnedPopups(FALSE) generates
2762 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2763 * regardless of the state of the owner
2765 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2766 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2770 WIN_ReleaseWndPtr( pWnd );
2772 HeapFree( GetProcessHeap(), 0, win_array );
2777 /*******************************************************************
2778 * GetLastActivePopup (USER32.@)
2780 HWND WINAPI GetLastActivePopup( HWND hwnd )
2783 WND *wndPtr =WIN_FindWndPtr(hwnd);
2784 if (!wndPtr) return hwnd;
2785 retval = wndPtr->hwndLastActive;
2786 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2787 WIN_ReleaseWndPtr(wndPtr);
2792 /*******************************************************************
2795 * Build an array of all parents of a given window, starting with
2796 * the immediate parent. The array must be freed with HeapFree.
2797 * Returns NULL if window is a top-level window.
2799 HWND *WIN_ListParents( HWND hwnd )
2802 HWND current, *list;
2803 int pos = 0, size = 16, count = 0;
2805 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2810 if (!(win = WIN_GetPtr( current ))) goto empty;
2811 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2812 list[pos] = win->parent;
2813 WIN_ReleasePtr( win );
2814 if (!(current = list[pos]))
2816 if (!pos) goto empty;
2819 if (++pos == size - 1)
2821 /* need to grow the list */
2822 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2823 if (!new_list) goto empty;
2829 /* at least one parent belongs to another process, have to query the server */
2834 SERVER_START_REQ( get_window_parents )
2837 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2838 if (!wine_server_call( req )) count = reply->count;
2841 if (!count) goto empty;
2847 HeapFree( GetProcessHeap(), 0, list );
2849 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2853 HeapFree( GetProcessHeap(), 0, list );
2858 /*******************************************************************
2861 * Build an array of the children of a given window. The array must be
2862 * freed with HeapFree. Returns NULL when no windows are found.
2864 HWND *WIN_ListChildren( HWND hwnd )
2866 return list_window_children( hwnd, 0, 0 );
2870 /*******************************************************************
2871 * EnumWindows (USER32.@)
2873 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2879 /* We have to build a list of all windows first, to avoid */
2880 /* unpleasant side-effects, for instance if the callback */
2881 /* function changes the Z-order of the windows. */
2883 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2885 /* Now call the callback function for every window */
2887 iWndsLocks = WIN_SuspendWndsLock();
2888 for (i = 0; list[i]; i++)
2890 /* Make sure that the window still exists */
2891 if (!IsWindow( list[i] )) continue;
2892 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2894 WIN_RestoreWndsLock(iWndsLocks);
2895 HeapFree( GetProcessHeap(), 0, list );
2900 /**********************************************************************
2901 * EnumThreadWindows (USER32.@)
2903 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2908 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2911 /* Now call the callback function for every window */
2913 iWndsLocks = WIN_SuspendWndsLock();
2914 for (i = 0; list[i]; i++)
2915 if (!func( list[i], lParam )) break;
2916 WIN_RestoreWndsLock(iWndsLocks);
2917 HeapFree( GetProcessHeap(), 0, list );
2922 /**********************************************************************
2923 * WIN_EnumChildWindows
2925 * Helper function for EnumChildWindows().
2927 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2932 for ( ; *list; list++)
2934 /* Make sure that the window still exists */
2935 if (!IsWindow( *list )) continue;
2936 /* skip owned windows */
2937 if (GetWindow( *list, GW_OWNER )) continue;
2938 /* Build children list first */
2939 childList = WIN_ListChildren( *list );
2941 ret = func( *list, lParam );
2945 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2946 HeapFree( GetProcessHeap(), 0, childList );
2948 if (!ret) return FALSE;
2954 /**********************************************************************
2955 * EnumChildWindows (USER32.@)
2957 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2962 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2963 iWndsLocks = WIN_SuspendWndsLock();
2964 WIN_EnumChildWindows( list, func, lParam );
2965 WIN_RestoreWndsLock(iWndsLocks);
2966 HeapFree( GetProcessHeap(), 0, list );
2971 /*******************************************************************
2972 * AnyPopup (USER.52)
2974 BOOL16 WINAPI AnyPopup16(void)
2980 /*******************************************************************
2981 * AnyPopup (USER32.@)
2983 BOOL WINAPI AnyPopup(void)
2987 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2989 if (!list) return FALSE;
2990 for (i = 0; list[i]; i++)
2992 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2994 retvalue = (list[i] != 0);
2995 HeapFree( GetProcessHeap(), 0, list );
3000 /*******************************************************************
3001 * FlashWindow (USER32.@)
3003 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3005 WND *wndPtr = WIN_FindWndPtr(hWnd);
3007 TRACE("%04x\n", hWnd);
3009 if (!wndPtr) return FALSE;
3010 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3012 if (wndPtr->dwStyle & WS_MINIMIZE)
3014 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3016 HDC hDC = GetDC(hWnd);
3018 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3019 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3021 ReleaseDC( hWnd, hDC );
3022 wndPtr->flags |= WIN_NCACTIVATED;
3026 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3027 wndPtr->flags &= ~WIN_NCACTIVATED;
3029 WIN_ReleaseWndPtr(wndPtr);
3035 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3036 else wparam = (hWnd == GetActiveWindow());
3038 WIN_ReleaseWndPtr(wndPtr);
3039 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3045 /*******************************************************************
3046 * GetWindowContextHelpId (USER32.@)
3048 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3051 WND *wnd = WIN_FindWndPtr( hwnd );
3053 retval = wnd->helpContext;
3054 WIN_ReleaseWndPtr(wnd);
3059 /*******************************************************************
3060 * SetWindowContextHelpId (USER32.@)
3062 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3064 WND *wnd = WIN_FindWndPtr( hwnd );
3065 if (!wnd) return FALSE;
3066 wnd->helpContext = id;
3067 WIN_ReleaseWndPtr(wnd);
3072 /*******************************************************************
3075 * recursively find a child that contains spDragInfo->pt point
3076 * and send WM_QUERYDROPOBJECT
3078 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3080 BOOL16 wParam, bResult = 0;
3082 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3085 if (!ptrDragInfo) return FALSE;
3087 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3089 GetWindowRect(hQueryWnd,&tempRect);
3091 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3093 if (!IsIconic( hQueryWnd ))
3095 GetClientRect( hQueryWnd, &tempRect );
3096 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3098 if (PtInRect( &tempRect, pt))
3101 HWND *list = WIN_ListChildren( hQueryWnd );
3107 for (i = 0; list[i]; i++)
3109 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3111 GetWindowRect( list[i], &tempRect );
3112 if (PtInRect( &tempRect, pt )) break;
3117 if (IsWindowEnabled( list[i] ))
3118 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
3120 HeapFree( GetProcessHeap(), 0, list );
3122 if(bResult) return bResult;
3128 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3130 ptrDragInfo->hScope = hQueryWnd;
3132 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3133 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3135 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3141 /*******************************************************************
3142 * DragDetect (USER32.@)
3144 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3149 rect.left = pt.x - wDragWidth;
3150 rect.right = pt.x + wDragWidth;
3152 rect.top = pt.y - wDragHeight;
3153 rect.bottom = pt.y + wDragHeight;
3159 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3161 if( msg.message == WM_LBUTTONUP )
3166 if( msg.message == WM_MOUSEMOVE )
3169 tmp.x = LOWORD(msg.lParam);
3170 tmp.y = HIWORD(msg.lParam);
3171 if( !PtInRect( &rect, tmp ))
3183 /******************************************************************************
3184 * DragObject (USER.464)
3186 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3187 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3190 LPDRAGINFO16 lpDragInfo;
3192 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3193 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3194 HCURSOR16 hCurrentCursor = 0;
3195 HWND16 hCurrentWnd = 0;
3197 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3198 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3200 if( !lpDragInfo || !spDragInfo ) return 0L;
3202 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3204 GlobalFree16(hDragInfo);
3210 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3212 GlobalFree16(hDragInfo);
3216 if( hDragCursor == hCursor ) hDragCursor = 0;
3217 else hCursor = hDragCursor;
3219 hOldCursor = SetCursor(hDragCursor);
3222 lpDragInfo->hWnd = hWnd;
3223 lpDragInfo->hScope = 0;
3224 lpDragInfo->wFlags = wObj;
3225 lpDragInfo->hList = szList; /* near pointer! */
3226 lpDragInfo->hOfStruct = hOfStruct;
3234 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3236 *(lpDragInfo+1) = *lpDragInfo;
3238 lpDragInfo->pt.x = msg.pt.x;
3239 lpDragInfo->pt.y = msg.pt.y;
3241 /* update DRAGINFO struct */
3242 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3244 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3245 hCurrentCursor = hCursor;
3248 hCurrentCursor = hBummer;
3249 lpDragInfo->hScope = 0;
3251 if( hCurrentCursor )
3252 SetCursor(hCurrentCursor);
3254 /* send WM_DRAGLOOP */
3255 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3256 (LPARAM) spDragInfo );
3257 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3258 if( hCurrentWnd != lpDragInfo->hScope )
3261 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3262 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3263 HIWORD(spDragInfo)) );
3264 hCurrentWnd = lpDragInfo->hScope;
3266 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3270 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3272 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3275 ShowCursor( FALSE );
3279 SetCursor( hOldCursor );
3280 if (hDragCursor) DestroyCursor( hDragCursor );
3283 if( hCurrentCursor != hBummer )
3284 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3285 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3288 GlobalFree16(hDragInfo);
3290 return (DWORD)(msg.lParam);
3294 /******************************************************************************
3295 * GetWindowModuleFileNameA (USER32.@)
3297 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3299 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3300 hwnd, lpszFileName, cchFileNameMax);
3304 /******************************************************************************
3305 * GetWindowModuleFileNameW (USER32.@)
3307 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3309 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3310 hwnd, lpszFileName, cchFileNameMax);