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"
30 #include "wine/server.h"
31 #include "wine/unicode.h"
36 #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->hwndLastActive = hwndDesktop;
767 pWndDesktop->clsStyle = clsStyle;
768 pWndDesktop->dce = NULL;
769 pWndDesktop->pVScroll = NULL;
770 pWndDesktop->pHScroll = NULL;
771 pWndDesktop->helpContext = 0;
772 pWndDesktop->flags = 0;
773 pWndDesktop->hSysMenu = 0;
774 pWndDesktop->winproc = winproc;
775 pWndDesktop->cbWndExtra = wndExtra;
777 cs.lpCreateParams = NULL;
783 cs.cx = GetSystemMetrics( SM_CXSCREEN );
784 cs.cy = GetSystemMetrics( SM_CYSCREEN );
785 cs.style = pWndDesktop->dwStyle;
786 cs.dwExStyle = pWndDesktop->dwExStyle;
788 cs.lpszClass = DESKTOP_CLASS_ATOM;
790 SetRect( &rect, 0, 0, cs.cx, cs.cy );
791 WIN_SetRectangles( hwndDesktop, &rect, &rect );
793 SERVER_START_REQ( set_window_info )
795 req->handle = hwndDesktop;
796 req->flags = 0; /* don't set anything, just retrieve */
797 wine_server_call( req );
798 pWndDesktop->dwStyle = reply->old_style;
799 pWndDesktop->dwExStyle = reply->old_ex_style;
800 pWndDesktop->hInstance = (ULONG_PTR)reply->old_instance;
801 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
802 pWndDesktop->wIDmenu = reply->old_id;
806 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
808 WIN_ReleaseWndPtr( pWndDesktop );
812 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
813 WIN_ReleaseWndPtr( pWndDesktop );
818 /***********************************************************************
821 * Fix the coordinates - Helper for WIN_CreateWindowEx.
822 * returns default show mode in sw.
823 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
825 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
827 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
828 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
830 if (cs->style & (WS_CHILD | WS_POPUP))
832 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
833 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
835 else /* overlapped window */
839 GetStartupInfoA( &info );
841 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
843 /* Never believe Microsoft's documentation... CreateWindowEx doc says
844 * that if an overlapped window is created with WS_VISIBLE style bit
845 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
846 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
849 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
850 * 2) it does not ignore the y parameter as the docs claim; instead, it
851 * uses it as second parameter to ShowWindow() unless y is either
852 * CW_USEDEFAULT or CW_USEDEFAULT16.
854 * The fact that we didn't do 2) caused bogus windows pop up when wine
855 * was running apps that were using this obscure feature. Example -
856 * calc.exe that comes with Win98 (only Win98, it's different from
857 * the one that comes with Win95 and NT)
859 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
860 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
861 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
864 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
866 if (info.dwFlags & STARTF_USESIZE)
868 cs->cx = info.dwXSize;
869 cs->cy = info.dwYSize;
871 else /* if no other hint from the app, pick 3/4 of the screen real estate */
874 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
875 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
876 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
883 /* neither x nor cx are default. Check the y values .
884 * In the trace we see Outlook and Outlook Express using
885 * cy set to CW_USEDEFAULT when opening the address book.
887 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
889 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
890 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
891 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
896 /***********************************************************************
899 static void dump_window_styles( DWORD style, DWORD exstyle )
902 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
903 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
904 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
905 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
906 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
907 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
908 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
909 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
910 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
913 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
914 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
916 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
917 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
918 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
919 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
920 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
921 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
922 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
923 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
925 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
926 #define DUMPED_STYLES \
946 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
951 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
952 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
953 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
954 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
955 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
956 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
957 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
958 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
959 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
960 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
961 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
962 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
963 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
964 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
965 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
966 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
967 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
968 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
970 #define DUMPED_EX_STYLES \
971 (WS_EX_DLGMODALFRAME | \
973 WS_EX_NOPARENTNOTIFY | \
975 WS_EX_ACCEPTFILES | \
976 WS_EX_TRANSPARENT | \
981 WS_EX_CONTEXTHELP | \
984 WS_EX_LEFTSCROLLBAR | \
985 WS_EX_CONTROLPARENT | \
990 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
992 #undef DUMPED_EX_STYLES
996 /***********************************************************************
999 * Implementation of CreateWindowEx().
1001 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
1002 WINDOWPROCTYPE type )
1005 struct tagCLASS *classPtr;
1007 HWND hwnd, parent, owner;
1012 BOOL unicode = (type == WIN_PROC_32W);
1014 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
1015 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1016 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1017 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1018 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1020 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1022 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1023 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1025 /* Find the parent window */
1027 parent = GetDesktopWindow();
1030 if (cs->hwndParent == HWND_MESSAGE)
1032 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1033 * message window (style: WS_POPUP|WS_DISABLED)
1035 FIXME("Parent is HWND_MESSAGE\n");
1037 else if (cs->hwndParent)
1039 /* Make sure parent is valid */
1040 if (!IsWindow( cs->hwndParent ))
1042 WARN("Bad parent %04x\n", cs->hwndParent );
1045 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1046 parent = WIN_GetFullHandle(cs->hwndParent);
1048 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1050 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1052 WARN("No parent for child window\n" );
1053 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1056 /* Find the window class */
1057 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1058 &wndExtra, &winproc, &clsStyle, &dce )))
1060 WARN("Bad class '%s'\n", cs->lpszClass );
1064 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1066 /* Correct the window style - stage 1
1068 * These are patches that appear to affect both the style loaded into the
1069 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1071 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1072 * why does the user get to set it?
1075 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1076 * tested for WS_POPUP
1078 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1079 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1080 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1081 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1083 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1085 /* Create the window structure */
1087 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1088 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1090 TRACE("out of memory\n" );
1093 hwnd = wndPtr->hwndSelf;
1095 /* Fill the window structure */
1097 wndPtr->tid = GetCurrentThreadId();
1098 wndPtr->owner = owner;
1099 wndPtr->parent = parent;
1100 wndPtr->class = classPtr;
1101 wndPtr->winproc = winproc;
1102 wndPtr->hInstance = cs->hInstance;
1103 wndPtr->text = NULL;
1104 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
1105 wndPtr->hrgnUpdate = 0;
1106 wndPtr->hrgnWnd = 0;
1107 wndPtr->hwndLastActive = hwnd;
1108 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1109 wndPtr->dwExStyle = cs->dwExStyle;
1110 wndPtr->clsStyle = clsStyle;
1111 wndPtr->wIDmenu = 0;
1112 wndPtr->helpContext = 0;
1113 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1114 wndPtr->pVScroll = NULL;
1115 wndPtr->pHScroll = NULL;
1116 wndPtr->userdata = 0;
1117 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1118 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1119 wndPtr->cbWndExtra = wndExtra;
1121 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1123 /* Correct the window style - stage 2 */
1125 if (!(cs->style & WS_CHILD))
1127 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1128 if (!(cs->style & WS_POPUP))
1130 wndPtr->dwStyle |= WS_CAPTION;
1131 wndPtr->flags |= WIN_NEED_SIZE;
1134 SERVER_START_REQ( set_window_info )
1137 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1138 req->style = wndPtr->dwStyle;
1139 req->ex_style = wndPtr->dwExStyle;
1140 req->instance = (void *)wndPtr->hInstance;
1141 wine_server_call( req );
1145 /* Get class or window DC if needed */
1147 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1148 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1149 else wndPtr->dce = NULL;
1151 /* Set the window menu */
1153 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1155 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1158 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1161 if (HIWORD(cs->hInstance))
1162 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1164 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1166 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1170 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1171 WIN_ReleaseWndPtr( wndPtr );
1173 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1175 WIN_DestroyWindow( hwnd );
1179 /* Notify the parent window only */
1181 send_parent_notify( hwnd, WM_CREATE );
1182 if (!IsWindow( hwnd )) return 0;
1184 if (cs->style & WS_VISIBLE)
1186 /* in case WS_VISIBLE got set in the meantime */
1187 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1188 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1189 WIN_ReleasePtr( wndPtr );
1190 ShowWindow( hwnd, sw );
1193 /* Call WH_SHELL hook */
1195 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1196 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1198 TRACE("created window %04x\n", hwnd);
1203 /***********************************************************************
1204 * CreateWindow (USER.41)
1206 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1207 DWORD style, INT16 x, INT16 y, INT16 width,
1208 INT16 height, HWND16 parent, HMENU16 menu,
1209 HINSTANCE16 instance, LPVOID data )
1211 return CreateWindowEx16( 0, className, windowName, style,
1212 x, y, width, height, parent, menu, instance, data );
1216 /***********************************************************************
1217 * CreateWindowEx (USER.452)
1219 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1220 LPCSTR windowName, DWORD style, INT16 x,
1221 INT16 y, INT16 width, INT16 height,
1222 HWND16 parent, HMENU16 menu,
1223 HINSTANCE16 instance, LPVOID data )
1229 /* Find the class atom */
1231 if (HIWORD(className))
1233 if (!(classAtom = GlobalFindAtomA( className )))
1235 ERR( "bad class name %s\n", debugstr_a(className) );
1241 classAtom = LOWORD(className);
1242 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1244 ERR( "bad atom %x\n", classAtom);
1250 /* Fix the coordinates */
1252 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1253 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1254 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1255 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1257 /* Create the window */
1259 cs.lpCreateParams = data;
1260 cs.hInstance = (HINSTANCE)instance;
1261 cs.hMenu = (HMENU)menu;
1262 cs.hwndParent = WIN_Handle32( parent );
1264 cs.lpszName = windowName;
1265 cs.lpszClass = className;
1266 cs.dwExStyle = exStyle;
1268 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1272 /***********************************************************************
1273 * CreateWindowExA (USER32.@)
1275 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1276 LPCSTR windowName, DWORD style, INT x,
1277 INT y, INT width, INT height,
1278 HWND parent, HMENU menu,
1279 HINSTANCE instance, LPVOID data )
1286 instance=GetModuleHandleA(NULL);
1288 if(exStyle & WS_EX_MDICHILD)
1289 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1291 /* Find the class atom */
1293 if (HIWORD(className))
1295 if (!(classAtom = GlobalFindAtomA( className )))
1297 ERR( "bad class name %s\n", debugstr_a(className) );
1303 classAtom = LOWORD(className);
1304 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1306 ERR( "bad atom %x\n", classAtom);
1312 /* Create the window */
1314 cs.lpCreateParams = data;
1315 cs.hInstance = instance;
1317 cs.hwndParent = parent;
1323 cs.lpszName = windowName;
1324 cs.lpszClass = className;
1325 cs.dwExStyle = exStyle;
1327 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1331 /***********************************************************************
1332 * CreateWindowExW (USER32.@)
1334 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1335 LPCWSTR windowName, DWORD style, INT x,
1336 INT y, INT width, INT height,
1337 HWND parent, HMENU menu,
1338 HINSTANCE instance, LPVOID data )
1345 instance=GetModuleHandleA(NULL);
1347 if(exStyle & WS_EX_MDICHILD)
1348 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1350 /* Find the class atom */
1352 if (HIWORD(className))
1354 if (!(classAtom = GlobalFindAtomW( className )))
1356 ERR( "bad class name %s\n", debugstr_w(className) );
1362 classAtom = LOWORD(className);
1363 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1365 ERR( "bad atom %x\n", classAtom);
1371 /* Create the window */
1373 cs.lpCreateParams = data;
1374 cs.hInstance = instance;
1376 cs.hwndParent = parent;
1382 cs.lpszName = windowName;
1383 cs.lpszClass = className;
1384 cs.dwExStyle = exStyle;
1386 /* Note: we rely on the fact that CREATESTRUCTA and */
1387 /* CREATESTRUCTW have the same layout. */
1388 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1392 /***********************************************************************
1393 * WIN_SendDestroyMsg
1395 static void WIN_SendDestroyMsg( HWND hwnd )
1397 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1398 if (USER_Driver.pResetSelectionOwner)
1399 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1402 * Send the WM_DESTROY to the window.
1404 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1407 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1408 * make sure that the window still exists when we come back.
1415 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1417 /* start from the end (FIXME: is this needed?) */
1418 for (i = 0; pWndArray[i]; i++) ;
1422 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1424 HeapFree( GetProcessHeap(), 0, pWndArray );
1427 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1431 /***********************************************************************
1432 * DestroyWindow (USER32.@)
1434 BOOL WINAPI DestroyWindow( HWND hwnd )
1439 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1441 SetLastError( ERROR_ACCESS_DENIED );
1445 TRACE("(%04x)\n", hwnd);
1447 /* Look whether the focus is within the tree of windows we will
1451 if (h == hwnd || IsChild( hwnd, h ))
1453 HWND parent = GetAncestor( hwnd, GA_PARENT );
1454 if (parent == GetDesktopWindow()) parent = 0;
1460 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1462 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1466 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1467 send_parent_notify( hwnd, WM_DESTROY );
1469 else if (!GetWindow( hwnd, GW_OWNER ))
1471 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1472 /* FIXME: clean up palette - see "Internals" p.352 */
1475 if (!IsWindow(hwnd)) return TRUE;
1477 if (USER_Driver.pResetSelectionOwner)
1478 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1480 /* Hide the window */
1482 ShowWindow( hwnd, SW_HIDE );
1483 if (!IsWindow(hwnd)) return TRUE;
1485 /* Recursively destroy owned windows */
1494 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1497 for (i = 0; list[i]; i++)
1499 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1500 if (WIN_IsCurrentThread( list[i] ))
1502 DestroyWindow( list[i] );
1506 WIN_SetOwner( list[i], 0 );
1508 HeapFree( GetProcessHeap(), 0, list );
1510 if (!got_one) break;
1513 WINPOS_ActivateOtherWindow( hwnd );
1515 if ((owner = GetWindow( hwnd, GW_OWNER )))
1517 WND *ptr = WIN_FindWndPtr( owner );
1520 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1521 WIN_ReleaseWndPtr( ptr );
1526 /* Send destroy messages */
1528 WIN_SendDestroyMsg( hwnd );
1529 if (!IsWindow( hwnd )) return TRUE;
1531 /* Unlink now so we won't bother with the children later on */
1533 WIN_UnlinkWindow( hwnd );
1535 /* Destroy the window storage */
1537 WIN_DestroyWindow( hwnd );
1542 /***********************************************************************
1543 * CloseWindow (USER32.@)
1545 BOOL WINAPI CloseWindow( HWND hwnd )
1547 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1548 ShowWindow( hwnd, SW_MINIMIZE );
1553 /***********************************************************************
1554 * OpenIcon (USER32.@)
1556 BOOL WINAPI OpenIcon( HWND hwnd )
1558 if (!IsIconic( hwnd )) return FALSE;
1559 ShowWindow( hwnd, SW_SHOWNORMAL );
1564 /***********************************************************************
1567 * Implementation of FindWindow() and FindWindowEx().
1569 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1574 WCHAR *buffer = NULL;
1576 if (!parent) parent = GetDesktopWindow();
1579 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1580 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1583 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1587 child = WIN_GetFullHandle( child );
1588 while (list[i] && list[i] != child) i++;
1589 if (!list[i]) goto done;
1590 i++; /* start from next window */
1597 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1604 if (list) HeapFree( GetProcessHeap(), 0, list );
1605 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1611 /***********************************************************************
1612 * FindWindowA (USER32.@)
1614 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1616 HWND ret = FindWindowExA( 0, 0, className, title );
1617 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1622 /***********************************************************************
1623 * FindWindowExA (USER32.@)
1625 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1626 LPCSTR className, LPCSTR title )
1635 /* If the atom doesn't exist, then no class */
1636 /* with this name exists either. */
1637 if (!(atom = GlobalFindAtomA( className )))
1639 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1643 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1645 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1646 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1647 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1648 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1649 HeapFree( GetProcessHeap(), 0, buffer );
1654 /***********************************************************************
1655 * FindWindowExW (USER32.@)
1657 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1658 LPCWSTR className, LPCWSTR title )
1664 /* If the atom doesn't exist, then no class */
1665 /* with this name exists either. */
1666 if (!(atom = GlobalFindAtomW( className )))
1668 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1672 return WIN_FindWindow( parent, child, atom, title );
1676 /***********************************************************************
1677 * FindWindowW (USER32.@)
1679 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1681 return FindWindowExW( 0, 0, className, title );
1685 /**********************************************************************
1686 * GetDesktopWindow (USER32.@)
1688 HWND WINAPI GetDesktopWindow(void)
1690 if (pWndDesktop) return pWndDesktop->hwndSelf;
1691 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" );
1697 /*******************************************************************
1698 * EnableWindow (USER32.@)
1700 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1707 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1708 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1712 TRACE("( %x, %d )\n", hwnd, enable);
1714 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1715 style = wndPtr->dwStyle;
1716 retvalue = ((style & WS_DISABLED) != 0);
1717 WIN_ReleasePtr( wndPtr );
1719 if (enable && retvalue)
1721 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1722 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1724 else if (!enable && !retvalue)
1726 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1728 WIN_SetStyle( hwnd, style | WS_DISABLED );
1730 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1731 SetFocus( 0 ); /* A disabled window can't have the focus */
1733 if (hwnd == GetCapture() || IsChild(hwnd, GetCapture()))
1734 ReleaseCapture(); /* A disabled window can't capture the mouse */
1736 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1742 /***********************************************************************
1743 * IsWindowEnabled (USER32.@)
1745 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1747 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1751 /***********************************************************************
1752 * IsWindowUnicode (USER32.@)
1754 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1759 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1760 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1761 WIN_ReleaseWndPtr(wndPtr);
1766 /**********************************************************************
1767 * GetWindowWord (USER32.@)
1769 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1774 WND *wndPtr = WIN_GetPtr( hwnd );
1777 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1780 if (wndPtr == WND_OTHER_PROCESS)
1782 if (IsWindow( hwnd ))
1783 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1784 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1787 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1789 WARN("Invalid offset %d\n", offset );
1790 SetLastError( ERROR_INVALID_INDEX );
1792 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1793 WIN_ReleasePtr( wndPtr );
1799 case GWL_HWNDPARENT:
1800 return GetWindowLongW( hwnd, offset );
1804 LONG ret = GetWindowLongW( hwnd, offset );
1806 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1810 WARN("Invalid offset %d\n", offset );
1816 /**********************************************************************
1817 * SetWindowWord (USER32.@)
1819 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1828 case GWL_HWNDPARENT:
1829 return SetWindowLongW( hwnd, offset, (UINT)newval );
1833 WARN("Invalid offset %d\n", offset );
1834 SetLastError( ERROR_INVALID_INDEX );
1839 wndPtr = WIN_GetPtr( hwnd );
1840 if (wndPtr == WND_OTHER_PROCESS)
1843 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1844 offset, newval, hwnd );
1849 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1853 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1855 WARN("Invalid offset %d\n", offset );
1856 WIN_ReleasePtr(wndPtr);
1857 SetLastError( ERROR_INVALID_INDEX );
1860 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1863 WIN_ReleasePtr(wndPtr);
1868 /**********************************************************************
1871 * Helper function for GetWindowLong().
1873 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1878 if (offset == GWL_HWNDPARENT)
1880 HWND parent = GetAncestor( hwnd, GA_PARENT );
1881 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1882 return (LONG)parent;
1885 if (!(wndPtr = WIN_GetPtr( hwnd )))
1887 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1891 if (wndPtr == WND_OTHER_PROCESS)
1896 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1897 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1900 if (offset == GWL_WNDPROC)
1902 SetLastError( ERROR_ACCESS_DENIED );
1905 SERVER_START_REQ( set_window_info )
1908 req->flags = 0; /* don't set anything, just retrieve */
1909 if (!wine_server_call_err( req ))
1913 case GWL_STYLE: retvalue = reply->old_style; break;
1914 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1915 case GWL_ID: retvalue = reply->old_id; break;
1916 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1917 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1919 SetLastError( ERROR_INVALID_INDEX );
1928 /* now we have a valid wndPtr */
1932 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1935 * Some programs try to access last element from 16 bit
1936 * code using illegal offset value. Hopefully this is
1937 * what those programs really expect.
1939 if (type == WIN_PROC_16 &&
1940 wndPtr->cbWndExtra >= 4 &&
1941 offset == wndPtr->cbWndExtra - sizeof(WORD))
1943 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1945 ERR( "- replaced invalid offset %d with %d\n",
1948 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1949 WIN_ReleasePtr( wndPtr );
1952 WARN("Invalid offset %d\n", offset );
1953 WIN_ReleasePtr( wndPtr );
1954 SetLastError( ERROR_INVALID_INDEX );
1957 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1958 /* Special case for dialog window procedure */
1959 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1960 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1961 WIN_ReleasePtr( wndPtr );
1967 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1968 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1969 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1970 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1971 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1972 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1974 WARN("Unknown offset %d\n", offset );
1975 SetLastError( ERROR_INVALID_INDEX );
1978 WIN_ReleasePtr(wndPtr);
1983 /**********************************************************************
1986 * Helper function for SetWindowLong().
1988 * 0 is the failure code. However, in the case of failure SetLastError
1989 * must be set to distinguish between a 0 return value and a failure.
1991 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1992 WINDOWPROCTYPE type )
1997 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1999 if (!WIN_IsCurrentProcess( hwnd ))
2001 if (offset == GWL_WNDPROC)
2003 SetLastError( ERROR_ACCESS_DENIED );
2006 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2009 wndPtr = WIN_GetPtr( hwnd );
2010 if (wndPtr->hwndSelf == GetDesktopWindow())
2012 /* can't change anything on the desktop window */
2013 WIN_ReleasePtr( wndPtr );
2014 SetLastError( ERROR_ACCESS_DENIED );
2020 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2021 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
2023 WARN("Invalid offset %d\n", offset );
2024 WIN_ReleasePtr( wndPtr );
2025 SetLastError( ERROR_INVALID_INDEX );
2028 /* Special case for dialog window procedure */
2029 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2031 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2032 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2033 type, WIN_PROC_WINDOW );
2034 WIN_ReleasePtr( wndPtr );
2039 WIN_ReleasePtr( wndPtr );
2046 /* first some special cases */
2051 style.styleOld = wndPtr->dwStyle;
2052 style.styleNew = newval;
2053 WIN_ReleasePtr( wndPtr );
2054 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2055 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2056 newval = style.styleNew;
2058 case GWL_HWNDPARENT:
2059 if (wndPtr->parent == GetDesktopWindow())
2061 WIN_ReleasePtr( wndPtr );
2062 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2066 WIN_ReleasePtr( wndPtr );
2067 return (LONG)SetParent( hwnd, (HWND)newval );
2070 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2071 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2072 type, WIN_PROC_WINDOW );
2073 WIN_ReleasePtr( wndPtr );
2080 WIN_ReleasePtr( wndPtr );
2081 WARN("Invalid offset %d\n", offset );
2082 SetLastError( ERROR_INVALID_INDEX );
2086 SERVER_START_REQ( set_window_info )
2092 req->flags = SET_WIN_STYLE;
2093 req->style = newval;
2096 req->flags = SET_WIN_EXSTYLE;
2097 req->ex_style = newval;
2100 req->flags = SET_WIN_ID;
2104 req->flags = SET_WIN_INSTANCE;
2105 req->instance = (void *)newval;
2108 req->flags = SET_WIN_USERDATA;
2109 req->user_data = (void *)newval;
2112 if ((ok = !wine_server_call_err( req )))
2117 wndPtr->dwStyle = newval;
2118 retval = reply->old_style;
2121 wndPtr->dwExStyle = newval;
2122 retval = reply->old_ex_style;
2125 wndPtr->wIDmenu = newval;
2126 retval = reply->old_id;
2129 wndPtr->hInstance = newval;
2130 retval = (HINSTANCE)reply->old_instance;
2133 wndPtr->userdata = newval;
2134 retval = (ULONG_PTR)reply->old_user_data;
2140 WIN_ReleasePtr( wndPtr );
2144 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2145 USER_Driver.pSetWindowStyle( hwnd, retval );
2147 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2148 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2155 /**********************************************************************
2156 * GetWindowLong (USER.135)
2158 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2160 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2164 /**********************************************************************
2165 * GetWindowLongA (USER32.@)
2167 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2169 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2173 /**********************************************************************
2174 * GetWindowLongW (USER32.@)
2176 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2178 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2182 /**********************************************************************
2183 * SetWindowLong (USER.136)
2185 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2187 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2191 /**********************************************************************
2192 * SetWindowLongA (USER32.@)
2194 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2196 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2200 /**********************************************************************
2201 * SetWindowLongW (USER32.@) Set window attribute
2203 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2204 * value in a window's extra memory.
2206 * The _hwnd_ parameter specifies the window. is the handle to a
2207 * window that has extra memory. The _newval_ parameter contains the
2208 * new attribute or extra memory value. If positive, the _offset_
2209 * parameter is the byte-addressed location in the window's extra
2210 * memory to set. If negative, _offset_ specifies the window
2211 * attribute to set, and should be one of the following values:
2213 * GWL_EXSTYLE The window's extended window style
2215 * GWL_STYLE The window's window style.
2217 * GWL_WNDPROC Pointer to the window's window procedure.
2219 * GWL_HINSTANCE The window's pplication instance handle.
2221 * GWL_ID The window's identifier.
2223 * GWL_USERDATA The window's user-specified data.
2225 * If the window is a dialog box, the _offset_ parameter can be one of
2226 * the following values:
2228 * DWL_DLGPROC The address of the window's dialog box procedure.
2230 * DWL_MSGRESULT The return value of a message
2231 * that the dialog box procedure processed.
2233 * DWL_USER Application specific information.
2237 * If successful, returns the previous value located at _offset_. Otherwise,
2242 * Extra memory for a window class is specified by a nonzero cbWndExtra
2243 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2244 * time of class creation.
2246 * Using GWL_WNDPROC to set a new window procedure effectively creates
2247 * a window subclass. Use CallWindowProc() in the new windows procedure
2248 * to pass messages to the superclass's window procedure.
2250 * The user data is reserved for use by the application which created
2253 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2254 * instead, call the EnableWindow() function to change the window's
2257 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2258 * SetParent() instead.
2261 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2262 * it sends WM_STYLECHANGING before changing the settings
2263 * and WM_STYLECHANGED afterwards.
2264 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2266 LONG WINAPI SetWindowLongW(
2267 HWND hwnd, /* [in] window to alter */
2268 INT offset, /* [in] offset, in bytes, of location to alter */
2269 LONG newval /* [in] new value of location */
2271 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2275 /*******************************************************************
2276 * GetWindowTextA (USER32.@)
2278 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2282 if (WIN_IsCurrentProcess( hwnd ))
2283 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2285 /* when window belongs to other process, don't send a message */
2286 if (nMaxCount <= 0) return 0;
2287 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2288 get_server_window_text( hwnd, buffer, nMaxCount );
2289 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2290 lpString[nMaxCount-1] = 0;
2291 HeapFree( GetProcessHeap(), 0, buffer );
2292 return strlen(lpString);
2296 /*******************************************************************
2297 * InternalGetWindowText (USER32.@)
2299 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2303 if (nMaxCount <= 0) return 0;
2304 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2305 if (win != WND_OTHER_PROCESS)
2307 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2308 else lpString[0] = 0;
2309 WIN_ReleasePtr( win );
2313 get_server_window_text( hwnd, lpString, nMaxCount );
2315 return strlenW(lpString);
2319 /*******************************************************************
2320 * GetWindowTextW (USER32.@)
2322 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2324 if (WIN_IsCurrentProcess( hwnd ))
2325 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2327 /* when window belongs to other process, don't send a message */
2328 if (nMaxCount <= 0) return 0;
2329 get_server_window_text( hwnd, lpString, nMaxCount );
2330 return strlenW(lpString);
2334 /*******************************************************************
2335 * SetWindowText (USER32.@)
2336 * SetWindowTextA (USER32.@)
2338 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2340 if (!WIN_IsCurrentProcess( hwnd ))
2342 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2343 SetLastError( ERROR_ACCESS_DENIED );
2346 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2350 /*******************************************************************
2351 * SetWindowTextW (USER32.@)
2353 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2355 if (!WIN_IsCurrentProcess( hwnd ))
2357 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2358 SetLastError( ERROR_ACCESS_DENIED );
2361 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2365 /*******************************************************************
2366 * GetWindowTextLengthA (USER32.@)
2368 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2370 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2373 /*******************************************************************
2374 * GetWindowTextLengthW (USER32.@)
2376 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2378 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2382 /*******************************************************************
2383 * IsWindow (USER32.@)
2385 BOOL WINAPI IsWindow( HWND hwnd )
2390 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2392 if (ptr != WND_OTHER_PROCESS)
2394 WIN_ReleasePtr( ptr );
2398 /* check other processes */
2399 SERVER_START_REQ( get_window_info )
2402 ret = !wine_server_call_err( req );
2409 /***********************************************************************
2410 * GetWindowThreadProcessId (USER32.@)
2412 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2417 if (!(ptr = WIN_GetPtr( hwnd )))
2419 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2423 if (ptr != WND_OTHER_PROCESS)
2425 /* got a valid window */
2427 if (process) *process = GetCurrentProcessId();
2428 WIN_ReleasePtr( ptr );
2432 /* check other processes */
2433 SERVER_START_REQ( get_window_info )
2436 if (!wine_server_call_err( req ))
2438 tid = (DWORD)reply->tid;
2439 if (process) *process = (DWORD)reply->pid;
2447 /*****************************************************************
2448 * GetParent (USER32.@)
2450 HWND WINAPI GetParent( HWND hwnd )
2455 if (!(wndPtr = WIN_GetPtr( hwnd )))
2457 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2460 if (wndPtr == WND_OTHER_PROCESS)
2462 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2463 if (style & (WS_POPUP | WS_CHILD))
2465 SERVER_START_REQ( get_window_tree )
2468 if (!wine_server_call_err( req ))
2470 if (style & WS_POPUP) retvalue = reply->owner;
2471 else if (style & WS_CHILD) retvalue = reply->parent;
2479 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2480 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2481 WIN_ReleasePtr( wndPtr );
2487 /*****************************************************************
2488 * GetAncestor (USER32.@)
2490 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2493 HWND *list, ret = 0;
2498 if (!(win = WIN_GetPtr( hwnd )))
2500 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2503 if (win != WND_OTHER_PROCESS)
2506 WIN_ReleasePtr( win );
2508 else /* need to query the server */
2510 SERVER_START_REQ( get_window_tree )
2513 if (!wine_server_call_err( req )) ret = reply->parent;
2520 if (!(list = WIN_ListParents( hwnd ))) return 0;
2522 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2526 while (list[count]) count++;
2527 ret = list[count - 2]; /* get the one before the desktop */
2529 HeapFree( GetProcessHeap(), 0, list );
2533 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2536 HWND parent = GetParent( ret );
2546 /*****************************************************************
2547 * SetParent (USER32.@)
2549 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2552 HWND retvalue, full_handle;
2555 if (!parent) parent = GetDesktopWindow();
2556 else parent = WIN_GetFullHandle( parent );
2558 if (!IsWindow( parent ))
2560 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2564 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2565 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2569 if (USER_Driver.pSetParent)
2570 return USER_Driver.pSetParent( hwnd, parent );
2572 /* Windows hides the window first, then shows it again
2573 * including the WM_SHOWWINDOW messages and all */
2574 was_visible = ShowWindow( hwnd, SW_HIDE );
2576 if (!IsWindow( parent )) return 0;
2577 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2579 retvalue = wndPtr->parent; /* old parent */
2580 if (parent != retvalue)
2582 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2584 if (parent != GetDesktopWindow()) /* a child window */
2586 if (!(wndPtr->dwStyle & WS_CHILD))
2588 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2589 if (menu) DestroyMenu( menu );
2593 WIN_ReleasePtr( wndPtr );
2595 /* SetParent additionally needs to make hwnd the topmost window
2596 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2597 WM_WINDOWPOSCHANGED notification messages.
2599 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2600 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2601 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2602 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2607 /*******************************************************************
2608 * IsChild (USER32.@)
2610 BOOL WINAPI IsChild( HWND parent, HWND child )
2612 HWND *list = WIN_ListParents( child );
2616 if (!list) return FALSE;
2617 parent = WIN_GetFullHandle( parent );
2618 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2619 ret = (list[i] != 0);
2620 HeapFree( GetProcessHeap(), 0, list );
2625 /***********************************************************************
2626 * IsWindowVisible (USER32.@)
2628 BOOL WINAPI IsWindowVisible( HWND hwnd )
2634 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2635 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2636 for (i = 0; list[i]; i++)
2637 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2639 HeapFree( GetProcessHeap(), 0, list );
2644 /***********************************************************************
2645 * WIN_IsWindowDrawable
2647 * hwnd is drawable when it is visible, all parents are not
2648 * minimized, and it is itself not minimized unless we are
2649 * trying to draw its default class icon.
2651 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2656 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2658 if (!(style & WS_VISIBLE)) return FALSE;
2659 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2661 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2662 for (i = 0; list[i]; i++)
2663 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2666 HeapFree( GetProcessHeap(), 0, list );
2671 /*******************************************************************
2672 * GetTopWindow (USER32.@)
2674 HWND WINAPI GetTopWindow( HWND hwnd )
2676 if (!hwnd) hwnd = GetDesktopWindow();
2677 return GetWindow( hwnd, GW_CHILD );
2681 /*******************************************************************
2682 * GetWindow (USER32.@)
2684 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2688 if (rel == GW_OWNER) /* this one may be available locally */
2690 WND *wndPtr = WIN_GetPtr( hwnd );
2693 SetLastError( ERROR_INVALID_HANDLE );
2696 if (wndPtr != WND_OTHER_PROCESS)
2698 retval = wndPtr->owner;
2699 WIN_ReleasePtr( wndPtr );
2702 /* else fall through to server call */
2705 SERVER_START_REQ( get_window_tree )
2708 if (!wine_server_call_err( req ))
2713 retval = reply->first_sibling;
2716 retval = reply->last_sibling;
2719 retval = reply->next_sibling;
2722 retval = reply->prev_sibling;
2725 retval = reply->owner;
2728 retval = reply->first_child;
2738 /***********************************************************************
2739 * WIN_InternalShowOwnedPopups
2741 * Internal version of ShowOwnedPopups; Wine functions should use this
2742 * to avoid interfering with application calls to ShowOwnedPopups
2743 * and to make sure the application can't prevent showing/hiding.
2745 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2749 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2753 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2755 if (!win_array) return TRUE;
2758 * Show windows Lowest first, Highest last to preserve Z-Order
2760 while (win_array[count]) count++;
2761 while (--count >= 0)
2763 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2764 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2766 if (pWnd->dwStyle & WS_POPUP)
2770 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2771 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2774 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2776 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2777 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2782 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2783 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2784 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2787 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2789 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2790 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2791 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2795 WIN_ReleaseWndPtr( pWnd );
2797 HeapFree( GetProcessHeap(), 0, win_array );
2802 /*******************************************************************
2803 * ShowOwnedPopups (USER32.@)
2805 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2809 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2811 if (!win_array) return TRUE;
2813 while (win_array[count]) count++;
2814 while (--count >= 0)
2816 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2817 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2819 if (pWnd->dwStyle & WS_POPUP)
2823 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2825 /* In Windows, ShowOwnedPopups(TRUE) generates
2826 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2827 * regardless of the state of the owner
2829 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2830 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2835 if (IsWindowVisible(pWnd->hwndSelf))
2837 /* In Windows, ShowOwnedPopups(FALSE) generates
2838 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2839 * regardless of the state of the owner
2841 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2842 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2846 WIN_ReleaseWndPtr( pWnd );
2848 HeapFree( GetProcessHeap(), 0, win_array );
2853 /*******************************************************************
2854 * GetLastActivePopup (USER32.@)
2856 HWND WINAPI GetLastActivePopup( HWND hwnd )
2859 WND *wndPtr =WIN_FindWndPtr(hwnd);
2860 if (!wndPtr) return hwnd;
2861 retval = wndPtr->hwndLastActive;
2862 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2863 WIN_ReleaseWndPtr(wndPtr);
2868 /*******************************************************************
2871 * Build an array of all parents of a given window, starting with
2872 * the immediate parent. The array must be freed with HeapFree.
2873 * Returns NULL if window is a top-level window.
2875 HWND *WIN_ListParents( HWND hwnd )
2878 HWND current, *list;
2879 int pos = 0, size = 16, count = 0;
2881 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2886 if (!(win = WIN_GetPtr( current ))) goto empty;
2887 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2888 list[pos] = win->parent;
2889 WIN_ReleasePtr( win );
2890 if (!(current = list[pos]))
2892 if (!pos) goto empty;
2895 if (++pos == size - 1)
2897 /* need to grow the list */
2898 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2899 if (!new_list) goto empty;
2905 /* at least one parent belongs to another process, have to query the server */
2910 SERVER_START_REQ( get_window_parents )
2913 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2914 if (!wine_server_call( req )) count = reply->count;
2917 if (!count) goto empty;
2923 HeapFree( GetProcessHeap(), 0, list );
2925 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2929 HeapFree( GetProcessHeap(), 0, list );
2934 /*******************************************************************
2937 * Build an array of the children of a given window. The array must be
2938 * freed with HeapFree. Returns NULL when no windows are found.
2940 HWND *WIN_ListChildren( HWND hwnd )
2942 return list_window_children( hwnd, 0, 0 );
2946 /*******************************************************************
2947 * EnumWindows (USER32.@)
2949 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2955 /* We have to build a list of all windows first, to avoid */
2956 /* unpleasant side-effects, for instance if the callback */
2957 /* function changes the Z-order of the windows. */
2959 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2961 /* Now call the callback function for every window */
2963 iWndsLocks = WIN_SuspendWndsLock();
2964 for (i = 0; list[i]; i++)
2966 /* Make sure that the window still exists */
2967 if (!IsWindow( list[i] )) continue;
2968 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2970 WIN_RestoreWndsLock(iWndsLocks);
2971 HeapFree( GetProcessHeap(), 0, list );
2976 /**********************************************************************
2977 * EnumThreadWindows (USER32.@)
2979 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2984 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2987 /* Now call the callback function for every window */
2989 iWndsLocks = WIN_SuspendWndsLock();
2990 for (i = 0; list[i]; i++)
2991 if (!func( list[i], lParam )) break;
2992 WIN_RestoreWndsLock(iWndsLocks);
2993 HeapFree( GetProcessHeap(), 0, list );
2998 /**********************************************************************
2999 * WIN_EnumChildWindows
3001 * Helper function for EnumChildWindows().
3003 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3008 for ( ; *list; list++)
3010 /* Make sure that the window still exists */
3011 if (!IsWindow( *list )) continue;
3012 /* skip owned windows */
3013 if (GetWindow( *list, GW_OWNER )) continue;
3014 /* Build children list first */
3015 childList = WIN_ListChildren( *list );
3017 ret = func( *list, lParam );
3021 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3022 HeapFree( GetProcessHeap(), 0, childList );
3024 if (!ret) return FALSE;
3030 /**********************************************************************
3031 * EnumChildWindows (USER32.@)
3033 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3038 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3039 iWndsLocks = WIN_SuspendWndsLock();
3040 WIN_EnumChildWindows( list, func, lParam );
3041 WIN_RestoreWndsLock(iWndsLocks);
3042 HeapFree( GetProcessHeap(), 0, list );
3047 /*******************************************************************
3048 * AnyPopup (USER.52)
3050 BOOL16 WINAPI AnyPopup16(void)
3056 /*******************************************************************
3057 * AnyPopup (USER32.@)
3059 BOOL WINAPI AnyPopup(void)
3063 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3065 if (!list) return FALSE;
3066 for (i = 0; list[i]; i++)
3068 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3070 retvalue = (list[i] != 0);
3071 HeapFree( GetProcessHeap(), 0, list );
3076 /*******************************************************************
3077 * FlashWindow (USER32.@)
3079 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3081 WND *wndPtr = WIN_FindWndPtr(hWnd);
3083 TRACE("%04x\n", hWnd);
3085 if (!wndPtr) return FALSE;
3086 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3088 if (wndPtr->dwStyle & WS_MINIMIZE)
3090 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3092 HDC hDC = GetDC(hWnd);
3094 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3095 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3097 ReleaseDC( hWnd, hDC );
3098 wndPtr->flags |= WIN_NCACTIVATED;
3102 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3103 wndPtr->flags &= ~WIN_NCACTIVATED;
3105 WIN_ReleaseWndPtr(wndPtr);
3111 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3112 else wparam = (hWnd == GetActiveWindow());
3114 WIN_ReleaseWndPtr(wndPtr);
3115 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3121 /*******************************************************************
3122 * GetWindowContextHelpId (USER32.@)
3124 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3127 WND *wnd = WIN_FindWndPtr( hwnd );
3129 retval = wnd->helpContext;
3130 WIN_ReleaseWndPtr(wnd);
3135 /*******************************************************************
3136 * SetWindowContextHelpId (USER32.@)
3138 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3140 WND *wnd = WIN_FindWndPtr( hwnd );
3141 if (!wnd) return FALSE;
3142 wnd->helpContext = id;
3143 WIN_ReleaseWndPtr(wnd);
3148 /*******************************************************************
3149 * DRAG_QueryUpdate16
3151 * recursively find a child that contains spDragInfo->pt point
3152 * and send WM_QUERYDROPOBJECT
3154 static BOOL16 DRAG_QueryUpdate16( HWND hQueryWnd, SEGPTR spDragInfo )
3156 BOOL16 wParam, bResult = 0;
3158 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3161 if (!ptrDragInfo) return FALSE;
3163 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3165 GetWindowRect(hQueryWnd,&tempRect);
3167 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3169 if (!IsIconic( hQueryWnd ))
3171 GetClientRect( hQueryWnd, &tempRect );
3172 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3174 if (PtInRect( &tempRect, pt))
3177 HWND *list = WIN_ListChildren( hQueryWnd );
3183 for (i = 0; list[i]; i++)
3185 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3187 GetWindowRect( list[i], &tempRect );
3188 if (PtInRect( &tempRect, pt )) break;
3193 if (IsWindowEnabled( list[i] ))
3194 bResult = DRAG_QueryUpdate16( list[i], spDragInfo );
3196 HeapFree( GetProcessHeap(), 0, list );
3198 if(bResult) return bResult;
3204 ScreenToClient16(HWND_16(hQueryWnd),&ptrDragInfo->pt);
3206 ptrDragInfo->hScope = HWND_16(hQueryWnd);
3208 bResult = SendMessage16( HWND_16(hQueryWnd), WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3210 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3216 /*******************************************************************
3217 * DragDetect (USER32.@)
3219 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3224 rect.left = pt.x - wDragWidth;
3225 rect.right = pt.x + wDragWidth;
3227 rect.top = pt.y - wDragHeight;
3228 rect.bottom = pt.y + wDragHeight;
3234 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3236 if( msg.message == WM_LBUTTONUP )
3241 if( msg.message == WM_MOUSEMOVE )
3244 tmp.x = LOWORD(msg.lParam);
3245 tmp.y = HIWORD(msg.lParam);
3246 if( !PtInRect( &rect, tmp ))
3258 /******************************************************************************
3259 * DragObject (USER.464)
3261 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3262 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3265 LPDRAGINFO16 lpDragInfo;
3267 HCURSOR16 hOldCursor=0, hBummer=0;
3268 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3269 HCURSOR16 hCurrentCursor = 0;
3270 HWND16 hCurrentWnd = 0;
3272 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3273 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3275 if( !lpDragInfo || !spDragInfo ) return 0L;
3277 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3279 GlobalFree16(hDragInfo);
3283 if(hCursor) hOldCursor = SetCursor(hCursor);
3285 lpDragInfo->hWnd = hWnd;
3286 lpDragInfo->hScope = 0;
3287 lpDragInfo->wFlags = wObj;
3288 lpDragInfo->hList = szList; /* near pointer! */
3289 lpDragInfo->hOfStruct = hOfStruct;
3292 SetCapture(WIN_Handle32(hWnd));
3297 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3299 *(lpDragInfo+1) = *lpDragInfo;
3301 lpDragInfo->pt.x = msg.pt.x;
3302 lpDragInfo->pt.y = msg.pt.y;
3304 /* update DRAGINFO struct */
3305 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3307 if( DRAG_QueryUpdate16(WIN_Handle32(hwndScope), spDragInfo) > 0 )
3308 hCurrentCursor = hCursor;
3311 hCurrentCursor = hBummer;
3312 lpDragInfo->hScope = 0;
3314 if( hCurrentCursor )
3315 SetCursor(hCurrentCursor);
3317 /* send WM_DRAGLOOP */
3318 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3319 (LPARAM) spDragInfo );
3320 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3321 if( hCurrentWnd != lpDragInfo->hScope )
3324 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3325 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3326 HIWORD(spDragInfo)) );
3327 hCurrentWnd = lpDragInfo->hScope;
3329 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3333 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3335 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3338 ShowCursor( FALSE );
3340 if( hCursor ) SetCursor( hOldCursor );
3342 if( hCurrentCursor != hBummer )
3343 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3344 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3347 GlobalFree16(hDragInfo);
3349 return (DWORD)(msg.lParam);
3353 /******************************************************************************
3354 * GetWindowModuleFileNameA (USER32.@)
3356 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3358 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3359 hwnd, lpszFileName, cchFileNameMax);
3363 /******************************************************************************
3364 * GetWindowModuleFileNameW (USER32.@)
3366 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3368 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3369 hwnd, lpszFileName, cchFileNameMax);
3373 /******************************************************************************
3374 * GetWindowInfo (USER32.@)
3377 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3378 * this may be because this structure changed over time. If this is the
3379 * the case, then please: FIXME.
3380 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3382 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3384 WND *wndInfo = NULL;
3385 if (!pwi) return FALSE;
3386 if (pwi->cbSize != sizeof(WINDOWINFO))
3388 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3391 wndInfo = WIN_GetPtr(hwnd);
3392 if (!wndInfo) return FALSE;
3393 if (wndInfo == WND_OTHER_PROCESS)
3395 FIXME("window belong to other process\n");
3399 pwi->rcWindow = wndInfo->rectWindow;
3400 pwi->rcClient = wndInfo->rectClient;
3401 pwi->dwStyle = wndInfo->dwStyle;
3402 pwi->dwExStyle = wndInfo->dwExStyle;
3403 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3404 /* if active WS_ACTIVECAPTION, else 0 */
3406 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3407 GetSystemMetrics(SM_CXBORDER) : 0);
3408 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3409 GetSystemMetrics(SM_CYBORDER) : 0);
3410 /* above two: I'm presuming that borders widths are the same
3411 * for each window - so long as its actually using a border.. */
3413 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3414 pwi->wCreatorVersion = GetVersion();
3415 /* Docs say this should be the version that
3416 * CREATED the window. But eh?.. Isn't that just the
3417 * version we are running.. Unless ofcourse its some wacky
3418 * RPC stuff or something */
3420 WIN_ReleasePtr(wndInfo);