2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "wine/server.h"
14 #include "wine/unicode.h"
20 #include "cursoricon.h"
27 #include "stackframe.h"
28 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(win);
31 DECLARE_DEBUG_CHANNEL(msg);
33 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
35 /**********************************************************************/
38 static WND *pWndDesktop = NULL;
40 static WORD wDragWidth = 4;
41 static WORD wDragHeight= 3;
43 static void *user_handles[NB_USER_HANDLES];
46 extern SYSLEVEL USER_SysLevel; /* FIXME */
48 /***********************************************************************
51 * Suspend the lock on WND structures.
52 * Returns the number of locks suspended
54 int WIN_SuspendWndsLock( void )
56 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
57 int count = isuspendedLocks;
60 _LeaveSysLevel( &USER_SysLevel );
62 return isuspendedLocks;
65 /***********************************************************************
68 * Restore the suspended locks on WND structures
70 void WIN_RestoreWndsLock( int ipreviousLocks )
72 while ( ipreviousLocks-- > 0 )
73 _EnterSysLevel( &USER_SysLevel );
76 /***********************************************************************
77 * create_window_handle
79 * Create a window handle with the server.
81 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
84 user_handle_t handle = 0;
86 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
88 if (!win) return NULL;
92 SERVER_START_REQ( create_window )
97 if ((res = !SERVER_CALL_ERR())) handle = req->handle;
104 HeapFree( GetProcessHeap(), 0, win );
107 index = LOWORD(handle) - FIRST_USER_HANDLE;
108 assert( index < NB_USER_HANDLES );
109 user_handles[index] = win;
110 win->hwndSelf = handle;
111 win->dwMagic = WND_MAGIC;
117 /***********************************************************************
120 * Free a window handle.
122 static WND *free_window_handle( HWND hwnd )
125 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
127 if (index >= NB_USER_HANDLES) return NULL;
129 if ((ptr = user_handles[index]))
131 SERVER_START_REQ( destroy_window )
134 if (!SERVER_CALL_ERR())
135 user_handles[index] = NULL;
142 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
147 /*******************************************************************
148 * list_window_children
150 * Build an array of the children of a given window. The array must be
151 * freed with HeapFree. Returns NULL when no windows are found.
153 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
157 SERVER_START_VAR_REQ( get_window_children, REQUEST_MAX_VAR_SIZE )
161 req->tid = (void *)tid;
164 user_handle_t *data = server_data_ptr(req);
165 int i, count = server_data_size(req) / sizeof(*data);
166 if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) ))))
168 for (i = 0; i < count; i++) list[i] = data[i];
178 /*******************************************************************
181 static void send_parent_notify( HWND hwnd, UINT msg )
183 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
184 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
185 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
186 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
190 /***********************************************************************
193 * Return a pointer to the WND structure if local to the process,
194 * or WND_OTHER_PROCESS is handle may be valid in other process.
195 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
197 WND *WIN_GetPtr( HWND hwnd )
200 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
202 if (index >= NB_USER_HANDLES) return NULL;
205 if ((ptr = user_handles[index]))
207 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
211 else ptr = WND_OTHER_PROCESS;
217 /***********************************************************************
218 * WIN_IsCurrentProcess
220 * Check whether a given window belongs to the current process (and return the full handle).
222 HWND WIN_IsCurrentProcess( HWND hwnd )
227 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
229 WIN_ReleasePtr( ptr );
234 /***********************************************************************
235 * WIN_IsCurrentThread
237 * Check whether a given window belongs to the current thread (and return the full handle).
239 HWND WIN_IsCurrentThread( HWND hwnd )
244 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
246 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
247 WIN_ReleasePtr( ptr );
253 /***********************************************************************
256 * Convert a 16-bit window handle to a full 32-bit handle.
258 HWND WIN_Handle32( HWND16 hwnd16 )
261 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
263 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
264 /* do sign extension for -2 and -3 */
265 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
267 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
269 if (ptr != WND_OTHER_PROCESS)
271 hwnd = ptr->hwndSelf;
272 WIN_ReleasePtr( ptr );
274 else /* may belong to another process */
276 SERVER_START_REQ( get_window_info )
279 if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
287 /***********************************************************************
290 * Return a pointer to the WND structure corresponding to a HWND.
292 WND * WIN_FindWndPtr( HWND hwnd )
296 if (!hwnd) return NULL;
298 if ((ptr = WIN_GetPtr( hwnd )))
300 if (ptr != WND_OTHER_PROCESS)
302 /* increment destruction monitoring */
306 if (IsWindow( hwnd )) /* check other processes */
308 ERR( "window %04x belongs to other process\n", hwnd );
309 /* DbgBreakPoint(); */
312 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
317 /***********************************************************************
320 * Release the pointer to the WND structure.
322 void WIN_ReleaseWndPtr(WND *wndPtr)
326 /* Decrement destruction monitoring value */
328 /* Check if it's time to release the memory */
329 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
332 free_window_handle( wndPtr->hwndSelf );
334 else if(wndPtr->irefCount < 0)
336 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
337 ERR("forgot a Lock on %p somewhere\n",wndPtr);
339 /* unlock all WND structures for thread safeness */
344 /***********************************************************************
347 * Remove a window from the siblings linked list.
349 void WIN_UnlinkWindow( HWND hwnd )
351 WIN_LinkWindow( hwnd, 0, 0 );
355 /***********************************************************************
358 * Insert a window into the siblings linked list.
359 * The window is inserted after the specified window, which can also
360 * be specified as HWND_TOP or HWND_BOTTOM.
361 * If parent is 0, window is unlinked from the tree.
363 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
365 WND *wndPtr = WIN_GetPtr( hwnd );
368 if (wndPtr == WND_OTHER_PROCESS)
370 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
374 SERVER_START_REQ( link_window )
377 req->parent = parent;
378 req->previous = hwndInsertAfter;
381 if (req->full_parent && req->full_parent != wndPtr->parent)
383 wndPtr->owner = 0; /* reset owner when changing parent */
384 wndPtr->parent = req->full_parent;
390 WIN_ReleasePtr( wndPtr );
394 /***********************************************************************
397 * Change the owner of a window.
399 void WIN_SetOwner( HWND hwnd, HWND owner )
401 WND *win = WIN_GetPtr( hwnd );
404 if (win == WND_OTHER_PROCESS)
406 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
409 SERVER_START_REQ( set_window_owner )
413 if (!SERVER_CALL()) win->owner = req->full_owner;
416 WIN_ReleasePtr( win );
420 /***********************************************************************
423 * Change the style of a window.
425 LONG WIN_SetStyle( HWND hwnd, LONG style )
429 WND *win = WIN_GetPtr( hwnd );
432 if (win == WND_OTHER_PROCESS)
435 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
438 if (style == win->dwStyle)
440 WIN_ReleasePtr( win );
443 SERVER_START_REQ( set_window_info )
446 req->flags = SET_WIN_STYLE;
448 if ((ok = !SERVER_CALL()))
450 ret = req->old_style;
451 win->dwStyle = style;
455 WIN_ReleasePtr( win );
456 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
461 /***********************************************************************
464 * Change the extended style of a window.
466 LONG WIN_SetExStyle( HWND hwnd, LONG style )
469 WND *win = WIN_GetPtr( hwnd );
472 if (win == WND_OTHER_PROCESS)
475 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
478 if (style == win->dwExStyle)
480 WIN_ReleasePtr( win );
483 SERVER_START_REQ( set_window_info )
486 req->flags = SET_WIN_EXSTYLE;
487 req->ex_style = style;
490 ret = req->old_ex_style;
491 win->dwExStyle = style;
495 WIN_ReleasePtr( win );
500 /***********************************************************************
503 * Set the window and client rectangles.
505 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
507 WND *win = WIN_GetPtr( hwnd );
511 if (win == WND_OTHER_PROCESS)
513 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
516 SERVER_START_REQ( set_window_rectangles )
519 req->window.left = rectWindow->left;
520 req->window.top = rectWindow->top;
521 req->window.right = rectWindow->right;
522 req->window.bottom = rectWindow->bottom;
523 req->client.left = rectClient->left;
524 req->client.top = rectClient->top;
525 req->client.right = rectClient->right;
526 req->client.bottom = rectClient->bottom;
527 ret = !SERVER_CALL();
532 win->rectWindow = *rectWindow;
533 win->rectClient = *rectClient;
535 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
536 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
537 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
539 WIN_ReleasePtr( win );
543 /***********************************************************************
544 * find_child_to_repaint
546 * Find a window that needs repaint among the children of the specified window.
548 static HWND find_child_to_repaint( HWND parent )
554 if (!parent) parent = GetDesktopWindow();
555 if (!(list = list_window_children( parent, 0, 0 ))) return 0;
557 for (i = 0; list[i] && !ret; i++)
559 WND *win = WIN_GetPtr( list[i] );
560 if (!win) continue; /* ignore it */
561 if (win == WND_OTHER_PROCESS)
563 /* doesn't belong to this process, but check children */
564 ret = find_child_to_repaint( list[i] );
567 if (!(win->dwStyle & WS_VISIBLE))
569 WIN_ReleasePtr( win );
572 if ((win->tid != GetCurrentThreadId()) ||
573 (!win->hrgnUpdate && !(win->flags & WIN_INTERNAL_PAINT)))
575 /* does not need repaint, check children */
576 WIN_ReleasePtr( win );
577 ret = find_child_to_repaint( list[i] );
581 /* now we have something */
583 if (!(win->dwExStyle & WS_EX_TRANSPARENT))
585 /* not transparent, we can repaint it */
586 WIN_ReleasePtr( win );
589 WIN_ReleasePtr( win );
591 /* transparent window, look for non-transparent sibling to paint first */
592 for (i++; list[i]; i++)
594 if (!(win = WIN_GetPtr( list[i] ))) continue;
595 if (win == WND_OTHER_PROCESS) continue;
596 if (!(win->dwStyle & WS_VISIBLE))
598 WIN_ReleasePtr( win );
601 if (!(win->dwExStyle & WS_EX_TRANSPARENT) &&
602 (win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
605 WIN_ReleasePtr( win );
608 WIN_ReleasePtr( win );
611 HeapFree( GetProcessHeap(), 0, list );
616 /***********************************************************************
617 * WIN_FindWinToRepaint
619 * Find a window that needs repaint.
621 HWND WIN_FindWinToRepaint( HWND hwnd )
623 /* Note: the desktop window never gets WM_PAINT messages
624 * The real reason why is because Windows DesktopWndProc
625 * does ValidateRgn inside WM_ERASEBKGND handler.
627 if (hwnd == GetDesktopWindow()) hwnd = 0;
631 /* check the window itself first */
632 WND *win = WIN_FindWndPtr( hwnd );
634 if ((win->dwStyle & WS_VISIBLE) &&
635 (win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
637 WIN_ReleaseWndPtr( win );
640 WIN_ReleaseWndPtr( win );
642 /* now check its children */
643 return find_child_to_repaint( hwnd );
647 /***********************************************************************
650 * Destroy storage associated to a window. "Internals" p.358
652 LRESULT WIN_DestroyWindow( HWND hwnd )
657 TRACE("%04x\n", hwnd );
659 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
661 ERR( "window doesn't belong to current thread\n" );
665 /* free child windows */
666 if ((list = WIN_ListChildren( hwnd )))
669 for (i = 0; list[i]; i++)
671 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
672 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
674 HeapFree( GetProcessHeap(), 0, list );
678 * Clear the update region to make sure no WM_PAINT messages will be
679 * generated for this window while processing the WM_NCDESTROY.
681 RedrawWindow( hwnd, NULL, 0,
682 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
685 * Send the WM_NCDESTROY to the window being destroyed.
687 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
689 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
691 WINPOS_CheckInternalPos( hwnd );
692 if( hwnd == GetCapture()) ReleaseCapture();
694 /* free resources associated with the window */
696 TIMER_RemoveWindowTimers( hwnd );
698 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
699 wndPtr->hmemTaskQ = 0;
701 if (!(wndPtr->dwStyle & WS_CHILD))
703 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
704 if (menu) DestroyMenu( menu );
706 if (wndPtr->hSysMenu)
708 DestroyMenu( wndPtr->hSysMenu );
709 wndPtr->hSysMenu = 0;
711 USER_Driver.pDestroyWindow( hwnd );
712 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
713 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
714 CLASS_RemoveWindow( wndPtr->class );
715 wndPtr->class = NULL;
716 wndPtr->dwMagic = 0; /* Mark it as invalid */
717 WIN_ReleaseWndPtr( wndPtr );
721 /***********************************************************************
722 * WIN_DestroyThreadWindows
724 * Destroy all children of 'wnd' owned by the current thread.
725 * Return TRUE if something was done.
727 void WIN_DestroyThreadWindows( HWND hwnd )
732 if (!(list = WIN_ListChildren( hwnd ))) return;
733 for (i = 0; list[i]; i++)
735 if (WIN_IsCurrentThread( list[i] ))
736 DestroyWindow( list[i] );
738 WIN_DestroyThreadWindows( list[i] );
740 HeapFree( GetProcessHeap(), 0, list );
743 /***********************************************************************
744 * WIN_CreateDesktopWindow
746 * Create the desktop window.
748 BOOL WIN_CreateDesktopWindow(void)
750 struct tagCLASS *class;
759 TRACE("Creating desktop window\n");
761 if (!WINPOS_CreateInternalPosAtom() ||
762 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
763 &wndExtra, &winproc, &clsStyle, &dce )))
766 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
767 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
768 if (!pWndDesktop) return FALSE;
769 hwndDesktop = pWndDesktop->hwndSelf;
771 pWndDesktop->tid = 0; /* nobody owns the desktop */
772 pWndDesktop->parent = 0;
773 pWndDesktop->owner = 0;
774 pWndDesktop->class = class;
775 pWndDesktop->hInstance = 0;
776 pWndDesktop->text = NULL;
777 pWndDesktop->hmemTaskQ = 0;
778 pWndDesktop->hrgnUpdate = 0;
779 pWndDesktop->hwndLastActive = hwndDesktop;
780 pWndDesktop->dwStyle = 0;
781 pWndDesktop->dwExStyle = 0;
782 pWndDesktop->clsStyle = clsStyle;
783 pWndDesktop->dce = NULL;
784 pWndDesktop->pVScroll = NULL;
785 pWndDesktop->pHScroll = NULL;
786 pWndDesktop->wIDmenu = 0;
787 pWndDesktop->helpContext = 0;
788 pWndDesktop->flags = 0;
789 pWndDesktop->hSysMenu = 0;
790 pWndDesktop->userdata = 0;
791 pWndDesktop->winproc = winproc;
792 pWndDesktop->cbWndExtra = wndExtra;
794 cs.lpCreateParams = NULL;
800 cs.cx = GetSystemMetrics( SM_CXSCREEN );
801 cs.cy = GetSystemMetrics( SM_CYSCREEN );
802 cs.style = pWndDesktop->dwStyle;
803 cs.dwExStyle = pWndDesktop->dwExStyle;
805 cs.lpszClass = DESKTOP_CLASS_ATOM;
807 SetRect( &rect, 0, 0, cs.cx, cs.cy );
808 WIN_SetRectangles( hwndDesktop, &rect, &rect );
809 WIN_SetStyle( hwndDesktop, WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
811 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
813 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
814 WIN_ReleaseWndPtr( pWndDesktop );
819 /***********************************************************************
822 * Fix the coordinates - Helper for WIN_CreateWindowEx.
823 * returns default show mode in sw.
824 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
826 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
828 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
829 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
831 if (cs->style & (WS_CHILD | WS_POPUP))
833 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
834 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
836 else /* overlapped window */
840 GetStartupInfoA( &info );
842 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
844 /* Never believe Microsoft's documentation... CreateWindowEx doc says
845 * that if an overlapped window is created with WS_VISIBLE style bit
846 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
847 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
850 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
851 * 2) it does not ignore the y parameter as the docs claim; instead, it
852 * uses it as second parameter to ShowWindow() unless y is either
853 * CW_USEDEFAULT or CW_USEDEFAULT16.
855 * The fact that we didn't do 2) caused bogus windows pop up when wine
856 * was running apps that were using this obscure feature. Example -
857 * calc.exe that comes with Win98 (only Win98, it's different from
858 * the one that comes with Win95 and NT)
860 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
861 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
862 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
865 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
867 if (info.dwFlags & STARTF_USESIZE)
869 cs->cx = info.dwXSize;
870 cs->cy = info.dwYSize;
872 else /* if no other hint from the app, pick 3/4 of the screen real estate */
875 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
876 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
877 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
884 /***********************************************************************
887 * Implementation of CreateWindowEx().
889 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
890 WINDOWPROCTYPE type )
893 struct tagCLASS *classPtr;
895 HWND hwnd, hwndLinkAfter, parent, owner;
900 BOOL unicode = (type == WIN_PROC_32W);
902 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
903 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
904 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
905 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
906 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
908 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
909 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
911 /* Find the parent window */
913 parent = GetDesktopWindow();
917 /* Make sure parent is valid */
918 if (!IsWindow( cs->hwndParent ))
920 WARN("Bad parent %04x\n", cs->hwndParent );
923 if (cs->style & WS_CHILD) parent = WIN_GetFullHandle(cs->hwndParent);
924 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
926 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
928 WARN("No parent for child window\n" );
929 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
932 /* Find the window class */
933 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
934 &wndExtra, &winproc, &clsStyle, &dce )))
936 WARN("Bad class '%s'\n", cs->lpszClass );
940 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
942 /* Correct the window style - stage 1
944 * These are patches that appear to affect both the style loaded into the
945 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
947 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
948 * why does the user get to set it?
951 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
952 * tested for WS_POPUP
954 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
955 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
956 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
957 cs->dwExStyle |= WS_EX_WINDOWEDGE;
959 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
961 /* Create the window structure */
963 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
964 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
966 TRACE("out of memory\n" );
969 hwnd = wndPtr->hwndSelf;
971 /* Fill the window structure */
973 wndPtr->tid = GetCurrentThreadId();
974 wndPtr->owner = owner;
975 wndPtr->parent = parent;
976 wndPtr->class = classPtr;
977 wndPtr->winproc = winproc;
978 wndPtr->hInstance = cs->hInstance;
980 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
981 wndPtr->hrgnUpdate = 0;
983 wndPtr->hwndLastActive = hwnd;
984 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
985 wndPtr->dwExStyle = cs->dwExStyle;
986 wndPtr->clsStyle = clsStyle;
988 wndPtr->helpContext = 0;
989 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
990 wndPtr->pVScroll = NULL;
991 wndPtr->pHScroll = NULL;
992 wndPtr->userdata = 0;
993 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
994 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
995 wndPtr->cbWndExtra = wndExtra;
997 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
999 /* Call the WH_CBT hook */
1001 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
1002 ? HWND_BOTTOM : HWND_TOP;
1004 if (HOOK_IsHooked( WH_CBT ))
1006 CBT_CREATEWNDA cbtc;
1010 cbtc.hwndInsertAfter = hwndLinkAfter;
1011 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND,
1012 (WPARAM)hwnd, (LPARAM)&cbtc)
1013 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND,
1014 (WPARAM)hwnd, (LPARAM)&cbtc);
1017 TRACE("CBT-hook returned 0\n");
1018 free_window_handle( hwnd );
1019 CLASS_RemoveWindow( classPtr );
1020 WIN_ReleaseWndPtr(wndPtr);
1025 /* Correct the window style - stage 2 */
1027 if (!(cs->style & WS_CHILD))
1029 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1030 if (!(cs->style & WS_POPUP))
1032 wndPtr->dwStyle |= WS_CAPTION;
1033 wndPtr->flags |= WIN_NEED_SIZE;
1036 SERVER_START_REQ( set_window_info )
1039 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1040 req->style = wndPtr->dwStyle;
1041 req->ex_style = wndPtr->dwExStyle;
1042 req->instance = (void *)wndPtr->hInstance;
1047 /* Get class or window DC if needed */
1049 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1050 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1051 else wndPtr->dce = NULL;
1053 /* Set the window menu */
1055 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1057 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1060 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1063 if (HIWORD(cs->hInstance))
1064 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1066 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1068 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1072 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1073 WIN_ReleaseWndPtr( wndPtr );
1075 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1077 WIN_DestroyWindow( hwnd );
1081 /* Notify the parent window only */
1083 send_parent_notify( hwnd, WM_CREATE );
1084 if (!IsWindow( hwnd )) return 0;
1086 if (cs->style & WS_VISIBLE)
1088 /* in case WS_VISIBLE got set in the meantime */
1089 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1090 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1091 WIN_ReleasePtr( wndPtr );
1092 ShowWindow( hwnd, sw );
1095 /* Call WH_SHELL hook */
1097 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1098 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1100 TRACE("created window %04x\n", hwnd);
1105 /***********************************************************************
1106 * CreateWindow (USER.41)
1108 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1109 DWORD style, INT16 x, INT16 y, INT16 width,
1110 INT16 height, HWND16 parent, HMENU16 menu,
1111 HINSTANCE16 instance, LPVOID data )
1113 return CreateWindowEx16( 0, className, windowName, style,
1114 x, y, width, height, parent, menu, instance, data );
1118 /***********************************************************************
1119 * CreateWindowEx (USER.452)
1121 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1122 LPCSTR windowName, DWORD style, INT16 x,
1123 INT16 y, INT16 width, INT16 height,
1124 HWND16 parent, HMENU16 menu,
1125 HINSTANCE16 instance, LPVOID data )
1131 /* Find the class atom */
1133 if (HIWORD(className))
1135 if (!(classAtom = GlobalFindAtomA( className )))
1137 ERR( "bad class name %s\n", debugres_a(className) );
1143 classAtom = LOWORD(className);
1144 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1146 ERR( "bad atom %x\n", classAtom);
1152 /* Fix the coordinates */
1154 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1155 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1156 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1157 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1159 /* Create the window */
1161 cs.lpCreateParams = data;
1162 cs.hInstance = (HINSTANCE)instance;
1163 cs.hMenu = (HMENU)menu;
1164 cs.hwndParent = WIN_Handle32( parent );
1166 cs.lpszName = windowName;
1167 cs.lpszClass = className;
1168 cs.dwExStyle = exStyle;
1170 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1174 /***********************************************************************
1175 * CreateWindowExA (USER32.@)
1177 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1178 LPCSTR windowName, DWORD style, INT x,
1179 INT y, INT width, INT height,
1180 HWND parent, HMENU menu,
1181 HINSTANCE instance, LPVOID data )
1188 instance=GetModuleHandleA(NULL);
1190 if(exStyle & WS_EX_MDICHILD)
1191 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1193 /* Find the class atom */
1195 if (HIWORD(className))
1197 if (!(classAtom = GlobalFindAtomA( className )))
1199 ERR( "bad class name %s\n", debugres_a(className) );
1205 classAtom = LOWORD(className);
1206 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1208 ERR( "bad atom %x\n", classAtom);
1214 /* Create the window */
1216 cs.lpCreateParams = data;
1217 cs.hInstance = instance;
1219 cs.hwndParent = parent;
1225 cs.lpszName = windowName;
1226 cs.lpszClass = className;
1227 cs.dwExStyle = exStyle;
1229 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1233 /***********************************************************************
1234 * CreateWindowExW (USER32.@)
1236 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1237 LPCWSTR windowName, DWORD style, INT x,
1238 INT y, INT width, INT height,
1239 HWND parent, HMENU menu,
1240 HINSTANCE instance, LPVOID data )
1247 instance=GetModuleHandleA(NULL);
1249 if(exStyle & WS_EX_MDICHILD)
1250 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1252 /* Find the class atom */
1254 if (HIWORD(className))
1256 if (!(classAtom = GlobalFindAtomW( className )))
1258 ERR( "bad class name %s\n", debugres_w(className) );
1264 classAtom = LOWORD(className);
1265 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1267 ERR( "bad atom %x\n", classAtom);
1273 /* Create the window */
1275 cs.lpCreateParams = data;
1276 cs.hInstance = instance;
1278 cs.hwndParent = parent;
1284 cs.lpszName = windowName;
1285 cs.lpszClass = className;
1286 cs.dwExStyle = exStyle;
1288 /* Note: we rely on the fact that CREATESTRUCTA and */
1289 /* CREATESTRUCTW have the same layout. */
1290 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1294 /***********************************************************************
1295 * WIN_SendDestroyMsg
1297 static void WIN_SendDestroyMsg( HWND hwnd )
1299 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1300 if (USER_Driver.pResetSelectionOwner)
1301 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1304 * Send the WM_DESTROY to the window.
1306 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1309 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1310 * make sure that the window still exists when we come back.
1317 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1319 /* start from the end (FIXME: is this needed?) */
1320 for (i = 0; pWndArray[i]; i++) ;
1324 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1326 HeapFree( GetProcessHeap(), 0, pWndArray );
1329 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1333 /***********************************************************************
1334 * DestroyWindow (USER32.@)
1336 BOOL WINAPI DestroyWindow( HWND hwnd )
1341 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1343 SetLastError( ERROR_ACCESS_DENIED );
1347 TRACE("(%04x)\n", hwnd);
1349 /* Look whether the focus is within the tree of windows we will
1353 if (h == hwnd || IsChild( hwnd, h ))
1355 HWND parent = GetAncestor( hwnd, GA_PARENT );
1356 if (parent == GetDesktopWindow()) parent = 0;
1362 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1364 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1368 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1369 send_parent_notify( hwnd, WM_DESTROY );
1371 else if (!GetWindow( hwnd, GW_OWNER ))
1373 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1374 /* FIXME: clean up palette - see "Internals" p.352 */
1377 if (!IsWindow(hwnd)) return TRUE;
1379 if (USER_Driver.pResetSelectionOwner)
1380 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1382 /* Hide the window */
1384 ShowWindow( hwnd, SW_HIDE );
1385 if (!IsWindow(hwnd)) return TRUE;
1387 /* Recursively destroy owned windows */
1396 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1399 for (i = 0; list[i]; i++)
1401 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1402 if (WIN_IsCurrentThread( list[i] ))
1404 DestroyWindow( list[i] );
1408 WIN_SetOwner( list[i], 0 );
1410 HeapFree( GetProcessHeap(), 0, list );
1412 if (!got_one) break;
1415 WINPOS_ActivateOtherWindow( hwnd );
1417 if ((owner = GetWindow( hwnd, GW_OWNER )))
1419 WND *ptr = WIN_FindWndPtr( owner );
1422 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1423 WIN_ReleaseWndPtr( ptr );
1428 /* Send destroy messages */
1430 WIN_SendDestroyMsg( hwnd );
1431 if (!IsWindow( hwnd )) return TRUE;
1433 /* Unlink now so we won't bother with the children later on */
1435 WIN_UnlinkWindow( hwnd );
1437 /* Destroy the window storage */
1439 WIN_DestroyWindow( hwnd );
1444 /***********************************************************************
1445 * CloseWindow (USER32.@)
1447 BOOL WINAPI CloseWindow( HWND hwnd )
1449 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1450 ShowWindow( hwnd, SW_MINIMIZE );
1455 /***********************************************************************
1456 * OpenIcon (USER32.@)
1458 BOOL WINAPI OpenIcon( HWND hwnd )
1460 if (!IsIconic( hwnd )) return FALSE;
1461 ShowWindow( hwnd, SW_SHOWNORMAL );
1466 /***********************************************************************
1469 * Implementation of FindWindow() and FindWindowEx().
1471 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1476 WCHAR *buffer = NULL;
1478 if (!parent) parent = GetDesktopWindow();
1481 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1482 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1485 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1489 child = WIN_GetFullHandle( child );
1490 while (list[i] && list[i] != child) i++;
1491 if (!list[i]) goto done;
1492 i++; /* start from next window */
1499 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1506 if (list) HeapFree( GetProcessHeap(), 0, list );
1507 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1513 /***********************************************************************
1514 * FindWindowA (USER32.@)
1516 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1518 HWND ret = FindWindowExA( 0, 0, className, title );
1519 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1524 /***********************************************************************
1525 * FindWindowExA (USER32.@)
1527 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1528 LPCSTR className, LPCSTR title )
1536 /* If the atom doesn't exist, then no class */
1537 /* with this name exists either. */
1538 if (!(atom = GlobalFindAtomA( className )))
1540 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1545 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1546 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1547 HeapFree( GetProcessHeap(), 0, buffer );
1552 /***********************************************************************
1553 * FindWindowExW (USER32.@)
1555 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1556 LPCWSTR className, LPCWSTR title )
1562 /* If the atom doesn't exist, then no class */
1563 /* with this name exists either. */
1564 if (!(atom = GlobalFindAtomW( className )))
1566 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1570 return WIN_FindWindow( parent, child, atom, title );
1574 /***********************************************************************
1575 * FindWindowW (USER32.@)
1577 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1579 return FindWindowExW( 0, 0, className, title );
1583 /**********************************************************************
1584 * GetDesktopWindow (USER32.@)
1586 HWND WINAPI GetDesktopWindow(void)
1588 if (pWndDesktop) return pWndDesktop->hwndSelf;
1589 ERR( "You need the -desktop option when running with native USER\n" );
1595 /*******************************************************************
1596 * EnableWindow (USER32.@)
1598 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1605 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1606 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1610 TRACE("( %x, %d )\n", hwnd, enable);
1612 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1613 style = wndPtr->dwStyle;
1614 retvalue = ((style & WS_DISABLED) != 0);
1615 WIN_ReleasePtr( wndPtr );
1617 if (enable && retvalue)
1619 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1620 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1622 else if (!enable && !retvalue)
1624 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1626 WIN_SetStyle( hwnd, style | WS_DISABLED );
1628 if (hwnd == GetFocus())
1629 SetFocus( 0 ); /* A disabled window can't have the focus */
1631 if (hwnd == GetCapture())
1632 ReleaseCapture(); /* A disabled window can't capture the mouse */
1634 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1640 /***********************************************************************
1641 * IsWindowEnabled (USER32.@)
1643 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1645 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1649 /***********************************************************************
1650 * IsWindowUnicode (USER32.@)
1652 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1657 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1658 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1659 WIN_ReleaseWndPtr(wndPtr);
1664 /**********************************************************************
1665 * GetWindowWord (USER32.@)
1667 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1672 WND *wndPtr = WIN_GetPtr( hwnd );
1675 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1678 if (wndPtr == WND_OTHER_PROCESS)
1680 if (IsWindow( hwnd ))
1681 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1682 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1685 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1687 WARN("Invalid offset %d\n", offset );
1688 SetLastError( ERROR_INVALID_INDEX );
1690 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1691 WIN_ReleasePtr( wndPtr );
1697 case GWL_HWNDPARENT:
1698 return GetWindowLongW( hwnd, offset );
1702 LONG ret = GetWindowLongW( hwnd, offset );
1704 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1708 WARN("Invalid offset %d\n", offset );
1714 /**********************************************************************
1715 * SetWindowWord (USER32.@)
1717 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1726 case GWL_HWNDPARENT:
1727 return SetWindowLongW( hwnd, offset, (UINT)newval );
1731 WARN("Invalid offset %d\n", offset );
1732 SetLastError( ERROR_INVALID_INDEX );
1737 wndPtr = WIN_GetPtr( hwnd );
1738 if (wndPtr == WND_OTHER_PROCESS)
1741 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1742 offset, newval, hwnd );
1747 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1751 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1753 WARN("Invalid offset %d\n", offset );
1754 WIN_ReleasePtr(wndPtr);
1755 SetLastError( ERROR_INVALID_INDEX );
1758 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1761 WIN_ReleasePtr(wndPtr);
1766 /**********************************************************************
1769 * Helper function for GetWindowLong().
1771 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1776 if (offset == GWL_HWNDPARENT) return (LONG)GetParent( hwnd );
1778 if (!(wndPtr = WIN_GetPtr( hwnd )))
1780 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1784 if (wndPtr == WND_OTHER_PROCESS)
1789 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1790 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1793 if (offset == GWL_WNDPROC)
1795 SetLastError( ERROR_ACCESS_DENIED );
1798 SERVER_START_REQ( set_window_info )
1801 req->flags = 0; /* don't set anything, just retrieve */
1802 if (!SERVER_CALL_ERR())
1806 case GWL_STYLE: retvalue = req->style; break;
1807 case GWL_EXSTYLE: retvalue = req->ex_style; break;
1808 case GWL_ID: retvalue = req->id; break;
1809 case GWL_HINSTANCE: retvalue = (ULONG_PTR)req->instance; break;
1810 case GWL_USERDATA: retvalue = (ULONG_PTR)req->user_data; break;
1812 SetLastError( ERROR_INVALID_INDEX );
1821 /* now we have a valid wndPtr */
1825 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1827 WARN("Invalid offset %d\n", offset );
1828 WIN_ReleasePtr( wndPtr );
1829 SetLastError( ERROR_INVALID_INDEX );
1832 /* Special case for dialog window procedure */
1833 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1834 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1836 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1837 WIN_ReleasePtr( wndPtr );
1843 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1844 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1845 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1846 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1847 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1848 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1850 WARN("Unknown offset %d\n", offset );
1851 SetLastError( ERROR_INVALID_INDEX );
1854 WIN_ReleasePtr(wndPtr);
1859 /**********************************************************************
1862 * Helper function for SetWindowLong().
1864 * 0 is the failure code. However, in the case of failure SetLastError
1865 * must be set to distinguish between a 0 return value and a failure.
1867 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1868 WINDOWPROCTYPE type )
1873 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1875 if (!WIN_IsCurrentProcess( hwnd ))
1877 if (offset == GWL_WNDPROC)
1879 SetLastError( ERROR_ACCESS_DENIED );
1882 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1885 wndPtr = WIN_GetPtr( hwnd );
1889 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1890 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1892 WARN("Invalid offset %d\n", offset );
1893 WIN_ReleasePtr( wndPtr );
1894 SetLastError( ERROR_INVALID_INDEX );
1897 /* Special case for dialog window procedure */
1898 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1900 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1901 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1902 type, WIN_PROC_WINDOW );
1903 WIN_ReleasePtr( wndPtr );
1908 WIN_ReleasePtr( wndPtr );
1915 /* first some special cases */
1920 style.styleOld = wndPtr->dwStyle;
1921 style.styleNew = newval;
1922 WIN_ReleasePtr( wndPtr );
1923 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1924 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1925 newval = style.styleNew;
1927 case GWL_HWNDPARENT:
1928 WIN_ReleasePtr( wndPtr );
1929 return (LONG)SetParent( hwnd, (HWND)newval );
1931 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1932 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1933 type, WIN_PROC_WINDOW );
1934 WIN_ReleasePtr( wndPtr );
1941 WIN_ReleasePtr( wndPtr );
1942 WARN("Invalid offset %d\n", offset );
1943 SetLastError( ERROR_INVALID_INDEX );
1947 SERVER_START_REQ( set_window_info )
1953 req->flags = SET_WIN_STYLE;
1954 req->style = newval;
1957 req->flags = SET_WIN_EXSTYLE;
1958 req->ex_style = newval;
1961 req->flags = SET_WIN_ID;
1965 req->flags = SET_WIN_INSTANCE;
1966 req->instance = (void *)newval;
1969 req->flags = SET_WIN_USERDATA;
1970 req->user_data = (void *)newval;
1973 if ((ok = !SERVER_CALL_ERR()))
1978 wndPtr->dwStyle = newval;
1979 retval = req->old_style;
1982 wndPtr->dwExStyle = newval;
1983 retval = req->old_ex_style;
1986 wndPtr->wIDmenu = newval;
1987 retval = req->old_id;
1990 wndPtr->hInstance = newval;
1991 retval = (HINSTANCE)req->old_instance;
1994 wndPtr->userdata = newval;
1995 retval = (ULONG_PTR)req->old_user_data;
2001 WIN_ReleasePtr( wndPtr );
2005 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2006 USER_Driver.pSetWindowStyle( hwnd, retval );
2008 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2009 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2016 /**********************************************************************
2017 * GetWindowLong (USER.135)
2019 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2021 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2025 /**********************************************************************
2026 * GetWindowLongA (USER32.@)
2028 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2030 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2034 /**********************************************************************
2035 * GetWindowLongW (USER32.@)
2037 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2039 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2043 /**********************************************************************
2044 * SetWindowLong (USER.136)
2046 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2048 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2052 /**********************************************************************
2053 * SetWindowLongA (USER32.@)
2055 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2057 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2061 /**********************************************************************
2062 * SetWindowLongW (USER32.@) Set window attribute
2064 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2065 * value in a window's extra memory.
2067 * The _hwnd_ parameter specifies the window. is the handle to a
2068 * window that has extra memory. The _newval_ parameter contains the
2069 * new attribute or extra memory value. If positive, the _offset_
2070 * parameter is the byte-addressed location in the window's extra
2071 * memory to set. If negative, _offset_ specifies the window
2072 * attribute to set, and should be one of the following values:
2074 * GWL_EXSTYLE The window's extended window style
2076 * GWL_STYLE The window's window style.
2078 * GWL_WNDPROC Pointer to the window's window procedure.
2080 * GWL_HINSTANCE The window's pplication instance handle.
2082 * GWL_ID The window's identifier.
2084 * GWL_USERDATA The window's user-specified data.
2086 * If the window is a dialog box, the _offset_ parameter can be one of
2087 * the following values:
2089 * DWL_DLGPROC The address of the window's dialog box procedure.
2091 * DWL_MSGRESULT The return value of a message
2092 * that the dialog box procedure processed.
2094 * DWL_USER Application specific information.
2098 * If successful, returns the previous value located at _offset_. Otherwise,
2103 * Extra memory for a window class is specified by a nonzero cbWndExtra
2104 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2105 * time of class creation.
2107 * Using GWL_WNDPROC to set a new window procedure effectively creates
2108 * a window subclass. Use CallWindowProc() in the new windows procedure
2109 * to pass messages to the superclass's window procedure.
2111 * The user data is reserved for use by the application which created
2114 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2115 * instead, call the EnableWindow() function to change the window's
2118 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2119 * SetParent() instead.
2122 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2123 * it sends WM_STYLECHANGING before changing the settings
2124 * and WM_STYLECHANGED afterwards.
2125 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2127 LONG WINAPI SetWindowLongW(
2128 HWND hwnd, /* [in] window to alter */
2129 INT offset, /* [in] offset, in bytes, of location to alter */
2130 LONG newval /* [in] new value of location */
2132 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2136 /*******************************************************************
2137 * GetWindowTextA (USER32.@)
2139 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2141 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2145 /*******************************************************************
2146 * InternalGetWindowText (USER32.@)
2148 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2150 WND *win = WIN_FindWndPtr( hwnd );
2152 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2153 else lpString[0] = 0;
2154 WIN_ReleaseWndPtr( win );
2155 return strlenW(lpString);
2159 /*******************************************************************
2160 * GetWindowTextW (USER32.@)
2162 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2164 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2169 /*******************************************************************
2170 * SetWindowText (USER32.@)
2171 * SetWindowTextA (USER32.@)
2173 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2175 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2179 /*******************************************************************
2180 * SetWindowTextW (USER32.@)
2182 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2184 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2188 /*******************************************************************
2189 * GetWindowTextLengthA (USER32.@)
2191 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2193 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2196 /*******************************************************************
2197 * GetWindowTextLengthW (USER32.@)
2199 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2201 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2205 /*******************************************************************
2206 * IsWindow (USER32.@)
2208 BOOL WINAPI IsWindow( HWND hwnd )
2213 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2215 if (ptr != WND_OTHER_PROCESS)
2217 WIN_ReleasePtr( ptr );
2221 /* check other processes */
2222 SERVER_START_REQ( get_window_info )
2225 ret = !SERVER_CALL_ERR();
2232 /***********************************************************************
2233 * GetWindowThreadProcessId (USER32.@)
2235 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2240 if (!(ptr = WIN_GetPtr( hwnd )))
2242 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2246 if (ptr != WND_OTHER_PROCESS)
2248 /* got a valid window */
2250 if (process) *process = GetCurrentProcessId();
2251 WIN_ReleasePtr( ptr );
2255 /* check other processes */
2256 SERVER_START_REQ( get_window_info )
2259 if (!SERVER_CALL_ERR())
2261 tid = (DWORD)req->tid;
2262 if (process) *process = (DWORD)req->pid;
2270 /*****************************************************************
2271 * GetParent (USER32.@)
2273 HWND WINAPI GetParent( HWND hwnd )
2278 if (!(wndPtr = WIN_GetPtr( hwnd )))
2280 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2283 if (wndPtr == WND_OTHER_PROCESS)
2285 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2286 if (style & (WS_POPUP | WS_CHILD))
2288 SERVER_START_REQ( get_window_tree )
2291 if (!SERVER_CALL_ERR())
2293 if (style & WS_CHILD) retvalue = req->parent;
2294 else retvalue = req->owner;
2302 if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2303 else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2304 WIN_ReleasePtr( wndPtr );
2310 /*****************************************************************
2311 * GetAncestor (USER32.@)
2313 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2321 if (!(win = WIN_GetPtr( hwnd )))
2323 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2326 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2328 WIN_ReleasePtr( win );
2329 if (type == GA_PARENT) return ret;
2330 if (!ret || ret == GetDesktopWindow())
2332 ret = hwnd; /* if ret is the desktop, hwnd is the root ancestor */
2335 hwnd = ret; /* restart with parent as hwnd */
2338 size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE;
2340 SERVER_START_VAR_REQ( get_window_parents, size )
2345 user_handle_t *data = server_data_ptr(req);
2346 int count = server_data_size(req) / sizeof(*data);
2356 if (count > 1) ret = data[count - 2]; /* get the one before the desktop */
2357 else ret = WIN_GetFullHandle( hwnd );
2366 if (ret && type == GA_ROOTOWNER)
2370 HWND owner = GetWindow( ret, GW_OWNER );
2379 /*****************************************************************
2380 * SetParent (USER32.@)
2382 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2385 HWND retvalue, full_handle;
2388 if (!parent) parent = GetDesktopWindow();
2389 else parent = WIN_GetFullHandle( parent );
2391 if (!IsWindow( parent ))
2393 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2397 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2398 return SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2402 if (USER_Driver.pSetParent)
2403 return USER_Driver.pSetParent( hwnd, parent );
2405 /* Windows hides the window first, then shows it again
2406 * including the WM_SHOWWINDOW messages and all */
2407 was_visible = ShowWindow( hwnd, SW_HIDE );
2409 if (!IsWindow( parent )) return 0;
2410 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2412 retvalue = wndPtr->parent; /* old parent */
2413 if (parent != retvalue)
2415 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2417 if (parent != GetDesktopWindow()) /* a child window */
2419 if (!(wndPtr->dwStyle & WS_CHILD))
2421 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2422 if (menu) DestroyMenu( menu );
2426 WIN_ReleasePtr( wndPtr );
2428 /* SetParent additionally needs to make hwnd the topmost window
2429 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2430 WM_WINDOWPOSCHANGED notification messages.
2432 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2433 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2434 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2435 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2440 /*******************************************************************
2441 * IsChild (USER32.@)
2443 BOOL WINAPI IsChild( HWND parent, HWND child )
2445 HWND *list = WIN_ListParents( child );
2449 if (!list) return FALSE;
2450 parent = WIN_GetFullHandle( parent );
2451 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2452 ret = (list[i] != 0);
2453 HeapFree( GetProcessHeap(), 0, list );
2458 /***********************************************************************
2459 * IsWindowVisible (USER32.@)
2461 BOOL WINAPI IsWindowVisible( HWND hwnd )
2467 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2468 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2469 for (i = 0; list[i]; i++)
2470 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2472 HeapFree( GetProcessHeap(), 0, list );
2477 /***********************************************************************
2478 * WIN_IsWindowDrawable
2480 * hwnd is drawable when it is visible, all parents are not
2481 * minimized, and it is itself not minimized unless we are
2482 * trying to draw its default class icon.
2484 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2489 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2491 if (!(style & WS_VISIBLE)) return FALSE;
2492 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2494 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2495 for (i = 0; list[i]; i++)
2496 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2499 HeapFree( GetProcessHeap(), 0, list );
2504 /*******************************************************************
2505 * GetTopWindow (USER32.@)
2507 HWND WINAPI GetTopWindow( HWND hwnd )
2509 if (!hwnd) hwnd = GetDesktopWindow();
2510 return GetWindow( hwnd, GW_CHILD );
2514 /*******************************************************************
2515 * GetWindow (USER32.@)
2517 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2521 if (rel == GW_OWNER) /* this one may be available locally */
2523 WND *wndPtr = WIN_GetPtr( hwnd );
2526 SetLastError( ERROR_INVALID_HANDLE );
2529 if (wndPtr != WND_OTHER_PROCESS)
2531 retval = wndPtr->owner;
2532 WIN_ReleasePtr( wndPtr );
2535 /* else fall through to server call */
2538 SERVER_START_REQ( get_window_tree )
2541 if (!SERVER_CALL_ERR())
2546 retval = req->first_sibling;
2549 retval = req->last_sibling;
2552 retval = req->next_sibling;
2555 retval = req->prev_sibling;
2558 retval = req->owner;
2561 retval = req->first_child;
2571 /***********************************************************************
2572 * WIN_InternalShowOwnedPopups
2574 * Internal version of ShowOwnedPopups; Wine functions should use this
2575 * to avoid interfering with application calls to ShowOwnedPopups
2576 * and to make sure the application can't prevent showing/hiding.
2578 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2582 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2586 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2588 if (!win_array) return TRUE;
2591 * Show windows Lowest first, Highest last to preserve Z-Order
2593 while (win_array[count]) count++;
2594 while (--count >= 0)
2596 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2597 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2599 if (pWnd->dwStyle & WS_POPUP)
2603 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2604 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2607 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2609 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2610 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2615 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2616 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2617 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2620 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2622 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2623 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2624 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2628 WIN_ReleaseWndPtr( pWnd );
2630 HeapFree( GetProcessHeap(), 0, win_array );
2635 /*******************************************************************
2636 * ShowOwnedPopups (USER32.@)
2638 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2642 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2644 if (!win_array) return TRUE;
2646 while (win_array[count]) count++;
2647 while (--count >= 0)
2649 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2650 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2652 if (pWnd->dwStyle & WS_POPUP)
2656 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2658 /* In Windows, ShowOwnedPopups(TRUE) generates
2659 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2660 * regardless of the state of the owner
2662 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2663 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2668 if (IsWindowVisible(pWnd->hwndSelf))
2670 /* In Windows, ShowOwnedPopups(FALSE) generates
2671 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2672 * regardless of the state of the owner
2674 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2675 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2679 WIN_ReleaseWndPtr( pWnd );
2681 HeapFree( GetProcessHeap(), 0, win_array );
2686 /*******************************************************************
2687 * GetLastActivePopup (USER32.@)
2689 HWND WINAPI GetLastActivePopup( HWND hwnd )
2692 WND *wndPtr =WIN_FindWndPtr(hwnd);
2693 if (!wndPtr) return hwnd;
2694 retval = wndPtr->hwndLastActive;
2695 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2696 WIN_ReleaseWndPtr(wndPtr);
2701 /*******************************************************************
2704 * Build an array of all parents of a given window, starting with
2705 * the immediate parent. The array must be freed with HeapFree.
2706 * Returns NULL if window is a top-level window.
2708 HWND *WIN_ListParents( HWND hwnd )
2711 HWND current, *list;
2712 int pos = 0, size = 16, count = 0;
2714 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2719 if (!(win = WIN_GetPtr( current ))) goto empty;
2720 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2721 list[pos] = win->parent;
2722 WIN_ReleasePtr( win );
2723 if (!(current = list[pos]))
2725 if (!pos) goto empty;
2728 if (++pos == size - 1)
2730 /* need to grow the list */
2731 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2732 if (!new_list) goto empty;
2738 /* at least one parent belongs to another process, have to query the server */
2739 SERVER_START_VAR_REQ( get_window_parents, REQUEST_MAX_VAR_SIZE )
2744 user_handle_t *data = server_data_ptr(req);
2745 count = server_data_size(req) / sizeof(*data);
2748 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0,
2749 list, (count + 1) * sizeof(HWND) );
2753 for (pos = 0; pos < count; pos++) list[pos] = data[pos];
2761 if (count) return list;
2764 HeapFree( GetProcessHeap(), 0, list );
2769 /*******************************************************************
2772 * Build an array of the children of a given window. The array must be
2773 * freed with HeapFree. Returns NULL when no windows are found.
2775 HWND *WIN_ListChildren( HWND hwnd )
2777 return list_window_children( hwnd, 0, 0 );
2781 /*******************************************************************
2782 * EnumWindows (USER32.@)
2784 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2790 /* We have to build a list of all windows first, to avoid */
2791 /* unpleasant side-effects, for instance if the callback */
2792 /* function changes the Z-order of the windows. */
2794 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2796 /* Now call the callback function for every window */
2798 iWndsLocks = WIN_SuspendWndsLock();
2799 for (i = 0; list[i]; i++)
2801 /* Make sure that the window still exists */
2802 if (!IsWindow( list[i] )) continue;
2803 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2805 WIN_RestoreWndsLock(iWndsLocks);
2806 HeapFree( GetProcessHeap(), 0, list );
2811 /**********************************************************************
2812 * EnumTaskWindows16 (USER.225)
2814 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2817 TDB *tdb = TASK_GetPtr( hTask );
2818 if (!tdb) return FALSE;
2819 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2823 /**********************************************************************
2824 * EnumThreadWindows (USER32.@)
2826 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2831 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2834 /* Now call the callback function for every window */
2836 iWndsLocks = WIN_SuspendWndsLock();
2837 for (i = 0; list[i]; i++)
2838 if (!func( list[i], lParam )) break;
2839 WIN_RestoreWndsLock(iWndsLocks);
2840 HeapFree( GetProcessHeap(), 0, list );
2845 /**********************************************************************
2846 * WIN_EnumChildWindows
2848 * Helper function for EnumChildWindows().
2850 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2855 for ( ; *list; list++)
2857 /* Make sure that the window still exists */
2858 if (!IsWindow( *list )) continue;
2859 /* skip owned windows */
2860 if (GetWindow( *list, GW_OWNER )) continue;
2861 /* Build children list first */
2862 childList = WIN_ListChildren( *list );
2864 ret = func( *list, lParam );
2868 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2869 HeapFree( GetProcessHeap(), 0, childList );
2871 if (!ret) return FALSE;
2877 /**********************************************************************
2878 * EnumChildWindows (USER32.@)
2880 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2885 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2886 iWndsLocks = WIN_SuspendWndsLock();
2887 WIN_EnumChildWindows( list, func, lParam );
2888 WIN_RestoreWndsLock(iWndsLocks);
2889 HeapFree( GetProcessHeap(), 0, list );
2894 /*******************************************************************
2895 * AnyPopup (USER.52)
2897 BOOL16 WINAPI AnyPopup16(void)
2903 /*******************************************************************
2904 * AnyPopup (USER32.@)
2906 BOOL WINAPI AnyPopup(void)
2910 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2912 if (!list) return FALSE;
2913 for (i = 0; list[i]; i++)
2915 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2917 retvalue = (list[i] != 0);
2918 HeapFree( GetProcessHeap(), 0, list );
2923 /*******************************************************************
2924 * FlashWindow (USER32.@)
2926 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2928 WND *wndPtr = WIN_FindWndPtr(hWnd);
2930 TRACE("%04x\n", hWnd);
2932 if (!wndPtr) return FALSE;
2933 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2935 if (wndPtr->dwStyle & WS_MINIMIZE)
2937 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2939 HDC hDC = GetDC(hWnd);
2941 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2942 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2944 ReleaseDC( hWnd, hDC );
2945 wndPtr->flags |= WIN_NCACTIVATED;
2949 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2950 wndPtr->flags &= ~WIN_NCACTIVATED;
2952 WIN_ReleaseWndPtr(wndPtr);
2958 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2959 else wparam = (hWnd == GetActiveWindow());
2961 WIN_ReleaseWndPtr(wndPtr);
2962 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2968 /*******************************************************************
2969 * GetWindowContextHelpId (USER32.@)
2971 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2974 WND *wnd = WIN_FindWndPtr( hwnd );
2976 retval = wnd->helpContext;
2977 WIN_ReleaseWndPtr(wnd);
2982 /*******************************************************************
2983 * SetWindowContextHelpId (USER32.@)
2985 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2987 WND *wnd = WIN_FindWndPtr( hwnd );
2988 if (!wnd) return FALSE;
2989 wnd->helpContext = id;
2990 WIN_ReleaseWndPtr(wnd);
2995 /*******************************************************************
2998 * recursively find a child that contains spDragInfo->pt point
2999 * and send WM_QUERYDROPOBJECT
3001 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3003 BOOL16 wParam, bResult = 0;
3005 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3008 if (!ptrDragInfo) return FALSE;
3010 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3012 GetWindowRect(hQueryWnd,&tempRect);
3014 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3016 if (!IsIconic( hQueryWnd ))
3018 GetClientRect( hQueryWnd, &tempRect );
3019 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3021 if (PtInRect( &tempRect, pt))
3024 HWND *list = WIN_ListChildren( hQueryWnd );
3030 for (i = 0; list[i]; i++)
3032 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3034 GetWindowRect( list[i], &tempRect );
3035 if (PtInRect( &tempRect, pt )) break;
3040 if (IsWindowEnabled( list[i] ))
3041 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
3043 HeapFree( GetProcessHeap(), 0, list );
3045 if(bResult) return bResult;
3051 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3053 ptrDragInfo->hScope = hQueryWnd;
3055 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3056 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3058 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3064 /*******************************************************************
3065 * DragDetect (USER32.@)
3067 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3072 rect.left = pt.x - wDragWidth;
3073 rect.right = pt.x + wDragWidth;
3075 rect.top = pt.y - wDragHeight;
3076 rect.bottom = pt.y + wDragHeight;
3082 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3084 if( msg.message == WM_LBUTTONUP )
3089 if( msg.message == WM_MOUSEMOVE )
3092 tmp.x = LOWORD(msg.lParam);
3093 tmp.y = HIWORD(msg.lParam);
3094 if( !PtInRect( &rect, tmp ))
3106 /******************************************************************************
3107 * DragObject (USER.464)
3109 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3110 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3113 LPDRAGINFO16 lpDragInfo;
3115 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3116 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3117 HCURSOR16 hCurrentCursor = 0;
3118 HWND16 hCurrentWnd = 0;
3120 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3121 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3123 if( !lpDragInfo || !spDragInfo ) return 0L;
3125 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3127 GlobalFree16(hDragInfo);
3133 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3135 GlobalFree16(hDragInfo);
3139 if( hDragCursor == hCursor ) hDragCursor = 0;
3140 else hCursor = hDragCursor;
3142 hOldCursor = SetCursor(hDragCursor);
3145 lpDragInfo->hWnd = hWnd;
3146 lpDragInfo->hScope = 0;
3147 lpDragInfo->wFlags = wObj;
3148 lpDragInfo->hList = szList; /* near pointer! */
3149 lpDragInfo->hOfStruct = hOfStruct;
3157 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3159 *(lpDragInfo+1) = *lpDragInfo;
3161 lpDragInfo->pt.x = msg.pt.x;
3162 lpDragInfo->pt.y = msg.pt.y;
3164 /* update DRAGINFO struct */
3165 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3167 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3168 hCurrentCursor = hCursor;
3171 hCurrentCursor = hBummer;
3172 lpDragInfo->hScope = 0;
3174 if( hCurrentCursor )
3175 SetCursor(hCurrentCursor);
3177 /* send WM_DRAGLOOP */
3178 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3179 (LPARAM) spDragInfo );
3180 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3181 if( hCurrentWnd != lpDragInfo->hScope )
3184 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3185 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3186 HIWORD(spDragInfo)) );
3187 hCurrentWnd = lpDragInfo->hScope;
3189 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3193 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3195 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3198 ShowCursor( FALSE );
3202 SetCursor( hOldCursor );
3203 if (hDragCursor) DestroyCursor( hDragCursor );
3206 if( hCurrentCursor != hBummer )
3207 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3208 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3211 GlobalFree16(hDragInfo);
3213 return (DWORD)(msg.lParam);
3217 /******************************************************************************
3218 * GetWindowModuleFileNameA (USER32.@)
3220 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3222 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3223 hwnd, lpszFileName, cchFileNameMax);
3227 /******************************************************************************
3228 * GetWindowModuleFileNameW (USER32.@)
3230 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3232 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3233 hwnd, lpszFileName, cchFileNameMax);