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 )
184 req->tid = (void *)tid;
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 && reply->full_parent != wndPtr->parent)
427 wndPtr->owner = 0; /* reset owner when changing parent */
428 wndPtr->parent = reply->full_parent;
434 WIN_ReleasePtr( wndPtr );
438 /***********************************************************************
441 * Change the owner of a window.
443 void WIN_SetOwner( HWND hwnd, HWND owner )
445 WND *win = WIN_GetPtr( hwnd );
448 if (win == WND_OTHER_PROCESS)
450 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
453 SERVER_START_REQ( set_window_owner )
457 if (!wine_server_call( req )) win->owner = reply->full_owner;
460 WIN_ReleasePtr( win );
464 /***********************************************************************
467 * Change the style of a window.
469 LONG WIN_SetStyle( HWND hwnd, LONG style )
473 WND *win = WIN_GetPtr( hwnd );
476 if (win == WND_OTHER_PROCESS)
479 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
482 if (style == win->dwStyle)
484 WIN_ReleasePtr( win );
487 SERVER_START_REQ( set_window_info )
490 req->flags = SET_WIN_STYLE;
492 if ((ok = !wine_server_call( req )))
494 ret = reply->old_style;
495 win->dwStyle = style;
499 WIN_ReleasePtr( win );
500 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
505 /***********************************************************************
508 * Change the extended style of a window.
510 LONG WIN_SetExStyle( HWND hwnd, LONG style )
513 WND *win = WIN_GetPtr( hwnd );
516 if (win == WND_OTHER_PROCESS)
519 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
522 if (style == win->dwExStyle)
524 WIN_ReleasePtr( win );
527 SERVER_START_REQ( set_window_info )
530 req->flags = SET_WIN_EXSTYLE;
531 req->ex_style = style;
532 if (!wine_server_call( req ))
534 ret = reply->old_ex_style;
535 win->dwExStyle = style;
539 WIN_ReleasePtr( win );
544 /***********************************************************************
547 * Set the window and client rectangles.
549 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
551 WND *win = WIN_GetPtr( hwnd );
555 if (win == WND_OTHER_PROCESS)
557 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
560 SERVER_START_REQ( set_window_rectangles )
563 req->window.left = rectWindow->left;
564 req->window.top = rectWindow->top;
565 req->window.right = rectWindow->right;
566 req->window.bottom = rectWindow->bottom;
567 req->client.left = rectClient->left;
568 req->client.top = rectClient->top;
569 req->client.right = rectClient->right;
570 req->client.bottom = rectClient->bottom;
571 ret = !wine_server_call( req );
576 win->rectWindow = *rectWindow;
577 win->rectClient = *rectClient;
579 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
580 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
581 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
583 WIN_ReleasePtr( win );
587 /***********************************************************************
590 * Get the window and client rectangles.
592 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
594 WND *win = WIN_GetPtr( hwnd );
597 if (!win) return FALSE;
598 if (win == WND_OTHER_PROCESS)
600 SERVER_START_REQ( get_window_rectangles )
603 if ((ret = !wine_server_call( req )))
607 rectWindow->left = reply->window.left;
608 rectWindow->top = reply->window.top;
609 rectWindow->right = reply->window.right;
610 rectWindow->bottom = reply->window.bottom;
614 rectClient->left = reply->client.left;
615 rectClient->top = reply->client.top;
616 rectClient->right = reply->client.right;
617 rectClient->bottom = reply->client.bottom;
625 if (rectWindow) *rectWindow = win->rectWindow;
626 if (rectClient) *rectClient = win->rectClient;
627 WIN_ReleasePtr( win );
633 /***********************************************************************
636 * Destroy storage associated to a window. "Internals" p.358
638 LRESULT WIN_DestroyWindow( HWND hwnd )
643 TRACE("%04x\n", hwnd );
645 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
647 ERR( "window doesn't belong to current thread\n" );
651 /* free child windows */
652 if ((list = WIN_ListChildren( hwnd )))
655 for (i = 0; list[i]; i++)
657 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
658 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
660 HeapFree( GetProcessHeap(), 0, list );
664 * Clear the update region to make sure no WM_PAINT messages will be
665 * generated for this window while processing the WM_NCDESTROY.
667 RedrawWindow( hwnd, NULL, 0,
668 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
671 * Send the WM_NCDESTROY to the window being destroyed.
673 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
675 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
677 WINPOS_CheckInternalPos( hwnd );
678 if( hwnd == GetCapture()) ReleaseCapture();
680 /* free resources associated with the window */
682 TIMER_RemoveWindowTimers( hwnd );
684 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
685 wndPtr->hmemTaskQ = 0;
687 if (!(wndPtr->dwStyle & WS_CHILD))
689 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
690 if (menu) DestroyMenu( menu );
692 if (wndPtr->hSysMenu)
694 DestroyMenu( wndPtr->hSysMenu );
695 wndPtr->hSysMenu = 0;
697 USER_Driver.pDestroyWindow( hwnd );
698 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
699 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
700 CLASS_RemoveWindow( wndPtr->class );
701 wndPtr->class = NULL;
702 wndPtr->dwMagic = 0; /* Mark it as invalid */
703 WIN_ReleaseWndPtr( wndPtr );
707 /***********************************************************************
708 * WIN_DestroyThreadWindows
710 * Destroy all children of 'wnd' owned by the current thread.
711 * Return TRUE if something was done.
713 void WIN_DestroyThreadWindows( HWND hwnd )
718 if (!(list = WIN_ListChildren( hwnd ))) return;
719 for (i = 0; list[i]; i++)
721 if (WIN_IsCurrentThread( list[i] ))
722 DestroyWindow( list[i] );
724 WIN_DestroyThreadWindows( list[i] );
726 HeapFree( GetProcessHeap(), 0, list );
729 /***********************************************************************
730 * WIN_CreateDesktopWindow
732 * Create the desktop window.
734 BOOL WIN_CreateDesktopWindow(void)
736 struct tagCLASS *class;
745 TRACE("Creating desktop window\n");
747 if (!WINPOS_CreateInternalPosAtom() ||
748 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
749 &wndExtra, &winproc, &clsStyle, &dce )))
752 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
753 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
754 if (!pWndDesktop) return FALSE;
755 hwndDesktop = pWndDesktop->hwndSelf;
757 pWndDesktop->tid = 0; /* nobody owns the desktop */
758 pWndDesktop->parent = 0;
759 pWndDesktop->owner = 0;
760 pWndDesktop->class = class;
761 pWndDesktop->hInstance = 0;
762 pWndDesktop->text = NULL;
763 pWndDesktop->hmemTaskQ = 0;
764 pWndDesktop->hrgnUpdate = 0;
765 pWndDesktop->hwndLastActive = hwndDesktop;
766 pWndDesktop->dwStyle = 0;
767 pWndDesktop->dwExStyle = 0;
768 pWndDesktop->clsStyle = clsStyle;
769 pWndDesktop->dce = NULL;
770 pWndDesktop->pVScroll = NULL;
771 pWndDesktop->pHScroll = NULL;
772 pWndDesktop->wIDmenu = 0;
773 pWndDesktop->helpContext = 0;
774 pWndDesktop->flags = 0;
775 pWndDesktop->hSysMenu = 0;
776 pWndDesktop->userdata = 0;
777 pWndDesktop->winproc = winproc;
778 pWndDesktop->cbWndExtra = wndExtra;
780 cs.lpCreateParams = NULL;
786 cs.cx = GetSystemMetrics( SM_CXSCREEN );
787 cs.cy = GetSystemMetrics( SM_CYSCREEN );
788 cs.style = pWndDesktop->dwStyle;
789 cs.dwExStyle = pWndDesktop->dwExStyle;
791 cs.lpszClass = DESKTOP_CLASS_ATOM;
793 SetRect( &rect, 0, 0, cs.cx, cs.cy );
794 WIN_SetRectangles( hwndDesktop, &rect, &rect );
795 WIN_SetStyle( hwndDesktop, WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
797 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
799 WIN_ReleaseWndPtr( pWndDesktop );
803 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
804 WIN_ReleaseWndPtr( pWndDesktop );
809 /***********************************************************************
812 * Fix the coordinates - Helper for WIN_CreateWindowEx.
813 * returns default show mode in sw.
814 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
816 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
818 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
819 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
821 if (cs->style & (WS_CHILD | WS_POPUP))
823 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
824 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
826 else /* overlapped window */
830 GetStartupInfoA( &info );
832 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
834 /* Never believe Microsoft's documentation... CreateWindowEx doc says
835 * that if an overlapped window is created with WS_VISIBLE style bit
836 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
837 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
840 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
841 * 2) it does not ignore the y parameter as the docs claim; instead, it
842 * uses it as second parameter to ShowWindow() unless y is either
843 * CW_USEDEFAULT or CW_USEDEFAULT16.
845 * The fact that we didn't do 2) caused bogus windows pop up when wine
846 * was running apps that were using this obscure feature. Example -
847 * calc.exe that comes with Win98 (only Win98, it's different from
848 * the one that comes with Win95 and NT)
850 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
851 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
852 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
855 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
857 if (info.dwFlags & STARTF_USESIZE)
859 cs->cx = info.dwXSize;
860 cs->cy = info.dwYSize;
862 else /* if no other hint from the app, pick 3/4 of the screen real estate */
865 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
866 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
867 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
874 /* neither x nor cx are default. Check the y values .
875 * In the trace we see Outlook and Outlook Express using
876 * cy set to CW_USEDEFAULT when opening the address book.
878 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
880 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
881 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
882 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
887 /***********************************************************************
890 static void dump_window_styles( DWORD style, DWORD exstyle )
893 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
894 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
895 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
896 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
897 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
898 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
899 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
900 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
901 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
904 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
905 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
907 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
908 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
909 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
910 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
911 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
912 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
913 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
914 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
916 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
917 #define DUMPED_STYLES \
937 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
942 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
943 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
944 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
945 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
946 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
947 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
948 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
949 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
950 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
951 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
952 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
953 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
954 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
955 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
956 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
957 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
958 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
959 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
961 #define DUMPED_EX_STYLES \
962 (WS_EX_DLGMODALFRAME | \
964 WS_EX_NOPARENTNOTIFY | \
966 WS_EX_ACCEPTFILES | \
967 WS_EX_TRANSPARENT | \
972 WS_EX_CONTEXTHELP | \
975 WS_EX_LEFTSCROLLBAR | \
976 WS_EX_CONTROLPARENT | \
981 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
983 #undef DUMPED_EX_STYLES
987 /***********************************************************************
990 * Implementation of CreateWindowEx().
992 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
993 WINDOWPROCTYPE type )
996 struct tagCLASS *classPtr;
998 HWND hwnd, parent, owner;
1003 BOOL unicode = (type == WIN_PROC_32W);
1005 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
1006 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1007 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1008 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1009 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1011 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1013 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1014 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1016 /* Find the parent window */
1018 parent = GetDesktopWindow();
1021 if (cs->hwndParent == HWND_MESSAGE)
1023 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1024 * message window (style: WS_POPUP|WS_DISABLED)
1026 FIXME("Parent is HWND_MESSAGE\n");
1028 else if (cs->hwndParent)
1030 /* Make sure parent is valid */
1031 if (!IsWindow( cs->hwndParent ))
1033 WARN("Bad parent %04x\n", cs->hwndParent );
1036 if (cs->style & WS_CHILD) parent = WIN_GetFullHandle(cs->hwndParent);
1037 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
1039 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
1041 WARN("No parent for child window\n" );
1042 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1045 /* Find the window class */
1046 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1047 &wndExtra, &winproc, &clsStyle, &dce )))
1049 WARN("Bad class '%s'\n", cs->lpszClass );
1053 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1055 /* Correct the window style - stage 1
1057 * These are patches that appear to affect both the style loaded into the
1058 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1060 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1061 * why does the user get to set it?
1064 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1065 * tested for WS_POPUP
1067 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1068 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1069 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1070 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1072 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1074 /* Create the window structure */
1076 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1077 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1079 TRACE("out of memory\n" );
1082 hwnd = wndPtr->hwndSelf;
1084 /* Fill the window structure */
1086 wndPtr->tid = GetCurrentThreadId();
1087 wndPtr->owner = owner;
1088 wndPtr->parent = parent;
1089 wndPtr->class = classPtr;
1090 wndPtr->winproc = winproc;
1091 wndPtr->hInstance = cs->hInstance;
1092 wndPtr->text = NULL;
1093 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
1094 wndPtr->hrgnUpdate = 0;
1095 wndPtr->hrgnWnd = 0;
1096 wndPtr->hwndLastActive = hwnd;
1097 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1098 wndPtr->dwExStyle = cs->dwExStyle;
1099 wndPtr->clsStyle = clsStyle;
1100 wndPtr->wIDmenu = 0;
1101 wndPtr->helpContext = 0;
1102 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1103 wndPtr->pVScroll = NULL;
1104 wndPtr->pHScroll = NULL;
1105 wndPtr->userdata = 0;
1106 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1107 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1108 wndPtr->cbWndExtra = wndExtra;
1110 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1112 /* Correct the window style - stage 2 */
1114 if (!(cs->style & WS_CHILD))
1116 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1117 if (!(cs->style & WS_POPUP))
1119 wndPtr->dwStyle |= WS_CAPTION;
1120 wndPtr->flags |= WIN_NEED_SIZE;
1123 SERVER_START_REQ( set_window_info )
1126 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1127 req->style = wndPtr->dwStyle;
1128 req->ex_style = wndPtr->dwExStyle;
1129 req->instance = (void *)wndPtr->hInstance;
1130 wine_server_call( req );
1134 /* Get class or window DC if needed */
1136 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1137 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1138 else wndPtr->dce = NULL;
1140 /* Set the window menu */
1142 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1144 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1147 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1150 if (HIWORD(cs->hInstance))
1151 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1153 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1155 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1159 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1160 WIN_ReleaseWndPtr( wndPtr );
1162 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1164 WIN_DestroyWindow( hwnd );
1168 /* Notify the parent window only */
1170 send_parent_notify( hwnd, WM_CREATE );
1171 if (!IsWindow( hwnd )) return 0;
1173 if (cs->style & WS_VISIBLE)
1175 /* in case WS_VISIBLE got set in the meantime */
1176 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1177 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1178 WIN_ReleasePtr( wndPtr );
1179 ShowWindow( hwnd, sw );
1182 /* Call WH_SHELL hook */
1184 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1185 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1187 TRACE("created window %04x\n", hwnd);
1192 /***********************************************************************
1193 * CreateWindow (USER.41)
1195 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1196 DWORD style, INT16 x, INT16 y, INT16 width,
1197 INT16 height, HWND16 parent, HMENU16 menu,
1198 HINSTANCE16 instance, LPVOID data )
1200 return CreateWindowEx16( 0, className, windowName, style,
1201 x, y, width, height, parent, menu, instance, data );
1205 /***********************************************************************
1206 * CreateWindowEx (USER.452)
1208 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1209 LPCSTR windowName, DWORD style, INT16 x,
1210 INT16 y, INT16 width, INT16 height,
1211 HWND16 parent, HMENU16 menu,
1212 HINSTANCE16 instance, LPVOID data )
1218 /* Find the class atom */
1220 if (HIWORD(className))
1222 if (!(classAtom = GlobalFindAtomA( className )))
1224 ERR( "bad class name %s\n", debugstr_a(className) );
1230 classAtom = LOWORD(className);
1231 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1233 ERR( "bad atom %x\n", classAtom);
1239 /* Fix the coordinates */
1241 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1242 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1243 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1244 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1246 /* Create the window */
1248 cs.lpCreateParams = data;
1249 cs.hInstance = (HINSTANCE)instance;
1250 cs.hMenu = (HMENU)menu;
1251 cs.hwndParent = WIN_Handle32( parent );
1253 cs.lpszName = windowName;
1254 cs.lpszClass = className;
1255 cs.dwExStyle = exStyle;
1257 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1261 /***********************************************************************
1262 * CreateWindowExA (USER32.@)
1264 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1265 LPCSTR windowName, DWORD style, INT x,
1266 INT y, INT width, INT height,
1267 HWND parent, HMENU menu,
1268 HINSTANCE instance, LPVOID data )
1275 instance=GetModuleHandleA(NULL);
1277 if(exStyle & WS_EX_MDICHILD)
1278 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1280 /* Find the class atom */
1282 if (HIWORD(className))
1284 if (!(classAtom = GlobalFindAtomA( className )))
1286 ERR( "bad class name %s\n", debugstr_a(className) );
1292 classAtom = LOWORD(className);
1293 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1295 ERR( "bad atom %x\n", classAtom);
1301 /* Create the window */
1303 cs.lpCreateParams = data;
1304 cs.hInstance = instance;
1306 cs.hwndParent = parent;
1312 cs.lpszName = windowName;
1313 cs.lpszClass = className;
1314 cs.dwExStyle = exStyle;
1316 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1320 /***********************************************************************
1321 * CreateWindowExW (USER32.@)
1323 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1324 LPCWSTR windowName, DWORD style, INT x,
1325 INT y, INT width, INT height,
1326 HWND parent, HMENU menu,
1327 HINSTANCE instance, LPVOID data )
1334 instance=GetModuleHandleA(NULL);
1336 if(exStyle & WS_EX_MDICHILD)
1337 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1339 /* Find the class atom */
1341 if (HIWORD(className))
1343 if (!(classAtom = GlobalFindAtomW( className )))
1345 ERR( "bad class name %s\n", debugstr_w(className) );
1351 classAtom = LOWORD(className);
1352 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1354 ERR( "bad atom %x\n", classAtom);
1360 /* Create the window */
1362 cs.lpCreateParams = data;
1363 cs.hInstance = instance;
1365 cs.hwndParent = parent;
1371 cs.lpszName = windowName;
1372 cs.lpszClass = className;
1373 cs.dwExStyle = exStyle;
1375 /* Note: we rely on the fact that CREATESTRUCTA and */
1376 /* CREATESTRUCTW have the same layout. */
1377 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1381 /***********************************************************************
1382 * WIN_SendDestroyMsg
1384 static void WIN_SendDestroyMsg( HWND hwnd )
1386 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1387 if (USER_Driver.pResetSelectionOwner)
1388 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1391 * Send the WM_DESTROY to the window.
1393 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1396 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1397 * make sure that the window still exists when we come back.
1404 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1406 /* start from the end (FIXME: is this needed?) */
1407 for (i = 0; pWndArray[i]; i++) ;
1411 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1413 HeapFree( GetProcessHeap(), 0, pWndArray );
1416 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1420 /***********************************************************************
1421 * DestroyWindow (USER32.@)
1423 BOOL WINAPI DestroyWindow( HWND hwnd )
1428 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1430 SetLastError( ERROR_ACCESS_DENIED );
1434 TRACE("(%04x)\n", hwnd);
1436 /* Look whether the focus is within the tree of windows we will
1440 if (h == hwnd || IsChild( hwnd, h ))
1442 HWND parent = GetAncestor( hwnd, GA_PARENT );
1443 if (parent == GetDesktopWindow()) parent = 0;
1449 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1451 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1455 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1456 send_parent_notify( hwnd, WM_DESTROY );
1458 else if (!GetWindow( hwnd, GW_OWNER ))
1460 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1461 /* FIXME: clean up palette - see "Internals" p.352 */
1464 if (!IsWindow(hwnd)) return TRUE;
1466 if (USER_Driver.pResetSelectionOwner)
1467 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1469 /* Hide the window */
1471 ShowWindow( hwnd, SW_HIDE );
1472 if (!IsWindow(hwnd)) return TRUE;
1474 /* Recursively destroy owned windows */
1483 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1486 for (i = 0; list[i]; i++)
1488 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1489 if (WIN_IsCurrentThread( list[i] ))
1491 DestroyWindow( list[i] );
1495 WIN_SetOwner( list[i], 0 );
1497 HeapFree( GetProcessHeap(), 0, list );
1499 if (!got_one) break;
1502 WINPOS_ActivateOtherWindow( hwnd );
1504 if ((owner = GetWindow( hwnd, GW_OWNER )))
1506 WND *ptr = WIN_FindWndPtr( owner );
1509 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1510 WIN_ReleaseWndPtr( ptr );
1515 /* Send destroy messages */
1517 WIN_SendDestroyMsg( hwnd );
1518 if (!IsWindow( hwnd )) return TRUE;
1520 /* Unlink now so we won't bother with the children later on */
1522 WIN_UnlinkWindow( hwnd );
1524 /* Destroy the window storage */
1526 WIN_DestroyWindow( hwnd );
1531 /***********************************************************************
1532 * CloseWindow (USER32.@)
1534 BOOL WINAPI CloseWindow( HWND hwnd )
1536 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1537 ShowWindow( hwnd, SW_MINIMIZE );
1542 /***********************************************************************
1543 * OpenIcon (USER32.@)
1545 BOOL WINAPI OpenIcon( HWND hwnd )
1547 if (!IsIconic( hwnd )) return FALSE;
1548 ShowWindow( hwnd, SW_SHOWNORMAL );
1553 /***********************************************************************
1556 * Implementation of FindWindow() and FindWindowEx().
1558 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1563 WCHAR *buffer = NULL;
1565 if (!parent) parent = GetDesktopWindow();
1568 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1569 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1572 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1576 child = WIN_GetFullHandle( child );
1577 while (list[i] && list[i] != child) i++;
1578 if (!list[i]) goto done;
1579 i++; /* start from next window */
1586 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1593 if (list) HeapFree( GetProcessHeap(), 0, list );
1594 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1600 /***********************************************************************
1601 * FindWindowA (USER32.@)
1603 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1605 HWND ret = FindWindowExA( 0, 0, className, title );
1606 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1611 /***********************************************************************
1612 * FindWindowExA (USER32.@)
1614 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1615 LPCSTR className, LPCSTR title )
1624 /* If the atom doesn't exist, then no class */
1625 /* with this name exists either. */
1626 if (!(atom = GlobalFindAtomA( className )))
1628 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1632 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1634 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1635 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1636 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1637 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1638 HeapFree( GetProcessHeap(), 0, buffer );
1643 /***********************************************************************
1644 * FindWindowExW (USER32.@)
1646 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1647 LPCWSTR className, LPCWSTR title )
1653 /* If the atom doesn't exist, then no class */
1654 /* with this name exists either. */
1655 if (!(atom = GlobalFindAtomW( className )))
1657 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1661 return WIN_FindWindow( parent, child, atom, title );
1665 /***********************************************************************
1666 * FindWindowW (USER32.@)
1668 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1670 return FindWindowExW( 0, 0, className, title );
1674 /**********************************************************************
1675 * GetDesktopWindow (USER32.@)
1677 HWND WINAPI GetDesktopWindow(void)
1679 if (pWndDesktop) return pWndDesktop->hwndSelf;
1680 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" );
1686 /*******************************************************************
1687 * EnableWindow (USER32.@)
1689 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1696 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1697 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1701 TRACE("( %x, %d )\n", hwnd, enable);
1703 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1704 style = wndPtr->dwStyle;
1705 retvalue = ((style & WS_DISABLED) != 0);
1706 WIN_ReleasePtr( wndPtr );
1708 if (enable && retvalue)
1710 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1711 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1713 else if (!enable && !retvalue)
1715 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1717 WIN_SetStyle( hwnd, style | WS_DISABLED );
1719 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1720 SetFocus( 0 ); /* A disabled window can't have the focus */
1722 if (hwnd == GetCapture() || IsChild(hwnd, GetCapture()))
1723 ReleaseCapture(); /* A disabled window can't capture the mouse */
1725 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1731 /***********************************************************************
1732 * IsWindowEnabled (USER32.@)
1734 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1736 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1740 /***********************************************************************
1741 * IsWindowUnicode (USER32.@)
1743 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1748 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1749 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1750 WIN_ReleaseWndPtr(wndPtr);
1755 /**********************************************************************
1756 * GetWindowWord (USER32.@)
1758 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1763 WND *wndPtr = WIN_GetPtr( hwnd );
1766 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1769 if (wndPtr == WND_OTHER_PROCESS)
1771 if (IsWindow( hwnd ))
1772 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1773 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1776 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1778 WARN("Invalid offset %d\n", offset );
1779 SetLastError( ERROR_INVALID_INDEX );
1781 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1782 WIN_ReleasePtr( wndPtr );
1788 case GWL_HWNDPARENT:
1789 return GetWindowLongW( hwnd, offset );
1793 LONG ret = GetWindowLongW( hwnd, offset );
1795 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1799 WARN("Invalid offset %d\n", offset );
1805 /**********************************************************************
1806 * SetWindowWord (USER32.@)
1808 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1817 case GWL_HWNDPARENT:
1818 return SetWindowLongW( hwnd, offset, (UINT)newval );
1822 WARN("Invalid offset %d\n", offset );
1823 SetLastError( ERROR_INVALID_INDEX );
1828 wndPtr = WIN_GetPtr( hwnd );
1829 if (wndPtr == WND_OTHER_PROCESS)
1832 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1833 offset, newval, hwnd );
1838 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1842 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1844 WARN("Invalid offset %d\n", offset );
1845 WIN_ReleasePtr(wndPtr);
1846 SetLastError( ERROR_INVALID_INDEX );
1849 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1852 WIN_ReleasePtr(wndPtr);
1857 /**********************************************************************
1860 * Helper function for GetWindowLong().
1862 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1867 if (offset == GWL_HWNDPARENT) return (LONG)GetParent( hwnd );
1869 if (!(wndPtr = WIN_GetPtr( hwnd )))
1871 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1875 if (wndPtr == WND_OTHER_PROCESS)
1880 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1881 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1884 if (offset == GWL_WNDPROC)
1886 SetLastError( ERROR_ACCESS_DENIED );
1889 SERVER_START_REQ( set_window_info )
1892 req->flags = 0; /* don't set anything, just retrieve */
1893 if (!wine_server_call_err( req ))
1897 case GWL_STYLE: retvalue = reply->old_style; break;
1898 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1899 case GWL_ID: retvalue = reply->old_id; break;
1900 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1901 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1903 SetLastError( ERROR_INVALID_INDEX );
1912 /* now we have a valid wndPtr */
1916 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1919 * Some programs try to access last element from 16 bit
1920 * code using illegal offset value. Hopefully this is
1921 * what those programs really expect.
1923 if (type == WIN_PROC_16 &&
1924 wndPtr->cbWndExtra >= 4 &&
1925 offset == wndPtr->cbWndExtra - sizeof(WORD))
1927 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1929 ERR( "- replaced invalid offset %d with %d\n",
1932 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1933 WIN_ReleasePtr( wndPtr );
1936 WARN("Invalid offset %d\n", offset );
1937 WIN_ReleasePtr( wndPtr );
1938 SetLastError( ERROR_INVALID_INDEX );
1941 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1942 /* Special case for dialog window procedure */
1943 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1944 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1945 WIN_ReleasePtr( wndPtr );
1951 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1952 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1953 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1954 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1955 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1956 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1958 WARN("Unknown offset %d\n", offset );
1959 SetLastError( ERROR_INVALID_INDEX );
1962 WIN_ReleasePtr(wndPtr);
1967 /**********************************************************************
1970 * Helper function for SetWindowLong().
1972 * 0 is the failure code. However, in the case of failure SetLastError
1973 * must be set to distinguish between a 0 return value and a failure.
1975 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1976 WINDOWPROCTYPE type )
1981 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1983 if (!WIN_IsCurrentProcess( hwnd ))
1985 if (offset == GWL_WNDPROC)
1987 SetLastError( ERROR_ACCESS_DENIED );
1990 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1993 wndPtr = WIN_GetPtr( hwnd );
1997 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1998 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
2000 WARN("Invalid offset %d\n", offset );
2001 WIN_ReleasePtr( wndPtr );
2002 SetLastError( ERROR_INVALID_INDEX );
2005 /* Special case for dialog window procedure */
2006 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2008 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2009 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2010 type, WIN_PROC_WINDOW );
2011 WIN_ReleasePtr( wndPtr );
2016 WIN_ReleasePtr( wndPtr );
2023 /* first some special cases */
2028 style.styleOld = wndPtr->dwStyle;
2029 style.styleNew = newval;
2030 WIN_ReleasePtr( wndPtr );
2031 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2032 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2033 newval = style.styleNew;
2035 case GWL_HWNDPARENT:
2036 WIN_ReleasePtr( wndPtr );
2037 return (LONG)SetParent( hwnd, (HWND)newval );
2039 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2040 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2041 type, WIN_PROC_WINDOW );
2042 WIN_ReleasePtr( wndPtr );
2049 WIN_ReleasePtr( wndPtr );
2050 WARN("Invalid offset %d\n", offset );
2051 SetLastError( ERROR_INVALID_INDEX );
2055 SERVER_START_REQ( set_window_info )
2061 req->flags = SET_WIN_STYLE;
2062 req->style = newval;
2065 req->flags = SET_WIN_EXSTYLE;
2066 req->ex_style = newval;
2069 req->flags = SET_WIN_ID;
2073 req->flags = SET_WIN_INSTANCE;
2074 req->instance = (void *)newval;
2077 req->flags = SET_WIN_USERDATA;
2078 req->user_data = (void *)newval;
2081 if ((ok = !wine_server_call_err( req )))
2086 wndPtr->dwStyle = newval;
2087 retval = reply->old_style;
2090 wndPtr->dwExStyle = newval;
2091 retval = reply->old_ex_style;
2094 wndPtr->wIDmenu = newval;
2095 retval = reply->old_id;
2098 wndPtr->hInstance = newval;
2099 retval = (HINSTANCE)reply->old_instance;
2102 wndPtr->userdata = newval;
2103 retval = (ULONG_PTR)reply->old_user_data;
2109 WIN_ReleasePtr( wndPtr );
2113 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2114 USER_Driver.pSetWindowStyle( hwnd, retval );
2116 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2117 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2124 /**********************************************************************
2125 * GetWindowLong (USER.135)
2127 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2129 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2133 /**********************************************************************
2134 * GetWindowLongA (USER32.@)
2136 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2138 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2142 /**********************************************************************
2143 * GetWindowLongW (USER32.@)
2145 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2147 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2151 /**********************************************************************
2152 * SetWindowLong (USER.136)
2154 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2156 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2160 /**********************************************************************
2161 * SetWindowLongA (USER32.@)
2163 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2165 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2169 /**********************************************************************
2170 * SetWindowLongW (USER32.@) Set window attribute
2172 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2173 * value in a window's extra memory.
2175 * The _hwnd_ parameter specifies the window. is the handle to a
2176 * window that has extra memory. The _newval_ parameter contains the
2177 * new attribute or extra memory value. If positive, the _offset_
2178 * parameter is the byte-addressed location in the window's extra
2179 * memory to set. If negative, _offset_ specifies the window
2180 * attribute to set, and should be one of the following values:
2182 * GWL_EXSTYLE The window's extended window style
2184 * GWL_STYLE The window's window style.
2186 * GWL_WNDPROC Pointer to the window's window procedure.
2188 * GWL_HINSTANCE The window's pplication instance handle.
2190 * GWL_ID The window's identifier.
2192 * GWL_USERDATA The window's user-specified data.
2194 * If the window is a dialog box, the _offset_ parameter can be one of
2195 * the following values:
2197 * DWL_DLGPROC The address of the window's dialog box procedure.
2199 * DWL_MSGRESULT The return value of a message
2200 * that the dialog box procedure processed.
2202 * DWL_USER Application specific information.
2206 * If successful, returns the previous value located at _offset_. Otherwise,
2211 * Extra memory for a window class is specified by a nonzero cbWndExtra
2212 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2213 * time of class creation.
2215 * Using GWL_WNDPROC to set a new window procedure effectively creates
2216 * a window subclass. Use CallWindowProc() in the new windows procedure
2217 * to pass messages to the superclass's window procedure.
2219 * The user data is reserved for use by the application which created
2222 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2223 * instead, call the EnableWindow() function to change the window's
2226 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2227 * SetParent() instead.
2230 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2231 * it sends WM_STYLECHANGING before changing the settings
2232 * and WM_STYLECHANGED afterwards.
2233 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2235 LONG WINAPI SetWindowLongW(
2236 HWND hwnd, /* [in] window to alter */
2237 INT offset, /* [in] offset, in bytes, of location to alter */
2238 LONG newval /* [in] new value of location */
2240 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2244 /*******************************************************************
2245 * GetWindowTextA (USER32.@)
2247 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2251 if (WIN_IsCurrentProcess( hwnd ))
2252 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2254 /* when window belongs to other process, don't send a message */
2255 if (nMaxCount <= 0) return 0;
2256 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2257 get_server_window_text( hwnd, buffer, nMaxCount );
2258 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2259 lpString[nMaxCount-1] = 0;
2260 HeapFree( GetProcessHeap(), 0, buffer );
2261 return strlen(lpString);
2265 /*******************************************************************
2266 * InternalGetWindowText (USER32.@)
2268 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2272 if (nMaxCount <= 0) return 0;
2273 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2274 if (win != WND_OTHER_PROCESS)
2276 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2277 else lpString[0] = 0;
2278 WIN_ReleasePtr( win );
2282 get_server_window_text( hwnd, lpString, nMaxCount );
2284 return strlenW(lpString);
2288 /*******************************************************************
2289 * GetWindowTextW (USER32.@)
2291 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2293 if (WIN_IsCurrentProcess( hwnd ))
2294 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2296 /* when window belongs to other process, don't send a message */
2297 if (nMaxCount <= 0) return 0;
2298 get_server_window_text( hwnd, lpString, nMaxCount );
2299 return strlenW(lpString);
2303 /*******************************************************************
2304 * SetWindowText (USER32.@)
2305 * SetWindowTextA (USER32.@)
2307 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2309 if (!WIN_IsCurrentProcess( hwnd ))
2311 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2312 SetLastError( ERROR_ACCESS_DENIED );
2315 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2319 /*******************************************************************
2320 * SetWindowTextW (USER32.@)
2322 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2324 if (!WIN_IsCurrentProcess( hwnd ))
2326 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2327 SetLastError( ERROR_ACCESS_DENIED );
2330 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2334 /*******************************************************************
2335 * GetWindowTextLengthA (USER32.@)
2337 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2339 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2342 /*******************************************************************
2343 * GetWindowTextLengthW (USER32.@)
2345 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2347 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2351 /*******************************************************************
2352 * IsWindow (USER32.@)
2354 BOOL WINAPI IsWindow( HWND hwnd )
2359 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2361 if (ptr != WND_OTHER_PROCESS)
2363 WIN_ReleasePtr( ptr );
2367 /* check other processes */
2368 SERVER_START_REQ( get_window_info )
2371 ret = !wine_server_call_err( req );
2378 /***********************************************************************
2379 * GetWindowThreadProcessId (USER32.@)
2381 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2386 if (!(ptr = WIN_GetPtr( hwnd )))
2388 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2392 if (ptr != WND_OTHER_PROCESS)
2394 /* got a valid window */
2396 if (process) *process = GetCurrentProcessId();
2397 WIN_ReleasePtr( ptr );
2401 /* check other processes */
2402 SERVER_START_REQ( get_window_info )
2405 if (!wine_server_call_err( req ))
2407 tid = (DWORD)reply->tid;
2408 if (process) *process = (DWORD)reply->pid;
2416 /*****************************************************************
2417 * GetParent (USER32.@)
2419 HWND WINAPI GetParent( HWND hwnd )
2424 if (!(wndPtr = WIN_GetPtr( hwnd )))
2426 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2429 if (wndPtr == WND_OTHER_PROCESS)
2431 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2432 if (style & (WS_POPUP | WS_CHILD))
2434 SERVER_START_REQ( get_window_tree )
2437 if (!wine_server_call_err( req ))
2439 if (style & WS_CHILD) retvalue = reply->parent;
2440 else retvalue = reply->owner;
2448 if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2449 else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2450 WIN_ReleasePtr( wndPtr );
2456 /*****************************************************************
2457 * GetAncestor (USER32.@)
2459 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2462 HWND *list, ret = 0;
2464 if (type == GA_PARENT)
2466 if (!(win = WIN_GetPtr( hwnd )))
2468 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2471 if (win != WND_OTHER_PROCESS)
2474 WIN_ReleasePtr( win );
2476 else /* need to query the server */
2478 SERVER_START_REQ( get_window_tree )
2481 if (!wine_server_call_err( req )) ret = reply->parent;
2488 if (!(list = WIN_ListParents( hwnd ))) return 0;
2490 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2494 while (list[count]) count++;
2495 ret = list[count - 2]; /* get the one before the desktop */
2497 HeapFree( GetProcessHeap(), 0, list );
2499 if (ret && type == GA_ROOTOWNER)
2503 HWND owner = GetWindow( ret, GW_OWNER );
2512 /*****************************************************************
2513 * SetParent (USER32.@)
2515 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2518 HWND retvalue, full_handle;
2521 if (!parent) parent = GetDesktopWindow();
2522 else parent = WIN_GetFullHandle( parent );
2524 if (!IsWindow( parent ))
2526 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2530 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2531 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2535 if (USER_Driver.pSetParent)
2536 return USER_Driver.pSetParent( hwnd, parent );
2538 /* Windows hides the window first, then shows it again
2539 * including the WM_SHOWWINDOW messages and all */
2540 was_visible = ShowWindow( hwnd, SW_HIDE );
2542 if (!IsWindow( parent )) return 0;
2543 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2545 retvalue = wndPtr->parent; /* old parent */
2546 if (parent != retvalue)
2548 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2550 if (parent != GetDesktopWindow()) /* a child window */
2552 if (!(wndPtr->dwStyle & WS_CHILD))
2554 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2555 if (menu) DestroyMenu( menu );
2559 WIN_ReleasePtr( wndPtr );
2561 /* SetParent additionally needs to make hwnd the topmost window
2562 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2563 WM_WINDOWPOSCHANGED notification messages.
2565 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2566 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2567 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2568 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2573 /*******************************************************************
2574 * IsChild (USER32.@)
2576 BOOL WINAPI IsChild( HWND parent, HWND child )
2578 HWND *list = WIN_ListParents( child );
2582 if (!list) return FALSE;
2583 parent = WIN_GetFullHandle( parent );
2584 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2585 ret = (list[i] != 0);
2586 HeapFree( GetProcessHeap(), 0, list );
2591 /***********************************************************************
2592 * IsWindowVisible (USER32.@)
2594 BOOL WINAPI IsWindowVisible( HWND hwnd )
2600 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2601 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2602 for (i = 0; list[i]; i++)
2603 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2605 HeapFree( GetProcessHeap(), 0, list );
2610 /***********************************************************************
2611 * WIN_IsWindowDrawable
2613 * hwnd is drawable when it is visible, all parents are not
2614 * minimized, and it is itself not minimized unless we are
2615 * trying to draw its default class icon.
2617 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2622 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2624 if (!(style & WS_VISIBLE)) return FALSE;
2625 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2627 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2628 for (i = 0; list[i]; i++)
2629 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2632 HeapFree( GetProcessHeap(), 0, list );
2637 /*******************************************************************
2638 * GetTopWindow (USER32.@)
2640 HWND WINAPI GetTopWindow( HWND hwnd )
2642 if (!hwnd) hwnd = GetDesktopWindow();
2643 return GetWindow( hwnd, GW_CHILD );
2647 /*******************************************************************
2648 * GetWindow (USER32.@)
2650 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2654 if (rel == GW_OWNER) /* this one may be available locally */
2656 WND *wndPtr = WIN_GetPtr( hwnd );
2659 SetLastError( ERROR_INVALID_HANDLE );
2662 if (wndPtr != WND_OTHER_PROCESS)
2664 retval = wndPtr->owner;
2665 WIN_ReleasePtr( wndPtr );
2668 /* else fall through to server call */
2671 SERVER_START_REQ( get_window_tree )
2674 if (!wine_server_call_err( req ))
2679 retval = reply->first_sibling;
2682 retval = reply->last_sibling;
2685 retval = reply->next_sibling;
2688 retval = reply->prev_sibling;
2691 retval = reply->owner;
2694 retval = reply->first_child;
2704 /***********************************************************************
2705 * WIN_InternalShowOwnedPopups
2707 * Internal version of ShowOwnedPopups; Wine functions should use this
2708 * to avoid interfering with application calls to ShowOwnedPopups
2709 * and to make sure the application can't prevent showing/hiding.
2711 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2715 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2719 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2721 if (!win_array) return TRUE;
2724 * Show windows Lowest first, Highest last to preserve Z-Order
2726 while (win_array[count]) count++;
2727 while (--count >= 0)
2729 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2730 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2732 if (pWnd->dwStyle & WS_POPUP)
2736 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2737 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2740 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2742 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2743 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2748 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2749 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2750 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2753 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2755 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2756 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2757 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2761 WIN_ReleaseWndPtr( pWnd );
2763 HeapFree( GetProcessHeap(), 0, win_array );
2768 /*******************************************************************
2769 * ShowOwnedPopups (USER32.@)
2771 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2775 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2777 if (!win_array) return TRUE;
2779 while (win_array[count]) count++;
2780 while (--count >= 0)
2782 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2783 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2785 if (pWnd->dwStyle & WS_POPUP)
2789 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2791 /* In Windows, ShowOwnedPopups(TRUE) generates
2792 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2793 * regardless of the state of the owner
2795 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2796 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2801 if (IsWindowVisible(pWnd->hwndSelf))
2803 /* In Windows, ShowOwnedPopups(FALSE) generates
2804 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2805 * regardless of the state of the owner
2807 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2808 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2812 WIN_ReleaseWndPtr( pWnd );
2814 HeapFree( GetProcessHeap(), 0, win_array );
2819 /*******************************************************************
2820 * GetLastActivePopup (USER32.@)
2822 HWND WINAPI GetLastActivePopup( HWND hwnd )
2825 WND *wndPtr =WIN_FindWndPtr(hwnd);
2826 if (!wndPtr) return hwnd;
2827 retval = wndPtr->hwndLastActive;
2828 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2829 WIN_ReleaseWndPtr(wndPtr);
2834 /*******************************************************************
2837 * Build an array of all parents of a given window, starting with
2838 * the immediate parent. The array must be freed with HeapFree.
2839 * Returns NULL if window is a top-level window.
2841 HWND *WIN_ListParents( HWND hwnd )
2844 HWND current, *list;
2845 int pos = 0, size = 16, count = 0;
2847 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2852 if (!(win = WIN_GetPtr( current ))) goto empty;
2853 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2854 list[pos] = win->parent;
2855 WIN_ReleasePtr( win );
2856 if (!(current = list[pos]))
2858 if (!pos) goto empty;
2861 if (++pos == size - 1)
2863 /* need to grow the list */
2864 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2865 if (!new_list) goto empty;
2871 /* at least one parent belongs to another process, have to query the server */
2876 SERVER_START_REQ( get_window_parents )
2879 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2880 if (!wine_server_call( req )) count = reply->count;
2883 if (!count) goto empty;
2889 HeapFree( GetProcessHeap(), 0, list );
2891 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2895 HeapFree( GetProcessHeap(), 0, list );
2900 /*******************************************************************
2903 * Build an array of the children of a given window. The array must be
2904 * freed with HeapFree. Returns NULL when no windows are found.
2906 HWND *WIN_ListChildren( HWND hwnd )
2908 return list_window_children( hwnd, 0, 0 );
2912 /*******************************************************************
2913 * EnumWindows (USER32.@)
2915 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2921 /* We have to build a list of all windows first, to avoid */
2922 /* unpleasant side-effects, for instance if the callback */
2923 /* function changes the Z-order of the windows. */
2925 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2927 /* Now call the callback function for every window */
2929 iWndsLocks = WIN_SuspendWndsLock();
2930 for (i = 0; list[i]; i++)
2932 /* Make sure that the window still exists */
2933 if (!IsWindow( list[i] )) continue;
2934 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2936 WIN_RestoreWndsLock(iWndsLocks);
2937 HeapFree( GetProcessHeap(), 0, list );
2942 /**********************************************************************
2943 * EnumThreadWindows (USER32.@)
2945 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2950 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2953 /* Now call the callback function for every window */
2955 iWndsLocks = WIN_SuspendWndsLock();
2956 for (i = 0; list[i]; i++)
2957 if (!func( list[i], lParam )) break;
2958 WIN_RestoreWndsLock(iWndsLocks);
2959 HeapFree( GetProcessHeap(), 0, list );
2964 /**********************************************************************
2965 * WIN_EnumChildWindows
2967 * Helper function for EnumChildWindows().
2969 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2974 for ( ; *list; list++)
2976 /* Make sure that the window still exists */
2977 if (!IsWindow( *list )) continue;
2978 /* skip owned windows */
2979 if (GetWindow( *list, GW_OWNER )) continue;
2980 /* Build children list first */
2981 childList = WIN_ListChildren( *list );
2983 ret = func( *list, lParam );
2987 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2988 HeapFree( GetProcessHeap(), 0, childList );
2990 if (!ret) return FALSE;
2996 /**********************************************************************
2997 * EnumChildWindows (USER32.@)
2999 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3004 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3005 iWndsLocks = WIN_SuspendWndsLock();
3006 WIN_EnumChildWindows( list, func, lParam );
3007 WIN_RestoreWndsLock(iWndsLocks);
3008 HeapFree( GetProcessHeap(), 0, list );
3013 /*******************************************************************
3014 * AnyPopup (USER.52)
3016 BOOL16 WINAPI AnyPopup16(void)
3022 /*******************************************************************
3023 * AnyPopup (USER32.@)
3025 BOOL WINAPI AnyPopup(void)
3029 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3031 if (!list) return FALSE;
3032 for (i = 0; list[i]; i++)
3034 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3036 retvalue = (list[i] != 0);
3037 HeapFree( GetProcessHeap(), 0, list );
3042 /*******************************************************************
3043 * FlashWindow (USER32.@)
3045 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3047 WND *wndPtr = WIN_FindWndPtr(hWnd);
3049 TRACE("%04x\n", hWnd);
3051 if (!wndPtr) return FALSE;
3052 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3054 if (wndPtr->dwStyle & WS_MINIMIZE)
3056 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3058 HDC hDC = GetDC(hWnd);
3060 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3061 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3063 ReleaseDC( hWnd, hDC );
3064 wndPtr->flags |= WIN_NCACTIVATED;
3068 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3069 wndPtr->flags &= ~WIN_NCACTIVATED;
3071 WIN_ReleaseWndPtr(wndPtr);
3077 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3078 else wparam = (hWnd == GetActiveWindow());
3080 WIN_ReleaseWndPtr(wndPtr);
3081 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3087 /*******************************************************************
3088 * GetWindowContextHelpId (USER32.@)
3090 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3093 WND *wnd = WIN_FindWndPtr( hwnd );
3095 retval = wnd->helpContext;
3096 WIN_ReleaseWndPtr(wnd);
3101 /*******************************************************************
3102 * SetWindowContextHelpId (USER32.@)
3104 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3106 WND *wnd = WIN_FindWndPtr( hwnd );
3107 if (!wnd) return FALSE;
3108 wnd->helpContext = id;
3109 WIN_ReleaseWndPtr(wnd);
3114 /*******************************************************************
3117 * recursively find a child that contains spDragInfo->pt point
3118 * and send WM_QUERYDROPOBJECT
3120 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3122 BOOL16 wParam, bResult = 0;
3124 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3127 if (!ptrDragInfo) return FALSE;
3129 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3131 GetWindowRect(hQueryWnd,&tempRect);
3133 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3135 if (!IsIconic( hQueryWnd ))
3137 GetClientRect( hQueryWnd, &tempRect );
3138 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3140 if (PtInRect( &tempRect, pt))
3143 HWND *list = WIN_ListChildren( hQueryWnd );
3149 for (i = 0; list[i]; i++)
3151 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3153 GetWindowRect( list[i], &tempRect );
3154 if (PtInRect( &tempRect, pt )) break;
3159 if (IsWindowEnabled( list[i] ))
3160 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
3162 HeapFree( GetProcessHeap(), 0, list );
3164 if(bResult) return bResult;
3170 ScreenToClient16(HWND_16(hQueryWnd),&ptrDragInfo->pt);
3172 ptrDragInfo->hScope = HWND_16(hQueryWnd);
3174 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3175 else bResult = SendMessage16( HWND_16(hQueryWnd), WM_QUERYDROPOBJECT,
3176 (WPARAM16)wParam, spDragInfo );
3178 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3184 /*******************************************************************
3185 * DragDetect (USER32.@)
3187 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3192 rect.left = pt.x - wDragWidth;
3193 rect.right = pt.x + wDragWidth;
3195 rect.top = pt.y - wDragHeight;
3196 rect.bottom = pt.y + wDragHeight;
3202 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3204 if( msg.message == WM_LBUTTONUP )
3209 if( msg.message == WM_MOUSEMOVE )
3212 tmp.x = LOWORD(msg.lParam);
3213 tmp.y = HIWORD(msg.lParam);
3214 if( !PtInRect( &rect, tmp ))
3226 /******************************************************************************
3227 * DragObject (USER.464)
3229 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3230 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3233 LPDRAGINFO16 lpDragInfo;
3235 HCURSOR16 hOldCursor=0, hBummer=0;
3236 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3237 HCURSOR16 hCurrentCursor = 0;
3238 HWND16 hCurrentWnd = 0;
3240 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3241 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3243 if( !lpDragInfo || !spDragInfo ) return 0L;
3245 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3247 GlobalFree16(hDragInfo);
3251 if(hCursor) hOldCursor = SetCursor(hCursor);
3253 lpDragInfo->hWnd = hWnd;
3254 lpDragInfo->hScope = 0;
3255 lpDragInfo->wFlags = wObj;
3256 lpDragInfo->hList = szList; /* near pointer! */
3257 lpDragInfo->hOfStruct = hOfStruct;
3260 SetCapture(WIN_Handle32(hWnd));
3265 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3267 *(lpDragInfo+1) = *lpDragInfo;
3269 lpDragInfo->pt.x = msg.pt.x;
3270 lpDragInfo->pt.y = msg.pt.y;
3272 /* update DRAGINFO struct */
3273 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3275 if( DRAG_QueryUpdate(WIN_Handle32(hwndScope), spDragInfo, FALSE) > 0 )
3276 hCurrentCursor = hCursor;
3279 hCurrentCursor = hBummer;
3280 lpDragInfo->hScope = 0;
3282 if( hCurrentCursor )
3283 SetCursor(hCurrentCursor);
3285 /* send WM_DRAGLOOP */
3286 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3287 (LPARAM) spDragInfo );
3288 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3289 if( hCurrentWnd != lpDragInfo->hScope )
3292 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3293 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3294 HIWORD(spDragInfo)) );
3295 hCurrentWnd = lpDragInfo->hScope;
3297 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3301 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3303 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3306 ShowCursor( FALSE );
3308 if( hCursor ) SetCursor( hOldCursor );
3310 if( hCurrentCursor != hBummer )
3311 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3312 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3315 GlobalFree16(hDragInfo);
3317 return (DWORD)(msg.lParam);
3321 /******************************************************************************
3322 * GetWindowModuleFileNameA (USER32.@)
3324 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3326 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3327 hwnd, lpszFileName, cchFileNameMax);
3331 /******************************************************************************
3332 * GetWindowModuleFileNameW (USER32.@)
3334 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3336 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3337 hwnd, lpszFileName, cchFileNameMax);
3341 /******************************************************************************
3342 * GetWindowInfo (USER32.@)
3345 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3346 * this may be because this structure changed over time. If this is the
3347 * the case, then please: FIXME.
3348 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3350 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3352 WND *wndInfo = NULL;
3353 if (!pwi) return FALSE;
3354 if (pwi->cbSize != sizeof(WINDOWINFO))
3356 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3359 wndInfo = WIN_GetPtr(hwnd);
3360 if (!wndInfo) return FALSE;
3361 if (wndInfo == WND_OTHER_PROCESS)
3363 FIXME("window belong to other process\n");
3367 pwi->rcWindow = wndInfo->rectWindow;
3368 pwi->rcClient = wndInfo->rectClient;
3369 pwi->dwStyle = wndInfo->dwStyle;
3370 pwi->dwExStyle = wndInfo->dwExStyle;
3371 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3372 /* if active WS_ACTIVECAPTION, else 0 */
3374 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3375 GetSystemMetrics(SM_CXBORDER) : 0);
3376 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3377 GetSystemMetrics(SM_CYBORDER) : 0);
3378 /* above two: I'm presuming that borders widths are the same
3379 * for each window - so long as its actually using a border.. */
3381 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3382 pwi->wCreatorVersion = GetVersion();
3383 /* Docs say this should be the version that
3384 * CREATED the window. But eh?.. Isn't that just the
3385 * version we are running.. Unless ofcourse its some wacky
3386 * RPC stuff or something */
3388 WIN_ReleasePtr(wndInfo);