2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
28 #include "wine/winbase16.h"
29 #include "wine/winuser16.h"
31 #include "wine/server.h"
32 #include "wine/unicode.h"
37 #include "cursoricon.h"
43 #include "stackframe.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(win);
47 WINE_DECLARE_DEBUG_CHANNEL(msg);
49 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
51 /**********************************************************************/
54 static WND *pWndDesktop = NULL;
56 static WORD wDragWidth = 4;
57 static WORD wDragHeight= 3;
59 static void *user_handles[NB_USER_HANDLES];
62 extern SYSLEVEL USER_SysLevel; /* FIXME */
64 /***********************************************************************
67 * Suspend the lock on WND structures.
68 * Returns the number of locks suspended
70 int WIN_SuspendWndsLock( void )
72 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
73 int count = isuspendedLocks;
76 _LeaveSysLevel( &USER_SysLevel );
78 return isuspendedLocks;
81 /***********************************************************************
84 * Restore the suspended locks on WND structures
86 void WIN_RestoreWndsLock( int ipreviousLocks )
88 while ( ipreviousLocks-- > 0 )
89 _EnterSysLevel( &USER_SysLevel );
92 /***********************************************************************
93 * create_window_handle
95 * Create a window handle with the server.
97 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
100 user_handle_t handle = 0;
102 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
104 if (!win) return NULL;
108 SERVER_START_REQ( create_window )
110 req->parent = parent;
113 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
120 HeapFree( GetProcessHeap(), 0, win );
123 index = LOWORD(handle) - FIRST_USER_HANDLE;
124 assert( index < NB_USER_HANDLES );
125 user_handles[index] = win;
126 win->hwndSelf = handle;
127 win->dwMagic = WND_MAGIC;
133 /***********************************************************************
136 * Free a window handle.
138 static WND *free_window_handle( HWND hwnd )
141 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
143 if (index >= NB_USER_HANDLES) return NULL;
145 if ((ptr = user_handles[index]))
147 SERVER_START_REQ( destroy_window )
150 if (!wine_server_call_err( req ))
151 user_handles[index] = NULL;
158 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
163 /*******************************************************************
164 * list_window_children
166 * Build an array of the children of a given window. The array must be
167 * freed with HeapFree. Returns NULL when no windows are found.
169 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
178 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
180 SERVER_START_REQ( get_window_children )
185 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
186 if (!wine_server_call( req )) count = reply->count;
189 if (count && count < size)
194 HeapFree( GetProcessHeap(), 0, list );
196 size = count + 1; /* restart with a large enough buffer */
202 /*******************************************************************
205 static void send_parent_notify( HWND hwnd, UINT msg )
207 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
208 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
209 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
210 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
214 /*******************************************************************
215 * get_server_window_text
217 * Retrieve the window text from the server.
219 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
223 SERVER_START_REQ( get_window_text )
226 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
227 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
230 text[len / sizeof(WCHAR)] = 0;
234 /***********************************************************************
237 * Return a pointer to the WND structure if local to the process,
238 * or WND_OTHER_PROCESS if handle may be valid in other process.
239 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
241 WND *WIN_GetPtr( HWND hwnd )
244 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
246 if (index >= NB_USER_HANDLES) return NULL;
249 if ((ptr = user_handles[index]))
251 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
255 else ptr = WND_OTHER_PROCESS;
261 /***********************************************************************
262 * WIN_IsCurrentProcess
264 * Check whether a given window belongs to the current process (and return the full handle).
266 HWND WIN_IsCurrentProcess( HWND hwnd )
271 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
273 WIN_ReleasePtr( ptr );
278 /***********************************************************************
279 * WIN_IsCurrentThread
281 * Check whether a given window belongs to the current thread (and return the full handle).
283 HWND WIN_IsCurrentThread( HWND hwnd )
288 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
290 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
291 WIN_ReleasePtr( ptr );
297 /***********************************************************************
300 * Convert a 16-bit window handle to a full 32-bit handle.
302 HWND WIN_Handle32( HWND16 hwnd16 )
305 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
307 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
308 /* do sign extension for -2 and -3 */
309 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
311 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
313 if (ptr != WND_OTHER_PROCESS)
315 hwnd = ptr->hwndSelf;
316 WIN_ReleasePtr( ptr );
318 else /* may belong to another process */
320 SERVER_START_REQ( get_window_info )
323 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
331 /***********************************************************************
334 * Return a pointer to the WND structure corresponding to a HWND.
336 WND * WIN_FindWndPtr( HWND hwnd )
340 if (!hwnd) return NULL;
342 if ((ptr = WIN_GetPtr( hwnd )))
344 if (ptr != WND_OTHER_PROCESS)
346 /* increment destruction monitoring */
350 if (IsWindow( hwnd )) /* check other processes */
352 ERR( "window %04x belongs to other process\n", hwnd );
353 /* DbgBreakPoint(); */
356 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
361 /***********************************************************************
364 * Release the pointer to the WND structure.
366 void WIN_ReleaseWndPtr(WND *wndPtr)
370 /* Decrement destruction monitoring value */
372 /* Check if it's time to release the memory */
373 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
376 free_window_handle( wndPtr->hwndSelf );
378 else if(wndPtr->irefCount < 0)
380 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
381 ERR("forgot a Lock on %p somewhere\n",wndPtr);
383 /* unlock all WND structures for thread safeness */
388 /***********************************************************************
391 * Remove a window from the siblings linked list.
393 void WIN_UnlinkWindow( HWND hwnd )
395 WIN_LinkWindow( hwnd, 0, 0 );
399 /***********************************************************************
402 * Insert a window into the siblings linked list.
403 * The window is inserted after the specified window, which can also
404 * be specified as HWND_TOP or HWND_BOTTOM.
405 * If parent is 0, window is unlinked from the tree.
407 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
409 WND *wndPtr = WIN_GetPtr( hwnd );
412 if (wndPtr == WND_OTHER_PROCESS)
414 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
418 SERVER_START_REQ( link_window )
421 req->parent = parent;
422 req->previous = hwndInsertAfter;
423 if (!wine_server_call( req ))
425 if (reply->full_parent) wndPtr->parent = reply->full_parent;
430 WIN_ReleasePtr( wndPtr );
434 /***********************************************************************
437 * Change the owner of a window.
439 HWND WIN_SetOwner( HWND hwnd, HWND owner )
441 WND *win = WIN_GetPtr( hwnd );
445 if (win == WND_OTHER_PROCESS)
447 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
450 SERVER_START_REQ( set_window_owner )
454 if (!wine_server_call( req ))
456 win->owner = reply->full_owner;
457 ret = reply->prev_owner;
461 WIN_ReleasePtr( win );
466 /***********************************************************************
469 * Change the style of a window.
471 LONG WIN_SetStyle( HWND hwnd, LONG style )
475 WND *win = WIN_GetPtr( hwnd );
478 if (win == WND_OTHER_PROCESS)
481 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
484 if (style == win->dwStyle)
486 WIN_ReleasePtr( win );
489 SERVER_START_REQ( set_window_info )
492 req->flags = SET_WIN_STYLE;
494 if ((ok = !wine_server_call( req )))
496 ret = reply->old_style;
497 win->dwStyle = style;
501 WIN_ReleasePtr( win );
502 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
507 /***********************************************************************
510 * Change the extended style of a window.
512 LONG WIN_SetExStyle( HWND hwnd, LONG style )
515 WND *win = WIN_GetPtr( hwnd );
518 if (win == WND_OTHER_PROCESS)
521 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
524 if (style == win->dwExStyle)
526 WIN_ReleasePtr( win );
529 SERVER_START_REQ( set_window_info )
532 req->flags = SET_WIN_EXSTYLE;
533 req->ex_style = style;
534 if (!wine_server_call( req ))
536 ret = reply->old_ex_style;
537 win->dwExStyle = style;
541 WIN_ReleasePtr( win );
546 /***********************************************************************
549 * Set the window and client rectangles.
551 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
553 WND *win = WIN_GetPtr( hwnd );
557 if (win == WND_OTHER_PROCESS)
559 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
562 SERVER_START_REQ( set_window_rectangles )
565 req->window.left = rectWindow->left;
566 req->window.top = rectWindow->top;
567 req->window.right = rectWindow->right;
568 req->window.bottom = rectWindow->bottom;
569 req->client.left = rectClient->left;
570 req->client.top = rectClient->top;
571 req->client.right = rectClient->right;
572 req->client.bottom = rectClient->bottom;
573 ret = !wine_server_call( req );
578 win->rectWindow = *rectWindow;
579 win->rectClient = *rectClient;
581 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
582 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
583 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
585 WIN_ReleasePtr( win );
589 /***********************************************************************
592 * Get the window and client rectangles.
594 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
596 WND *win = WIN_GetPtr( hwnd );
599 if (!win) return FALSE;
600 if (win == WND_OTHER_PROCESS)
602 SERVER_START_REQ( get_window_rectangles )
605 if ((ret = !wine_server_call( req )))
609 rectWindow->left = reply->window.left;
610 rectWindow->top = reply->window.top;
611 rectWindow->right = reply->window.right;
612 rectWindow->bottom = reply->window.bottom;
616 rectClient->left = reply->client.left;
617 rectClient->top = reply->client.top;
618 rectClient->right = reply->client.right;
619 rectClient->bottom = reply->client.bottom;
627 if (rectWindow) *rectWindow = win->rectWindow;
628 if (rectClient) *rectClient = win->rectClient;
629 WIN_ReleasePtr( win );
635 /***********************************************************************
638 * Destroy storage associated to a window. "Internals" p.358
640 LRESULT WIN_DestroyWindow( HWND hwnd )
645 TRACE("%04x\n", hwnd );
647 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
649 ERR( "window doesn't belong to current thread\n" );
653 /* free child windows */
654 if ((list = WIN_ListChildren( hwnd )))
657 for (i = 0; list[i]; i++)
659 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
660 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
662 HeapFree( GetProcessHeap(), 0, list );
666 * Clear the update region to make sure no WM_PAINT messages will be
667 * generated for this window while processing the WM_NCDESTROY.
669 RedrawWindow( hwnd, NULL, 0,
670 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
673 * Send the WM_NCDESTROY to the window being destroyed.
675 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
677 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
679 WINPOS_CheckInternalPos( hwnd );
680 if( hwnd == GetCapture()) ReleaseCapture();
682 /* free resources associated with the window */
684 TIMER_RemoveWindowTimers( hwnd );
686 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
687 wndPtr->hmemTaskQ = 0;
689 if (!(wndPtr->dwStyle & WS_CHILD))
691 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
692 if (menu) DestroyMenu( menu );
694 if (wndPtr->hSysMenu)
696 DestroyMenu( wndPtr->hSysMenu );
697 wndPtr->hSysMenu = 0;
699 USER_Driver.pDestroyWindow( hwnd );
700 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
701 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
702 CLASS_RemoveWindow( wndPtr->class );
703 wndPtr->class = NULL;
704 wndPtr->dwMagic = 0; /* Mark it as invalid */
705 WIN_ReleaseWndPtr( wndPtr );
709 /***********************************************************************
710 * WIN_DestroyThreadWindows
712 * Destroy all children of 'wnd' owned by the current thread.
713 * Return TRUE if something was done.
715 void WIN_DestroyThreadWindows( HWND hwnd )
720 if (!(list = WIN_ListChildren( hwnd ))) return;
721 for (i = 0; list[i]; i++)
723 if (WIN_IsCurrentThread( list[i] ))
724 DestroyWindow( list[i] );
726 WIN_DestroyThreadWindows( list[i] );
728 HeapFree( GetProcessHeap(), 0, list );
731 /***********************************************************************
732 * WIN_CreateDesktopWindow
734 * Create the desktop window.
736 BOOL WIN_CreateDesktopWindow(void)
738 struct tagCLASS *class;
747 TRACE("Creating desktop window\n");
749 if (!WINPOS_CreateInternalPosAtom() ||
750 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
751 &wndExtra, &winproc, &clsStyle, &dce )))
754 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
755 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
756 if (!pWndDesktop) return FALSE;
757 hwndDesktop = pWndDesktop->hwndSelf;
759 pWndDesktop->tid = 0; /* nobody owns the desktop */
760 pWndDesktop->parent = 0;
761 pWndDesktop->owner = 0;
762 pWndDesktop->class = class;
763 pWndDesktop->text = NULL;
764 pWndDesktop->hmemTaskQ = 0;
765 pWndDesktop->hrgnUpdate = 0;
766 pWndDesktop->clsStyle = clsStyle;
767 pWndDesktop->dce = NULL;
768 pWndDesktop->pVScroll = NULL;
769 pWndDesktop->pHScroll = NULL;
770 pWndDesktop->helpContext = 0;
771 pWndDesktop->flags = 0;
772 pWndDesktop->hSysMenu = 0;
773 pWndDesktop->winproc = winproc;
774 pWndDesktop->cbWndExtra = wndExtra;
776 cs.lpCreateParams = NULL;
782 cs.cx = GetSystemMetrics( SM_CXSCREEN );
783 cs.cy = GetSystemMetrics( SM_CYSCREEN );
784 cs.style = pWndDesktop->dwStyle;
785 cs.dwExStyle = pWndDesktop->dwExStyle;
787 cs.lpszClass = DESKTOP_CLASS_ATOM;
789 SetRect( &rect, 0, 0, cs.cx, cs.cy );
790 WIN_SetRectangles( hwndDesktop, &rect, &rect );
792 SERVER_START_REQ( set_window_info )
794 req->handle = hwndDesktop;
795 req->flags = 0; /* don't set anything, just retrieve */
796 wine_server_call( req );
797 pWndDesktop->dwStyle = reply->old_style;
798 pWndDesktop->dwExStyle = reply->old_ex_style;
799 pWndDesktop->hInstance = (ULONG_PTR)reply->old_instance;
800 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
801 pWndDesktop->wIDmenu = reply->old_id;
805 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
807 WIN_ReleaseWndPtr( pWndDesktop );
811 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
812 WIN_ReleaseWndPtr( pWndDesktop );
817 /***********************************************************************
820 * Fix the coordinates - Helper for WIN_CreateWindowEx.
821 * returns default show mode in sw.
822 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
824 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
826 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
827 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
829 if (cs->style & (WS_CHILD | WS_POPUP))
831 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
832 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
834 else /* overlapped window */
838 GetStartupInfoA( &info );
840 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
842 /* Never believe Microsoft's documentation... CreateWindowEx doc says
843 * that if an overlapped window is created with WS_VISIBLE style bit
844 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
845 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
848 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
849 * 2) it does not ignore the y parameter as the docs claim; instead, it
850 * uses it as second parameter to ShowWindow() unless y is either
851 * CW_USEDEFAULT or CW_USEDEFAULT16.
853 * The fact that we didn't do 2) caused bogus windows pop up when wine
854 * was running apps that were using this obscure feature. Example -
855 * calc.exe that comes with Win98 (only Win98, it's different from
856 * the one that comes with Win95 and NT)
858 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
859 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
860 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
863 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
865 if (info.dwFlags & STARTF_USESIZE)
867 cs->cx = info.dwXSize;
868 cs->cy = info.dwYSize;
870 else /* if no other hint from the app, pick 3/4 of the screen real estate */
873 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
874 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
875 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
882 /* neither x nor cx are default. Check the y values .
883 * In the trace we see Outlook and Outlook Express using
884 * cy set to CW_USEDEFAULT when opening the address book.
886 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
888 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
889 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
890 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
895 /***********************************************************************
898 static void dump_window_styles( DWORD style, DWORD exstyle )
901 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
902 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
903 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
904 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
905 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
906 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
907 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
908 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
909 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
912 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
913 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
915 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
916 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
917 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
918 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
919 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
920 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
921 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
922 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
924 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
925 #define DUMPED_STYLES \
945 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
950 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
951 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
952 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
953 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
954 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
955 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
956 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
957 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
958 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
959 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
960 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
961 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
962 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
963 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
964 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
965 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
966 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
967 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
969 #define DUMPED_EX_STYLES \
970 (WS_EX_DLGMODALFRAME | \
972 WS_EX_NOPARENTNOTIFY | \
974 WS_EX_ACCEPTFILES | \
975 WS_EX_TRANSPARENT | \
980 WS_EX_CONTEXTHELP | \
983 WS_EX_LEFTSCROLLBAR | \
984 WS_EX_CONTROLPARENT | \
989 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
991 #undef DUMPED_EX_STYLES
995 /***********************************************************************
998 * Implementation of CreateWindowEx().
1000 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
1001 WINDOWPROCTYPE type )
1004 struct tagCLASS *classPtr;
1006 HWND hwnd, parent, owner;
1011 BOOL unicode = (type == WIN_PROC_32W);
1013 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
1014 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1015 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1016 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1017 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1019 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1021 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1022 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1024 /* Find the parent window */
1026 parent = GetDesktopWindow();
1029 if (cs->hwndParent == HWND_MESSAGE)
1031 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1032 * message window (style: WS_POPUP|WS_DISABLED)
1034 FIXME("Parent is HWND_MESSAGE\n");
1036 else if (cs->hwndParent)
1038 /* Make sure parent is valid */
1039 if (!IsWindow( cs->hwndParent ))
1041 WARN("Bad parent %04x\n", cs->hwndParent );
1044 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1045 parent = WIN_GetFullHandle(cs->hwndParent);
1047 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1049 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1051 WARN("No parent for child window\n" );
1052 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1055 /* Find the window class */
1056 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1057 &wndExtra, &winproc, &clsStyle, &dce )))
1059 WARN("Bad class '%s'\n", cs->lpszClass );
1063 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1065 /* Correct the window style - stage 1
1067 * These are patches that appear to affect both the style loaded into the
1068 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1070 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1071 * why does the user get to set it?
1074 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1075 * tested for WS_POPUP
1077 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1078 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1079 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1080 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1082 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1084 /* Create the window structure */
1086 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1087 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1089 TRACE("out of memory\n" );
1092 hwnd = wndPtr->hwndSelf;
1094 /* Fill the window structure */
1096 wndPtr->tid = GetCurrentThreadId();
1097 wndPtr->owner = owner;
1098 wndPtr->parent = parent;
1099 wndPtr->class = classPtr;
1100 wndPtr->winproc = winproc;
1101 wndPtr->hInstance = cs->hInstance;
1102 wndPtr->text = NULL;
1103 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
1104 wndPtr->hrgnUpdate = 0;
1105 wndPtr->hrgnWnd = 0;
1106 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1107 wndPtr->dwExStyle = cs->dwExStyle;
1108 wndPtr->clsStyle = clsStyle;
1109 wndPtr->wIDmenu = 0;
1110 wndPtr->helpContext = 0;
1111 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1112 wndPtr->pVScroll = NULL;
1113 wndPtr->pHScroll = NULL;
1114 wndPtr->userdata = 0;
1115 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1116 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1117 wndPtr->cbWndExtra = wndExtra;
1119 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1121 /* Correct the window style - stage 2 */
1123 if (!(cs->style & WS_CHILD))
1125 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1126 if (!(cs->style & WS_POPUP))
1128 wndPtr->dwStyle |= WS_CAPTION;
1129 wndPtr->flags |= WIN_NEED_SIZE;
1132 SERVER_START_REQ( set_window_info )
1135 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1136 req->style = wndPtr->dwStyle;
1137 req->ex_style = wndPtr->dwExStyle;
1138 req->instance = (void *)wndPtr->hInstance;
1139 wine_server_call( req );
1143 /* Get class or window DC if needed */
1145 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1146 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1147 else wndPtr->dce = NULL;
1149 /* Set the window menu */
1151 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1153 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1156 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1159 if (HIWORD(cs->hInstance))
1160 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1162 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1164 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1168 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1169 WIN_ReleaseWndPtr( wndPtr );
1171 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1173 WIN_DestroyWindow( hwnd );
1177 /* Notify the parent window only */
1179 send_parent_notify( hwnd, WM_CREATE );
1180 if (!IsWindow( hwnd )) return 0;
1182 if (cs->style & WS_VISIBLE)
1184 /* in case WS_VISIBLE got set in the meantime */
1185 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1186 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1187 WIN_ReleasePtr( wndPtr );
1188 ShowWindow( hwnd, sw );
1191 /* Call WH_SHELL hook */
1193 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1194 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1196 TRACE("created window %04x\n", hwnd);
1201 /***********************************************************************
1202 * CreateWindow (USER.41)
1204 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1205 DWORD style, INT16 x, INT16 y, INT16 width,
1206 INT16 height, HWND16 parent, HMENU16 menu,
1207 HINSTANCE16 instance, LPVOID data )
1209 return CreateWindowEx16( 0, className, windowName, style,
1210 x, y, width, height, parent, menu, instance, data );
1214 /***********************************************************************
1215 * CreateWindowEx (USER.452)
1217 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1218 LPCSTR windowName, DWORD style, INT16 x,
1219 INT16 y, INT16 width, INT16 height,
1220 HWND16 parent, HMENU16 menu,
1221 HINSTANCE16 instance, LPVOID data )
1227 /* Find the class atom */
1229 if (HIWORD(className))
1231 if (!(classAtom = GlobalFindAtomA( className )))
1233 ERR( "bad class name %s\n", debugstr_a(className) );
1239 classAtom = LOWORD(className);
1240 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1242 ERR( "bad atom %x\n", classAtom);
1248 /* Fix the coordinates */
1250 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1251 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1252 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1253 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1255 /* Create the window */
1257 cs.lpCreateParams = data;
1258 cs.hInstance = (HINSTANCE)instance;
1259 cs.hMenu = (HMENU)menu;
1260 cs.hwndParent = WIN_Handle32( parent );
1262 cs.lpszName = windowName;
1263 cs.lpszClass = className;
1264 cs.dwExStyle = exStyle;
1266 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1270 /***********************************************************************
1271 * CreateWindowExA (USER32.@)
1273 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1274 LPCSTR windowName, DWORD style, INT x,
1275 INT y, INT width, INT height,
1276 HWND parent, HMENU menu,
1277 HINSTANCE instance, LPVOID data )
1284 instance=GetModuleHandleA(NULL);
1286 if(exStyle & WS_EX_MDICHILD)
1287 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1289 /* Find the class atom */
1291 if (HIWORD(className))
1293 if (!(classAtom = GlobalFindAtomA( className )))
1295 ERR( "bad class name %s\n", debugstr_a(className) );
1301 classAtom = LOWORD(className);
1302 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1304 ERR( "bad atom %x\n", classAtom);
1310 /* Create the window */
1312 cs.lpCreateParams = data;
1313 cs.hInstance = instance;
1315 cs.hwndParent = parent;
1321 cs.lpszName = windowName;
1322 cs.lpszClass = className;
1323 cs.dwExStyle = exStyle;
1325 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1329 /***********************************************************************
1330 * CreateWindowExW (USER32.@)
1332 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1333 LPCWSTR windowName, DWORD style, INT x,
1334 INT y, INT width, INT height,
1335 HWND parent, HMENU menu,
1336 HINSTANCE instance, LPVOID data )
1343 instance=GetModuleHandleA(NULL);
1345 if(exStyle & WS_EX_MDICHILD)
1346 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1348 /* Find the class atom */
1350 if (HIWORD(className))
1352 if (!(classAtom = GlobalFindAtomW( className )))
1354 ERR( "bad class name %s\n", debugstr_w(className) );
1360 classAtom = LOWORD(className);
1361 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1363 ERR( "bad atom %x\n", classAtom);
1369 /* Create the window */
1371 cs.lpCreateParams = data;
1372 cs.hInstance = instance;
1374 cs.hwndParent = parent;
1380 cs.lpszName = windowName;
1381 cs.lpszClass = className;
1382 cs.dwExStyle = exStyle;
1384 /* Note: we rely on the fact that CREATESTRUCTA and */
1385 /* CREATESTRUCTW have the same layout. */
1386 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1390 /***********************************************************************
1391 * WIN_SendDestroyMsg
1393 static void WIN_SendDestroyMsg( HWND hwnd )
1397 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1399 if (hwnd == info.hwndCaret) DestroyCaret();
1401 if (USER_Driver.pResetSelectionOwner)
1402 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1405 * Send the WM_DESTROY to the window.
1407 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1410 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1411 * make sure that the window still exists when we come back.
1418 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1420 /* start from the end (FIXME: is this needed?) */
1421 for (i = 0; pWndArray[i]; i++) ;
1425 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1427 HeapFree( GetProcessHeap(), 0, pWndArray );
1430 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1434 /***********************************************************************
1435 * DestroyWindow (USER32.@)
1437 BOOL WINAPI DestroyWindow( HWND hwnd )
1442 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1444 SetLastError( ERROR_ACCESS_DENIED );
1448 TRACE("(%04x)\n", hwnd);
1450 /* Look whether the focus is within the tree of windows we will
1454 if (h == hwnd || IsChild( hwnd, h ))
1456 HWND parent = GetAncestor( hwnd, GA_PARENT );
1457 if (parent == GetDesktopWindow()) parent = 0;
1463 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1465 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1469 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1470 send_parent_notify( hwnd, WM_DESTROY );
1472 else if (!GetWindow( hwnd, GW_OWNER ))
1474 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1475 /* FIXME: clean up palette - see "Internals" p.352 */
1478 if (!IsWindow(hwnd)) return TRUE;
1480 if (USER_Driver.pResetSelectionOwner)
1481 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1483 /* Hide the window */
1485 if (!ShowWindow( hwnd, SW_HIDE ))
1487 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1489 if (!IsWindow(hwnd)) return TRUE;
1491 /* Recursively destroy owned windows */
1498 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1501 for (i = 0; list[i]; i++)
1503 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1504 if (WIN_IsCurrentThread( list[i] ))
1506 DestroyWindow( list[i] );
1510 WIN_SetOwner( list[i], 0 );
1512 HeapFree( GetProcessHeap(), 0, list );
1514 if (!got_one) break;
1518 /* Send destroy messages */
1520 WIN_SendDestroyMsg( hwnd );
1521 if (!IsWindow( hwnd )) return TRUE;
1523 /* Unlink now so we won't bother with the children later on */
1525 WIN_UnlinkWindow( hwnd );
1527 /* Destroy the window storage */
1529 WIN_DestroyWindow( hwnd );
1534 /***********************************************************************
1535 * CloseWindow (USER32.@)
1537 BOOL WINAPI CloseWindow( HWND hwnd )
1539 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1540 ShowWindow( hwnd, SW_MINIMIZE );
1545 /***********************************************************************
1546 * OpenIcon (USER32.@)
1548 BOOL WINAPI OpenIcon( HWND hwnd )
1550 if (!IsIconic( hwnd )) return FALSE;
1551 ShowWindow( hwnd, SW_SHOWNORMAL );
1556 /***********************************************************************
1559 * Implementation of FindWindow() and FindWindowEx().
1561 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1566 WCHAR *buffer = NULL;
1568 if (!parent) parent = GetDesktopWindow();
1571 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1572 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1575 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1579 child = WIN_GetFullHandle( child );
1580 while (list[i] && list[i] != child) i++;
1581 if (!list[i]) goto done;
1582 i++; /* start from next window */
1589 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1596 if (list) HeapFree( GetProcessHeap(), 0, list );
1597 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1603 /***********************************************************************
1604 * FindWindowA (USER32.@)
1606 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1608 HWND ret = FindWindowExA( 0, 0, className, title );
1609 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1614 /***********************************************************************
1615 * FindWindowExA (USER32.@)
1617 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1618 LPCSTR className, LPCSTR title )
1627 /* If the atom doesn't exist, then no class */
1628 /* with this name exists either. */
1629 if (!(atom = GlobalFindAtomA( className )))
1631 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1635 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1637 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1638 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1639 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1640 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1641 HeapFree( GetProcessHeap(), 0, buffer );
1646 /***********************************************************************
1647 * FindWindowExW (USER32.@)
1649 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1650 LPCWSTR className, LPCWSTR title )
1656 /* If the atom doesn't exist, then no class */
1657 /* with this name exists either. */
1658 if (!(atom = GlobalFindAtomW( className )))
1660 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1664 return WIN_FindWindow( parent, child, atom, title );
1668 /***********************************************************************
1669 * FindWindowW (USER32.@)
1671 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1673 return FindWindowExW( 0, 0, className, title );
1677 /**********************************************************************
1678 * GetDesktopWindow (USER32.@)
1680 HWND WINAPI GetDesktopWindow(void)
1682 if (pWndDesktop) return pWndDesktop->hwndSelf;
1683 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" );
1689 /*******************************************************************
1690 * EnableWindow (USER32.@)
1692 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1699 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1700 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1704 TRACE("( %x, %d )\n", hwnd, enable);
1706 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1707 style = wndPtr->dwStyle;
1708 retvalue = ((style & WS_DISABLED) != 0);
1709 WIN_ReleasePtr( wndPtr );
1711 if (enable && retvalue)
1713 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1714 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1716 else if (!enable && !retvalue)
1718 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1720 WIN_SetStyle( hwnd, style | WS_DISABLED );
1722 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1723 SetFocus( 0 ); /* A disabled window can't have the focus */
1725 if (hwnd == GetCapture() || IsChild(hwnd, GetCapture()))
1726 ReleaseCapture(); /* A disabled window can't capture the mouse */
1728 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1734 /***********************************************************************
1735 * IsWindowEnabled (USER32.@)
1737 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1739 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1743 /***********************************************************************
1744 * IsWindowUnicode (USER32.@)
1746 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1751 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1752 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1753 WIN_ReleaseWndPtr(wndPtr);
1758 /**********************************************************************
1759 * GetWindowWord (USER32.@)
1761 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1766 WND *wndPtr = WIN_GetPtr( hwnd );
1769 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1772 if (wndPtr == WND_OTHER_PROCESS)
1774 if (IsWindow( hwnd ))
1775 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1776 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1779 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1781 WARN("Invalid offset %d\n", offset );
1782 SetLastError( ERROR_INVALID_INDEX );
1784 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1785 WIN_ReleasePtr( wndPtr );
1791 case GWL_HWNDPARENT:
1792 return GetWindowLongW( hwnd, offset );
1796 LONG ret = GetWindowLongW( hwnd, offset );
1798 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1802 WARN("Invalid offset %d\n", offset );
1808 /**********************************************************************
1809 * SetWindowWord (USER32.@)
1811 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1820 case GWL_HWNDPARENT:
1821 return SetWindowLongW( hwnd, offset, (UINT)newval );
1825 WARN("Invalid offset %d\n", offset );
1826 SetLastError( ERROR_INVALID_INDEX );
1831 wndPtr = WIN_GetPtr( hwnd );
1832 if (wndPtr == WND_OTHER_PROCESS)
1835 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1836 offset, newval, hwnd );
1841 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1845 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1847 WARN("Invalid offset %d\n", offset );
1848 WIN_ReleasePtr(wndPtr);
1849 SetLastError( ERROR_INVALID_INDEX );
1852 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1855 WIN_ReleasePtr(wndPtr);
1860 /**********************************************************************
1863 * Helper function for GetWindowLong().
1865 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1870 if (offset == GWL_HWNDPARENT)
1872 HWND parent = GetAncestor( hwnd, GA_PARENT );
1873 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1874 return (LONG)parent;
1877 if (!(wndPtr = WIN_GetPtr( hwnd )))
1879 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1883 if (wndPtr == WND_OTHER_PROCESS)
1888 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1889 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1892 if (offset == GWL_WNDPROC)
1894 SetLastError( ERROR_ACCESS_DENIED );
1897 SERVER_START_REQ( set_window_info )
1900 req->flags = 0; /* don't set anything, just retrieve */
1901 if (!wine_server_call_err( req ))
1905 case GWL_STYLE: retvalue = reply->old_style; break;
1906 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1907 case GWL_ID: retvalue = reply->old_id; break;
1908 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1909 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1911 SetLastError( ERROR_INVALID_INDEX );
1920 /* now we have a valid wndPtr */
1924 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1927 * Some programs try to access last element from 16 bit
1928 * code using illegal offset value. Hopefully this is
1929 * what those programs really expect.
1931 if (type == WIN_PROC_16 &&
1932 wndPtr->cbWndExtra >= 4 &&
1933 offset == wndPtr->cbWndExtra - sizeof(WORD))
1935 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1937 ERR( "- replaced invalid offset %d with %d\n",
1940 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1941 WIN_ReleasePtr( wndPtr );
1944 WARN("Invalid offset %d\n", offset );
1945 WIN_ReleasePtr( wndPtr );
1946 SetLastError( ERROR_INVALID_INDEX );
1949 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1950 /* Special case for dialog window procedure */
1951 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1952 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1953 WIN_ReleasePtr( wndPtr );
1959 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1960 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1961 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1962 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1963 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1964 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1966 WARN("Unknown offset %d\n", offset );
1967 SetLastError( ERROR_INVALID_INDEX );
1970 WIN_ReleasePtr(wndPtr);
1975 /**********************************************************************
1978 * Helper function for SetWindowLong().
1980 * 0 is the failure code. However, in the case of failure SetLastError
1981 * must be set to distinguish between a 0 return value and a failure.
1983 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1984 WINDOWPROCTYPE type )
1989 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1991 if (!WIN_IsCurrentProcess( hwnd ))
1993 if (offset == GWL_WNDPROC)
1995 SetLastError( ERROR_ACCESS_DENIED );
1998 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2001 wndPtr = WIN_GetPtr( hwnd );
2002 if (wndPtr->hwndSelf == GetDesktopWindow())
2004 /* can't change anything on the desktop window */
2005 WIN_ReleasePtr( wndPtr );
2006 SetLastError( ERROR_ACCESS_DENIED );
2012 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2013 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
2015 WARN("Invalid offset %d\n", offset );
2016 WIN_ReleasePtr( wndPtr );
2017 SetLastError( ERROR_INVALID_INDEX );
2020 /* Special case for dialog window procedure */
2021 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2023 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2024 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2025 type, WIN_PROC_WINDOW );
2026 WIN_ReleasePtr( wndPtr );
2031 WIN_ReleasePtr( wndPtr );
2038 /* first some special cases */
2043 style.styleOld = wndPtr->dwStyle;
2044 style.styleNew = newval;
2045 WIN_ReleasePtr( wndPtr );
2046 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2047 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2048 newval = style.styleNew;
2050 case GWL_HWNDPARENT:
2051 if (wndPtr->parent == GetDesktopWindow())
2053 WIN_ReleasePtr( wndPtr );
2054 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2058 WIN_ReleasePtr( wndPtr );
2059 return (LONG)SetParent( hwnd, (HWND)newval );
2062 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2063 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2064 type, WIN_PROC_WINDOW );
2065 WIN_ReleasePtr( wndPtr );
2072 WIN_ReleasePtr( wndPtr );
2073 WARN("Invalid offset %d\n", offset );
2074 SetLastError( ERROR_INVALID_INDEX );
2078 SERVER_START_REQ( set_window_info )
2084 req->flags = SET_WIN_STYLE;
2085 req->style = newval;
2088 req->flags = SET_WIN_EXSTYLE;
2089 req->ex_style = newval;
2092 req->flags = SET_WIN_ID;
2096 req->flags = SET_WIN_INSTANCE;
2097 req->instance = (void *)newval;
2100 req->flags = SET_WIN_USERDATA;
2101 req->user_data = (void *)newval;
2104 if ((ok = !wine_server_call_err( req )))
2109 wndPtr->dwStyle = newval;
2110 retval = reply->old_style;
2113 wndPtr->dwExStyle = newval;
2114 retval = reply->old_ex_style;
2117 wndPtr->wIDmenu = newval;
2118 retval = reply->old_id;
2121 wndPtr->hInstance = newval;
2122 retval = (HINSTANCE)reply->old_instance;
2125 wndPtr->userdata = newval;
2126 retval = (ULONG_PTR)reply->old_user_data;
2132 WIN_ReleasePtr( wndPtr );
2136 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2137 USER_Driver.pSetWindowStyle( hwnd, retval );
2139 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2140 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2147 /**********************************************************************
2148 * GetWindowLong (USER.135)
2150 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2152 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2156 /**********************************************************************
2157 * GetWindowLongA (USER32.@)
2159 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2161 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2165 /**********************************************************************
2166 * GetWindowLongW (USER32.@)
2168 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2170 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2174 /**********************************************************************
2175 * SetWindowLong (USER.136)
2177 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2179 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2183 /**********************************************************************
2184 * SetWindowLongA (USER32.@)
2186 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2188 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2192 /**********************************************************************
2193 * SetWindowLongW (USER32.@) Set window attribute
2195 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2196 * value in a window's extra memory.
2198 * The _hwnd_ parameter specifies the window. is the handle to a
2199 * window that has extra memory. The _newval_ parameter contains the
2200 * new attribute or extra memory value. If positive, the _offset_
2201 * parameter is the byte-addressed location in the window's extra
2202 * memory to set. If negative, _offset_ specifies the window
2203 * attribute to set, and should be one of the following values:
2205 * GWL_EXSTYLE The window's extended window style
2207 * GWL_STYLE The window's window style.
2209 * GWL_WNDPROC Pointer to the window's window procedure.
2211 * GWL_HINSTANCE The window's pplication instance handle.
2213 * GWL_ID The window's identifier.
2215 * GWL_USERDATA The window's user-specified data.
2217 * If the window is a dialog box, the _offset_ parameter can be one of
2218 * the following values:
2220 * DWL_DLGPROC The address of the window's dialog box procedure.
2222 * DWL_MSGRESULT The return value of a message
2223 * that the dialog box procedure processed.
2225 * DWL_USER Application specific information.
2229 * If successful, returns the previous value located at _offset_. Otherwise,
2234 * Extra memory for a window class is specified by a nonzero cbWndExtra
2235 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2236 * time of class creation.
2238 * Using GWL_WNDPROC to set a new window procedure effectively creates
2239 * a window subclass. Use CallWindowProc() in the new windows procedure
2240 * to pass messages to the superclass's window procedure.
2242 * The user data is reserved for use by the application which created
2245 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2246 * instead, call the EnableWindow() function to change the window's
2249 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2250 * SetParent() instead.
2253 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2254 * it sends WM_STYLECHANGING before changing the settings
2255 * and WM_STYLECHANGED afterwards.
2256 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2258 LONG WINAPI SetWindowLongW(
2259 HWND hwnd, /* [in] window to alter */
2260 INT offset, /* [in] offset, in bytes, of location to alter */
2261 LONG newval /* [in] new value of location */
2263 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2267 /*******************************************************************
2268 * GetWindowTextA (USER32.@)
2270 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2274 if (WIN_IsCurrentProcess( hwnd ))
2275 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2277 /* when window belongs to other process, don't send a message */
2278 if (nMaxCount <= 0) return 0;
2279 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2280 get_server_window_text( hwnd, buffer, nMaxCount );
2281 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2282 lpString[nMaxCount-1] = 0;
2283 HeapFree( GetProcessHeap(), 0, buffer );
2284 return strlen(lpString);
2288 /*******************************************************************
2289 * InternalGetWindowText (USER32.@)
2291 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2295 if (nMaxCount <= 0) return 0;
2296 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2297 if (win != WND_OTHER_PROCESS)
2299 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2300 else lpString[0] = 0;
2301 WIN_ReleasePtr( win );
2305 get_server_window_text( hwnd, lpString, nMaxCount );
2307 return strlenW(lpString);
2311 /*******************************************************************
2312 * GetWindowTextW (USER32.@)
2314 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2316 if (WIN_IsCurrentProcess( hwnd ))
2317 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2319 /* when window belongs to other process, don't send a message */
2320 if (nMaxCount <= 0) return 0;
2321 get_server_window_text( hwnd, lpString, nMaxCount );
2322 return strlenW(lpString);
2326 /*******************************************************************
2327 * SetWindowText (USER32.@)
2328 * SetWindowTextA (USER32.@)
2330 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2332 if (!WIN_IsCurrentProcess( hwnd ))
2334 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2335 SetLastError( ERROR_ACCESS_DENIED );
2338 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2342 /*******************************************************************
2343 * SetWindowTextW (USER32.@)
2345 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2347 if (!WIN_IsCurrentProcess( hwnd ))
2349 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2350 SetLastError( ERROR_ACCESS_DENIED );
2353 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2357 /*******************************************************************
2358 * GetWindowTextLengthA (USER32.@)
2360 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2362 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2365 /*******************************************************************
2366 * GetWindowTextLengthW (USER32.@)
2368 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2370 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2374 /*******************************************************************
2375 * IsWindow (USER32.@)
2377 BOOL WINAPI IsWindow( HWND hwnd )
2382 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2384 if (ptr != WND_OTHER_PROCESS)
2386 WIN_ReleasePtr( ptr );
2390 /* check other processes */
2391 SERVER_START_REQ( get_window_info )
2394 ret = !wine_server_call_err( req );
2401 /***********************************************************************
2402 * GetWindowThreadProcessId (USER32.@)
2404 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2409 if (!(ptr = WIN_GetPtr( hwnd )))
2411 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2415 if (ptr != WND_OTHER_PROCESS)
2417 /* got a valid window */
2419 if (process) *process = GetCurrentProcessId();
2420 WIN_ReleasePtr( ptr );
2424 /* check other processes */
2425 SERVER_START_REQ( get_window_info )
2428 if (!wine_server_call_err( req ))
2430 tid = (DWORD)reply->tid;
2431 if (process) *process = (DWORD)reply->pid;
2439 /*****************************************************************
2440 * GetParent (USER32.@)
2442 HWND WINAPI GetParent( HWND hwnd )
2447 if (!(wndPtr = WIN_GetPtr( hwnd )))
2449 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2452 if (wndPtr == WND_OTHER_PROCESS)
2454 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2455 if (style & (WS_POPUP | WS_CHILD))
2457 SERVER_START_REQ( get_window_tree )
2460 if (!wine_server_call_err( req ))
2462 if (style & WS_POPUP) retvalue = reply->owner;
2463 else if (style & WS_CHILD) retvalue = reply->parent;
2471 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2472 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2473 WIN_ReleasePtr( wndPtr );
2479 /*****************************************************************
2480 * GetAncestor (USER32.@)
2482 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2485 HWND *list, ret = 0;
2490 if (!(win = WIN_GetPtr( hwnd )))
2492 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2495 if (win != WND_OTHER_PROCESS)
2498 WIN_ReleasePtr( win );
2500 else /* need to query the server */
2502 SERVER_START_REQ( get_window_tree )
2505 if (!wine_server_call_err( req )) ret = reply->parent;
2512 if (!(list = WIN_ListParents( hwnd ))) return 0;
2514 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2518 while (list[count]) count++;
2519 ret = list[count - 2]; /* get the one before the desktop */
2521 HeapFree( GetProcessHeap(), 0, list );
2525 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2528 HWND parent = GetParent( ret );
2538 /*****************************************************************
2539 * SetParent (USER32.@)
2541 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2544 HWND retvalue, full_handle;
2547 if (!parent) parent = GetDesktopWindow();
2548 else parent = WIN_GetFullHandle( parent );
2550 if (!IsWindow( parent ))
2552 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2556 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2557 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2561 if (USER_Driver.pSetParent)
2562 return USER_Driver.pSetParent( hwnd, parent );
2564 /* Windows hides the window first, then shows it again
2565 * including the WM_SHOWWINDOW messages and all */
2566 was_visible = ShowWindow( hwnd, SW_HIDE );
2568 if (!IsWindow( parent )) return 0;
2569 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2571 retvalue = wndPtr->parent; /* old parent */
2572 if (parent != retvalue)
2574 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2576 if (parent != GetDesktopWindow()) /* a child window */
2578 if (!(wndPtr->dwStyle & WS_CHILD))
2580 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2581 if (menu) DestroyMenu( menu );
2585 WIN_ReleasePtr( wndPtr );
2587 /* SetParent additionally needs to make hwnd the topmost window
2588 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2589 WM_WINDOWPOSCHANGED notification messages.
2591 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2592 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2593 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2594 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2599 /*******************************************************************
2600 * IsChild (USER32.@)
2602 BOOL WINAPI IsChild( HWND parent, HWND child )
2604 HWND *list = WIN_ListParents( child );
2608 if (!list) return FALSE;
2609 parent = WIN_GetFullHandle( parent );
2610 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2611 ret = (list[i] != 0);
2612 HeapFree( GetProcessHeap(), 0, list );
2617 /***********************************************************************
2618 * IsWindowVisible (USER32.@)
2620 BOOL WINAPI IsWindowVisible( HWND hwnd )
2626 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2627 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2628 for (i = 0; list[i]; i++)
2629 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2631 HeapFree( GetProcessHeap(), 0, list );
2636 /***********************************************************************
2637 * WIN_IsWindowDrawable
2639 * hwnd is drawable when it is visible, all parents are not
2640 * minimized, and it is itself not minimized unless we are
2641 * trying to draw its default class icon.
2643 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2648 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2650 if (!(style & WS_VISIBLE)) return FALSE;
2651 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2653 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2654 for (i = 0; list[i]; i++)
2655 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2658 HeapFree( GetProcessHeap(), 0, list );
2663 /*******************************************************************
2664 * GetTopWindow (USER32.@)
2666 HWND WINAPI GetTopWindow( HWND hwnd )
2668 if (!hwnd) hwnd = GetDesktopWindow();
2669 return GetWindow( hwnd, GW_CHILD );
2673 /*******************************************************************
2674 * GetWindow (USER32.@)
2676 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2680 if (rel == GW_OWNER) /* this one may be available locally */
2682 WND *wndPtr = WIN_GetPtr( hwnd );
2685 SetLastError( ERROR_INVALID_HANDLE );
2688 if (wndPtr != WND_OTHER_PROCESS)
2690 retval = wndPtr->owner;
2691 WIN_ReleasePtr( wndPtr );
2694 /* else fall through to server call */
2697 SERVER_START_REQ( get_window_tree )
2700 if (!wine_server_call_err( req ))
2705 retval = reply->first_sibling;
2708 retval = reply->last_sibling;
2711 retval = reply->next_sibling;
2714 retval = reply->prev_sibling;
2717 retval = reply->owner;
2720 retval = reply->first_child;
2730 /***********************************************************************
2731 * WIN_InternalShowOwnedPopups
2733 * Internal version of ShowOwnedPopups; Wine functions should use this
2734 * to avoid interfering with application calls to ShowOwnedPopups
2735 * and to make sure the application can't prevent showing/hiding.
2737 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2741 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2745 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2747 if (!win_array) return TRUE;
2750 * Show windows Lowest first, Highest last to preserve Z-Order
2752 while (win_array[count]) count++;
2753 while (--count >= 0)
2755 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2756 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2758 if (pWnd->dwStyle & WS_POPUP)
2762 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2763 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2766 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2768 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2769 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2774 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2775 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2776 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2779 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2781 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2782 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2783 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2787 WIN_ReleaseWndPtr( pWnd );
2789 HeapFree( GetProcessHeap(), 0, win_array );
2794 /*******************************************************************
2795 * ShowOwnedPopups (USER32.@)
2797 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2801 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2803 if (!win_array) return TRUE;
2805 while (win_array[count]) count++;
2806 while (--count >= 0)
2808 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2809 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2811 if (pWnd->dwStyle & WS_POPUP)
2815 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2817 /* In Windows, ShowOwnedPopups(TRUE) generates
2818 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2819 * regardless of the state of the owner
2821 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2822 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2827 if (IsWindowVisible(pWnd->hwndSelf))
2829 /* In Windows, ShowOwnedPopups(FALSE) generates
2830 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2831 * regardless of the state of the owner
2833 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2834 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2838 WIN_ReleaseWndPtr( pWnd );
2840 HeapFree( GetProcessHeap(), 0, win_array );
2845 /*******************************************************************
2846 * GetLastActivePopup (USER32.@)
2848 HWND WINAPI GetLastActivePopup( HWND hwnd )
2852 SERVER_START_REQ( get_window_info )
2855 if (!wine_server_call_err( req )) retval = reply->last_active;
2862 /*******************************************************************
2865 * Build an array of all parents of a given window, starting with
2866 * the immediate parent. The array must be freed with HeapFree.
2867 * Returns NULL if window is a top-level window.
2869 HWND *WIN_ListParents( HWND hwnd )
2872 HWND current, *list;
2873 int pos = 0, size = 16, count = 0;
2875 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2880 if (!(win = WIN_GetPtr( current ))) goto empty;
2881 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2882 list[pos] = win->parent;
2883 WIN_ReleasePtr( win );
2884 if (!(current = list[pos]))
2886 if (!pos) goto empty;
2889 if (++pos == size - 1)
2891 /* need to grow the list */
2892 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2893 if (!new_list) goto empty;
2899 /* at least one parent belongs to another process, have to query the server */
2904 SERVER_START_REQ( get_window_parents )
2907 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2908 if (!wine_server_call( req )) count = reply->count;
2911 if (!count) goto empty;
2917 HeapFree( GetProcessHeap(), 0, list );
2919 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2923 HeapFree( GetProcessHeap(), 0, list );
2928 /*******************************************************************
2931 * Build an array of the children of a given window. The array must be
2932 * freed with HeapFree. Returns NULL when no windows are found.
2934 HWND *WIN_ListChildren( HWND hwnd )
2936 return list_window_children( hwnd, 0, 0 );
2940 /*******************************************************************
2941 * EnumWindows (USER32.@)
2943 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2949 /* We have to build a list of all windows first, to avoid */
2950 /* unpleasant side-effects, for instance if the callback */
2951 /* function changes the Z-order of the windows. */
2953 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2955 /* Now call the callback function for every window */
2957 iWndsLocks = WIN_SuspendWndsLock();
2958 for (i = 0; list[i]; i++)
2960 /* Make sure that the window still exists */
2961 if (!IsWindow( list[i] )) continue;
2962 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2964 WIN_RestoreWndsLock(iWndsLocks);
2965 HeapFree( GetProcessHeap(), 0, list );
2970 /**********************************************************************
2971 * EnumThreadWindows (USER32.@)
2973 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2978 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2980 /* Now call the callback function for every window */
2982 iWndsLocks = WIN_SuspendWndsLock();
2983 for (i = 0; list[i]; i++)
2984 if (!func( list[i], lParam )) break;
2985 WIN_RestoreWndsLock(iWndsLocks);
2986 HeapFree( GetProcessHeap(), 0, list );
2991 /**********************************************************************
2992 * WIN_EnumChildWindows
2994 * Helper function for EnumChildWindows().
2996 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3001 for ( ; *list; list++)
3003 /* Make sure that the window still exists */
3004 if (!IsWindow( *list )) continue;
3005 /* skip owned windows */
3006 if (GetWindow( *list, GW_OWNER )) continue;
3007 /* Build children list first */
3008 childList = WIN_ListChildren( *list );
3010 ret = func( *list, lParam );
3014 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3015 HeapFree( GetProcessHeap(), 0, childList );
3017 if (!ret) return FALSE;
3023 /**********************************************************************
3024 * EnumChildWindows (USER32.@)
3026 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3031 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3032 iWndsLocks = WIN_SuspendWndsLock();
3033 WIN_EnumChildWindows( list, func, lParam );
3034 WIN_RestoreWndsLock(iWndsLocks);
3035 HeapFree( GetProcessHeap(), 0, list );
3040 /*******************************************************************
3041 * AnyPopup (USER.52)
3043 BOOL16 WINAPI AnyPopup16(void)
3049 /*******************************************************************
3050 * AnyPopup (USER32.@)
3052 BOOL WINAPI AnyPopup(void)
3056 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3058 if (!list) return FALSE;
3059 for (i = 0; list[i]; i++)
3061 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3063 retvalue = (list[i] != 0);
3064 HeapFree( GetProcessHeap(), 0, list );
3069 /*******************************************************************
3070 * FlashWindow (USER32.@)
3072 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3074 WND *wndPtr = WIN_FindWndPtr(hWnd);
3076 TRACE("%04x\n", hWnd);
3078 if (!wndPtr) return FALSE;
3079 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3081 if (wndPtr->dwStyle & WS_MINIMIZE)
3083 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3085 HDC hDC = GetDC(hWnd);
3087 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3088 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3090 ReleaseDC( hWnd, hDC );
3091 wndPtr->flags |= WIN_NCACTIVATED;
3095 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3096 wndPtr->flags &= ~WIN_NCACTIVATED;
3098 WIN_ReleaseWndPtr(wndPtr);
3104 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3105 else wparam = (hWnd == GetForegroundWindow());
3107 WIN_ReleaseWndPtr(wndPtr);
3108 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3114 /*******************************************************************
3115 * GetWindowContextHelpId (USER32.@)
3117 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3120 WND *wnd = WIN_FindWndPtr( hwnd );
3122 retval = wnd->helpContext;
3123 WIN_ReleaseWndPtr(wnd);
3128 /*******************************************************************
3129 * SetWindowContextHelpId (USER32.@)
3131 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3133 WND *wnd = WIN_FindWndPtr( hwnd );
3134 if (!wnd) return FALSE;
3135 wnd->helpContext = id;
3136 WIN_ReleaseWndPtr(wnd);
3141 /*******************************************************************
3142 * DRAG_QueryUpdate16
3144 * recursively find a child that contains spDragInfo->pt point
3145 * and send WM_QUERYDROPOBJECT
3147 static BOOL16 DRAG_QueryUpdate16( HWND hQueryWnd, SEGPTR spDragInfo )
3149 BOOL16 wParam, bResult = 0;
3151 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3154 if (!ptrDragInfo) return FALSE;
3156 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3158 GetWindowRect(hQueryWnd,&tempRect);
3160 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3162 if (!IsIconic( hQueryWnd ))
3164 GetClientRect( hQueryWnd, &tempRect );
3165 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3167 if (PtInRect( &tempRect, pt))
3170 HWND *list = WIN_ListChildren( hQueryWnd );
3176 for (i = 0; list[i]; i++)
3178 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3180 GetWindowRect( list[i], &tempRect );
3181 if (PtInRect( &tempRect, pt )) break;
3186 if (IsWindowEnabled( list[i] ))
3187 bResult = DRAG_QueryUpdate16( list[i], spDragInfo );
3189 HeapFree( GetProcessHeap(), 0, list );
3191 if(bResult) return bResult;
3197 ScreenToClient16(HWND_16(hQueryWnd),&ptrDragInfo->pt);
3199 ptrDragInfo->hScope = HWND_16(hQueryWnd);
3201 bResult = SendMessage16( HWND_16(hQueryWnd), WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3203 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3209 /*******************************************************************
3210 * DragDetect (USER32.@)
3212 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3217 rect.left = pt.x - wDragWidth;
3218 rect.right = pt.x + wDragWidth;
3220 rect.top = pt.y - wDragHeight;
3221 rect.bottom = pt.y + wDragHeight;
3227 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3229 if( msg.message == WM_LBUTTONUP )
3234 if( msg.message == WM_MOUSEMOVE )
3237 tmp.x = LOWORD(msg.lParam);
3238 tmp.y = HIWORD(msg.lParam);
3239 if( !PtInRect( &rect, tmp ))
3251 /******************************************************************************
3252 * DragObject (USER.464)
3254 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3255 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3258 LPDRAGINFO16 lpDragInfo;
3260 HCURSOR hOldCursor=0, hBummer=0;
3261 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3262 HCURSOR hCurrentCursor = 0;
3263 HWND16 hCurrentWnd = 0;
3265 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3266 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3268 if( !lpDragInfo || !spDragInfo ) return 0L;
3270 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3272 GlobalFree16(hDragInfo);
3276 if(hCursor) hOldCursor = SetCursor(HCURSOR_32(hCursor));
3278 lpDragInfo->hWnd = hWnd;
3279 lpDragInfo->hScope = 0;
3280 lpDragInfo->wFlags = wObj;
3281 lpDragInfo->hList = szList; /* near pointer! */
3282 lpDragInfo->hOfStruct = hOfStruct;
3285 SetCapture(WIN_Handle32(hWnd));
3290 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3292 *(lpDragInfo+1) = *lpDragInfo;
3294 lpDragInfo->pt.x = msg.pt.x;
3295 lpDragInfo->pt.y = msg.pt.y;
3297 /* update DRAGINFO struct */
3298 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3300 if( DRAG_QueryUpdate16(WIN_Handle32(hwndScope), spDragInfo) > 0 )
3301 hCurrentCursor = HCURSOR_32(hCursor);
3304 hCurrentCursor = hBummer;
3305 lpDragInfo->hScope = 0;
3307 if( hCurrentCursor )
3308 SetCursor(hCurrentCursor);
3310 /* send WM_DRAGLOOP */
3311 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3312 (LPARAM) spDragInfo );
3313 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3314 if( hCurrentWnd != lpDragInfo->hScope )
3317 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3318 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3319 HIWORD(spDragInfo)) );
3320 hCurrentWnd = lpDragInfo->hScope;
3322 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3326 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3328 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3331 ShowCursor( FALSE );
3333 if( hCursor ) SetCursor(hOldCursor);
3335 if( hCurrentCursor != hBummer )
3336 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3337 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3340 GlobalFree16(hDragInfo);
3342 return (DWORD)(msg.lParam);
3346 /******************************************************************************
3347 * GetWindowModuleFileNameA (USER32.@)
3349 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3351 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3352 hwnd, lpszFileName, cchFileNameMax);
3356 /******************************************************************************
3357 * GetWindowModuleFileNameW (USER32.@)
3359 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3361 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3362 hwnd, lpszFileName, cchFileNameMax);
3366 /******************************************************************************
3367 * GetWindowInfo (USER32.@)
3370 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3371 * this may be because this structure changed over time. If this is the
3372 * the case, then please: FIXME.
3373 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3375 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3377 WND *wndInfo = NULL;
3378 if (!pwi) return FALSE;
3379 if (pwi->cbSize != sizeof(WINDOWINFO))
3381 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3384 wndInfo = WIN_GetPtr(hwnd);
3385 if (!wndInfo) return FALSE;
3386 if (wndInfo == WND_OTHER_PROCESS)
3388 FIXME("window belong to other process\n");
3392 pwi->rcWindow = wndInfo->rectWindow;
3393 pwi->rcClient = wndInfo->rectClient;
3394 pwi->dwStyle = wndInfo->dwStyle;
3395 pwi->dwExStyle = wndInfo->dwExStyle;
3396 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3397 /* if active WS_ACTIVECAPTION, else 0 */
3399 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3400 GetSystemMetrics(SM_CXBORDER) : 0);
3401 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3402 GetSystemMetrics(SM_CYBORDER) : 0);
3403 /* above two: I'm presuming that borders widths are the same
3404 * for each window - so long as its actually using a border.. */
3406 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3407 pwi->wCreatorVersion = GetVersion();
3408 /* Docs say this should be the version that
3409 * CREATED the window. But eh?.. Isn't that just the
3410 * version we are running.. Unless ofcourse its some wacky
3411 * RPC stuff or something */
3413 WIN_ReleasePtr(wndInfo);