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"
44 #include "stackframe.h"
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(win);
48 WINE_DECLARE_DEBUG_CHANNEL(msg);
50 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
52 /**********************************************************************/
55 static WND *pWndDesktop = NULL;
57 static WORD wDragWidth = 4;
58 static WORD wDragHeight= 3;
60 static void *user_handles[NB_USER_HANDLES];
63 extern SYSLEVEL USER_SysLevel; /* FIXME */
65 /***********************************************************************
68 * Suspend the lock on WND structures.
69 * Returns the number of locks suspended
71 int WIN_SuspendWndsLock( void )
73 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
74 int count = isuspendedLocks;
77 _LeaveSysLevel( &USER_SysLevel );
79 return isuspendedLocks;
82 /***********************************************************************
85 * Restore the suspended locks on WND structures
87 void WIN_RestoreWndsLock( int ipreviousLocks )
89 while ( ipreviousLocks-- > 0 )
90 _EnterSysLevel( &USER_SysLevel );
93 /***********************************************************************
94 * create_window_handle
96 * Create a window handle with the server.
98 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
101 user_handle_t handle = 0;
103 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
105 if (!win) return NULL;
109 SERVER_START_REQ( create_window )
111 req->parent = parent;
114 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
121 HeapFree( GetProcessHeap(), 0, win );
124 index = LOWORD(handle) - FIRST_USER_HANDLE;
125 assert( index < NB_USER_HANDLES );
126 user_handles[index] = win;
127 win->hwndSelf = handle;
128 win->dwMagic = WND_MAGIC;
134 /***********************************************************************
137 * Free a window handle.
139 static WND *free_window_handle( HWND hwnd )
142 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
144 if (index >= NB_USER_HANDLES) return NULL;
146 if ((ptr = user_handles[index]))
148 SERVER_START_REQ( destroy_window )
151 if (!wine_server_call_err( req ))
152 user_handles[index] = NULL;
159 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
164 /*******************************************************************
165 * list_window_children
167 * Build an array of the children of a given window. The array must be
168 * freed with HeapFree. Returns NULL when no windows are found.
170 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
179 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
181 SERVER_START_REQ( get_window_children )
186 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
187 if (!wine_server_call( req )) count = reply->count;
190 if (count && count < size)
195 HeapFree( GetProcessHeap(), 0, list );
197 size = count + 1; /* restart with a large enough buffer */
203 /*******************************************************************
206 static void send_parent_notify( HWND hwnd, UINT msg )
208 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
209 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
210 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
211 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
215 /*******************************************************************
216 * get_server_window_text
218 * Retrieve the window text from the server.
220 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
224 SERVER_START_REQ( get_window_text )
227 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
228 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
231 text[len / sizeof(WCHAR)] = 0;
235 /***********************************************************************
238 * Return a pointer to the WND structure if local to the process,
239 * or WND_OTHER_PROCESS if handle may be valid in other process.
240 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
242 WND *WIN_GetPtr( HWND hwnd )
245 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
247 if (index >= NB_USER_HANDLES) return NULL;
250 if ((ptr = user_handles[index]))
252 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
256 else ptr = WND_OTHER_PROCESS;
262 /***********************************************************************
263 * WIN_IsCurrentProcess
265 * Check whether a given window belongs to the current process (and return the full handle).
267 HWND WIN_IsCurrentProcess( HWND hwnd )
272 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
274 WIN_ReleasePtr( ptr );
279 /***********************************************************************
280 * WIN_IsCurrentThread
282 * Check whether a given window belongs to the current thread (and return the full handle).
284 HWND WIN_IsCurrentThread( HWND hwnd )
289 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
291 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
292 WIN_ReleasePtr( ptr );
298 /***********************************************************************
301 * Convert a 16-bit window handle to a full 32-bit handle.
303 HWND WIN_Handle32( HWND16 hwnd16 )
306 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
308 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
309 /* do sign extension for -2 and -3 */
310 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
312 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
314 if (ptr != WND_OTHER_PROCESS)
316 hwnd = ptr->hwndSelf;
317 WIN_ReleasePtr( ptr );
319 else /* may belong to another process */
321 SERVER_START_REQ( get_window_info )
324 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
332 /***********************************************************************
335 * Return a pointer to the WND structure corresponding to a HWND.
337 WND * WIN_FindWndPtr( HWND hwnd )
341 if (!hwnd) return NULL;
343 if ((ptr = WIN_GetPtr( hwnd )))
345 if (ptr != WND_OTHER_PROCESS)
347 /* increment destruction monitoring */
351 if (IsWindow( hwnd )) /* check other processes */
353 ERR( "window %04x belongs to other process\n", hwnd );
354 /* DbgBreakPoint(); */
357 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
362 /***********************************************************************
365 * Release the pointer to the WND structure.
367 void WIN_ReleaseWndPtr(WND *wndPtr)
371 /* Decrement destruction monitoring value */
373 /* Check if it's time to release the memory */
374 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
377 free_window_handle( wndPtr->hwndSelf );
379 else if(wndPtr->irefCount < 0)
381 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
382 ERR("forgot a Lock on %p somewhere\n",wndPtr);
384 /* unlock all WND structures for thread safeness */
389 /***********************************************************************
392 * Remove a window from the siblings linked list.
394 void WIN_UnlinkWindow( HWND hwnd )
396 WIN_LinkWindow( hwnd, 0, 0 );
400 /***********************************************************************
403 * Insert a window into the siblings linked list.
404 * The window is inserted after the specified window, which can also
405 * be specified as HWND_TOP or HWND_BOTTOM.
406 * If parent is 0, window is unlinked from the tree.
408 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
410 WND *wndPtr = WIN_GetPtr( hwnd );
413 if (wndPtr == WND_OTHER_PROCESS)
415 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
419 SERVER_START_REQ( link_window )
422 req->parent = parent;
423 req->previous = hwndInsertAfter;
424 if (!wine_server_call( req ))
426 if (reply->full_parent) wndPtr->parent = reply->full_parent;
431 WIN_ReleasePtr( wndPtr );
435 /***********************************************************************
438 * Change the owner of a window.
440 HWND WIN_SetOwner( HWND hwnd, HWND owner )
442 WND *win = WIN_GetPtr( hwnd );
446 if (win == WND_OTHER_PROCESS)
448 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
451 SERVER_START_REQ( set_window_owner )
455 if (!wine_server_call( req ))
457 win->owner = reply->full_owner;
458 ret = reply->prev_owner;
462 WIN_ReleasePtr( win );
467 /***********************************************************************
470 * Change the style of a window.
472 LONG WIN_SetStyle( HWND hwnd, LONG style )
476 WND *win = WIN_GetPtr( hwnd );
479 if (win == WND_OTHER_PROCESS)
482 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
485 if (style == win->dwStyle)
487 WIN_ReleasePtr( win );
490 SERVER_START_REQ( set_window_info )
493 req->flags = SET_WIN_STYLE;
495 if ((ok = !wine_server_call( req )))
497 ret = reply->old_style;
498 win->dwStyle = style;
502 WIN_ReleasePtr( win );
503 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
508 /***********************************************************************
511 * Change the extended style of a window.
513 LONG WIN_SetExStyle( HWND hwnd, LONG style )
516 WND *win = WIN_GetPtr( hwnd );
519 if (win == WND_OTHER_PROCESS)
522 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
525 if (style == win->dwExStyle)
527 WIN_ReleasePtr( win );
530 SERVER_START_REQ( set_window_info )
533 req->flags = SET_WIN_EXSTYLE;
534 req->ex_style = style;
535 if (!wine_server_call( req ))
537 ret = reply->old_ex_style;
538 win->dwExStyle = style;
542 WIN_ReleasePtr( win );
547 /***********************************************************************
550 * Set the window and client rectangles.
552 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
554 WND *win = WIN_GetPtr( hwnd );
558 if (win == WND_OTHER_PROCESS)
560 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
563 SERVER_START_REQ( set_window_rectangles )
566 req->window.left = rectWindow->left;
567 req->window.top = rectWindow->top;
568 req->window.right = rectWindow->right;
569 req->window.bottom = rectWindow->bottom;
570 req->client.left = rectClient->left;
571 req->client.top = rectClient->top;
572 req->client.right = rectClient->right;
573 req->client.bottom = rectClient->bottom;
574 ret = !wine_server_call( req );
579 win->rectWindow = *rectWindow;
580 win->rectClient = *rectClient;
582 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
583 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
584 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
586 WIN_ReleasePtr( win );
590 /***********************************************************************
593 * Get the window and client rectangles.
595 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
597 WND *win = WIN_GetPtr( hwnd );
600 if (!win) return FALSE;
601 if (win == WND_OTHER_PROCESS)
603 SERVER_START_REQ( get_window_rectangles )
606 if ((ret = !wine_server_call( req )))
610 rectWindow->left = reply->window.left;
611 rectWindow->top = reply->window.top;
612 rectWindow->right = reply->window.right;
613 rectWindow->bottom = reply->window.bottom;
617 rectClient->left = reply->client.left;
618 rectClient->top = reply->client.top;
619 rectClient->right = reply->client.right;
620 rectClient->bottom = reply->client.bottom;
628 if (rectWindow) *rectWindow = win->rectWindow;
629 if (rectClient) *rectClient = win->rectClient;
630 WIN_ReleasePtr( win );
636 /***********************************************************************
639 * Destroy storage associated to a window. "Internals" p.358
641 LRESULT WIN_DestroyWindow( HWND hwnd )
646 TRACE("%04x\n", hwnd );
648 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
650 ERR( "window doesn't belong to current thread\n" );
654 /* free child windows */
655 if ((list = WIN_ListChildren( hwnd )))
658 for (i = 0; list[i]; i++)
660 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
661 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
663 HeapFree( GetProcessHeap(), 0, list );
667 * Clear the update region to make sure no WM_PAINT messages will be
668 * generated for this window while processing the WM_NCDESTROY.
670 RedrawWindow( hwnd, NULL, 0,
671 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
674 * Send the WM_NCDESTROY to the window being destroyed.
676 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
678 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
680 WINPOS_CheckInternalPos( hwnd );
681 if( hwnd == GetCapture()) ReleaseCapture();
683 /* free resources associated with the window */
685 TIMER_RemoveWindowTimers( hwnd );
687 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
688 wndPtr->hmemTaskQ = 0;
690 if (!(wndPtr->dwStyle & WS_CHILD))
692 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
693 if (menu) DestroyMenu( menu );
695 if (wndPtr->hSysMenu)
697 DestroyMenu( wndPtr->hSysMenu );
698 wndPtr->hSysMenu = 0;
700 USER_Driver.pDestroyWindow( hwnd );
701 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
702 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
703 CLASS_RemoveWindow( wndPtr->class );
704 wndPtr->class = NULL;
705 wndPtr->dwMagic = 0; /* Mark it as invalid */
706 WIN_ReleaseWndPtr( wndPtr );
710 /***********************************************************************
711 * WIN_DestroyThreadWindows
713 * Destroy all children of 'wnd' owned by the current thread.
714 * Return TRUE if something was done.
716 void WIN_DestroyThreadWindows( HWND hwnd )
721 if (!(list = WIN_ListChildren( hwnd ))) return;
722 for (i = 0; list[i]; i++)
724 if (WIN_IsCurrentThread( list[i] ))
725 DestroyWindow( list[i] );
727 WIN_DestroyThreadWindows( list[i] );
729 HeapFree( GetProcessHeap(), 0, list );
732 /***********************************************************************
733 * WIN_CreateDesktopWindow
735 * Create the desktop window.
737 BOOL WIN_CreateDesktopWindow(void)
739 struct tagCLASS *class;
748 TRACE("Creating desktop window\n");
750 if (!WINPOS_CreateInternalPosAtom() ||
751 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
752 &wndExtra, &winproc, &clsStyle, &dce )))
755 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
756 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
757 if (!pWndDesktop) return FALSE;
758 hwndDesktop = pWndDesktop->hwndSelf;
760 pWndDesktop->tid = 0; /* nobody owns the desktop */
761 pWndDesktop->parent = 0;
762 pWndDesktop->owner = 0;
763 pWndDesktop->class = class;
764 pWndDesktop->text = NULL;
765 pWndDesktop->hmemTaskQ = 0;
766 pWndDesktop->hrgnUpdate = 0;
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->dwStyle = cs->style & ~WS_VISIBLE;
1108 wndPtr->dwExStyle = cs->dwExStyle;
1109 wndPtr->clsStyle = clsStyle;
1110 wndPtr->wIDmenu = 0;
1111 wndPtr->helpContext = 0;
1112 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1113 wndPtr->pVScroll = NULL;
1114 wndPtr->pHScroll = NULL;
1115 wndPtr->userdata = 0;
1116 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1117 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1118 wndPtr->cbWndExtra = wndExtra;
1120 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1122 /* Correct the window style - stage 2 */
1124 if (!(cs->style & WS_CHILD))
1126 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1127 if (!(cs->style & WS_POPUP))
1129 wndPtr->dwStyle |= WS_CAPTION;
1130 wndPtr->flags |= WIN_NEED_SIZE;
1133 SERVER_START_REQ( set_window_info )
1136 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1137 req->style = wndPtr->dwStyle;
1138 req->ex_style = wndPtr->dwExStyle;
1139 req->instance = (void *)wndPtr->hInstance;
1140 wine_server_call( req );
1144 /* Get class or window DC if needed */
1146 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1147 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1148 else wndPtr->dce = NULL;
1150 /* Set the window menu */
1152 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1154 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1157 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1160 if (HIWORD(cs->hInstance))
1161 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1163 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1165 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1169 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1170 WIN_ReleaseWndPtr( wndPtr );
1172 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1174 WIN_DestroyWindow( hwnd );
1178 /* Notify the parent window only */
1180 send_parent_notify( hwnd, WM_CREATE );
1181 if (!IsWindow( hwnd )) return 0;
1183 if (cs->style & WS_VISIBLE)
1185 /* in case WS_VISIBLE got set in the meantime */
1186 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1187 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1188 WIN_ReleasePtr( wndPtr );
1189 ShowWindow( hwnd, sw );
1192 /* Call WH_SHELL hook */
1194 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1195 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1197 TRACE("created window %04x\n", hwnd);
1202 /***********************************************************************
1203 * CreateWindow (USER.41)
1205 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1206 DWORD style, INT16 x, INT16 y, INT16 width,
1207 INT16 height, HWND16 parent, HMENU16 menu,
1208 HINSTANCE16 instance, LPVOID data )
1210 return CreateWindowEx16( 0, className, windowName, style,
1211 x, y, width, height, parent, menu, instance, data );
1215 /***********************************************************************
1216 * CreateWindowEx (USER.452)
1218 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1219 LPCSTR windowName, DWORD style, INT16 x,
1220 INT16 y, INT16 width, INT16 height,
1221 HWND16 parent, HMENU16 menu,
1222 HINSTANCE16 instance, LPVOID data )
1228 /* Find the class atom */
1230 if (HIWORD(className))
1232 if (!(classAtom = GlobalFindAtomA( className )))
1234 ERR( "bad class name %s\n", debugstr_a(className) );
1240 classAtom = LOWORD(className);
1241 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1243 ERR( "bad atom %x\n", classAtom);
1249 /* Fix the coordinates */
1251 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1252 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1253 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1254 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1256 /* Create the window */
1258 cs.lpCreateParams = data;
1259 cs.hInstance = (HINSTANCE)instance;
1260 cs.hMenu = (HMENU)menu;
1261 cs.hwndParent = WIN_Handle32( parent );
1263 cs.lpszName = windowName;
1264 cs.lpszClass = className;
1265 cs.dwExStyle = exStyle;
1267 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1271 /***********************************************************************
1272 * CreateWindowExA (USER32.@)
1274 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1275 LPCSTR windowName, DWORD style, INT x,
1276 INT y, INT width, INT height,
1277 HWND parent, HMENU menu,
1278 HINSTANCE instance, LPVOID data )
1285 instance=GetModuleHandleA(NULL);
1287 if(exStyle & WS_EX_MDICHILD)
1288 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1290 /* Find the class atom */
1292 if (HIWORD(className))
1294 if (!(classAtom = GlobalFindAtomA( className )))
1296 ERR( "bad class name %s\n", debugstr_a(className) );
1302 classAtom = LOWORD(className);
1303 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1305 ERR( "bad atom %x\n", classAtom);
1311 /* Create the window */
1313 cs.lpCreateParams = data;
1314 cs.hInstance = instance;
1316 cs.hwndParent = parent;
1322 cs.lpszName = windowName;
1323 cs.lpszClass = className;
1324 cs.dwExStyle = exStyle;
1326 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1330 /***********************************************************************
1331 * CreateWindowExW (USER32.@)
1333 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1334 LPCWSTR windowName, DWORD style, INT x,
1335 INT y, INT width, INT height,
1336 HWND parent, HMENU menu,
1337 HINSTANCE instance, LPVOID data )
1344 instance=GetModuleHandleA(NULL);
1346 if(exStyle & WS_EX_MDICHILD)
1347 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1349 /* Find the class atom */
1351 if (HIWORD(className))
1353 if (!(classAtom = GlobalFindAtomW( className )))
1355 ERR( "bad class name %s\n", debugstr_w(className) );
1361 classAtom = LOWORD(className);
1362 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1364 ERR( "bad atom %x\n", classAtom);
1370 /* Create the window */
1372 cs.lpCreateParams = data;
1373 cs.hInstance = instance;
1375 cs.hwndParent = parent;
1381 cs.lpszName = windowName;
1382 cs.lpszClass = className;
1383 cs.dwExStyle = exStyle;
1385 /* Note: we rely on the fact that CREATESTRUCTA and */
1386 /* CREATESTRUCTW have the same layout. */
1387 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1391 /***********************************************************************
1392 * WIN_SendDestroyMsg
1394 static void WIN_SendDestroyMsg( HWND hwnd )
1398 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1400 if (hwnd == info.hwndCaret) DestroyCaret();
1402 if (USER_Driver.pResetSelectionOwner)
1403 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1406 * Send the WM_DESTROY to the window.
1408 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1411 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1412 * make sure that the window still exists when we come back.
1419 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1421 /* start from the end (FIXME: is this needed?) */
1422 for (i = 0; pWndArray[i]; i++) ;
1426 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1428 HeapFree( GetProcessHeap(), 0, pWndArray );
1431 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1435 /***********************************************************************
1436 * DestroyWindow (USER32.@)
1438 BOOL WINAPI DestroyWindow( HWND hwnd )
1443 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1445 SetLastError( ERROR_ACCESS_DENIED );
1449 TRACE("(%04x)\n", hwnd);
1451 /* Look whether the focus is within the tree of windows we will
1455 if (h == hwnd || IsChild( hwnd, h ))
1457 HWND parent = GetAncestor( hwnd, GA_PARENT );
1458 if (parent == GetDesktopWindow()) parent = 0;
1464 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1466 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1470 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1471 send_parent_notify( hwnd, WM_DESTROY );
1473 else if (!GetWindow( hwnd, GW_OWNER ))
1475 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1476 /* FIXME: clean up palette - see "Internals" p.352 */
1479 if (!IsWindow(hwnd)) return TRUE;
1481 if (USER_Driver.pResetSelectionOwner)
1482 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1484 /* Hide the window */
1486 if (!ShowWindow( hwnd, SW_HIDE ))
1488 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1490 if (!IsWindow(hwnd)) return TRUE;
1492 /* Recursively destroy owned windows */
1499 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1502 for (i = 0; list[i]; i++)
1504 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1505 if (WIN_IsCurrentThread( list[i] ))
1507 DestroyWindow( list[i] );
1511 WIN_SetOwner( list[i], 0 );
1513 HeapFree( GetProcessHeap(), 0, list );
1515 if (!got_one) break;
1519 /* Send destroy messages */
1521 WIN_SendDestroyMsg( hwnd );
1522 if (!IsWindow( hwnd )) return TRUE;
1524 /* Unlink now so we won't bother with the children later on */
1526 WIN_UnlinkWindow( hwnd );
1528 /* Destroy the window storage */
1530 WIN_DestroyWindow( hwnd );
1535 /***********************************************************************
1536 * CloseWindow (USER32.@)
1538 BOOL WINAPI CloseWindow( HWND hwnd )
1540 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1541 ShowWindow( hwnd, SW_MINIMIZE );
1546 /***********************************************************************
1547 * OpenIcon (USER32.@)
1549 BOOL WINAPI OpenIcon( HWND hwnd )
1551 if (!IsIconic( hwnd )) return FALSE;
1552 ShowWindow( hwnd, SW_SHOWNORMAL );
1557 /***********************************************************************
1560 * Implementation of FindWindow() and FindWindowEx().
1562 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1567 WCHAR *buffer = NULL;
1569 if (!parent) parent = GetDesktopWindow();
1572 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1573 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1576 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1580 child = WIN_GetFullHandle( child );
1581 while (list[i] && list[i] != child) i++;
1582 if (!list[i]) goto done;
1583 i++; /* start from next window */
1590 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1597 if (list) HeapFree( GetProcessHeap(), 0, list );
1598 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1604 /***********************************************************************
1605 * FindWindowA (USER32.@)
1607 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1609 HWND ret = FindWindowExA( 0, 0, className, title );
1610 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1615 /***********************************************************************
1616 * FindWindowExA (USER32.@)
1618 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1619 LPCSTR className, LPCSTR title )
1628 /* If the atom doesn't exist, then no class */
1629 /* with this name exists either. */
1630 if (!(atom = GlobalFindAtomA( className )))
1632 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1636 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1638 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1639 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1640 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1641 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1642 HeapFree( GetProcessHeap(), 0, buffer );
1647 /***********************************************************************
1648 * FindWindowExW (USER32.@)
1650 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1651 LPCWSTR className, LPCWSTR title )
1657 /* If the atom doesn't exist, then no class */
1658 /* with this name exists either. */
1659 if (!(atom = GlobalFindAtomW( className )))
1661 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1665 return WIN_FindWindow( parent, child, atom, title );
1669 /***********************************************************************
1670 * FindWindowW (USER32.@)
1672 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1674 return FindWindowExW( 0, 0, className, title );
1678 /**********************************************************************
1679 * GetDesktopWindow (USER32.@)
1681 HWND WINAPI GetDesktopWindow(void)
1683 if (pWndDesktop) return pWndDesktop->hwndSelf;
1684 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" );
1690 /*******************************************************************
1691 * EnableWindow (USER32.@)
1693 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1700 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1701 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1705 TRACE("( %x, %d )\n", hwnd, enable);
1707 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1708 style = wndPtr->dwStyle;
1709 retvalue = ((style & WS_DISABLED) != 0);
1710 WIN_ReleasePtr( wndPtr );
1712 if (enable && retvalue)
1714 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1715 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1717 else if (!enable && !retvalue)
1719 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1721 WIN_SetStyle( hwnd, style | WS_DISABLED );
1723 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1724 SetFocus( 0 ); /* A disabled window can't have the focus */
1726 if (hwnd == GetCapture() || IsChild(hwnd, GetCapture()))
1727 ReleaseCapture(); /* A disabled window can't capture the mouse */
1729 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1735 /***********************************************************************
1736 * IsWindowEnabled (USER32.@)
1738 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1740 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1744 /***********************************************************************
1745 * IsWindowUnicode (USER32.@)
1747 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1752 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1753 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1754 WIN_ReleaseWndPtr(wndPtr);
1759 /**********************************************************************
1760 * GetWindowWord (USER32.@)
1762 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1767 WND *wndPtr = WIN_GetPtr( hwnd );
1770 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1773 if (wndPtr == WND_OTHER_PROCESS)
1775 if (IsWindow( hwnd ))
1776 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1777 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1780 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1782 WARN("Invalid offset %d\n", offset );
1783 SetLastError( ERROR_INVALID_INDEX );
1785 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1786 WIN_ReleasePtr( wndPtr );
1792 case GWL_HWNDPARENT:
1793 return GetWindowLongW( hwnd, offset );
1797 LONG ret = GetWindowLongW( hwnd, offset );
1799 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1803 WARN("Invalid offset %d\n", offset );
1809 /**********************************************************************
1810 * SetWindowWord (USER32.@)
1812 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1821 case GWL_HWNDPARENT:
1822 return SetWindowLongW( hwnd, offset, (UINT)newval );
1826 WARN("Invalid offset %d\n", offset );
1827 SetLastError( ERROR_INVALID_INDEX );
1832 wndPtr = WIN_GetPtr( hwnd );
1833 if (wndPtr == WND_OTHER_PROCESS)
1836 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1837 offset, newval, hwnd );
1842 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1846 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1848 WARN("Invalid offset %d\n", offset );
1849 WIN_ReleasePtr(wndPtr);
1850 SetLastError( ERROR_INVALID_INDEX );
1853 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1856 WIN_ReleasePtr(wndPtr);
1861 /**********************************************************************
1864 * Helper function for GetWindowLong().
1866 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1871 if (offset == GWL_HWNDPARENT)
1873 HWND parent = GetAncestor( hwnd, GA_PARENT );
1874 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1875 return (LONG)parent;
1878 if (!(wndPtr = WIN_GetPtr( hwnd )))
1880 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1884 if (wndPtr == WND_OTHER_PROCESS)
1889 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1890 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1893 if (offset == GWL_WNDPROC)
1895 SetLastError( ERROR_ACCESS_DENIED );
1898 SERVER_START_REQ( set_window_info )
1901 req->flags = 0; /* don't set anything, just retrieve */
1902 if (!wine_server_call_err( req ))
1906 case GWL_STYLE: retvalue = reply->old_style; break;
1907 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1908 case GWL_ID: retvalue = reply->old_id; break;
1909 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1910 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1912 SetLastError( ERROR_INVALID_INDEX );
1921 /* now we have a valid wndPtr */
1925 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1928 * Some programs try to access last element from 16 bit
1929 * code using illegal offset value. Hopefully this is
1930 * what those programs really expect.
1932 if (type == WIN_PROC_16 &&
1933 wndPtr->cbWndExtra >= 4 &&
1934 offset == wndPtr->cbWndExtra - sizeof(WORD))
1936 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1938 ERR( "- replaced invalid offset %d with %d\n",
1941 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1942 WIN_ReleasePtr( wndPtr );
1945 WARN("Invalid offset %d\n", offset );
1946 WIN_ReleasePtr( wndPtr );
1947 SetLastError( ERROR_INVALID_INDEX );
1950 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1951 /* Special case for dialog window procedure */
1952 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1953 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1954 WIN_ReleasePtr( wndPtr );
1960 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1961 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1962 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1963 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1964 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1965 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1967 WARN("Unknown offset %d\n", offset );
1968 SetLastError( ERROR_INVALID_INDEX );
1971 WIN_ReleasePtr(wndPtr);
1976 /**********************************************************************
1979 * Helper function for SetWindowLong().
1981 * 0 is the failure code. However, in the case of failure SetLastError
1982 * must be set to distinguish between a 0 return value and a failure.
1984 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1985 WINDOWPROCTYPE type )
1990 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1992 if (!WIN_IsCurrentProcess( hwnd ))
1994 if (offset == GWL_WNDPROC)
1996 SetLastError( ERROR_ACCESS_DENIED );
1999 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2002 wndPtr = WIN_GetPtr( hwnd );
2003 if (wndPtr->hwndSelf == GetDesktopWindow())
2005 /* can't change anything on the desktop window */
2006 WIN_ReleasePtr( wndPtr );
2007 SetLastError( ERROR_ACCESS_DENIED );
2013 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2014 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
2016 WARN("Invalid offset %d\n", offset );
2017 WIN_ReleasePtr( wndPtr );
2018 SetLastError( ERROR_INVALID_INDEX );
2021 /* Special case for dialog window procedure */
2022 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2024 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2025 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2026 type, WIN_PROC_WINDOW );
2027 WIN_ReleasePtr( wndPtr );
2032 WIN_ReleasePtr( wndPtr );
2039 /* first some special cases */
2044 style.styleOld = wndPtr->dwStyle;
2045 style.styleNew = newval;
2046 WIN_ReleasePtr( wndPtr );
2047 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2048 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2049 newval = style.styleNew;
2051 case GWL_HWNDPARENT:
2052 if (wndPtr->parent == GetDesktopWindow())
2054 WIN_ReleasePtr( wndPtr );
2055 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2059 WIN_ReleasePtr( wndPtr );
2060 return (LONG)SetParent( hwnd, (HWND)newval );
2063 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2064 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2065 type, WIN_PROC_WINDOW );
2066 WIN_ReleasePtr( wndPtr );
2073 WIN_ReleasePtr( wndPtr );
2074 WARN("Invalid offset %d\n", offset );
2075 SetLastError( ERROR_INVALID_INDEX );
2079 SERVER_START_REQ( set_window_info )
2085 req->flags = SET_WIN_STYLE;
2086 req->style = newval;
2089 req->flags = SET_WIN_EXSTYLE;
2090 req->ex_style = newval;
2093 req->flags = SET_WIN_ID;
2097 req->flags = SET_WIN_INSTANCE;
2098 req->instance = (void *)newval;
2101 req->flags = SET_WIN_USERDATA;
2102 req->user_data = (void *)newval;
2105 if ((ok = !wine_server_call_err( req )))
2110 wndPtr->dwStyle = newval;
2111 retval = reply->old_style;
2114 wndPtr->dwExStyle = newval;
2115 retval = reply->old_ex_style;
2118 wndPtr->wIDmenu = newval;
2119 retval = reply->old_id;
2122 wndPtr->hInstance = newval;
2123 retval = (HINSTANCE)reply->old_instance;
2126 wndPtr->userdata = newval;
2127 retval = (ULONG_PTR)reply->old_user_data;
2133 WIN_ReleasePtr( wndPtr );
2137 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2138 USER_Driver.pSetWindowStyle( hwnd, retval );
2140 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2141 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2148 /**********************************************************************
2149 * GetWindowLong (USER.135)
2151 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2153 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2157 /**********************************************************************
2158 * GetWindowLongA (USER32.@)
2160 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2162 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2166 /**********************************************************************
2167 * GetWindowLongW (USER32.@)
2169 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2171 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2175 /**********************************************************************
2176 * SetWindowLong (USER.136)
2178 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2180 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2184 /**********************************************************************
2185 * SetWindowLongA (USER32.@)
2187 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2189 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2193 /**********************************************************************
2194 * SetWindowLongW (USER32.@) Set window attribute
2196 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2197 * value in a window's extra memory.
2199 * The _hwnd_ parameter specifies the window. is the handle to a
2200 * window that has extra memory. The _newval_ parameter contains the
2201 * new attribute or extra memory value. If positive, the _offset_
2202 * parameter is the byte-addressed location in the window's extra
2203 * memory to set. If negative, _offset_ specifies the window
2204 * attribute to set, and should be one of the following values:
2206 * GWL_EXSTYLE The window's extended window style
2208 * GWL_STYLE The window's window style.
2210 * GWL_WNDPROC Pointer to the window's window procedure.
2212 * GWL_HINSTANCE The window's pplication instance handle.
2214 * GWL_ID The window's identifier.
2216 * GWL_USERDATA The window's user-specified data.
2218 * If the window is a dialog box, the _offset_ parameter can be one of
2219 * the following values:
2221 * DWL_DLGPROC The address of the window's dialog box procedure.
2223 * DWL_MSGRESULT The return value of a message
2224 * that the dialog box procedure processed.
2226 * DWL_USER Application specific information.
2230 * If successful, returns the previous value located at _offset_. Otherwise,
2235 * Extra memory for a window class is specified by a nonzero cbWndExtra
2236 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2237 * time of class creation.
2239 * Using GWL_WNDPROC to set a new window procedure effectively creates
2240 * a window subclass. Use CallWindowProc() in the new windows procedure
2241 * to pass messages to the superclass's window procedure.
2243 * The user data is reserved for use by the application which created
2246 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2247 * instead, call the EnableWindow() function to change the window's
2250 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2251 * SetParent() instead.
2254 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2255 * it sends WM_STYLECHANGING before changing the settings
2256 * and WM_STYLECHANGED afterwards.
2257 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2259 LONG WINAPI SetWindowLongW(
2260 HWND hwnd, /* [in] window to alter */
2261 INT offset, /* [in] offset, in bytes, of location to alter */
2262 LONG newval /* [in] new value of location */
2264 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2268 /*******************************************************************
2269 * GetWindowTextA (USER32.@)
2271 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2275 if (WIN_IsCurrentProcess( hwnd ))
2276 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2278 /* when window belongs to other process, don't send a message */
2279 if (nMaxCount <= 0) return 0;
2280 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2281 get_server_window_text( hwnd, buffer, nMaxCount );
2282 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2283 lpString[nMaxCount-1] = 0;
2284 HeapFree( GetProcessHeap(), 0, buffer );
2285 return strlen(lpString);
2289 /*******************************************************************
2290 * InternalGetWindowText (USER32.@)
2292 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2296 if (nMaxCount <= 0) return 0;
2297 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2298 if (win != WND_OTHER_PROCESS)
2300 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2301 else lpString[0] = 0;
2302 WIN_ReleasePtr( win );
2306 get_server_window_text( hwnd, lpString, nMaxCount );
2308 return strlenW(lpString);
2312 /*******************************************************************
2313 * GetWindowTextW (USER32.@)
2315 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2317 if (WIN_IsCurrentProcess( hwnd ))
2318 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2320 /* when window belongs to other process, don't send a message */
2321 if (nMaxCount <= 0) return 0;
2322 get_server_window_text( hwnd, lpString, nMaxCount );
2323 return strlenW(lpString);
2327 /*******************************************************************
2328 * SetWindowText (USER32.@)
2329 * SetWindowTextA (USER32.@)
2331 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2333 if (!WIN_IsCurrentProcess( hwnd ))
2335 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2336 SetLastError( ERROR_ACCESS_DENIED );
2339 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2343 /*******************************************************************
2344 * SetWindowTextW (USER32.@)
2346 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2348 if (!WIN_IsCurrentProcess( hwnd ))
2350 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2351 SetLastError( ERROR_ACCESS_DENIED );
2354 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2358 /*******************************************************************
2359 * GetWindowTextLengthA (USER32.@)
2361 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2363 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2366 /*******************************************************************
2367 * GetWindowTextLengthW (USER32.@)
2369 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2371 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2375 /*******************************************************************
2376 * IsWindow (USER32.@)
2378 BOOL WINAPI IsWindow( HWND hwnd )
2383 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2385 if (ptr != WND_OTHER_PROCESS)
2387 WIN_ReleasePtr( ptr );
2391 /* check other processes */
2392 SERVER_START_REQ( get_window_info )
2395 ret = !wine_server_call_err( req );
2402 /***********************************************************************
2403 * GetWindowThreadProcessId (USER32.@)
2405 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2410 if (!(ptr = WIN_GetPtr( hwnd )))
2412 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2416 if (ptr != WND_OTHER_PROCESS)
2418 /* got a valid window */
2420 if (process) *process = GetCurrentProcessId();
2421 WIN_ReleasePtr( ptr );
2425 /* check other processes */
2426 SERVER_START_REQ( get_window_info )
2429 if (!wine_server_call_err( req ))
2431 tid = (DWORD)reply->tid;
2432 if (process) *process = (DWORD)reply->pid;
2440 /*****************************************************************
2441 * GetParent (USER32.@)
2443 HWND WINAPI GetParent( HWND hwnd )
2448 if (!(wndPtr = WIN_GetPtr( hwnd )))
2450 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2453 if (wndPtr == WND_OTHER_PROCESS)
2455 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2456 if (style & (WS_POPUP | WS_CHILD))
2458 SERVER_START_REQ( get_window_tree )
2461 if (!wine_server_call_err( req ))
2463 if (style & WS_POPUP) retvalue = reply->owner;
2464 else if (style & WS_CHILD) retvalue = reply->parent;
2472 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2473 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2474 WIN_ReleasePtr( wndPtr );
2480 /*****************************************************************
2481 * GetAncestor (USER32.@)
2483 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2486 HWND *list, ret = 0;
2491 if (!(win = WIN_GetPtr( hwnd )))
2493 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2496 if (win != WND_OTHER_PROCESS)
2499 WIN_ReleasePtr( win );
2501 else /* need to query the server */
2503 SERVER_START_REQ( get_window_tree )
2506 if (!wine_server_call_err( req )) ret = reply->parent;
2513 if (!(list = WIN_ListParents( hwnd ))) return 0;
2515 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2519 while (list[count]) count++;
2520 ret = list[count - 2]; /* get the one before the desktop */
2522 HeapFree( GetProcessHeap(), 0, list );
2526 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2529 HWND parent = GetParent( ret );
2539 /*****************************************************************
2540 * SetParent (USER32.@)
2542 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2545 HWND retvalue, full_handle;
2548 if (!parent) parent = GetDesktopWindow();
2549 else parent = WIN_GetFullHandle( parent );
2551 if (!IsWindow( parent ))
2553 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2557 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2558 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2562 if (USER_Driver.pSetParent)
2563 return USER_Driver.pSetParent( hwnd, parent );
2565 /* Windows hides the window first, then shows it again
2566 * including the WM_SHOWWINDOW messages and all */
2567 was_visible = ShowWindow( hwnd, SW_HIDE );
2569 if (!IsWindow( parent )) return 0;
2570 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2572 retvalue = wndPtr->parent; /* old parent */
2573 if (parent != retvalue)
2575 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2577 if (parent != GetDesktopWindow()) /* a child window */
2579 if (!(wndPtr->dwStyle & WS_CHILD))
2581 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2582 if (menu) DestroyMenu( menu );
2586 WIN_ReleasePtr( wndPtr );
2588 /* SetParent additionally needs to make hwnd the topmost window
2589 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2590 WM_WINDOWPOSCHANGED notification messages.
2592 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2593 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2594 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2595 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2600 /*******************************************************************
2601 * IsChild (USER32.@)
2603 BOOL WINAPI IsChild( HWND parent, HWND child )
2605 HWND *list = WIN_ListParents( child );
2609 if (!list) return FALSE;
2610 parent = WIN_GetFullHandle( parent );
2611 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2612 ret = (list[i] != 0);
2613 HeapFree( GetProcessHeap(), 0, list );
2618 /***********************************************************************
2619 * IsWindowVisible (USER32.@)
2621 BOOL WINAPI IsWindowVisible( HWND hwnd )
2627 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2628 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2629 for (i = 0; list[i]; i++)
2630 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2632 HeapFree( GetProcessHeap(), 0, list );
2637 /***********************************************************************
2638 * WIN_IsWindowDrawable
2640 * hwnd is drawable when it is visible, all parents are not
2641 * minimized, and it is itself not minimized unless we are
2642 * trying to draw its default class icon.
2644 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2649 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2651 if (!(style & WS_VISIBLE)) return FALSE;
2652 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2654 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2655 for (i = 0; list[i]; i++)
2656 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2659 HeapFree( GetProcessHeap(), 0, list );
2664 /*******************************************************************
2665 * GetTopWindow (USER32.@)
2667 HWND WINAPI GetTopWindow( HWND hwnd )
2669 if (!hwnd) hwnd = GetDesktopWindow();
2670 return GetWindow( hwnd, GW_CHILD );
2674 /*******************************************************************
2675 * GetWindow (USER32.@)
2677 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2681 if (rel == GW_OWNER) /* this one may be available locally */
2683 WND *wndPtr = WIN_GetPtr( hwnd );
2686 SetLastError( ERROR_INVALID_HANDLE );
2689 if (wndPtr != WND_OTHER_PROCESS)
2691 retval = wndPtr->owner;
2692 WIN_ReleasePtr( wndPtr );
2695 /* else fall through to server call */
2698 SERVER_START_REQ( get_window_tree )
2701 if (!wine_server_call_err( req ))
2706 retval = reply->first_sibling;
2709 retval = reply->last_sibling;
2712 retval = reply->next_sibling;
2715 retval = reply->prev_sibling;
2718 retval = reply->owner;
2721 retval = reply->first_child;
2731 /***********************************************************************
2732 * WIN_InternalShowOwnedPopups
2734 * Internal version of ShowOwnedPopups; Wine functions should use this
2735 * to avoid interfering with application calls to ShowOwnedPopups
2736 * and to make sure the application can't prevent showing/hiding.
2738 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2742 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2746 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2748 if (!win_array) return TRUE;
2751 * Show windows Lowest first, Highest last to preserve Z-Order
2753 while (win_array[count]) count++;
2754 while (--count >= 0)
2756 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2757 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2759 if (pWnd->dwStyle & WS_POPUP)
2763 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2764 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2767 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2769 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2770 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2775 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2776 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2777 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2780 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2782 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2783 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2784 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2788 WIN_ReleaseWndPtr( pWnd );
2790 HeapFree( GetProcessHeap(), 0, win_array );
2795 /*******************************************************************
2796 * ShowOwnedPopups (USER32.@)
2798 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2802 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2804 if (!win_array) return TRUE;
2806 while (win_array[count]) count++;
2807 while (--count >= 0)
2809 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2810 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2812 if (pWnd->dwStyle & WS_POPUP)
2816 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2818 /* In Windows, ShowOwnedPopups(TRUE) generates
2819 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2820 * regardless of the state of the owner
2822 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2823 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2828 if (IsWindowVisible(pWnd->hwndSelf))
2830 /* In Windows, ShowOwnedPopups(FALSE) generates
2831 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2832 * regardless of the state of the owner
2834 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2835 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2839 WIN_ReleaseWndPtr( pWnd );
2841 HeapFree( GetProcessHeap(), 0, win_array );
2846 /*******************************************************************
2847 * GetLastActivePopup (USER32.@)
2849 HWND WINAPI GetLastActivePopup( HWND hwnd )
2853 SERVER_START_REQ( get_window_info )
2856 if (!wine_server_call_err( req )) retval = reply->last_active;
2863 /*******************************************************************
2866 * Build an array of all parents of a given window, starting with
2867 * the immediate parent. The array must be freed with HeapFree.
2868 * Returns NULL if window is a top-level window.
2870 HWND *WIN_ListParents( HWND hwnd )
2873 HWND current, *list;
2874 int pos = 0, size = 16, count = 0;
2876 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2881 if (!(win = WIN_GetPtr( current ))) goto empty;
2882 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2883 list[pos] = win->parent;
2884 WIN_ReleasePtr( win );
2885 if (!(current = list[pos]))
2887 if (!pos) goto empty;
2890 if (++pos == size - 1)
2892 /* need to grow the list */
2893 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2894 if (!new_list) goto empty;
2900 /* at least one parent belongs to another process, have to query the server */
2905 SERVER_START_REQ( get_window_parents )
2908 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2909 if (!wine_server_call( req )) count = reply->count;
2912 if (!count) goto empty;
2918 HeapFree( GetProcessHeap(), 0, list );
2920 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2924 HeapFree( GetProcessHeap(), 0, list );
2929 /*******************************************************************
2932 * Build an array of the children of a given window. The array must be
2933 * freed with HeapFree. Returns NULL when no windows are found.
2935 HWND *WIN_ListChildren( HWND hwnd )
2937 return list_window_children( hwnd, 0, 0 );
2941 /*******************************************************************
2942 * EnumWindows (USER32.@)
2944 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2950 /* We have to build a list of all windows first, to avoid */
2951 /* unpleasant side-effects, for instance if the callback */
2952 /* function changes the Z-order of the windows. */
2954 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2956 /* Now call the callback function for every window */
2958 iWndsLocks = WIN_SuspendWndsLock();
2959 for (i = 0; list[i]; i++)
2961 /* Make sure that the window still exists */
2962 if (!IsWindow( list[i] )) continue;
2963 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2965 WIN_RestoreWndsLock(iWndsLocks);
2966 HeapFree( GetProcessHeap(), 0, list );
2971 /**********************************************************************
2972 * EnumThreadWindows (USER32.@)
2974 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2979 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2982 /* Now call the callback function for every window */
2984 iWndsLocks = WIN_SuspendWndsLock();
2985 for (i = 0; list[i]; i++)
2986 if (!func( list[i], lParam )) break;
2987 WIN_RestoreWndsLock(iWndsLocks);
2988 HeapFree( GetProcessHeap(), 0, list );
2993 /**********************************************************************
2994 * WIN_EnumChildWindows
2996 * Helper function for EnumChildWindows().
2998 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3003 for ( ; *list; list++)
3005 /* Make sure that the window still exists */
3006 if (!IsWindow( *list )) continue;
3007 /* skip owned windows */
3008 if (GetWindow( *list, GW_OWNER )) continue;
3009 /* Build children list first */
3010 childList = WIN_ListChildren( *list );
3012 ret = func( *list, lParam );
3016 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3017 HeapFree( GetProcessHeap(), 0, childList );
3019 if (!ret) return FALSE;
3025 /**********************************************************************
3026 * EnumChildWindows (USER32.@)
3028 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3033 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3034 iWndsLocks = WIN_SuspendWndsLock();
3035 WIN_EnumChildWindows( list, func, lParam );
3036 WIN_RestoreWndsLock(iWndsLocks);
3037 HeapFree( GetProcessHeap(), 0, list );
3042 /*******************************************************************
3043 * AnyPopup (USER.52)
3045 BOOL16 WINAPI AnyPopup16(void)
3051 /*******************************************************************
3052 * AnyPopup (USER32.@)
3054 BOOL WINAPI AnyPopup(void)
3058 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3060 if (!list) return FALSE;
3061 for (i = 0; list[i]; i++)
3063 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3065 retvalue = (list[i] != 0);
3066 HeapFree( GetProcessHeap(), 0, list );
3071 /*******************************************************************
3072 * FlashWindow (USER32.@)
3074 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3076 WND *wndPtr = WIN_FindWndPtr(hWnd);
3078 TRACE("%04x\n", hWnd);
3080 if (!wndPtr) return FALSE;
3081 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3083 if (wndPtr->dwStyle & WS_MINIMIZE)
3085 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3087 HDC hDC = GetDC(hWnd);
3089 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3090 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3092 ReleaseDC( hWnd, hDC );
3093 wndPtr->flags |= WIN_NCACTIVATED;
3097 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3098 wndPtr->flags &= ~WIN_NCACTIVATED;
3100 WIN_ReleaseWndPtr(wndPtr);
3106 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3107 else wparam = (hWnd == GetForegroundWindow());
3109 WIN_ReleaseWndPtr(wndPtr);
3110 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3116 /*******************************************************************
3117 * GetWindowContextHelpId (USER32.@)
3119 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3122 WND *wnd = WIN_FindWndPtr( hwnd );
3124 retval = wnd->helpContext;
3125 WIN_ReleaseWndPtr(wnd);
3130 /*******************************************************************
3131 * SetWindowContextHelpId (USER32.@)
3133 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3135 WND *wnd = WIN_FindWndPtr( hwnd );
3136 if (!wnd) return FALSE;
3137 wnd->helpContext = id;
3138 WIN_ReleaseWndPtr(wnd);
3143 /*******************************************************************
3144 * DRAG_QueryUpdate16
3146 * recursively find a child that contains spDragInfo->pt point
3147 * and send WM_QUERYDROPOBJECT
3149 static BOOL16 DRAG_QueryUpdate16( HWND hQueryWnd, SEGPTR spDragInfo )
3151 BOOL16 wParam, bResult = 0;
3153 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3156 if (!ptrDragInfo) return FALSE;
3158 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3160 GetWindowRect(hQueryWnd,&tempRect);
3162 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3164 if (!IsIconic( hQueryWnd ))
3166 GetClientRect( hQueryWnd, &tempRect );
3167 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3169 if (PtInRect( &tempRect, pt))
3172 HWND *list = WIN_ListChildren( hQueryWnd );
3178 for (i = 0; list[i]; i++)
3180 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3182 GetWindowRect( list[i], &tempRect );
3183 if (PtInRect( &tempRect, pt )) break;
3188 if (IsWindowEnabled( list[i] ))
3189 bResult = DRAG_QueryUpdate16( list[i], spDragInfo );
3191 HeapFree( GetProcessHeap(), 0, list );
3193 if(bResult) return bResult;
3199 ScreenToClient16(HWND_16(hQueryWnd),&ptrDragInfo->pt);
3201 ptrDragInfo->hScope = HWND_16(hQueryWnd);
3203 bResult = SendMessage16( HWND_16(hQueryWnd), WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3205 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3211 /*******************************************************************
3212 * DragDetect (USER32.@)
3214 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3219 rect.left = pt.x - wDragWidth;
3220 rect.right = pt.x + wDragWidth;
3222 rect.top = pt.y - wDragHeight;
3223 rect.bottom = pt.y + wDragHeight;
3229 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3231 if( msg.message == WM_LBUTTONUP )
3236 if( msg.message == WM_MOUSEMOVE )
3239 tmp.x = LOWORD(msg.lParam);
3240 tmp.y = HIWORD(msg.lParam);
3241 if( !PtInRect( &rect, tmp ))
3253 /******************************************************************************
3254 * DragObject (USER.464)
3256 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3257 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3260 LPDRAGINFO16 lpDragInfo;
3262 HCURSOR hOldCursor=0, hBummer=0;
3263 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3264 HCURSOR hCurrentCursor = 0;
3265 HWND16 hCurrentWnd = 0;
3267 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3268 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3270 if( !lpDragInfo || !spDragInfo ) return 0L;
3272 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3274 GlobalFree16(hDragInfo);
3278 if(hCursor) hOldCursor = SetCursor(HCURSOR_32(hCursor));
3280 lpDragInfo->hWnd = hWnd;
3281 lpDragInfo->hScope = 0;
3282 lpDragInfo->wFlags = wObj;
3283 lpDragInfo->hList = szList; /* near pointer! */
3284 lpDragInfo->hOfStruct = hOfStruct;
3287 SetCapture(WIN_Handle32(hWnd));
3292 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3294 *(lpDragInfo+1) = *lpDragInfo;
3296 lpDragInfo->pt.x = msg.pt.x;
3297 lpDragInfo->pt.y = msg.pt.y;
3299 /* update DRAGINFO struct */
3300 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3302 if( DRAG_QueryUpdate16(WIN_Handle32(hwndScope), spDragInfo) > 0 )
3303 hCurrentCursor = HCURSOR_32(hCursor);
3306 hCurrentCursor = hBummer;
3307 lpDragInfo->hScope = 0;
3309 if( hCurrentCursor )
3310 SetCursor(hCurrentCursor);
3312 /* send WM_DRAGLOOP */
3313 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3314 (LPARAM) spDragInfo );
3315 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3316 if( hCurrentWnd != lpDragInfo->hScope )
3319 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3320 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3321 HIWORD(spDragInfo)) );
3322 hCurrentWnd = lpDragInfo->hScope;
3324 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3328 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3330 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3333 ShowCursor( FALSE );
3335 if( hCursor ) SetCursor(hOldCursor);
3337 if( hCurrentCursor != hBummer )
3338 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3339 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3342 GlobalFree16(hDragInfo);
3344 return (DWORD)(msg.lParam);
3348 /******************************************************************************
3349 * GetWindowModuleFileNameA (USER32.@)
3351 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3353 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3354 hwnd, lpszFileName, cchFileNameMax);
3358 /******************************************************************************
3359 * GetWindowModuleFileNameW (USER32.@)
3361 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3363 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3364 hwnd, lpszFileName, cchFileNameMax);
3368 /******************************************************************************
3369 * GetWindowInfo (USER32.@)
3372 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3373 * this may be because this structure changed over time. If this is the
3374 * the case, then please: FIXME.
3375 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3377 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3379 WND *wndInfo = NULL;
3380 if (!pwi) return FALSE;
3381 if (pwi->cbSize != sizeof(WINDOWINFO))
3383 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3386 wndInfo = WIN_GetPtr(hwnd);
3387 if (!wndInfo) return FALSE;
3388 if (wndInfo == WND_OTHER_PROCESS)
3390 FIXME("window belong to other process\n");
3394 pwi->rcWindow = wndInfo->rectWindow;
3395 pwi->rcClient = wndInfo->rectClient;
3396 pwi->dwStyle = wndInfo->dwStyle;
3397 pwi->dwExStyle = wndInfo->dwExStyle;
3398 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3399 /* if active WS_ACTIVECAPTION, else 0 */
3401 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3402 GetSystemMetrics(SM_CXBORDER) : 0);
3403 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3404 GetSystemMetrics(SM_CYBORDER) : 0);
3405 /* above two: I'm presuming that borders widths are the same
3406 * for each window - so long as its actually using a border.. */
3408 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3409 pwi->wCreatorVersion = GetVersion();
3410 /* Docs say this should be the version that
3411 * CREATED the window. But eh?.. Isn't that just the
3412 * version we are running.. Unless ofcourse its some wacky
3413 * RPC stuff or something */
3415 WIN_ReleasePtr(wndInfo);