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, hwndLinkAfter, 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 /* Call the WH_CBT hook */
1072 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
1073 ? HWND_BOTTOM : HWND_TOP;
1075 if (HOOK_IsHooked( WH_CBT ))
1077 CBT_CREATEWNDA cbtc;
1081 cbtc.hwndInsertAfter = hwndLinkAfter;
1082 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND,
1083 (WPARAM)hwnd, (LPARAM)&cbtc)
1084 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND,
1085 (WPARAM)hwnd, (LPARAM)&cbtc);
1088 TRACE("CBT-hook returned 0\n");
1089 free_window_handle( hwnd );
1090 CLASS_RemoveWindow( classPtr );
1091 WIN_ReleaseWndPtr(wndPtr);
1096 /* Correct the window style - stage 2 */
1098 if (!(cs->style & WS_CHILD))
1100 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1101 if (!(cs->style & WS_POPUP))
1103 wndPtr->dwStyle |= WS_CAPTION;
1104 wndPtr->flags |= WIN_NEED_SIZE;
1107 SERVER_START_REQ( set_window_info )
1110 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1111 req->style = wndPtr->dwStyle;
1112 req->ex_style = wndPtr->dwExStyle;
1113 req->instance = (void *)wndPtr->hInstance;
1114 wine_server_call( req );
1118 /* Get class or window DC if needed */
1120 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1121 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1122 else wndPtr->dce = NULL;
1124 /* Set the window menu */
1126 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1128 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1131 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1134 if (HIWORD(cs->hInstance))
1135 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1137 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1139 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1143 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1144 WIN_ReleaseWndPtr( wndPtr );
1146 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1148 WIN_DestroyWindow( hwnd );
1152 /* Notify the parent window only */
1154 send_parent_notify( hwnd, WM_CREATE );
1155 if (!IsWindow( hwnd )) return 0;
1157 if (cs->style & WS_VISIBLE)
1159 /* in case WS_VISIBLE got set in the meantime */
1160 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1161 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1162 WIN_ReleasePtr( wndPtr );
1163 ShowWindow( hwnd, sw );
1166 /* Call WH_SHELL hook */
1168 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1169 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1171 TRACE("created window %04x\n", hwnd);
1176 /***********************************************************************
1177 * CreateWindow (USER.41)
1179 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1180 DWORD style, INT16 x, INT16 y, INT16 width,
1181 INT16 height, HWND16 parent, HMENU16 menu,
1182 HINSTANCE16 instance, LPVOID data )
1184 return CreateWindowEx16( 0, className, windowName, style,
1185 x, y, width, height, parent, menu, instance, data );
1189 /***********************************************************************
1190 * CreateWindowEx (USER.452)
1192 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1193 LPCSTR windowName, DWORD style, INT16 x,
1194 INT16 y, INT16 width, INT16 height,
1195 HWND16 parent, HMENU16 menu,
1196 HINSTANCE16 instance, LPVOID data )
1202 /* Find the class atom */
1204 if (HIWORD(className))
1206 if (!(classAtom = GlobalFindAtomA( className )))
1208 ERR( "bad class name %s\n", debugres_a(className) );
1214 classAtom = LOWORD(className);
1215 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1217 ERR( "bad atom %x\n", classAtom);
1223 /* Fix the coordinates */
1225 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1226 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1227 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1228 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1230 /* Create the window */
1232 cs.lpCreateParams = data;
1233 cs.hInstance = (HINSTANCE)instance;
1234 cs.hMenu = (HMENU)menu;
1235 cs.hwndParent = WIN_Handle32( parent );
1237 cs.lpszName = windowName;
1238 cs.lpszClass = className;
1239 cs.dwExStyle = exStyle;
1241 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1245 /***********************************************************************
1246 * CreateWindowExA (USER32.@)
1248 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1249 LPCSTR windowName, DWORD style, INT x,
1250 INT y, INT width, INT height,
1251 HWND parent, HMENU menu,
1252 HINSTANCE instance, LPVOID data )
1259 instance=GetModuleHandleA(NULL);
1261 if(exStyle & WS_EX_MDICHILD)
1262 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1264 /* Find the class atom */
1266 if (HIWORD(className))
1268 if (!(classAtom = GlobalFindAtomA( className )))
1270 ERR( "bad class name %s\n", debugres_a(className) );
1276 classAtom = LOWORD(className);
1277 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1279 ERR( "bad atom %x\n", classAtom);
1285 /* Create the window */
1287 cs.lpCreateParams = data;
1288 cs.hInstance = instance;
1290 cs.hwndParent = parent;
1296 cs.lpszName = windowName;
1297 cs.lpszClass = className;
1298 cs.dwExStyle = exStyle;
1300 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1304 /***********************************************************************
1305 * CreateWindowExW (USER32.@)
1307 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1308 LPCWSTR windowName, DWORD style, INT x,
1309 INT y, INT width, INT height,
1310 HWND parent, HMENU menu,
1311 HINSTANCE instance, LPVOID data )
1318 instance=GetModuleHandleA(NULL);
1320 if(exStyle & WS_EX_MDICHILD)
1321 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1323 /* Find the class atom */
1325 if (HIWORD(className))
1327 if (!(classAtom = GlobalFindAtomW( className )))
1329 ERR( "bad class name %s\n", debugres_w(className) );
1335 classAtom = LOWORD(className);
1336 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1338 ERR( "bad atom %x\n", classAtom);
1344 /* Create the window */
1346 cs.lpCreateParams = data;
1347 cs.hInstance = instance;
1349 cs.hwndParent = parent;
1355 cs.lpszName = windowName;
1356 cs.lpszClass = className;
1357 cs.dwExStyle = exStyle;
1359 /* Note: we rely on the fact that CREATESTRUCTA and */
1360 /* CREATESTRUCTW have the same layout. */
1361 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1365 /***********************************************************************
1366 * WIN_SendDestroyMsg
1368 static void WIN_SendDestroyMsg( HWND hwnd )
1370 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1371 if (USER_Driver.pResetSelectionOwner)
1372 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1375 * Send the WM_DESTROY to the window.
1377 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1380 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1381 * make sure that the window still exists when we come back.
1388 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1390 /* start from the end (FIXME: is this needed?) */
1391 for (i = 0; pWndArray[i]; i++) ;
1395 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1397 HeapFree( GetProcessHeap(), 0, pWndArray );
1400 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1404 /***********************************************************************
1405 * DestroyWindow (USER32.@)
1407 BOOL WINAPI DestroyWindow( HWND hwnd )
1412 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1414 SetLastError( ERROR_ACCESS_DENIED );
1418 TRACE("(%04x)\n", hwnd);
1420 /* Look whether the focus is within the tree of windows we will
1424 if (h == hwnd || IsChild( hwnd, h ))
1426 HWND parent = GetAncestor( hwnd, GA_PARENT );
1427 if (parent == GetDesktopWindow()) parent = 0;
1433 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1435 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1439 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1440 send_parent_notify( hwnd, WM_DESTROY );
1442 else if (!GetWindow( hwnd, GW_OWNER ))
1444 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1445 /* FIXME: clean up palette - see "Internals" p.352 */
1448 if (!IsWindow(hwnd)) return TRUE;
1450 if (USER_Driver.pResetSelectionOwner)
1451 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1453 /* Hide the window */
1455 ShowWindow( hwnd, SW_HIDE );
1456 if (!IsWindow(hwnd)) return TRUE;
1458 /* Recursively destroy owned windows */
1467 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1470 for (i = 0; list[i]; i++)
1472 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1473 if (WIN_IsCurrentThread( list[i] ))
1475 DestroyWindow( list[i] );
1479 WIN_SetOwner( list[i], 0 );
1481 HeapFree( GetProcessHeap(), 0, list );
1483 if (!got_one) break;
1486 WINPOS_ActivateOtherWindow( hwnd );
1488 if ((owner = GetWindow( hwnd, GW_OWNER )))
1490 WND *ptr = WIN_FindWndPtr( owner );
1493 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1494 WIN_ReleaseWndPtr( ptr );
1499 /* Send destroy messages */
1501 WIN_SendDestroyMsg( hwnd );
1502 if (!IsWindow( hwnd )) return TRUE;
1504 /* Unlink now so we won't bother with the children later on */
1506 WIN_UnlinkWindow( hwnd );
1508 /* Destroy the window storage */
1510 WIN_DestroyWindow( hwnd );
1515 /***********************************************************************
1516 * CloseWindow (USER32.@)
1518 BOOL WINAPI CloseWindow( HWND hwnd )
1520 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1521 ShowWindow( hwnd, SW_MINIMIZE );
1526 /***********************************************************************
1527 * OpenIcon (USER32.@)
1529 BOOL WINAPI OpenIcon( HWND hwnd )
1531 if (!IsIconic( hwnd )) return FALSE;
1532 ShowWindow( hwnd, SW_SHOWNORMAL );
1537 /***********************************************************************
1540 * Implementation of FindWindow() and FindWindowEx().
1542 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1547 WCHAR *buffer = NULL;
1549 if (!parent) parent = GetDesktopWindow();
1552 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1553 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1556 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1560 child = WIN_GetFullHandle( child );
1561 while (list[i] && list[i] != child) i++;
1562 if (!list[i]) goto done;
1563 i++; /* start from next window */
1570 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1577 if (list) HeapFree( GetProcessHeap(), 0, list );
1578 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1584 /***********************************************************************
1585 * FindWindowA (USER32.@)
1587 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1589 HWND ret = FindWindowExA( 0, 0, className, title );
1590 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1595 /***********************************************************************
1596 * FindWindowExA (USER32.@)
1598 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1599 LPCSTR className, LPCSTR title )
1608 /* If the atom doesn't exist, then no class */
1609 /* with this name exists either. */
1610 if (!(atom = GlobalFindAtomA( className )))
1612 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1616 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1618 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1619 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1620 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1621 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1622 HeapFree( GetProcessHeap(), 0, buffer );
1627 /***********************************************************************
1628 * FindWindowExW (USER32.@)
1630 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1631 LPCWSTR className, LPCWSTR title )
1637 /* If the atom doesn't exist, then no class */
1638 /* with this name exists either. */
1639 if (!(atom = GlobalFindAtomW( className )))
1641 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1645 return WIN_FindWindow( parent, child, atom, title );
1649 /***********************************************************************
1650 * FindWindowW (USER32.@)
1652 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1654 return FindWindowExW( 0, 0, className, title );
1658 /**********************************************************************
1659 * GetDesktopWindow (USER32.@)
1661 HWND WINAPI GetDesktopWindow(void)
1663 if (pWndDesktop) return pWndDesktop->hwndSelf;
1664 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" );
1670 /*******************************************************************
1671 * EnableWindow (USER32.@)
1673 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1680 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1681 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1685 TRACE("( %x, %d )\n", hwnd, enable);
1687 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1688 style = wndPtr->dwStyle;
1689 retvalue = ((style & WS_DISABLED) != 0);
1690 WIN_ReleasePtr( wndPtr );
1692 if (enable && retvalue)
1694 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1695 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1697 else if (!enable && !retvalue)
1699 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1701 WIN_SetStyle( hwnd, style | WS_DISABLED );
1703 if (hwnd == GetFocus())
1704 SetFocus( 0 ); /* A disabled window can't have the focus */
1706 if (hwnd == GetCapture())
1707 ReleaseCapture(); /* A disabled window can't capture the mouse */
1709 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1715 /***********************************************************************
1716 * IsWindowEnabled (USER32.@)
1718 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1720 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1724 /***********************************************************************
1725 * IsWindowUnicode (USER32.@)
1727 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1732 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1733 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1734 WIN_ReleaseWndPtr(wndPtr);
1739 /**********************************************************************
1740 * GetWindowWord (USER32.@)
1742 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1747 WND *wndPtr = WIN_GetPtr( hwnd );
1750 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1753 if (wndPtr == WND_OTHER_PROCESS)
1755 if (IsWindow( hwnd ))
1756 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1757 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1760 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1762 WARN("Invalid offset %d\n", offset );
1763 SetLastError( ERROR_INVALID_INDEX );
1765 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1766 WIN_ReleasePtr( wndPtr );
1772 case GWL_HWNDPARENT:
1773 return GetWindowLongW( hwnd, offset );
1777 LONG ret = GetWindowLongW( hwnd, offset );
1779 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1783 WARN("Invalid offset %d\n", offset );
1789 /**********************************************************************
1790 * SetWindowWord (USER32.@)
1792 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1801 case GWL_HWNDPARENT:
1802 return SetWindowLongW( hwnd, offset, (UINT)newval );
1806 WARN("Invalid offset %d\n", offset );
1807 SetLastError( ERROR_INVALID_INDEX );
1812 wndPtr = WIN_GetPtr( hwnd );
1813 if (wndPtr == WND_OTHER_PROCESS)
1816 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1817 offset, newval, hwnd );
1822 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1826 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1828 WARN("Invalid offset %d\n", offset );
1829 WIN_ReleasePtr(wndPtr);
1830 SetLastError( ERROR_INVALID_INDEX );
1833 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1836 WIN_ReleasePtr(wndPtr);
1841 /**********************************************************************
1844 * Helper function for GetWindowLong().
1846 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1851 if (offset == GWL_HWNDPARENT) return (LONG)GetParent( hwnd );
1853 if (!(wndPtr = WIN_GetPtr( hwnd )))
1855 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1859 if (wndPtr == WND_OTHER_PROCESS)
1864 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1865 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1868 if (offset == GWL_WNDPROC)
1870 SetLastError( ERROR_ACCESS_DENIED );
1873 SERVER_START_REQ( set_window_info )
1876 req->flags = 0; /* don't set anything, just retrieve */
1877 if (!wine_server_call_err( req ))
1881 case GWL_STYLE: retvalue = reply->old_style; break;
1882 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1883 case GWL_ID: retvalue = reply->old_id; break;
1884 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1885 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1887 SetLastError( ERROR_INVALID_INDEX );
1896 /* now we have a valid wndPtr */
1900 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1902 WARN("Invalid offset %d\n", offset );
1903 WIN_ReleasePtr( wndPtr );
1904 SetLastError( ERROR_INVALID_INDEX );
1907 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1908 /* Special case for dialog window procedure */
1909 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1910 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1911 WIN_ReleasePtr( wndPtr );
1917 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1918 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1919 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1920 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1921 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1922 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1924 WARN("Unknown offset %d\n", offset );
1925 SetLastError( ERROR_INVALID_INDEX );
1928 WIN_ReleasePtr(wndPtr);
1933 /**********************************************************************
1936 * Helper function for SetWindowLong().
1938 * 0 is the failure code. However, in the case of failure SetLastError
1939 * must be set to distinguish between a 0 return value and a failure.
1941 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1942 WINDOWPROCTYPE type )
1947 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1949 if (!WIN_IsCurrentProcess( hwnd ))
1951 if (offset == GWL_WNDPROC)
1953 SetLastError( ERROR_ACCESS_DENIED );
1956 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1959 wndPtr = WIN_GetPtr( hwnd );
1963 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1964 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1966 WARN("Invalid offset %d\n", offset );
1967 WIN_ReleasePtr( wndPtr );
1968 SetLastError( ERROR_INVALID_INDEX );
1971 /* Special case for dialog window procedure */
1972 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1974 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1975 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1976 type, WIN_PROC_WINDOW );
1977 WIN_ReleasePtr( wndPtr );
1982 WIN_ReleasePtr( wndPtr );
1989 /* first some special cases */
1994 style.styleOld = wndPtr->dwStyle;
1995 style.styleNew = newval;
1996 WIN_ReleasePtr( wndPtr );
1997 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1998 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1999 newval = style.styleNew;
2001 case GWL_HWNDPARENT:
2002 WIN_ReleasePtr( wndPtr );
2003 return (LONG)SetParent( hwnd, (HWND)newval );
2005 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2006 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2007 type, WIN_PROC_WINDOW );
2008 WIN_ReleasePtr( wndPtr );
2015 WIN_ReleasePtr( wndPtr );
2016 WARN("Invalid offset %d\n", offset );
2017 SetLastError( ERROR_INVALID_INDEX );
2021 SERVER_START_REQ( set_window_info )
2027 req->flags = SET_WIN_STYLE;
2028 req->style = newval;
2031 req->flags = SET_WIN_EXSTYLE;
2032 req->ex_style = newval;
2035 req->flags = SET_WIN_ID;
2039 req->flags = SET_WIN_INSTANCE;
2040 req->instance = (void *)newval;
2043 req->flags = SET_WIN_USERDATA;
2044 req->user_data = (void *)newval;
2047 if ((ok = !wine_server_call_err( req )))
2052 wndPtr->dwStyle = newval;
2053 retval = reply->old_style;
2056 wndPtr->dwExStyle = newval;
2057 retval = reply->old_ex_style;
2060 wndPtr->wIDmenu = newval;
2061 retval = reply->old_id;
2064 wndPtr->hInstance = newval;
2065 retval = (HINSTANCE)reply->old_instance;
2068 wndPtr->userdata = newval;
2069 retval = (ULONG_PTR)reply->old_user_data;
2075 WIN_ReleasePtr( wndPtr );
2079 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2080 USER_Driver.pSetWindowStyle( hwnd, retval );
2082 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2083 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2090 /**********************************************************************
2091 * GetWindowLong (USER.135)
2093 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2095 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2099 /**********************************************************************
2100 * GetWindowLongA (USER32.@)
2102 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2104 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2108 /**********************************************************************
2109 * GetWindowLongW (USER32.@)
2111 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2113 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2117 /**********************************************************************
2118 * SetWindowLong (USER.136)
2120 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2122 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2126 /**********************************************************************
2127 * SetWindowLongA (USER32.@)
2129 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2131 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2135 /**********************************************************************
2136 * SetWindowLongW (USER32.@) Set window attribute
2138 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2139 * value in a window's extra memory.
2141 * The _hwnd_ parameter specifies the window. is the handle to a
2142 * window that has extra memory. The _newval_ parameter contains the
2143 * new attribute or extra memory value. If positive, the _offset_
2144 * parameter is the byte-addressed location in the window's extra
2145 * memory to set. If negative, _offset_ specifies the window
2146 * attribute to set, and should be one of the following values:
2148 * GWL_EXSTYLE The window's extended window style
2150 * GWL_STYLE The window's window style.
2152 * GWL_WNDPROC Pointer to the window's window procedure.
2154 * GWL_HINSTANCE The window's pplication instance handle.
2156 * GWL_ID The window's identifier.
2158 * GWL_USERDATA The window's user-specified data.
2160 * If the window is a dialog box, the _offset_ parameter can be one of
2161 * the following values:
2163 * DWL_DLGPROC The address of the window's dialog box procedure.
2165 * DWL_MSGRESULT The return value of a message
2166 * that the dialog box procedure processed.
2168 * DWL_USER Application specific information.
2172 * If successful, returns the previous value located at _offset_. Otherwise,
2177 * Extra memory for a window class is specified by a nonzero cbWndExtra
2178 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2179 * time of class creation.
2181 * Using GWL_WNDPROC to set a new window procedure effectively creates
2182 * a window subclass. Use CallWindowProc() in the new windows procedure
2183 * to pass messages to the superclass's window procedure.
2185 * The user data is reserved for use by the application which created
2188 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2189 * instead, call the EnableWindow() function to change the window's
2192 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2193 * SetParent() instead.
2196 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2197 * it sends WM_STYLECHANGING before changing the settings
2198 * and WM_STYLECHANGED afterwards.
2199 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2201 LONG WINAPI SetWindowLongW(
2202 HWND hwnd, /* [in] window to alter */
2203 INT offset, /* [in] offset, in bytes, of location to alter */
2204 LONG newval /* [in] new value of location */
2206 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2210 /*******************************************************************
2211 * GetWindowTextA (USER32.@)
2213 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2217 if (WIN_IsCurrentProcess( hwnd ))
2218 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2220 /* when window belongs to other process, don't send a message */
2221 if (nMaxCount <= 0) return 0;
2222 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2223 get_server_window_text( hwnd, buffer, nMaxCount );
2224 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2225 lpString[nMaxCount-1] = 0;
2226 HeapFree( GetProcessHeap(), 0, buffer );
2227 return strlen(lpString);
2231 /*******************************************************************
2232 * InternalGetWindowText (USER32.@)
2234 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2238 if (nMaxCount <= 0) return 0;
2239 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2240 if (win != WND_OTHER_PROCESS)
2242 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2243 else lpString[0] = 0;
2244 WIN_ReleasePtr( win );
2248 get_server_window_text( hwnd, lpString, nMaxCount );
2250 return strlenW(lpString);
2254 /*******************************************************************
2255 * GetWindowTextW (USER32.@)
2257 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2259 if (WIN_IsCurrentProcess( hwnd ))
2260 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2262 /* when window belongs to other process, don't send a message */
2263 if (nMaxCount <= 0) return 0;
2264 get_server_window_text( hwnd, lpString, nMaxCount );
2265 return strlenW(lpString);
2269 /*******************************************************************
2270 * SetWindowText (USER32.@)
2271 * SetWindowTextA (USER32.@)
2273 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2275 if (!WIN_IsCurrentProcess( hwnd ))
2277 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2278 SetLastError( ERROR_ACCESS_DENIED );
2281 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2285 /*******************************************************************
2286 * SetWindowTextW (USER32.@)
2288 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2290 if (!WIN_IsCurrentProcess( hwnd ))
2292 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2293 SetLastError( ERROR_ACCESS_DENIED );
2296 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2300 /*******************************************************************
2301 * GetWindowTextLengthA (USER32.@)
2303 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2305 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2308 /*******************************************************************
2309 * GetWindowTextLengthW (USER32.@)
2311 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2313 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2317 /*******************************************************************
2318 * IsWindow (USER32.@)
2320 BOOL WINAPI IsWindow( HWND hwnd )
2325 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2327 if (ptr != WND_OTHER_PROCESS)
2329 WIN_ReleasePtr( ptr );
2333 /* check other processes */
2334 SERVER_START_REQ( get_window_info )
2337 ret = !wine_server_call_err( req );
2344 /***********************************************************************
2345 * GetWindowThreadProcessId (USER32.@)
2347 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2352 if (!(ptr = WIN_GetPtr( hwnd )))
2354 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2358 if (ptr != WND_OTHER_PROCESS)
2360 /* got a valid window */
2362 if (process) *process = GetCurrentProcessId();
2363 WIN_ReleasePtr( ptr );
2367 /* check other processes */
2368 SERVER_START_REQ( get_window_info )
2371 if (!wine_server_call_err( req ))
2373 tid = (DWORD)reply->tid;
2374 if (process) *process = (DWORD)reply->pid;
2382 /*****************************************************************
2383 * GetParent (USER32.@)
2385 HWND WINAPI GetParent( HWND hwnd )
2390 if (!(wndPtr = WIN_GetPtr( hwnd )))
2392 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2395 if (wndPtr == WND_OTHER_PROCESS)
2397 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2398 if (style & (WS_POPUP | WS_CHILD))
2400 SERVER_START_REQ( get_window_tree )
2403 if (!wine_server_call_err( req ))
2405 if (style & WS_CHILD) retvalue = reply->parent;
2406 else retvalue = reply->owner;
2414 if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2415 else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2416 WIN_ReleasePtr( wndPtr );
2422 /*****************************************************************
2423 * GetAncestor (USER32.@)
2425 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2428 HWND *list, ret = 0;
2430 if (type == GA_PARENT)
2432 if (!(win = WIN_GetPtr( hwnd )))
2434 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2437 if (win != WND_OTHER_PROCESS)
2440 WIN_ReleasePtr( win );
2442 else /* need to query the server */
2444 SERVER_START_REQ( get_window_tree )
2447 if (!wine_server_call_err( req )) ret = reply->parent;
2454 if (!(list = WIN_ListParents( hwnd ))) return 0;
2456 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2460 while (list[count]) count++;
2461 ret = list[count - 2]; /* get the one before the desktop */
2463 HeapFree( GetProcessHeap(), 0, list );
2465 if (ret && type == GA_ROOTOWNER)
2469 HWND owner = GetWindow( ret, GW_OWNER );
2478 /*****************************************************************
2479 * SetParent (USER32.@)
2481 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2484 HWND retvalue, full_handle;
2487 if (!parent) parent = GetDesktopWindow();
2488 else parent = WIN_GetFullHandle( parent );
2490 if (!IsWindow( parent ))
2492 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2496 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2497 return SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2501 if (USER_Driver.pSetParent)
2502 return USER_Driver.pSetParent( hwnd, parent );
2504 /* Windows hides the window first, then shows it again
2505 * including the WM_SHOWWINDOW messages and all */
2506 was_visible = ShowWindow( hwnd, SW_HIDE );
2508 if (!IsWindow( parent )) return 0;
2509 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2511 retvalue = wndPtr->parent; /* old parent */
2512 if (parent != retvalue)
2514 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2516 if (parent != GetDesktopWindow()) /* a child window */
2518 if (!(wndPtr->dwStyle & WS_CHILD))
2520 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2521 if (menu) DestroyMenu( menu );
2525 WIN_ReleasePtr( wndPtr );
2527 /* SetParent additionally needs to make hwnd the topmost window
2528 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2529 WM_WINDOWPOSCHANGED notification messages.
2531 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2532 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2533 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2534 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2539 /*******************************************************************
2540 * IsChild (USER32.@)
2542 BOOL WINAPI IsChild( HWND parent, HWND child )
2544 HWND *list = WIN_ListParents( child );
2548 if (!list) return FALSE;
2549 parent = WIN_GetFullHandle( parent );
2550 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2551 ret = (list[i] != 0);
2552 HeapFree( GetProcessHeap(), 0, list );
2557 /***********************************************************************
2558 * IsWindowVisible (USER32.@)
2560 BOOL WINAPI IsWindowVisible( HWND hwnd )
2566 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2567 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2568 for (i = 0; list[i]; i++)
2569 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2571 HeapFree( GetProcessHeap(), 0, list );
2576 /***********************************************************************
2577 * WIN_IsWindowDrawable
2579 * hwnd is drawable when it is visible, all parents are not
2580 * minimized, and it is itself not minimized unless we are
2581 * trying to draw its default class icon.
2583 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2588 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2590 if (!(style & WS_VISIBLE)) return FALSE;
2591 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2593 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2594 for (i = 0; list[i]; i++)
2595 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2598 HeapFree( GetProcessHeap(), 0, list );
2603 /*******************************************************************
2604 * GetTopWindow (USER32.@)
2606 HWND WINAPI GetTopWindow( HWND hwnd )
2608 if (!hwnd) hwnd = GetDesktopWindow();
2609 return GetWindow( hwnd, GW_CHILD );
2613 /*******************************************************************
2614 * GetWindow (USER32.@)
2616 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2620 if (rel == GW_OWNER) /* this one may be available locally */
2622 WND *wndPtr = WIN_GetPtr( hwnd );
2625 SetLastError( ERROR_INVALID_HANDLE );
2628 if (wndPtr != WND_OTHER_PROCESS)
2630 retval = wndPtr->owner;
2631 WIN_ReleasePtr( wndPtr );
2634 /* else fall through to server call */
2637 SERVER_START_REQ( get_window_tree )
2640 if (!wine_server_call_err( req ))
2645 retval = reply->first_sibling;
2648 retval = reply->last_sibling;
2651 retval = reply->next_sibling;
2654 retval = reply->prev_sibling;
2657 retval = reply->owner;
2660 retval = reply->first_child;
2670 /***********************************************************************
2671 * WIN_InternalShowOwnedPopups
2673 * Internal version of ShowOwnedPopups; Wine functions should use this
2674 * to avoid interfering with application calls to ShowOwnedPopups
2675 * and to make sure the application can't prevent showing/hiding.
2677 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2681 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2685 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2687 if (!win_array) return TRUE;
2690 * Show windows Lowest first, Highest last to preserve Z-Order
2692 while (win_array[count]) count++;
2693 while (--count >= 0)
2695 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2696 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2698 if (pWnd->dwStyle & WS_POPUP)
2702 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2703 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2706 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2708 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2709 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2714 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2715 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2716 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2719 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2721 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2722 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2723 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2727 WIN_ReleaseWndPtr( pWnd );
2729 HeapFree( GetProcessHeap(), 0, win_array );
2734 /*******************************************************************
2735 * ShowOwnedPopups (USER32.@)
2737 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2741 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2743 if (!win_array) return TRUE;
2745 while (win_array[count]) count++;
2746 while (--count >= 0)
2748 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2749 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2751 if (pWnd->dwStyle & WS_POPUP)
2755 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2757 /* In Windows, ShowOwnedPopups(TRUE) generates
2758 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2759 * regardless of the state of the owner
2761 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2762 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2767 if (IsWindowVisible(pWnd->hwndSelf))
2769 /* In Windows, ShowOwnedPopups(FALSE) generates
2770 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2771 * regardless of the state of the owner
2773 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2774 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2778 WIN_ReleaseWndPtr( pWnd );
2780 HeapFree( GetProcessHeap(), 0, win_array );
2785 /*******************************************************************
2786 * GetLastActivePopup (USER32.@)
2788 HWND WINAPI GetLastActivePopup( HWND hwnd )
2791 WND *wndPtr =WIN_FindWndPtr(hwnd);
2792 if (!wndPtr) return hwnd;
2793 retval = wndPtr->hwndLastActive;
2794 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2795 WIN_ReleaseWndPtr(wndPtr);
2800 /*******************************************************************
2803 * Build an array of all parents of a given window, starting with
2804 * the immediate parent. The array must be freed with HeapFree.
2805 * Returns NULL if window is a top-level window.
2807 HWND *WIN_ListParents( HWND hwnd )
2810 HWND current, *list;
2811 int pos = 0, size = 16, count = 0;
2813 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2818 if (!(win = WIN_GetPtr( current ))) goto empty;
2819 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2820 list[pos] = win->parent;
2821 WIN_ReleasePtr( win );
2822 if (!(current = list[pos]))
2824 if (!pos) goto empty;
2827 if (++pos == size - 1)
2829 /* need to grow the list */
2830 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2831 if (!new_list) goto empty;
2837 /* at least one parent belongs to another process, have to query the server */
2842 SERVER_START_REQ( get_window_parents )
2845 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2846 if (!wine_server_call( req )) count = reply->count;
2849 if (!count) goto empty;
2855 HeapFree( GetProcessHeap(), 0, list );
2857 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2861 HeapFree( GetProcessHeap(), 0, list );
2866 /*******************************************************************
2869 * Build an array of the children of a given window. The array must be
2870 * freed with HeapFree. Returns NULL when no windows are found.
2872 HWND *WIN_ListChildren( HWND hwnd )
2874 return list_window_children( hwnd, 0, 0 );
2878 /*******************************************************************
2879 * EnumWindows (USER32.@)
2881 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2887 /* We have to build a list of all windows first, to avoid */
2888 /* unpleasant side-effects, for instance if the callback */
2889 /* function changes the Z-order of the windows. */
2891 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2893 /* Now call the callback function for every window */
2895 iWndsLocks = WIN_SuspendWndsLock();
2896 for (i = 0; list[i]; i++)
2898 /* Make sure that the window still exists */
2899 if (!IsWindow( list[i] )) continue;
2900 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2902 WIN_RestoreWndsLock(iWndsLocks);
2903 HeapFree( GetProcessHeap(), 0, list );
2908 /**********************************************************************
2909 * EnumThreadWindows (USER32.@)
2911 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2916 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2919 /* Now call the callback function for every window */
2921 iWndsLocks = WIN_SuspendWndsLock();
2922 for (i = 0; list[i]; i++)
2923 if (!func( list[i], lParam )) break;
2924 WIN_RestoreWndsLock(iWndsLocks);
2925 HeapFree( GetProcessHeap(), 0, list );
2930 /**********************************************************************
2931 * WIN_EnumChildWindows
2933 * Helper function for EnumChildWindows().
2935 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2940 for ( ; *list; list++)
2942 /* Make sure that the window still exists */
2943 if (!IsWindow( *list )) continue;
2944 /* skip owned windows */
2945 if (GetWindow( *list, GW_OWNER )) continue;
2946 /* Build children list first */
2947 childList = WIN_ListChildren( *list );
2949 ret = func( *list, lParam );
2953 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2954 HeapFree( GetProcessHeap(), 0, childList );
2956 if (!ret) return FALSE;
2962 /**********************************************************************
2963 * EnumChildWindows (USER32.@)
2965 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2970 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2971 iWndsLocks = WIN_SuspendWndsLock();
2972 WIN_EnumChildWindows( list, func, lParam );
2973 WIN_RestoreWndsLock(iWndsLocks);
2974 HeapFree( GetProcessHeap(), 0, list );
2979 /*******************************************************************
2980 * AnyPopup (USER.52)
2982 BOOL16 WINAPI AnyPopup16(void)
2988 /*******************************************************************
2989 * AnyPopup (USER32.@)
2991 BOOL WINAPI AnyPopup(void)
2995 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2997 if (!list) return FALSE;
2998 for (i = 0; list[i]; i++)
3000 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3002 retvalue = (list[i] != 0);
3003 HeapFree( GetProcessHeap(), 0, list );
3008 /*******************************************************************
3009 * FlashWindow (USER32.@)
3011 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3013 WND *wndPtr = WIN_FindWndPtr(hWnd);
3015 TRACE("%04x\n", hWnd);
3017 if (!wndPtr) return FALSE;
3018 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3020 if (wndPtr->dwStyle & WS_MINIMIZE)
3022 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3024 HDC hDC = GetDC(hWnd);
3026 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3027 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3029 ReleaseDC( hWnd, hDC );
3030 wndPtr->flags |= WIN_NCACTIVATED;
3034 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3035 wndPtr->flags &= ~WIN_NCACTIVATED;
3037 WIN_ReleaseWndPtr(wndPtr);
3043 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3044 else wparam = (hWnd == GetActiveWindow());
3046 WIN_ReleaseWndPtr(wndPtr);
3047 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3053 /*******************************************************************
3054 * GetWindowContextHelpId (USER32.@)
3056 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3059 WND *wnd = WIN_FindWndPtr( hwnd );
3061 retval = wnd->helpContext;
3062 WIN_ReleaseWndPtr(wnd);
3067 /*******************************************************************
3068 * SetWindowContextHelpId (USER32.@)
3070 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3072 WND *wnd = WIN_FindWndPtr( hwnd );
3073 if (!wnd) return FALSE;
3074 wnd->helpContext = id;
3075 WIN_ReleaseWndPtr(wnd);
3080 /*******************************************************************
3083 * recursively find a child that contains spDragInfo->pt point
3084 * and send WM_QUERYDROPOBJECT
3086 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3088 BOOL16 wParam, bResult = 0;
3090 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3093 if (!ptrDragInfo) return FALSE;
3095 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3097 GetWindowRect(hQueryWnd,&tempRect);
3099 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3101 if (!IsIconic( hQueryWnd ))
3103 GetClientRect( hQueryWnd, &tempRect );
3104 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3106 if (PtInRect( &tempRect, pt))
3109 HWND *list = WIN_ListChildren( hQueryWnd );
3115 for (i = 0; list[i]; i++)
3117 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3119 GetWindowRect( list[i], &tempRect );
3120 if (PtInRect( &tempRect, pt )) break;
3125 if (IsWindowEnabled( list[i] ))
3126 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
3128 HeapFree( GetProcessHeap(), 0, list );
3130 if(bResult) return bResult;
3136 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3138 ptrDragInfo->hScope = hQueryWnd;
3140 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3141 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3143 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3149 /*******************************************************************
3150 * DragDetect (USER32.@)
3152 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3157 rect.left = pt.x - wDragWidth;
3158 rect.right = pt.x + wDragWidth;
3160 rect.top = pt.y - wDragHeight;
3161 rect.bottom = pt.y + wDragHeight;
3167 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3169 if( msg.message == WM_LBUTTONUP )
3174 if( msg.message == WM_MOUSEMOVE )
3177 tmp.x = LOWORD(msg.lParam);
3178 tmp.y = HIWORD(msg.lParam);
3179 if( !PtInRect( &rect, tmp ))
3191 /******************************************************************************
3192 * DragObject (USER.464)
3194 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3195 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3198 LPDRAGINFO16 lpDragInfo;
3200 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3201 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3202 HCURSOR16 hCurrentCursor = 0;
3203 HWND16 hCurrentWnd = 0;
3205 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3206 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3208 if( !lpDragInfo || !spDragInfo ) return 0L;
3210 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3212 GlobalFree16(hDragInfo);
3218 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3220 GlobalFree16(hDragInfo);
3224 if( hDragCursor == hCursor ) hDragCursor = 0;
3225 else hCursor = hDragCursor;
3227 hOldCursor = SetCursor(hDragCursor);
3230 lpDragInfo->hWnd = hWnd;
3231 lpDragInfo->hScope = 0;
3232 lpDragInfo->wFlags = wObj;
3233 lpDragInfo->hList = szList; /* near pointer! */
3234 lpDragInfo->hOfStruct = hOfStruct;
3242 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3244 *(lpDragInfo+1) = *lpDragInfo;
3246 lpDragInfo->pt.x = msg.pt.x;
3247 lpDragInfo->pt.y = msg.pt.y;
3249 /* update DRAGINFO struct */
3250 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3252 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3253 hCurrentCursor = hCursor;
3256 hCurrentCursor = hBummer;
3257 lpDragInfo->hScope = 0;
3259 if( hCurrentCursor )
3260 SetCursor(hCurrentCursor);
3262 /* send WM_DRAGLOOP */
3263 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3264 (LPARAM) spDragInfo );
3265 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3266 if( hCurrentWnd != lpDragInfo->hScope )
3269 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3270 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3271 HIWORD(spDragInfo)) );
3272 hCurrentWnd = lpDragInfo->hScope;
3274 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3278 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3280 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3283 ShowCursor( FALSE );
3287 SetCursor( hOldCursor );
3288 if (hDragCursor) DestroyCursor( hDragCursor );
3291 if( hCurrentCursor != hBummer )
3292 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3293 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3296 GlobalFree16(hDragInfo);
3298 return (DWORD)(msg.lParam);
3302 /******************************************************************************
3303 * GetWindowModuleFileNameA (USER32.@)
3305 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3307 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3308 hwnd, lpszFileName, cchFileNameMax);
3312 /******************************************************************************
3313 * GetWindowModuleFileNameW (USER32.@)
3315 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3317 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3318 hwnd, lpszFileName, cchFileNameMax);