2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "wine/server.h"
14 #include "wine/unicode.h"
20 #include "cursoricon.h"
27 #include "stackframe.h"
28 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(win);
31 DECLARE_DEBUG_CHANNEL(msg);
33 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
35 /**********************************************************************/
38 static WND *pWndDesktop = NULL;
40 static WORD wDragWidth = 4;
41 static WORD wDragHeight= 3;
43 static void *user_handles[NB_USER_HANDLES];
46 extern SYSLEVEL USER_SysLevel; /* FIXME */
48 /***********************************************************************
51 * Suspend the lock on WND structures.
52 * Returns the number of locks suspended
54 int WIN_SuspendWndsLock( void )
56 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
57 int count = isuspendedLocks;
60 _LeaveSysLevel( &USER_SysLevel );
62 return isuspendedLocks;
65 /***********************************************************************
68 * Restore the suspended locks on WND structures
70 void WIN_RestoreWndsLock( int ipreviousLocks )
72 while ( ipreviousLocks-- > 0 )
73 _EnterSysLevel( &USER_SysLevel );
76 /***********************************************************************
77 * create_window_handle
79 * Create a window handle with the server.
81 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
84 user_handle_t handle = 0;
86 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
88 if (!win) return NULL;
92 SERVER_START_REQ( create_window )
97 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
104 HeapFree( GetProcessHeap(), 0, win );
107 index = LOWORD(handle) - FIRST_USER_HANDLE;
108 assert( index < NB_USER_HANDLES );
109 user_handles[index] = win;
110 win->hwndSelf = handle;
111 win->dwMagic = WND_MAGIC;
117 /***********************************************************************
120 * Free a window handle.
122 static WND *free_window_handle( HWND hwnd )
125 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
127 if (index >= NB_USER_HANDLES) return NULL;
129 if ((ptr = user_handles[index]))
131 SERVER_START_REQ( destroy_window )
134 if (!wine_server_call_err( req ))
135 user_handles[index] = NULL;
142 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
147 /*******************************************************************
148 * list_window_children
150 * Build an array of the children of a given window. The array must be
151 * freed with HeapFree. Returns NULL when no windows are found.
153 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
162 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
164 SERVER_START_REQ( get_window_children )
168 req->tid = (void *)tid;
169 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
170 if (!wine_server_call( req )) count = reply->count;
173 if (count && count < size)
178 HeapFree( GetProcessHeap(), 0, list );
180 size = count + 1; /* restart with a large enough buffer */
186 /*******************************************************************
189 static void send_parent_notify( HWND hwnd, UINT msg )
191 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
192 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
193 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
194 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
198 /*******************************************************************
199 * get_server_window_text
201 * Retrieve the window text from the server.
203 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
207 SERVER_START_REQ( get_window_text )
210 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
211 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
214 text[len / sizeof(WCHAR)] = 0;
218 /***********************************************************************
221 * Return a pointer to the WND structure if local to the process,
222 * or WND_OTHER_PROCESS is handle may be valid in other process.
223 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
225 WND *WIN_GetPtr( HWND hwnd )
228 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
230 if (index >= NB_USER_HANDLES) return NULL;
233 if ((ptr = user_handles[index]))
235 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
239 else ptr = WND_OTHER_PROCESS;
245 /***********************************************************************
246 * WIN_IsCurrentProcess
248 * Check whether a given window belongs to the current process (and return the full handle).
250 HWND WIN_IsCurrentProcess( HWND hwnd )
255 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
257 WIN_ReleasePtr( ptr );
262 /***********************************************************************
263 * WIN_IsCurrentThread
265 * Check whether a given window belongs to the current thread (and return the full handle).
267 HWND WIN_IsCurrentThread( HWND hwnd )
272 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
274 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
275 WIN_ReleasePtr( ptr );
281 /***********************************************************************
284 * Convert a 16-bit window handle to a full 32-bit handle.
286 HWND WIN_Handle32( HWND16 hwnd16 )
289 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
291 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
292 /* do sign extension for -2 and -3 */
293 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
295 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
297 if (ptr != WND_OTHER_PROCESS)
299 hwnd = ptr->hwndSelf;
300 WIN_ReleasePtr( ptr );
302 else /* may belong to another process */
304 SERVER_START_REQ( get_window_info )
307 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
315 /***********************************************************************
318 * Return a pointer to the WND structure corresponding to a HWND.
320 WND * WIN_FindWndPtr( HWND hwnd )
324 if (!hwnd) return NULL;
326 if ((ptr = WIN_GetPtr( hwnd )))
328 if (ptr != WND_OTHER_PROCESS)
330 /* increment destruction monitoring */
334 if (IsWindow( hwnd )) /* check other processes */
336 ERR( "window %04x belongs to other process\n", hwnd );
337 /* DbgBreakPoint(); */
340 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
345 /***********************************************************************
348 * Release the pointer to the WND structure.
350 void WIN_ReleaseWndPtr(WND *wndPtr)
354 /* Decrement destruction monitoring value */
356 /* Check if it's time to release the memory */
357 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
360 free_window_handle( wndPtr->hwndSelf );
362 else if(wndPtr->irefCount < 0)
364 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
365 ERR("forgot a Lock on %p somewhere\n",wndPtr);
367 /* unlock all WND structures for thread safeness */
372 /***********************************************************************
375 * Remove a window from the siblings linked list.
377 void WIN_UnlinkWindow( HWND hwnd )
379 WIN_LinkWindow( hwnd, 0, 0 );
383 /***********************************************************************
386 * Insert a window into the siblings linked list.
387 * The window is inserted after the specified window, which can also
388 * be specified as HWND_TOP or HWND_BOTTOM.
389 * If parent is 0, window is unlinked from the tree.
391 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
393 WND *wndPtr = WIN_GetPtr( hwnd );
396 if (wndPtr == WND_OTHER_PROCESS)
398 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
402 SERVER_START_REQ( link_window )
405 req->parent = parent;
406 req->previous = hwndInsertAfter;
407 if (!wine_server_call( req ))
409 if (reply->full_parent && reply->full_parent != wndPtr->parent)
411 wndPtr->owner = 0; /* reset owner when changing parent */
412 wndPtr->parent = reply->full_parent;
418 WIN_ReleasePtr( wndPtr );
422 /***********************************************************************
425 * Change the owner of a window.
427 void WIN_SetOwner( HWND hwnd, HWND owner )
429 WND *win = WIN_GetPtr( hwnd );
432 if (win == WND_OTHER_PROCESS)
434 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
437 SERVER_START_REQ( set_window_owner )
441 if (!wine_server_call( req )) win->owner = reply->full_owner;
444 WIN_ReleasePtr( win );
448 /***********************************************************************
451 * Change the style of a window.
453 LONG WIN_SetStyle( HWND hwnd, LONG style )
457 WND *win = WIN_GetPtr( hwnd );
460 if (win == WND_OTHER_PROCESS)
463 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
466 if (style == win->dwStyle)
468 WIN_ReleasePtr( win );
471 SERVER_START_REQ( set_window_info )
474 req->flags = SET_WIN_STYLE;
476 if ((ok = !wine_server_call( req )))
478 ret = reply->old_style;
479 win->dwStyle = style;
483 WIN_ReleasePtr( win );
484 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
489 /***********************************************************************
492 * Change the extended style of a window.
494 LONG WIN_SetExStyle( HWND hwnd, LONG style )
497 WND *win = WIN_GetPtr( hwnd );
500 if (win == WND_OTHER_PROCESS)
503 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
506 if (style == win->dwExStyle)
508 WIN_ReleasePtr( win );
511 SERVER_START_REQ( set_window_info )
514 req->flags = SET_WIN_EXSTYLE;
515 req->ex_style = style;
516 if (!wine_server_call( req ))
518 ret = reply->old_ex_style;
519 win->dwExStyle = style;
523 WIN_ReleasePtr( win );
528 /***********************************************************************
531 * Set the window and client rectangles.
533 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
535 WND *win = WIN_GetPtr( hwnd );
539 if (win == WND_OTHER_PROCESS)
541 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
544 SERVER_START_REQ( set_window_rectangles )
547 req->window.left = rectWindow->left;
548 req->window.top = rectWindow->top;
549 req->window.right = rectWindow->right;
550 req->window.bottom = rectWindow->bottom;
551 req->client.left = rectClient->left;
552 req->client.top = rectClient->top;
553 req->client.right = rectClient->right;
554 req->client.bottom = rectClient->bottom;
555 ret = !wine_server_call( req );
560 win->rectWindow = *rectWindow;
561 win->rectClient = *rectClient;
563 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
564 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
565 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
567 WIN_ReleasePtr( win );
571 /***********************************************************************
574 * Get the window and client rectangles.
576 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
578 WND *win = WIN_GetPtr( hwnd );
581 if (!win) return FALSE;
582 if (win == WND_OTHER_PROCESS)
584 SERVER_START_REQ( get_window_rectangles )
587 if ((ret = !wine_server_call( req )))
591 rectWindow->left = reply->window.left;
592 rectWindow->top = reply->window.top;
593 rectWindow->right = reply->window.right;
594 rectWindow->bottom = reply->window.bottom;
598 rectClient->left = reply->client.left;
599 rectClient->top = reply->client.top;
600 rectClient->right = reply->client.right;
601 rectClient->bottom = reply->client.bottom;
609 if (rectWindow) *rectWindow = win->rectWindow;
610 if (rectClient) *rectClient = win->rectClient;
611 WIN_ReleasePtr( win );
617 /***********************************************************************
620 * Destroy storage associated to a window. "Internals" p.358
622 LRESULT WIN_DestroyWindow( HWND hwnd )
627 TRACE("%04x\n", hwnd );
629 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
631 ERR( "window doesn't belong to current thread\n" );
635 /* free child windows */
636 if ((list = WIN_ListChildren( hwnd )))
639 for (i = 0; list[i]; i++)
641 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
642 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
644 HeapFree( GetProcessHeap(), 0, list );
648 * Clear the update region to make sure no WM_PAINT messages will be
649 * generated for this window while processing the WM_NCDESTROY.
651 RedrawWindow( hwnd, NULL, 0,
652 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
655 * Send the WM_NCDESTROY to the window being destroyed.
657 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
659 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
661 WINPOS_CheckInternalPos( hwnd );
662 if( hwnd == GetCapture()) ReleaseCapture();
664 /* free resources associated with the window */
666 TIMER_RemoveWindowTimers( hwnd );
668 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
669 wndPtr->hmemTaskQ = 0;
671 if (!(wndPtr->dwStyle & WS_CHILD))
673 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
674 if (menu) DestroyMenu( menu );
676 if (wndPtr->hSysMenu)
678 DestroyMenu( wndPtr->hSysMenu );
679 wndPtr->hSysMenu = 0;
681 USER_Driver.pDestroyWindow( hwnd );
682 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
683 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
684 CLASS_RemoveWindow( wndPtr->class );
685 wndPtr->class = NULL;
686 wndPtr->dwMagic = 0; /* Mark it as invalid */
687 WIN_ReleaseWndPtr( wndPtr );
691 /***********************************************************************
692 * WIN_DestroyThreadWindows
694 * Destroy all children of 'wnd' owned by the current thread.
695 * Return TRUE if something was done.
697 void WIN_DestroyThreadWindows( HWND hwnd )
702 if (!(list = WIN_ListChildren( hwnd ))) return;
703 for (i = 0; list[i]; i++)
705 if (WIN_IsCurrentThread( list[i] ))
706 DestroyWindow( list[i] );
708 WIN_DestroyThreadWindows( list[i] );
710 HeapFree( GetProcessHeap(), 0, list );
713 /***********************************************************************
714 * WIN_CreateDesktopWindow
716 * Create the desktop window.
718 BOOL WIN_CreateDesktopWindow(void)
720 struct tagCLASS *class;
729 TRACE("Creating desktop window\n");
731 if (!WINPOS_CreateInternalPosAtom() ||
732 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
733 &wndExtra, &winproc, &clsStyle, &dce )))
736 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
737 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
738 if (!pWndDesktop) return FALSE;
739 hwndDesktop = pWndDesktop->hwndSelf;
741 pWndDesktop->tid = 0; /* nobody owns the desktop */
742 pWndDesktop->parent = 0;
743 pWndDesktop->owner = 0;
744 pWndDesktop->class = class;
745 pWndDesktop->hInstance = 0;
746 pWndDesktop->text = NULL;
747 pWndDesktop->hmemTaskQ = 0;
748 pWndDesktop->hrgnUpdate = 0;
749 pWndDesktop->hwndLastActive = hwndDesktop;
750 pWndDesktop->dwStyle = 0;
751 pWndDesktop->dwExStyle = 0;
752 pWndDesktop->clsStyle = clsStyle;
753 pWndDesktop->dce = NULL;
754 pWndDesktop->pVScroll = NULL;
755 pWndDesktop->pHScroll = NULL;
756 pWndDesktop->wIDmenu = 0;
757 pWndDesktop->helpContext = 0;
758 pWndDesktop->flags = 0;
759 pWndDesktop->hSysMenu = 0;
760 pWndDesktop->userdata = 0;
761 pWndDesktop->winproc = winproc;
762 pWndDesktop->cbWndExtra = wndExtra;
764 cs.lpCreateParams = NULL;
770 cs.cx = GetSystemMetrics( SM_CXSCREEN );
771 cs.cy = GetSystemMetrics( SM_CYSCREEN );
772 cs.style = pWndDesktop->dwStyle;
773 cs.dwExStyle = pWndDesktop->dwExStyle;
775 cs.lpszClass = DESKTOP_CLASS_ATOM;
777 SetRect( &rect, 0, 0, cs.cx, cs.cy );
778 WIN_SetRectangles( hwndDesktop, &rect, &rect );
779 WIN_SetStyle( hwndDesktop, WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
781 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
783 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
784 WIN_ReleaseWndPtr( pWndDesktop );
789 /***********************************************************************
792 * Fix the coordinates - Helper for WIN_CreateWindowEx.
793 * returns default show mode in sw.
794 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
796 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
798 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
799 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
801 if (cs->style & (WS_CHILD | WS_POPUP))
803 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
804 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
806 else /* overlapped window */
810 GetStartupInfoA( &info );
812 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
814 /* Never believe Microsoft's documentation... CreateWindowEx doc says
815 * that if an overlapped window is created with WS_VISIBLE style bit
816 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
817 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
820 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
821 * 2) it does not ignore the y parameter as the docs claim; instead, it
822 * uses it as second parameter to ShowWindow() unless y is either
823 * CW_USEDEFAULT or CW_USEDEFAULT16.
825 * The fact that we didn't do 2) caused bogus windows pop up when wine
826 * was running apps that were using this obscure feature. Example -
827 * calc.exe that comes with Win98 (only Win98, it's different from
828 * the one that comes with Win95 and NT)
830 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
831 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
832 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
835 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
837 if (info.dwFlags & STARTF_USESIZE)
839 cs->cx = info.dwXSize;
840 cs->cy = info.dwYSize;
842 else /* if no other hint from the app, pick 3/4 of the screen real estate */
845 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
846 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
847 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
854 /***********************************************************************
857 static void dump_window_styles( DWORD style, DWORD exstyle )
860 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
861 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
862 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
863 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
864 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
865 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
866 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
867 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
868 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
871 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
872 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
874 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
875 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
876 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
877 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
878 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
879 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
880 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
881 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
883 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
884 #define DUMPED_STYLES \
904 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
909 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
910 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
911 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
912 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
913 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
914 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
915 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
916 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
917 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
918 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
919 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
920 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
921 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
922 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
923 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
924 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
925 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
926 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
928 #define DUMPED_EX_STYLES \
929 (WS_EX_DLGMODALFRAME | \
931 WS_EX_NOPARENTNOTIFY | \
933 WS_EX_ACCEPTFILES | \
934 WS_EX_TRANSPARENT | \
939 WS_EX_CONTEXTHELP | \
942 WS_EX_LEFTSCROLLBAR | \
943 WS_EX_CONTROLPARENT | \
948 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
950 #undef DUMPED_EX_STYLES
954 /***********************************************************************
957 * Implementation of CreateWindowEx().
959 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
960 WINDOWPROCTYPE type )
963 struct tagCLASS *classPtr;
965 HWND hwnd, hwndLinkAfter, parent, owner;
970 BOOL unicode = (type == WIN_PROC_32W);
972 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
973 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
974 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
975 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
976 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
978 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
980 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
981 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
983 /* Find the parent window */
985 parent = GetDesktopWindow();
989 /* Make sure parent is valid */
990 if (!IsWindow( cs->hwndParent ))
992 WARN("Bad parent %04x\n", cs->hwndParent );
995 if (cs->style & WS_CHILD) parent = WIN_GetFullHandle(cs->hwndParent);
996 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
998 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
1000 WARN("No parent for child window\n" );
1001 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1004 /* Find the window class */
1005 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1006 &wndExtra, &winproc, &clsStyle, &dce )))
1008 WARN("Bad class '%s'\n", cs->lpszClass );
1012 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1014 /* Correct the window style - stage 1
1016 * These are patches that appear to affect both the style loaded into the
1017 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1019 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1020 * why does the user get to set it?
1023 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1024 * tested for WS_POPUP
1026 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1027 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1028 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1029 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1031 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1033 /* Create the window structure */
1035 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1036 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1038 TRACE("out of memory\n" );
1041 hwnd = wndPtr->hwndSelf;
1043 /* Fill the window structure */
1045 wndPtr->tid = GetCurrentThreadId();
1046 wndPtr->owner = owner;
1047 wndPtr->parent = parent;
1048 wndPtr->class = classPtr;
1049 wndPtr->winproc = winproc;
1050 wndPtr->hInstance = cs->hInstance;
1051 wndPtr->text = NULL;
1052 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
1053 wndPtr->hrgnUpdate = 0;
1054 wndPtr->hrgnWnd = 0;
1055 wndPtr->hwndLastActive = hwnd;
1056 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1057 wndPtr->dwExStyle = cs->dwExStyle;
1058 wndPtr->clsStyle = clsStyle;
1059 wndPtr->wIDmenu = 0;
1060 wndPtr->helpContext = 0;
1061 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1062 wndPtr->pVScroll = NULL;
1063 wndPtr->pHScroll = NULL;
1064 wndPtr->userdata = 0;
1065 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1066 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1067 wndPtr->cbWndExtra = wndExtra;
1069 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1071 /* Call the WH_CBT hook */
1073 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
1074 ? HWND_BOTTOM : HWND_TOP;
1076 if (HOOK_IsHooked( WH_CBT ))
1078 CBT_CREATEWNDA cbtc;
1082 cbtc.hwndInsertAfter = hwndLinkAfter;
1083 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND,
1084 (WPARAM)hwnd, (LPARAM)&cbtc)
1085 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND,
1086 (WPARAM)hwnd, (LPARAM)&cbtc);
1089 TRACE("CBT-hook returned 0\n");
1090 free_window_handle( hwnd );
1091 CLASS_RemoveWindow( classPtr );
1092 WIN_ReleaseWndPtr(wndPtr);
1097 /* Correct the window style - stage 2 */
1099 if (!(cs->style & WS_CHILD))
1101 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1102 if (!(cs->style & WS_POPUP))
1104 wndPtr->dwStyle |= WS_CAPTION;
1105 wndPtr->flags |= WIN_NEED_SIZE;
1108 SERVER_START_REQ( set_window_info )
1111 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1112 req->style = wndPtr->dwStyle;
1113 req->ex_style = wndPtr->dwExStyle;
1114 req->instance = (void *)wndPtr->hInstance;
1115 wine_server_call( req );
1119 /* Get class or window DC if needed */
1121 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1122 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1123 else wndPtr->dce = NULL;
1125 /* Set the window menu */
1127 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1129 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1132 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1135 if (HIWORD(cs->hInstance))
1136 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1138 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1140 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1144 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1145 WIN_ReleaseWndPtr( wndPtr );
1147 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1149 WIN_DestroyWindow( hwnd );
1153 /* Notify the parent window only */
1155 send_parent_notify( hwnd, WM_CREATE );
1156 if (!IsWindow( hwnd )) return 0;
1158 if (cs->style & WS_VISIBLE)
1160 /* in case WS_VISIBLE got set in the meantime */
1161 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1162 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1163 WIN_ReleasePtr( wndPtr );
1164 ShowWindow( hwnd, sw );
1167 /* Call WH_SHELL hook */
1169 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1170 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1172 TRACE("created window %04x\n", hwnd);
1177 /***********************************************************************
1178 * CreateWindow (USER.41)
1180 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1181 DWORD style, INT16 x, INT16 y, INT16 width,
1182 INT16 height, HWND16 parent, HMENU16 menu,
1183 HINSTANCE16 instance, LPVOID data )
1185 return CreateWindowEx16( 0, className, windowName, style,
1186 x, y, width, height, parent, menu, instance, data );
1190 /***********************************************************************
1191 * CreateWindowEx (USER.452)
1193 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1194 LPCSTR windowName, DWORD style, INT16 x,
1195 INT16 y, INT16 width, INT16 height,
1196 HWND16 parent, HMENU16 menu,
1197 HINSTANCE16 instance, LPVOID data )
1203 /* Find the class atom */
1205 if (HIWORD(className))
1207 if (!(classAtom = GlobalFindAtomA( className )))
1209 ERR( "bad class name %s\n", debugres_a(className) );
1215 classAtom = LOWORD(className);
1216 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1218 ERR( "bad atom %x\n", classAtom);
1224 /* Fix the coordinates */
1226 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1227 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1228 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1229 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1231 /* Create the window */
1233 cs.lpCreateParams = data;
1234 cs.hInstance = (HINSTANCE)instance;
1235 cs.hMenu = (HMENU)menu;
1236 cs.hwndParent = WIN_Handle32( parent );
1238 cs.lpszName = windowName;
1239 cs.lpszClass = className;
1240 cs.dwExStyle = exStyle;
1242 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1246 /***********************************************************************
1247 * CreateWindowExA (USER32.@)
1249 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1250 LPCSTR windowName, DWORD style, INT x,
1251 INT y, INT width, INT height,
1252 HWND parent, HMENU menu,
1253 HINSTANCE instance, LPVOID data )
1260 instance=GetModuleHandleA(NULL);
1262 if(exStyle & WS_EX_MDICHILD)
1263 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1265 /* Find the class atom */
1267 if (HIWORD(className))
1269 if (!(classAtom = GlobalFindAtomA( className )))
1271 ERR( "bad class name %s\n", debugres_a(className) );
1277 classAtom = LOWORD(className);
1278 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1280 ERR( "bad atom %x\n", classAtom);
1286 /* Create the window */
1288 cs.lpCreateParams = data;
1289 cs.hInstance = instance;
1291 cs.hwndParent = parent;
1297 cs.lpszName = windowName;
1298 cs.lpszClass = className;
1299 cs.dwExStyle = exStyle;
1301 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1305 /***********************************************************************
1306 * CreateWindowExW (USER32.@)
1308 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1309 LPCWSTR windowName, DWORD style, INT x,
1310 INT y, INT width, INT height,
1311 HWND parent, HMENU menu,
1312 HINSTANCE instance, LPVOID data )
1319 instance=GetModuleHandleA(NULL);
1321 if(exStyle & WS_EX_MDICHILD)
1322 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1324 /* Find the class atom */
1326 if (HIWORD(className))
1328 if (!(classAtom = GlobalFindAtomW( className )))
1330 ERR( "bad class name %s\n", debugres_w(className) );
1336 classAtom = LOWORD(className);
1337 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1339 ERR( "bad atom %x\n", classAtom);
1345 /* Create the window */
1347 cs.lpCreateParams = data;
1348 cs.hInstance = instance;
1350 cs.hwndParent = parent;
1356 cs.lpszName = windowName;
1357 cs.lpszClass = className;
1358 cs.dwExStyle = exStyle;
1360 /* Note: we rely on the fact that CREATESTRUCTA and */
1361 /* CREATESTRUCTW have the same layout. */
1362 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1366 /***********************************************************************
1367 * WIN_SendDestroyMsg
1369 static void WIN_SendDestroyMsg( HWND hwnd )
1371 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1372 if (USER_Driver.pResetSelectionOwner)
1373 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1376 * Send the WM_DESTROY to the window.
1378 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1381 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1382 * make sure that the window still exists when we come back.
1389 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1391 /* start from the end (FIXME: is this needed?) */
1392 for (i = 0; pWndArray[i]; i++) ;
1396 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1398 HeapFree( GetProcessHeap(), 0, pWndArray );
1401 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1405 /***********************************************************************
1406 * DestroyWindow (USER32.@)
1408 BOOL WINAPI DestroyWindow( HWND hwnd )
1413 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1415 SetLastError( ERROR_ACCESS_DENIED );
1419 TRACE("(%04x)\n", hwnd);
1421 /* Look whether the focus is within the tree of windows we will
1425 if (h == hwnd || IsChild( hwnd, h ))
1427 HWND parent = GetAncestor( hwnd, GA_PARENT );
1428 if (parent == GetDesktopWindow()) parent = 0;
1434 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1436 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1440 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1441 send_parent_notify( hwnd, WM_DESTROY );
1443 else if (!GetWindow( hwnd, GW_OWNER ))
1445 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1446 /* FIXME: clean up palette - see "Internals" p.352 */
1449 if (!IsWindow(hwnd)) return TRUE;
1451 if (USER_Driver.pResetSelectionOwner)
1452 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1454 /* Hide the window */
1456 ShowWindow( hwnd, SW_HIDE );
1457 if (!IsWindow(hwnd)) return TRUE;
1459 /* Recursively destroy owned windows */
1468 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1471 for (i = 0; list[i]; i++)
1473 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1474 if (WIN_IsCurrentThread( list[i] ))
1476 DestroyWindow( list[i] );
1480 WIN_SetOwner( list[i], 0 );
1482 HeapFree( GetProcessHeap(), 0, list );
1484 if (!got_one) break;
1487 WINPOS_ActivateOtherWindow( hwnd );
1489 if ((owner = GetWindow( hwnd, GW_OWNER )))
1491 WND *ptr = WIN_FindWndPtr( owner );
1494 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1495 WIN_ReleaseWndPtr( ptr );
1500 /* Send destroy messages */
1502 WIN_SendDestroyMsg( hwnd );
1503 if (!IsWindow( hwnd )) return TRUE;
1505 /* Unlink now so we won't bother with the children later on */
1507 WIN_UnlinkWindow( hwnd );
1509 /* Destroy the window storage */
1511 WIN_DestroyWindow( hwnd );
1516 /***********************************************************************
1517 * CloseWindow (USER32.@)
1519 BOOL WINAPI CloseWindow( HWND hwnd )
1521 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1522 ShowWindow( hwnd, SW_MINIMIZE );
1527 /***********************************************************************
1528 * OpenIcon (USER32.@)
1530 BOOL WINAPI OpenIcon( HWND hwnd )
1532 if (!IsIconic( hwnd )) return FALSE;
1533 ShowWindow( hwnd, SW_SHOWNORMAL );
1538 /***********************************************************************
1541 * Implementation of FindWindow() and FindWindowEx().
1543 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1548 WCHAR *buffer = NULL;
1550 if (!parent) parent = GetDesktopWindow();
1553 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1554 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1557 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1561 child = WIN_GetFullHandle( child );
1562 while (list[i] && list[i] != child) i++;
1563 if (!list[i]) goto done;
1564 i++; /* start from next window */
1571 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1578 if (list) HeapFree( GetProcessHeap(), 0, list );
1579 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1585 /***********************************************************************
1586 * FindWindowA (USER32.@)
1588 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1590 HWND ret = FindWindowExA( 0, 0, className, title );
1591 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1596 /***********************************************************************
1597 * FindWindowExA (USER32.@)
1599 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1600 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);
1617 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1618 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1619 HeapFree( GetProcessHeap(), 0, buffer );
1624 /***********************************************************************
1625 * FindWindowExW (USER32.@)
1627 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1628 LPCWSTR className, LPCWSTR title )
1634 /* If the atom doesn't exist, then no class */
1635 /* with this name exists either. */
1636 if (!(atom = GlobalFindAtomW( className )))
1638 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1642 return WIN_FindWindow( parent, child, atom, title );
1646 /***********************************************************************
1647 * FindWindowW (USER32.@)
1649 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1651 return FindWindowExW( 0, 0, className, title );
1655 /**********************************************************************
1656 * GetDesktopWindow (USER32.@)
1658 HWND WINAPI GetDesktopWindow(void)
1660 if (pWndDesktop) return pWndDesktop->hwndSelf;
1661 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" );
1667 /*******************************************************************
1668 * EnableWindow (USER32.@)
1670 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1677 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1678 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1682 TRACE("( %x, %d )\n", hwnd, enable);
1684 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1685 style = wndPtr->dwStyle;
1686 retvalue = ((style & WS_DISABLED) != 0);
1687 WIN_ReleasePtr( wndPtr );
1689 if (enable && retvalue)
1691 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1692 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1694 else if (!enable && !retvalue)
1696 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1698 WIN_SetStyle( hwnd, style | WS_DISABLED );
1700 if (hwnd == GetFocus())
1701 SetFocus( 0 ); /* A disabled window can't have the focus */
1703 if (hwnd == GetCapture())
1704 ReleaseCapture(); /* A disabled window can't capture the mouse */
1706 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1712 /***********************************************************************
1713 * IsWindowEnabled (USER32.@)
1715 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1717 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1721 /***********************************************************************
1722 * IsWindowUnicode (USER32.@)
1724 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1729 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1730 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1731 WIN_ReleaseWndPtr(wndPtr);
1736 /**********************************************************************
1737 * GetWindowWord (USER32.@)
1739 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1744 WND *wndPtr = WIN_GetPtr( hwnd );
1747 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1750 if (wndPtr == WND_OTHER_PROCESS)
1752 if (IsWindow( hwnd ))
1753 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1754 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1757 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1759 WARN("Invalid offset %d\n", offset );
1760 SetLastError( ERROR_INVALID_INDEX );
1762 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1763 WIN_ReleasePtr( wndPtr );
1769 case GWL_HWNDPARENT:
1770 return GetWindowLongW( hwnd, offset );
1774 LONG ret = GetWindowLongW( hwnd, offset );
1776 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1780 WARN("Invalid offset %d\n", offset );
1786 /**********************************************************************
1787 * SetWindowWord (USER32.@)
1789 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1798 case GWL_HWNDPARENT:
1799 return SetWindowLongW( hwnd, offset, (UINT)newval );
1803 WARN("Invalid offset %d\n", offset );
1804 SetLastError( ERROR_INVALID_INDEX );
1809 wndPtr = WIN_GetPtr( hwnd );
1810 if (wndPtr == WND_OTHER_PROCESS)
1813 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1814 offset, newval, hwnd );
1819 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1823 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1825 WARN("Invalid offset %d\n", offset );
1826 WIN_ReleasePtr(wndPtr);
1827 SetLastError( ERROR_INVALID_INDEX );
1830 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1833 WIN_ReleasePtr(wndPtr);
1838 /**********************************************************************
1841 * Helper function for GetWindowLong().
1843 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1848 if (offset == GWL_HWNDPARENT) return (LONG)GetParent( hwnd );
1850 if (!(wndPtr = WIN_GetPtr( hwnd )))
1852 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1856 if (wndPtr == WND_OTHER_PROCESS)
1861 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1862 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1865 if (offset == GWL_WNDPROC)
1867 SetLastError( ERROR_ACCESS_DENIED );
1870 SERVER_START_REQ( set_window_info )
1873 req->flags = 0; /* don't set anything, just retrieve */
1874 if (!wine_server_call_err( req ))
1878 case GWL_STYLE: retvalue = reply->old_style; break;
1879 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1880 case GWL_ID: retvalue = reply->old_id; break;
1881 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1882 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1884 SetLastError( ERROR_INVALID_INDEX );
1893 /* now we have a valid wndPtr */
1897 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1899 WARN("Invalid offset %d\n", offset );
1900 WIN_ReleasePtr( wndPtr );
1901 SetLastError( ERROR_INVALID_INDEX );
1904 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1905 /* Special case for dialog window procedure */
1906 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1907 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1908 WIN_ReleasePtr( wndPtr );
1914 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1915 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1916 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1917 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1918 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1919 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1921 WARN("Unknown offset %d\n", offset );
1922 SetLastError( ERROR_INVALID_INDEX );
1925 WIN_ReleasePtr(wndPtr);
1930 /**********************************************************************
1933 * Helper function for SetWindowLong().
1935 * 0 is the failure code. However, in the case of failure SetLastError
1936 * must be set to distinguish between a 0 return value and a failure.
1938 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1939 WINDOWPROCTYPE type )
1944 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1946 if (!WIN_IsCurrentProcess( hwnd ))
1948 if (offset == GWL_WNDPROC)
1950 SetLastError( ERROR_ACCESS_DENIED );
1953 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1956 wndPtr = WIN_GetPtr( hwnd );
1960 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1961 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1963 WARN("Invalid offset %d\n", offset );
1964 WIN_ReleasePtr( wndPtr );
1965 SetLastError( ERROR_INVALID_INDEX );
1968 /* Special case for dialog window procedure */
1969 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1971 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1972 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1973 type, WIN_PROC_WINDOW );
1974 WIN_ReleasePtr( wndPtr );
1979 WIN_ReleasePtr( wndPtr );
1986 /* first some special cases */
1991 style.styleOld = wndPtr->dwStyle;
1992 style.styleNew = newval;
1993 WIN_ReleasePtr( wndPtr );
1994 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1995 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1996 newval = style.styleNew;
1998 case GWL_HWNDPARENT:
1999 WIN_ReleasePtr( wndPtr );
2000 return (LONG)SetParent( hwnd, (HWND)newval );
2002 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2003 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2004 type, WIN_PROC_WINDOW );
2005 WIN_ReleasePtr( wndPtr );
2012 WIN_ReleasePtr( wndPtr );
2013 WARN("Invalid offset %d\n", offset );
2014 SetLastError( ERROR_INVALID_INDEX );
2018 SERVER_START_REQ( set_window_info )
2024 req->flags = SET_WIN_STYLE;
2025 req->style = newval;
2028 req->flags = SET_WIN_EXSTYLE;
2029 req->ex_style = newval;
2032 req->flags = SET_WIN_ID;
2036 req->flags = SET_WIN_INSTANCE;
2037 req->instance = (void *)newval;
2040 req->flags = SET_WIN_USERDATA;
2041 req->user_data = (void *)newval;
2044 if ((ok = !wine_server_call_err( req )))
2049 wndPtr->dwStyle = newval;
2050 retval = reply->old_style;
2053 wndPtr->dwExStyle = newval;
2054 retval = reply->old_ex_style;
2057 wndPtr->wIDmenu = newval;
2058 retval = reply->old_id;
2061 wndPtr->hInstance = newval;
2062 retval = (HINSTANCE)reply->old_instance;
2065 wndPtr->userdata = newval;
2066 retval = (ULONG_PTR)reply->old_user_data;
2072 WIN_ReleasePtr( wndPtr );
2076 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2077 USER_Driver.pSetWindowStyle( hwnd, retval );
2079 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2080 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2087 /**********************************************************************
2088 * GetWindowLong (USER.135)
2090 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2092 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2096 /**********************************************************************
2097 * GetWindowLongA (USER32.@)
2099 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2101 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2105 /**********************************************************************
2106 * GetWindowLongW (USER32.@)
2108 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2110 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2114 /**********************************************************************
2115 * SetWindowLong (USER.136)
2117 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2119 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2123 /**********************************************************************
2124 * SetWindowLongA (USER32.@)
2126 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2128 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2132 /**********************************************************************
2133 * SetWindowLongW (USER32.@) Set window attribute
2135 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2136 * value in a window's extra memory.
2138 * The _hwnd_ parameter specifies the window. is the handle to a
2139 * window that has extra memory. The _newval_ parameter contains the
2140 * new attribute or extra memory value. If positive, the _offset_
2141 * parameter is the byte-addressed location in the window's extra
2142 * memory to set. If negative, _offset_ specifies the window
2143 * attribute to set, and should be one of the following values:
2145 * GWL_EXSTYLE The window's extended window style
2147 * GWL_STYLE The window's window style.
2149 * GWL_WNDPROC Pointer to the window's window procedure.
2151 * GWL_HINSTANCE The window's pplication instance handle.
2153 * GWL_ID The window's identifier.
2155 * GWL_USERDATA The window's user-specified data.
2157 * If the window is a dialog box, the _offset_ parameter can be one of
2158 * the following values:
2160 * DWL_DLGPROC The address of the window's dialog box procedure.
2162 * DWL_MSGRESULT The return value of a message
2163 * that the dialog box procedure processed.
2165 * DWL_USER Application specific information.
2169 * If successful, returns the previous value located at _offset_. Otherwise,
2174 * Extra memory for a window class is specified by a nonzero cbWndExtra
2175 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2176 * time of class creation.
2178 * Using GWL_WNDPROC to set a new window procedure effectively creates
2179 * a window subclass. Use CallWindowProc() in the new windows procedure
2180 * to pass messages to the superclass's window procedure.
2182 * The user data is reserved for use by the application which created
2185 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2186 * instead, call the EnableWindow() function to change the window's
2189 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2190 * SetParent() instead.
2193 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2194 * it sends WM_STYLECHANGING before changing the settings
2195 * and WM_STYLECHANGED afterwards.
2196 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2198 LONG WINAPI SetWindowLongW(
2199 HWND hwnd, /* [in] window to alter */
2200 INT offset, /* [in] offset, in bytes, of location to alter */
2201 LONG newval /* [in] new value of location */
2203 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2207 /*******************************************************************
2208 * GetWindowTextA (USER32.@)
2210 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2214 if (WIN_IsCurrentProcess( hwnd ))
2215 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2217 /* when window belongs to other process, don't send a message */
2218 if (nMaxCount <= 0) return 0;
2219 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2220 get_server_window_text( hwnd, buffer, nMaxCount );
2221 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2222 lpString[nMaxCount-1] = 0;
2223 HeapFree( GetProcessHeap(), 0, buffer );
2224 return strlen(lpString);
2228 /*******************************************************************
2229 * InternalGetWindowText (USER32.@)
2231 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2235 if (nMaxCount <= 0) return 0;
2236 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2237 if (win != WND_OTHER_PROCESS)
2239 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2240 else lpString[0] = 0;
2241 WIN_ReleasePtr( win );
2245 get_server_window_text( hwnd, lpString, nMaxCount );
2247 return strlenW(lpString);
2251 /*******************************************************************
2252 * GetWindowTextW (USER32.@)
2254 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2256 if (WIN_IsCurrentProcess( hwnd ))
2257 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2259 /* when window belongs to other process, don't send a message */
2260 if (nMaxCount <= 0) return 0;
2261 get_server_window_text( hwnd, lpString, nMaxCount );
2262 return strlenW(lpString);
2266 /*******************************************************************
2267 * SetWindowText (USER32.@)
2268 * SetWindowTextA (USER32.@)
2270 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2272 if (!WIN_IsCurrentProcess( hwnd ))
2274 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2275 SetLastError( ERROR_ACCESS_DENIED );
2278 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2282 /*******************************************************************
2283 * SetWindowTextW (USER32.@)
2285 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2287 if (!WIN_IsCurrentProcess( hwnd ))
2289 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2290 SetLastError( ERROR_ACCESS_DENIED );
2293 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2297 /*******************************************************************
2298 * GetWindowTextLengthA (USER32.@)
2300 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2302 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2305 /*******************************************************************
2306 * GetWindowTextLengthW (USER32.@)
2308 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2310 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2314 /*******************************************************************
2315 * IsWindow (USER32.@)
2317 BOOL WINAPI IsWindow( HWND hwnd )
2322 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2324 if (ptr != WND_OTHER_PROCESS)
2326 WIN_ReleasePtr( ptr );
2330 /* check other processes */
2331 SERVER_START_REQ( get_window_info )
2334 ret = !wine_server_call_err( req );
2341 /***********************************************************************
2342 * GetWindowThreadProcessId (USER32.@)
2344 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2349 if (!(ptr = WIN_GetPtr( hwnd )))
2351 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2355 if (ptr != WND_OTHER_PROCESS)
2357 /* got a valid window */
2359 if (process) *process = GetCurrentProcessId();
2360 WIN_ReleasePtr( ptr );
2364 /* check other processes */
2365 SERVER_START_REQ( get_window_info )
2368 if (!wine_server_call_err( req ))
2370 tid = (DWORD)reply->tid;
2371 if (process) *process = (DWORD)reply->pid;
2379 /*****************************************************************
2380 * GetParent (USER32.@)
2382 HWND WINAPI GetParent( HWND hwnd )
2387 if (!(wndPtr = WIN_GetPtr( hwnd )))
2389 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2392 if (wndPtr == WND_OTHER_PROCESS)
2394 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2395 if (style & (WS_POPUP | WS_CHILD))
2397 SERVER_START_REQ( get_window_tree )
2400 if (!wine_server_call_err( req ))
2402 if (style & WS_CHILD) retvalue = reply->parent;
2403 else retvalue = reply->owner;
2411 if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2412 else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2413 WIN_ReleasePtr( wndPtr );
2419 /*****************************************************************
2420 * GetAncestor (USER32.@)
2422 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2425 HWND *list, ret = 0;
2427 if (type == GA_PARENT)
2429 if (!(win = WIN_GetPtr( hwnd )))
2431 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2434 if (win != WND_OTHER_PROCESS)
2437 WIN_ReleasePtr( win );
2439 else /* need to query the server */
2441 SERVER_START_REQ( get_window_tree )
2444 if (!wine_server_call_err( req )) ret = reply->parent;
2451 if (!(list = WIN_ListParents( hwnd ))) return 0;
2453 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2457 while (list[count]) count++;
2458 ret = list[count - 2]; /* get the one before the desktop */
2460 HeapFree( GetProcessHeap(), 0, list );
2462 if (ret && type == GA_ROOTOWNER)
2466 HWND owner = GetWindow( ret, GW_OWNER );
2475 /*****************************************************************
2476 * SetParent (USER32.@)
2478 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2481 HWND retvalue, full_handle;
2484 if (!parent) parent = GetDesktopWindow();
2485 else parent = WIN_GetFullHandle( parent );
2487 if (!IsWindow( parent ))
2489 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2493 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2494 return SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2498 if (USER_Driver.pSetParent)
2499 return USER_Driver.pSetParent( hwnd, parent );
2501 /* Windows hides the window first, then shows it again
2502 * including the WM_SHOWWINDOW messages and all */
2503 was_visible = ShowWindow( hwnd, SW_HIDE );
2505 if (!IsWindow( parent )) return 0;
2506 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2508 retvalue = wndPtr->parent; /* old parent */
2509 if (parent != retvalue)
2511 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2513 if (parent != GetDesktopWindow()) /* a child window */
2515 if (!(wndPtr->dwStyle & WS_CHILD))
2517 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2518 if (menu) DestroyMenu( menu );
2522 WIN_ReleasePtr( wndPtr );
2524 /* SetParent additionally needs to make hwnd the topmost window
2525 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2526 WM_WINDOWPOSCHANGED notification messages.
2528 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2529 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2530 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2531 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2536 /*******************************************************************
2537 * IsChild (USER32.@)
2539 BOOL WINAPI IsChild( HWND parent, HWND child )
2541 HWND *list = WIN_ListParents( child );
2545 if (!list) return FALSE;
2546 parent = WIN_GetFullHandle( parent );
2547 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2548 ret = (list[i] != 0);
2549 HeapFree( GetProcessHeap(), 0, list );
2554 /***********************************************************************
2555 * IsWindowVisible (USER32.@)
2557 BOOL WINAPI IsWindowVisible( HWND hwnd )
2563 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2564 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2565 for (i = 0; list[i]; i++)
2566 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2568 HeapFree( GetProcessHeap(), 0, list );
2573 /***********************************************************************
2574 * WIN_IsWindowDrawable
2576 * hwnd is drawable when it is visible, all parents are not
2577 * minimized, and it is itself not minimized unless we are
2578 * trying to draw its default class icon.
2580 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2585 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2587 if (!(style & WS_VISIBLE)) return FALSE;
2588 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2590 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2591 for (i = 0; list[i]; i++)
2592 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2595 HeapFree( GetProcessHeap(), 0, list );
2600 /*******************************************************************
2601 * GetTopWindow (USER32.@)
2603 HWND WINAPI GetTopWindow( HWND hwnd )
2605 if (!hwnd) hwnd = GetDesktopWindow();
2606 return GetWindow( hwnd, GW_CHILD );
2610 /*******************************************************************
2611 * GetWindow (USER32.@)
2613 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2617 if (rel == GW_OWNER) /* this one may be available locally */
2619 WND *wndPtr = WIN_GetPtr( hwnd );
2622 SetLastError( ERROR_INVALID_HANDLE );
2625 if (wndPtr != WND_OTHER_PROCESS)
2627 retval = wndPtr->owner;
2628 WIN_ReleasePtr( wndPtr );
2631 /* else fall through to server call */
2634 SERVER_START_REQ( get_window_tree )
2637 if (!wine_server_call_err( req ))
2642 retval = reply->first_sibling;
2645 retval = reply->last_sibling;
2648 retval = reply->next_sibling;
2651 retval = reply->prev_sibling;
2654 retval = reply->owner;
2657 retval = reply->first_child;
2667 /***********************************************************************
2668 * WIN_InternalShowOwnedPopups
2670 * Internal version of ShowOwnedPopups; Wine functions should use this
2671 * to avoid interfering with application calls to ShowOwnedPopups
2672 * and to make sure the application can't prevent showing/hiding.
2674 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2678 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2682 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2684 if (!win_array) return TRUE;
2687 * Show windows Lowest first, Highest last to preserve Z-Order
2689 while (win_array[count]) count++;
2690 while (--count >= 0)
2692 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2693 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2695 if (pWnd->dwStyle & WS_POPUP)
2699 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2700 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2703 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2705 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2706 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2711 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2712 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2713 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2716 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2718 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2719 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2720 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2724 WIN_ReleaseWndPtr( pWnd );
2726 HeapFree( GetProcessHeap(), 0, win_array );
2731 /*******************************************************************
2732 * ShowOwnedPopups (USER32.@)
2734 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2738 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2740 if (!win_array) return TRUE;
2742 while (win_array[count]) count++;
2743 while (--count >= 0)
2745 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2746 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2748 if (pWnd->dwStyle & WS_POPUP)
2752 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2754 /* In Windows, ShowOwnedPopups(TRUE) generates
2755 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2756 * regardless of the state of the owner
2758 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2759 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2764 if (IsWindowVisible(pWnd->hwndSelf))
2766 /* In Windows, ShowOwnedPopups(FALSE) generates
2767 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2768 * regardless of the state of the owner
2770 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2771 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2775 WIN_ReleaseWndPtr( pWnd );
2777 HeapFree( GetProcessHeap(), 0, win_array );
2782 /*******************************************************************
2783 * GetLastActivePopup (USER32.@)
2785 HWND WINAPI GetLastActivePopup( HWND hwnd )
2788 WND *wndPtr =WIN_FindWndPtr(hwnd);
2789 if (!wndPtr) return hwnd;
2790 retval = wndPtr->hwndLastActive;
2791 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2792 WIN_ReleaseWndPtr(wndPtr);
2797 /*******************************************************************
2800 * Build an array of all parents of a given window, starting with
2801 * the immediate parent. The array must be freed with HeapFree.
2802 * Returns NULL if window is a top-level window.
2804 HWND *WIN_ListParents( HWND hwnd )
2807 HWND current, *list;
2808 int pos = 0, size = 16, count = 0;
2810 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2815 if (!(win = WIN_GetPtr( current ))) goto empty;
2816 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2817 list[pos] = win->parent;
2818 WIN_ReleasePtr( win );
2819 if (!(current = list[pos]))
2821 if (!pos) goto empty;
2824 if (++pos == size - 1)
2826 /* need to grow the list */
2827 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2828 if (!new_list) goto empty;
2834 /* at least one parent belongs to another process, have to query the server */
2839 SERVER_START_REQ( get_window_parents )
2842 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2843 if (!wine_server_call( req )) count = reply->count;
2846 if (!count) goto empty;
2852 HeapFree( GetProcessHeap(), 0, list );
2854 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2858 HeapFree( GetProcessHeap(), 0, list );
2863 /*******************************************************************
2866 * Build an array of the children of a given window. The array must be
2867 * freed with HeapFree. Returns NULL when no windows are found.
2869 HWND *WIN_ListChildren( HWND hwnd )
2871 return list_window_children( hwnd, 0, 0 );
2875 /*******************************************************************
2876 * EnumWindows (USER32.@)
2878 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2884 /* We have to build a list of all windows first, to avoid */
2885 /* unpleasant side-effects, for instance if the callback */
2886 /* function changes the Z-order of the windows. */
2888 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2890 /* Now call the callback function for every window */
2892 iWndsLocks = WIN_SuspendWndsLock();
2893 for (i = 0; list[i]; i++)
2895 /* Make sure that the window still exists */
2896 if (!IsWindow( list[i] )) continue;
2897 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2899 WIN_RestoreWndsLock(iWndsLocks);
2900 HeapFree( GetProcessHeap(), 0, list );
2905 /**********************************************************************
2906 * EnumTaskWindows16 (USER.225)
2908 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2911 TDB *tdb = TASK_GetPtr( hTask );
2912 if (!tdb) return FALSE;
2913 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2917 /**********************************************************************
2918 * EnumThreadWindows (USER32.@)
2920 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2925 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2928 /* Now call the callback function for every window */
2930 iWndsLocks = WIN_SuspendWndsLock();
2931 for (i = 0; list[i]; i++)
2932 if (!func( list[i], lParam )) break;
2933 WIN_RestoreWndsLock(iWndsLocks);
2934 HeapFree( GetProcessHeap(), 0, list );
2939 /**********************************************************************
2940 * WIN_EnumChildWindows
2942 * Helper function for EnumChildWindows().
2944 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2949 for ( ; *list; list++)
2951 /* Make sure that the window still exists */
2952 if (!IsWindow( *list )) continue;
2953 /* skip owned windows */
2954 if (GetWindow( *list, GW_OWNER )) continue;
2955 /* Build children list first */
2956 childList = WIN_ListChildren( *list );
2958 ret = func( *list, lParam );
2962 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2963 HeapFree( GetProcessHeap(), 0, childList );
2965 if (!ret) return FALSE;
2971 /**********************************************************************
2972 * EnumChildWindows (USER32.@)
2974 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2979 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2980 iWndsLocks = WIN_SuspendWndsLock();
2981 WIN_EnumChildWindows( list, func, lParam );
2982 WIN_RestoreWndsLock(iWndsLocks);
2983 HeapFree( GetProcessHeap(), 0, list );
2988 /*******************************************************************
2989 * AnyPopup (USER.52)
2991 BOOL16 WINAPI AnyPopup16(void)
2997 /*******************************************************************
2998 * AnyPopup (USER32.@)
3000 BOOL WINAPI AnyPopup(void)
3004 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3006 if (!list) return FALSE;
3007 for (i = 0; list[i]; i++)
3009 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3011 retvalue = (list[i] != 0);
3012 HeapFree( GetProcessHeap(), 0, list );
3017 /*******************************************************************
3018 * FlashWindow (USER32.@)
3020 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3022 WND *wndPtr = WIN_FindWndPtr(hWnd);
3024 TRACE("%04x\n", hWnd);
3026 if (!wndPtr) return FALSE;
3027 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3029 if (wndPtr->dwStyle & WS_MINIMIZE)
3031 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3033 HDC hDC = GetDC(hWnd);
3035 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3036 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3038 ReleaseDC( hWnd, hDC );
3039 wndPtr->flags |= WIN_NCACTIVATED;
3043 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3044 wndPtr->flags &= ~WIN_NCACTIVATED;
3046 WIN_ReleaseWndPtr(wndPtr);
3052 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3053 else wparam = (hWnd == GetActiveWindow());
3055 WIN_ReleaseWndPtr(wndPtr);
3056 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3062 /*******************************************************************
3063 * GetWindowContextHelpId (USER32.@)
3065 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3068 WND *wnd = WIN_FindWndPtr( hwnd );
3070 retval = wnd->helpContext;
3071 WIN_ReleaseWndPtr(wnd);
3076 /*******************************************************************
3077 * SetWindowContextHelpId (USER32.@)
3079 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3081 WND *wnd = WIN_FindWndPtr( hwnd );
3082 if (!wnd) return FALSE;
3083 wnd->helpContext = id;
3084 WIN_ReleaseWndPtr(wnd);
3089 /*******************************************************************
3092 * recursively find a child that contains spDragInfo->pt point
3093 * and send WM_QUERYDROPOBJECT
3095 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3097 BOOL16 wParam, bResult = 0;
3099 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3102 if (!ptrDragInfo) return FALSE;
3104 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3106 GetWindowRect(hQueryWnd,&tempRect);
3108 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3110 if (!IsIconic( hQueryWnd ))
3112 GetClientRect( hQueryWnd, &tempRect );
3113 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3115 if (PtInRect( &tempRect, pt))
3118 HWND *list = WIN_ListChildren( hQueryWnd );
3124 for (i = 0; list[i]; i++)
3126 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3128 GetWindowRect( list[i], &tempRect );
3129 if (PtInRect( &tempRect, pt )) break;
3134 if (IsWindowEnabled( list[i] ))
3135 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
3137 HeapFree( GetProcessHeap(), 0, list );
3139 if(bResult) return bResult;
3145 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3147 ptrDragInfo->hScope = hQueryWnd;
3149 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3150 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3152 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3158 /*******************************************************************
3159 * DragDetect (USER32.@)
3161 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3166 rect.left = pt.x - wDragWidth;
3167 rect.right = pt.x + wDragWidth;
3169 rect.top = pt.y - wDragHeight;
3170 rect.bottom = pt.y + wDragHeight;
3176 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3178 if( msg.message == WM_LBUTTONUP )
3183 if( msg.message == WM_MOUSEMOVE )
3186 tmp.x = LOWORD(msg.lParam);
3187 tmp.y = HIWORD(msg.lParam);
3188 if( !PtInRect( &rect, tmp ))
3200 /******************************************************************************
3201 * DragObject (USER.464)
3203 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3204 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3207 LPDRAGINFO16 lpDragInfo;
3209 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3210 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3211 HCURSOR16 hCurrentCursor = 0;
3212 HWND16 hCurrentWnd = 0;
3214 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3215 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3217 if( !lpDragInfo || !spDragInfo ) return 0L;
3219 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3221 GlobalFree16(hDragInfo);
3227 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3229 GlobalFree16(hDragInfo);
3233 if( hDragCursor == hCursor ) hDragCursor = 0;
3234 else hCursor = hDragCursor;
3236 hOldCursor = SetCursor(hDragCursor);
3239 lpDragInfo->hWnd = hWnd;
3240 lpDragInfo->hScope = 0;
3241 lpDragInfo->wFlags = wObj;
3242 lpDragInfo->hList = szList; /* near pointer! */
3243 lpDragInfo->hOfStruct = hOfStruct;
3251 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3253 *(lpDragInfo+1) = *lpDragInfo;
3255 lpDragInfo->pt.x = msg.pt.x;
3256 lpDragInfo->pt.y = msg.pt.y;
3258 /* update DRAGINFO struct */
3259 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3261 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3262 hCurrentCursor = hCursor;
3265 hCurrentCursor = hBummer;
3266 lpDragInfo->hScope = 0;
3268 if( hCurrentCursor )
3269 SetCursor(hCurrentCursor);
3271 /* send WM_DRAGLOOP */
3272 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3273 (LPARAM) spDragInfo );
3274 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3275 if( hCurrentWnd != lpDragInfo->hScope )
3278 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3279 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3280 HIWORD(spDragInfo)) );
3281 hCurrentWnd = lpDragInfo->hScope;
3283 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3287 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3289 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3292 ShowCursor( FALSE );
3296 SetCursor( hOldCursor );
3297 if (hDragCursor) DestroyCursor( hDragCursor );
3300 if( hCurrentCursor != hBummer )
3301 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3302 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3305 GlobalFree16(hDragInfo);
3307 return (DWORD)(msg.lParam);
3311 /******************************************************************************
3312 * GetWindowModuleFileNameA (USER32.@)
3314 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3316 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3317 hwnd, lpszFileName, cchFileNameMax);
3321 /******************************************************************************
3322 * GetWindowModuleFileNameW (USER32.@)
3324 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3326 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3327 hwnd, lpszFileName, cchFileNameMax);