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 * Return a pointer to the WND structure if local to the process,
182 * or BAD_WND_PTR is handle is local but not valid.
183 * If ret value is a valid pointer, the user lock is held.
185 WND *WIN_GetWndPtr( HWND hwnd )
188 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
190 if (index >= NB_USER_HANDLES) return BAD_WND_PTR;
193 if ((ptr = user_handles[index]))
195 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
204 /***********************************************************************
205 * WIN_IsCurrentProcess
207 * Check whether a given window belongs to the current process.
209 BOOL WIN_IsCurrentProcess( HWND hwnd )
213 if (!(ptr = WIN_GetWndPtr( hwnd )) || ptr == BAD_WND_PTR) return FALSE;
219 /***********************************************************************
220 * WIN_IsCurrentThread
222 * Check whether a given window belongs to the current thread.
224 BOOL WIN_IsCurrentThread( HWND hwnd )
229 if ((ptr = WIN_GetWndPtr( hwnd )) && ptr != BAD_WND_PTR)
231 ret = (ptr->tid == GetCurrentThreadId());
238 /***********************************************************************
241 * Convert a 16-bit window handle to a full 32-bit handle.
243 HWND WIN_Handle32( HWND16 hwnd16 )
246 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
248 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
249 /* do sign extension for -2 and -3 */
250 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
252 if ((ptr = WIN_GetWndPtr( hwnd )))
254 if (ptr != BAD_WND_PTR)
256 hwnd = ptr->hwndSelf;
260 else /* may belong to another process */
262 SERVER_START_REQ( get_window_info )
265 if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
273 /***********************************************************************
276 * Return a pointer to the WND structure corresponding to a HWND.
278 WND * WIN_FindWndPtr( HWND hwnd )
282 if (!hwnd) return NULL;
284 if ((ptr = WIN_GetWndPtr( hwnd )))
286 if (ptr != BAD_WND_PTR)
288 /* increment destruction monitoring */
293 else if (IsWindow( hwnd )) /* check other processes */
295 ERR( "window %04x belongs to other process\n", hwnd );
296 /* DbgBreakPoint(); */
298 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
303 /***********************************************************************
306 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
308 * Returns the locked initialisation pointer
310 WND *WIN_LockWndPtr(WND *initWndPtr)
312 if(!initWndPtr) return 0;
314 /* Lock all WND structures for thread safeness*/
316 /*and increment destruction monitoring*/
317 initWndPtr->irefCount++;
323 /***********************************************************************
326 * Release the pointer to the WND structure.
328 void WIN_ReleaseWndPtr(WND *wndPtr)
332 /*Decrement destruction monitoring value*/
334 /* Check if it's time to release the memory*/
335 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
338 free_window_handle( wndPtr->hwndSelf );
340 else if(wndPtr->irefCount < 0)
342 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
343 ERR("forgot a Lock on %p somewhere\n",wndPtr);
345 /*unlock all WND structures for thread safeness*/
349 /***********************************************************************
352 * Updates the value of oldPtr to newPtr.
354 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
358 tmpWnd = WIN_LockWndPtr(newPtr);
359 WIN_ReleaseWndPtr(*oldPtr);
365 /***********************************************************************
368 * Remove a window from the siblings linked list.
370 void WIN_UnlinkWindow( HWND hwnd )
372 WIN_LinkWindow( hwnd, 0, 0 );
376 /***********************************************************************
379 * Insert a window into the siblings linked list.
380 * The window is inserted after the specified window, which can also
381 * be specified as HWND_TOP or HWND_BOTTOM.
382 * If parent is 0, window is unlinked from the tree.
384 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
386 WND *wndPtr, **ppWnd, *parentPtr = NULL;
389 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
390 if (parent && !(parentPtr = WIN_FindWndPtr( parent )))
392 WIN_ReleaseWndPtr(wndPtr);
396 SERVER_START_REQ( link_window )
399 req->parent = parent;
400 req->previous = hwndInsertAfter;
401 ret = !SERVER_CALL_ERR();
406 /* first unlink it if it is linked */
409 ppWnd = &wndPtr->parent->child;
410 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
411 if (*ppWnd) *ppWnd = wndPtr->next;
416 wndPtr->parent = parentPtr;
417 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
419 ppWnd = &parentPtr->child; /* Point to first sibling hwnd */
420 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
421 while (*ppWnd) ppWnd = &(*ppWnd)->next;
423 else /* Normal case */
425 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
426 if (!afterPtr) goto done;
427 ppWnd = &afterPtr->next;
428 WIN_ReleaseWndPtr(afterPtr);
430 wndPtr->next = *ppWnd;
433 else wndPtr->next = NULL; /* unlinked */
436 WIN_ReleaseWndPtr( parentPtr );
437 WIN_ReleaseWndPtr( wndPtr );
441 /***********************************************************************
442 * WIN_FindWinToRepaint
444 * Find a window that needs repaint.
446 HWND WIN_FindWinToRepaint( HWND hwnd )
451 /* Note: the desktop window never gets WM_PAINT messages
452 * The real reason why is because Windows DesktopWndProc
453 * does ValidateRgn inside WM_ERASEBKGND handler.
455 if (hwnd == GetDesktopWindow()) hwnd = 0;
457 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
459 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
461 if (!(pWnd->dwStyle & WS_VISIBLE)) continue;
462 if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
463 WIN_IsCurrentThread( pWnd->hwndSelf ))
467 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
469 WIN_ReleaseWndPtr(pWnd);
477 TRACE("nothing found\n");
480 hwndRet = pWnd->hwndSelf;
482 /* look among siblings if we got a transparent window */
485 if (!(pWnd->dwExStyle & WS_EX_TRANSPARENT) &&
486 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
487 WIN_IsCurrentThread( pWnd->hwndSelf ))
489 hwndRet = pWnd->hwndSelf;
490 WIN_ReleaseWndPtr(pWnd);
493 WIN_UpdateWndPtr(&pWnd,pWnd->next);
495 TRACE("found %04x\n",hwndRet);
500 /***********************************************************************
503 * Destroy storage associated to a window. "Internals" p.358
504 * returns a locked wndPtr->next
506 static WND* WIN_DestroyWindow( WND* wndPtr )
508 HWND hwnd = wndPtr->hwndSelf;
511 TRACE("%04x\n", wndPtr->hwndSelf );
513 /* free child windows */
514 WIN_LockWndPtr(wndPtr->child);
515 while ((pWnd = wndPtr->child))
517 wndPtr->child = WIN_DestroyWindow( pWnd );
518 WIN_ReleaseWndPtr(pWnd);
522 * Clear the update region to make sure no WM_PAINT messages will be
523 * generated for this window while processing the WM_NCDESTROY.
525 RedrawWindow( wndPtr->hwndSelf, NULL, 0,
526 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
529 * Send the WM_NCDESTROY to the window being destroyed.
531 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
533 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
535 WINPOS_CheckInternalPos( hwnd );
536 if( hwnd == GetCapture()) ReleaseCapture();
538 /* free resources associated with the window */
540 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
541 PROPERTY_RemoveWindowProps( wndPtr );
543 /* toss stale messages from the queue */
545 QUEUE_CleanupWindow( hwnd );
546 wndPtr->hmemTaskQ = 0;
548 if (!(wndPtr->dwStyle & WS_CHILD))
551 DestroyMenu( wndPtr->wIDmenu );
554 if (wndPtr->hSysMenu)
556 DestroyMenu( wndPtr->hSysMenu );
557 wndPtr->hSysMenu = 0;
559 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
560 DCE_FreeWindowDCE( wndPtr->hwndSelf ); /* Always do this to catch orphaned DCs */
561 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
562 CLASS_RemoveWindow( wndPtr->class );
563 wndPtr->class = NULL;
564 wndPtr->dwMagic = 0; /* Mark it as invalid */
566 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
571 /***********************************************************************
572 * WIN_DestroyThreadWindows
574 * Destroy all children of 'wnd' owned by the current thread.
575 * Return TRUE if something was done.
577 void WIN_DestroyThreadWindows( HWND hwnd )
582 if (!(list = WIN_ListChildren( hwnd ))) return;
583 for (i = 0; list[i]; i++)
585 if (!IsWindow( list[i] )) continue;
586 if (WIN_IsCurrentThread( list[i] ))
587 DestroyWindow( list[i] );
589 WIN_DestroyThreadWindows( list[i] );
591 HeapFree( GetProcessHeap(), 0, list );
594 /***********************************************************************
595 * WIN_CreateDesktopWindow
597 * Create the desktop window.
599 BOOL WIN_CreateDesktopWindow(void)
601 struct tagCLASS *class;
609 TRACE("Creating desktop window\n");
612 if (!WINPOS_CreateInternalPosAtom() ||
613 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
614 &wndExtra, &winproc, &clsStyle, &dce )))
617 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
618 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
619 if (!pWndDesktop) return FALSE;
620 hwndDesktop = pWndDesktop->hwndSelf;
622 pWndDesktop->tid = 0; /* nobody owns the desktop */
623 pWndDesktop->next = NULL;
624 pWndDesktop->child = NULL;
625 pWndDesktop->parent = NULL;
626 pWndDesktop->owner = 0;
627 pWndDesktop->class = class;
628 pWndDesktop->hInstance = 0;
629 pWndDesktop->rectWindow.left = 0;
630 pWndDesktop->rectWindow.top = 0;
631 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
632 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
633 pWndDesktop->rectClient = pWndDesktop->rectWindow;
634 pWndDesktop->text = NULL;
635 pWndDesktop->hmemTaskQ = 0;
636 pWndDesktop->hrgnUpdate = 0;
637 pWndDesktop->hwndLastActive = hwndDesktop;
638 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
640 pWndDesktop->dwExStyle = 0;
641 pWndDesktop->clsStyle = clsStyle;
642 pWndDesktop->dce = NULL;
643 pWndDesktop->pVScroll = NULL;
644 pWndDesktop->pHScroll = NULL;
645 pWndDesktop->pProp = NULL;
646 pWndDesktop->wIDmenu = 0;
647 pWndDesktop->helpContext = 0;
648 pWndDesktop->flags = 0;
649 pWndDesktop->hSysMenu = 0;
650 pWndDesktop->userdata = 0;
651 pWndDesktop->winproc = winproc;
652 pWndDesktop->cbWndExtra = wndExtra;
654 cs.lpCreateParams = NULL;
660 cs.cx = pWndDesktop->rectWindow.right;
661 cs.cy = pWndDesktop->rectWindow.bottom;
662 cs.style = pWndDesktop->dwStyle;
663 cs.dwExStyle = pWndDesktop->dwExStyle;
665 cs.lpszClass = DESKTOP_CLASS_ATOM;
667 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
669 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
670 WIN_ReleaseWndPtr( pWndDesktop );
675 /***********************************************************************
678 * Fix the coordinates - Helper for WIN_CreateWindowEx.
679 * returns default show mode in sw.
680 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
682 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
684 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
685 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
687 if (cs->style & (WS_CHILD | WS_POPUP))
689 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
690 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
692 else /* overlapped window */
696 GetStartupInfoA( &info );
698 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
700 /* Never believe Microsoft's documentation... CreateWindowEx doc says
701 * that if an overlapped window is created with WS_VISIBLE style bit
702 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
703 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
706 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
707 * 2) it does not ignore the y parameter as the docs claim; instead, it
708 * uses it as second parameter to ShowWindow() unless y is either
709 * CW_USEDEFAULT or CW_USEDEFAULT16.
711 * The fact that we didn't do 2) caused bogus windows pop up when wine
712 * was running apps that were using this obscure feature. Example -
713 * calc.exe that comes with Win98 (only Win98, it's different from
714 * the one that comes with Win95 and NT)
716 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
717 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
718 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
721 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
723 if (info.dwFlags & STARTF_USESIZE)
725 cs->cx = info.dwXSize;
726 cs->cy = info.dwYSize;
728 else /* if no other hint from the app, pick 3/4 of the screen real estate */
731 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
732 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
733 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
740 /***********************************************************************
743 * Implementation of CreateWindowEx().
745 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
746 WINDOWPROCTYPE type )
749 struct tagCLASS *classPtr;
751 HWND hwnd, hwndLinkAfter, parent, owner;
752 POINT maxSize, maxPos, minTrack, maxTrack;
757 BOOL unicode = (type == WIN_PROC_32W);
759 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
760 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
761 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
762 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
763 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
765 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
766 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
768 /* Find the parent window */
770 parent = GetDesktopWindow();
774 /* Make sure parent is valid */
775 if (!IsWindow( cs->hwndParent ))
777 WARN("Bad parent %04x\n", cs->hwndParent );
780 if (cs->style & WS_CHILD) parent = cs->hwndParent;
781 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
783 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
785 WARN("No parent for child window\n" );
786 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
789 /* Find the window class */
790 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
791 &wndExtra, &winproc, &clsStyle, &dce )))
793 WARN("Bad class '%s'\n", cs->lpszClass );
797 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
799 /* Correct the window style - stage 1
801 * These are patches that appear to affect both the style loaded into the
802 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
804 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
805 * why does the user get to set it?
808 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
809 * tested for WS_POPUP
811 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
812 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
813 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
814 cs->dwExStyle |= WS_EX_WINDOWEDGE;
816 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
818 /* Create the window structure */
820 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
821 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
823 TRACE("out of memory\n" );
826 hwnd = wndPtr->hwndSelf;
828 /* Fill the window structure */
830 wndPtr->tid = GetCurrentThreadId();
832 wndPtr->child = NULL;
833 wndPtr->owner = owner;
834 wndPtr->parent = WIN_FindWndPtr( parent );
835 WIN_ReleaseWndPtr(wndPtr->parent);
837 wndPtr->class = classPtr;
838 wndPtr->winproc = winproc;
839 wndPtr->hInstance = cs->hInstance;
841 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
842 wndPtr->hrgnUpdate = 0;
844 wndPtr->hwndLastActive = hwnd;
845 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
846 wndPtr->dwExStyle = cs->dwExStyle;
847 wndPtr->clsStyle = clsStyle;
849 wndPtr->helpContext = 0;
850 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
851 wndPtr->pVScroll = NULL;
852 wndPtr->pHScroll = NULL;
853 wndPtr->pProp = NULL;
854 wndPtr->userdata = 0;
855 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
856 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
857 wndPtr->cbWndExtra = wndExtra;
859 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
861 /* Call the WH_CBT hook */
863 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
864 ? HWND_BOTTOM : HWND_TOP;
866 if (HOOK_IsHooked( WH_CBT ))
872 cbtc.hwndInsertAfter = hwndLinkAfter;
873 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND,
874 (WPARAM)hwnd, (LPARAM)&cbtc)
875 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND,
876 (WPARAM)hwnd, (LPARAM)&cbtc);
879 TRACE("CBT-hook returned 0\n");
880 free_window_handle( hwnd );
881 CLASS_RemoveWindow( classPtr );
887 /* Correct the window style - stage 2 */
889 if (!(cs->style & WS_CHILD))
891 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
892 if (!(cs->style & WS_POPUP))
894 wndPtr->dwStyle |= WS_CAPTION;
895 wndPtr->flags |= WIN_NEED_SIZE;
899 /* Get class or window DC if needed */
901 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
902 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
903 else wndPtr->dce = NULL;
905 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
907 wndPtr->rectWindow.left = cs->x;
908 wndPtr->rectWindow.top = cs->y;
909 wndPtr->rectWindow.right = cs->x + cs->cx;
910 wndPtr->rectWindow.bottom = cs->y + cs->cy;
911 wndPtr->rectClient = wndPtr->rectWindow;
913 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
915 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
917 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
918 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
919 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
920 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
921 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
924 if (cs->cx < 0) cs->cx = 0;
925 if (cs->cy < 0) cs->cy = 0;
927 wndPtr->rectWindow.left = cs->x;
928 wndPtr->rectWindow.top = cs->y;
929 wndPtr->rectWindow.right = cs->x + cs->cx;
930 wndPtr->rectWindow.bottom = cs->y + cs->cy;
931 wndPtr->rectClient = wndPtr->rectWindow;
933 /* Set the window menu */
935 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
937 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
940 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
943 if (HIWORD(cs->hInstance))
944 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
946 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
948 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
952 else wndPtr->wIDmenu = (UINT)cs->hMenu;
954 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
956 WARN("aborted by WM_xxCREATE!\n");
957 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
958 CLASS_RemoveWindow( classPtr );
959 WIN_ReleaseWndPtr(wndPtr);
963 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
965 /* Notify the parent window only */
967 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
968 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
969 if( !IsWindow(hwnd) )
976 if (cs->style & WS_VISIBLE)
978 /* in case WS_VISIBLE got set in the meantime */
979 wndPtr->dwStyle &= ~WS_VISIBLE;
980 ShowWindow( hwnd, sw );
983 /* Call WH_SHELL hook */
985 if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
986 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
988 TRACE("created window %04x\n", hwnd);
990 WIN_ReleaseWndPtr(wndPtr);
995 /***********************************************************************
996 * CreateWindow (USER.41)
998 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
999 DWORD style, INT16 x, INT16 y, INT16 width,
1000 INT16 height, HWND16 parent, HMENU16 menu,
1001 HINSTANCE16 instance, LPVOID data )
1003 return CreateWindowEx16( 0, className, windowName, style,
1004 x, y, width, height, parent, menu, instance, data );
1008 /***********************************************************************
1009 * CreateWindowEx (USER.452)
1011 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1012 LPCSTR windowName, DWORD style, INT16 x,
1013 INT16 y, INT16 width, INT16 height,
1014 HWND16 parent, HMENU16 menu,
1015 HINSTANCE16 instance, LPVOID data )
1021 /* Find the class atom */
1023 if (HIWORD(className))
1025 if (!(classAtom = GlobalFindAtomA( className )))
1027 ERR( "bad class name %s\n", debugres_a(className) );
1033 classAtom = LOWORD(className);
1034 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1036 ERR( "bad atom %x\n", classAtom);
1042 /* Fix the coordinates */
1044 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1045 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1046 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1047 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1049 /* Create the window */
1051 cs.lpCreateParams = data;
1052 cs.hInstance = (HINSTANCE)instance;
1053 cs.hMenu = (HMENU)menu;
1054 cs.hwndParent = WIN_Handle32( parent );
1056 cs.lpszName = windowName;
1057 cs.lpszClass = className;
1058 cs.dwExStyle = exStyle;
1060 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1064 /***********************************************************************
1065 * CreateWindowExA (USER32.@)
1067 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1068 LPCSTR windowName, DWORD style, INT x,
1069 INT y, INT width, INT height,
1070 HWND parent, HMENU menu,
1071 HINSTANCE instance, LPVOID data )
1078 instance=GetModuleHandleA(NULL);
1080 if(exStyle & WS_EX_MDICHILD)
1081 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1083 /* Find the class atom */
1085 if (HIWORD(className))
1087 if (!(classAtom = GlobalFindAtomA( className )))
1089 ERR( "bad class name %s\n", debugres_a(className) );
1095 classAtom = LOWORD(className);
1096 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1098 ERR( "bad atom %x\n", classAtom);
1104 /* Create the window */
1106 cs.lpCreateParams = data;
1107 cs.hInstance = instance;
1109 cs.hwndParent = parent;
1115 cs.lpszName = windowName;
1116 cs.lpszClass = className;
1117 cs.dwExStyle = exStyle;
1119 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1123 /***********************************************************************
1124 * CreateWindowExW (USER32.@)
1126 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1127 LPCWSTR windowName, DWORD style, INT x,
1128 INT y, INT width, INT height,
1129 HWND parent, HMENU menu,
1130 HINSTANCE instance, LPVOID data )
1137 instance=GetModuleHandleA(NULL);
1139 if(exStyle & WS_EX_MDICHILD)
1140 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1142 /* Find the class atom */
1144 if (HIWORD(className))
1146 if (!(classAtom = GlobalFindAtomW( className )))
1148 ERR( "bad class name %s\n", debugres_w(className) );
1154 classAtom = LOWORD(className);
1155 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1157 ERR( "bad atom %x\n", classAtom);
1163 /* Create the window */
1165 cs.lpCreateParams = data;
1166 cs.hInstance = instance;
1168 cs.hwndParent = parent;
1174 cs.lpszName = windowName;
1175 cs.lpszClass = className;
1176 cs.dwExStyle = exStyle;
1178 /* Note: we rely on the fact that CREATESTRUCTA and */
1179 /* CREATESTRUCTW have the same layout. */
1180 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1184 /***********************************************************************
1185 * WIN_SendDestroyMsg
1187 static void WIN_SendDestroyMsg( HWND hwnd )
1189 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1190 if (USER_Driver.pResetSelectionOwner)
1191 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1194 * Send the WM_DESTROY to the window.
1196 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1199 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1200 * make sure that the window still exists when we come back.
1207 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1209 /* start from the end (FIXME: is this needed?) */
1210 for (i = 0; pWndArray[i]; i++) ;
1214 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1216 HeapFree( GetProcessHeap(), 0, pWndArray );
1219 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1223 /***********************************************************************
1224 * DestroyWindow (USER32.@)
1226 BOOL WINAPI DestroyWindow( HWND hwnd )
1232 hwnd = WIN_GetFullHandle( hwnd );
1233 TRACE("(%04x)\n", hwnd);
1235 /* Initialization */
1237 if (hwnd == GetDesktopWindow()) return FALSE; /* Can't destroy desktop */
1239 /* Look whether the focus is within the tree of windows we will
1243 if (h == hwnd || IsChild( hwnd, h ))
1245 HWND parent = GetAncestor( hwnd, GA_PARENT );
1246 if (parent == GetDesktopWindow()) parent = 0;
1252 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1254 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1255 if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1257 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1258 /* FIXME: clean up palette - see "Internals" p.352 */
1261 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1262 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1264 /* Notify the parent window only */
1265 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1266 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1267 if( !IsWindow(hwnd) )
1274 if (USER_Driver.pResetSelectionOwner)
1275 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1277 /* Hide the window */
1279 ShowWindow( hwnd, SW_HIDE );
1280 if (!IsWindow(hwnd))
1286 /* Recursively destroy owned windows */
1288 if( !(wndPtr->dwStyle & WS_CHILD) )
1295 HWND *list = WIN_ListChildren( wndPtr->parent->hwndSelf );
1298 for (i = 0; list[i]; i++)
1301 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1302 if (!(siblingPtr = WIN_FindWndPtr( list[i] ))) continue;
1303 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1305 WIN_ReleaseWndPtr( siblingPtr );
1306 DestroyWindow( list[i] );
1310 else siblingPtr->owner = 0;
1311 WIN_ReleaseWndPtr( siblingPtr );
1313 HeapFree( GetProcessHeap(), 0, list );
1315 if (!got_one) break;
1318 WINPOS_ActivateOtherWindow( hwnd );
1320 if ((owner = GetWindow( hwnd, GW_OWNER )))
1322 WND *ptr = WIN_FindWndPtr( owner );
1325 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1326 WIN_ReleaseWndPtr( ptr );
1331 /* Send destroy messages */
1333 WIN_SendDestroyMsg( hwnd );
1334 if (!IsWindow(hwnd))
1340 /* Unlink now so we won't bother with the children later on */
1342 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1344 /* Destroy the window storage */
1346 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1349 WIN_ReleaseWndPtr(wndPtr);
1354 /***********************************************************************
1355 * CloseWindow (USER32.@)
1357 BOOL WINAPI CloseWindow( HWND hwnd )
1359 WND * wndPtr = WIN_FindWndPtr( hwnd );
1362 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1367 ShowWindow( hwnd, SW_MINIMIZE );
1370 WIN_ReleaseWndPtr(wndPtr);
1376 /***********************************************************************
1377 * OpenIcon (USER32.@)
1379 BOOL WINAPI OpenIcon( HWND hwnd )
1381 if (!IsIconic( hwnd )) return FALSE;
1382 ShowWindow( hwnd, SW_SHOWNORMAL );
1387 /***********************************************************************
1390 * Implementation of FindWindow() and FindWindowEx().
1392 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1397 WCHAR *buffer = NULL;
1399 if (!parent) parent = GetDesktopWindow();
1402 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1403 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1406 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1410 child = WIN_GetFullHandle( child );
1411 while (list[i] && list[i] != child) i++;
1412 if (!list[i]) goto done;
1413 i++; /* start from next window */
1420 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1427 if (list) HeapFree( GetProcessHeap(), 0, list );
1428 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1434 /***********************************************************************
1435 * FindWindowA (USER32.@)
1437 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1439 HWND ret = FindWindowExA( 0, 0, className, title );
1440 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1445 /***********************************************************************
1446 * FindWindowExA (USER32.@)
1448 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1449 LPCSTR className, LPCSTR title )
1457 /* If the atom doesn't exist, then no class */
1458 /* with this name exists either. */
1459 if (!(atom = GlobalFindAtomA( className )))
1461 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1466 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1467 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1468 HeapFree( GetProcessHeap(), 0, buffer );
1473 /***********************************************************************
1474 * FindWindowExW (USER32.@)
1476 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1477 LPCWSTR className, LPCWSTR title )
1483 /* If the atom doesn't exist, then no class */
1484 /* with this name exists either. */
1485 if (!(atom = GlobalFindAtomW( className )))
1487 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1491 return WIN_FindWindow( parent, child, atom, title );
1495 /***********************************************************************
1496 * FindWindowW (USER32.@)
1498 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1500 return FindWindowExW( 0, 0, className, title );
1504 /**********************************************************************
1505 * GetDesktopWindow (USER32.@)
1507 HWND WINAPI GetDesktopWindow(void)
1509 if (pWndDesktop) return pWndDesktop->hwndSelf;
1510 ERR( "You need the -desktop option when running with native USER\n" );
1516 /*******************************************************************
1517 * EnableWindow (USER32.@)
1519 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1524 TRACE("( %x, %d )\n", hwnd, enable);
1526 if (USER_Driver.pEnableWindow)
1527 return USER_Driver.pEnableWindow( hwnd, enable );
1529 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1530 hwnd = wndPtr->hwndSelf; /* make it a full handle */
1532 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1534 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1536 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1537 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1539 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1541 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1543 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1545 if (hwnd == GetFocus())
1546 SetFocus( 0 ); /* A disabled window can't have the focus */
1548 if (hwnd == GetCapture())
1549 ReleaseCapture(); /* A disabled window can't capture the mouse */
1551 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1553 WIN_ReleaseWndPtr(wndPtr);
1558 /***********************************************************************
1559 * IsWindowEnabled (USER32.@)
1561 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1566 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1567 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1568 WIN_ReleaseWndPtr(wndPtr);
1574 /***********************************************************************
1575 * IsWindowUnicode (USER32.@)
1577 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1582 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1583 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1584 WIN_ReleaseWndPtr(wndPtr);
1589 /**********************************************************************
1590 * GetWindowWord (USER32.@)
1592 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1595 WND * wndPtr = WIN_FindWndPtr( hwnd );
1596 if (!wndPtr) return 0;
1599 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1601 WARN("Invalid offset %d\n", offset );
1604 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1605 WIN_ReleaseWndPtr(wndPtr);
1609 WIN_ReleaseWndPtr(wndPtr);
1612 case GWL_HWNDPARENT:
1613 return GetWindowLongW( hwnd, offset );
1617 LONG ret = GetWindowLongW( hwnd, offset );
1619 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1623 WARN("Invalid offset %d\n", offset );
1629 /**********************************************************************
1630 * SetWindowWord (USER32.@)
1632 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1635 WND * wndPtr = WIN_FindWndPtr( hwnd );
1636 if (!wndPtr) return 0;
1639 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1641 WARN("Invalid offset %d\n", offset );
1642 WIN_ReleaseWndPtr(wndPtr);
1645 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1648 WIN_ReleaseWndPtr(wndPtr);
1652 WIN_ReleaseWndPtr(wndPtr);
1657 case GWL_HWNDPARENT:
1658 return SetWindowLongW( hwnd, offset, (UINT)newval );
1660 WARN("Invalid offset %d\n", offset );
1666 /**********************************************************************
1669 * Helper function for GetWindowLong().
1671 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1674 WND * wndPtr = WIN_FindWndPtr( hwnd );
1675 if (!wndPtr) return 0;
1678 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1680 WARN("Invalid offset %d\n", offset );
1684 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1685 /* Special case for dialog window procedure */
1686 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1688 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1695 case GWL_USERDATA: retvalue = wndPtr->userdata;
1697 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1699 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1701 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1703 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1706 case GWL_HWNDPARENT: retvalue = (LONG)GetParent(hwnd);
1708 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1711 WARN("Unknown offset %d\n", offset );
1715 WIN_ReleaseWndPtr(wndPtr);
1720 /**********************************************************************
1723 * Helper function for SetWindowLong().
1725 * 0 is the failure code. However, in the case of failure SetLastError
1726 * must be set to distinguish between a 0 return value and a failure.
1728 * FIXME: The error values for SetLastError may not be right. Can
1729 * someone check with the real thing?
1731 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1732 WINDOWPROCTYPE type )
1735 WND * wndPtr = WIN_FindWndPtr( hwnd );
1738 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1742 /* Is this the right error? */
1743 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1749 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1751 WARN("Invalid offset %d\n", offset );
1753 /* Is this the right error? */
1754 SetLastError( ERROR_OUTOFMEMORY );
1759 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1760 /* Special case for dialog window procedure */
1761 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1763 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1764 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1765 type, WIN_PROC_WINDOW );
1772 ptr = (DWORD*)&wndPtr->wIDmenu;
1775 ptr = (DWORD*)&wndPtr->hInstance;
1778 ptr = &wndPtr->userdata;
1780 case GWL_HWNDPARENT:
1781 retval = SetParent( hwnd, (HWND)newval );
1784 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1785 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1786 type, WIN_PROC_WINDOW );
1789 retval = wndPtr->dwStyle;
1790 style.styleOld = wndPtr->dwStyle;
1791 style.styleNew = newval;
1792 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1793 wndPtr->dwStyle = style.styleNew;
1794 if (USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, retval );
1795 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1796 retval = style.styleOld;
1799 style.styleOld = wndPtr->dwExStyle;
1800 style.styleNew = newval;
1801 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1802 wndPtr->dwExStyle = style.styleNew;
1803 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1804 retval = style.styleOld;
1808 WARN("Invalid offset %d\n", offset );
1810 /* Don't think this is right error but it should do */
1811 SetLastError( ERROR_OUTOFMEMORY );
1819 WIN_ReleaseWndPtr(wndPtr);
1824 /**********************************************************************
1825 * GetWindowLong (USER.135)
1827 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1829 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
1833 /**********************************************************************
1834 * GetWindowLongA (USER32.@)
1836 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1838 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1842 /**********************************************************************
1843 * GetWindowLongW (USER32.@)
1845 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1847 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1851 /**********************************************************************
1852 * SetWindowLong (USER.136)
1854 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1856 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
1860 /**********************************************************************
1861 * SetWindowLongA (USER32.@)
1863 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1865 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1869 /**********************************************************************
1870 * SetWindowLongW (USER32.@) Set window attribute
1872 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1873 * value in a window's extra memory.
1875 * The _hwnd_ parameter specifies the window. is the handle to a
1876 * window that has extra memory. The _newval_ parameter contains the
1877 * new attribute or extra memory value. If positive, the _offset_
1878 * parameter is the byte-addressed location in the window's extra
1879 * memory to set. If negative, _offset_ specifies the window
1880 * attribute to set, and should be one of the following values:
1882 * GWL_EXSTYLE The window's extended window style
1884 * GWL_STYLE The window's window style.
1886 * GWL_WNDPROC Pointer to the window's window procedure.
1888 * GWL_HINSTANCE The window's pplication instance handle.
1890 * GWL_ID The window's identifier.
1892 * GWL_USERDATA The window's user-specified data.
1894 * If the window is a dialog box, the _offset_ parameter can be one of
1895 * the following values:
1897 * DWL_DLGPROC The address of the window's dialog box procedure.
1899 * DWL_MSGRESULT The return value of a message
1900 * that the dialog box procedure processed.
1902 * DWL_USER Application specific information.
1906 * If successful, returns the previous value located at _offset_. Otherwise,
1911 * Extra memory for a window class is specified by a nonzero cbWndExtra
1912 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1913 * time of class creation.
1915 * Using GWL_WNDPROC to set a new window procedure effectively creates
1916 * a window subclass. Use CallWindowProc() in the new windows procedure
1917 * to pass messages to the superclass's window procedure.
1919 * The user data is reserved for use by the application which created
1922 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1923 * instead, call the EnableWindow() function to change the window's
1926 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1927 * SetParent() instead.
1930 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1931 * it sends WM_STYLECHANGING before changing the settings
1932 * and WM_STYLECHANGED afterwards.
1933 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1937 * GWL_STYLE does not dispatch WM_STYLE... messages.
1944 LONG WINAPI SetWindowLongW(
1945 HWND hwnd, /* [in] window to alter */
1946 INT offset, /* [in] offset, in bytes, of location to alter */
1947 LONG newval /* [in] new value of location */
1949 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1953 /*******************************************************************
1954 * GetWindowTextA (USER32.@)
1956 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
1958 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
1962 /*******************************************************************
1963 * InternalGetWindowText (USER32.@)
1965 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
1967 WND *win = WIN_FindWndPtr( hwnd );
1969 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
1970 else lpString[0] = 0;
1971 WIN_ReleaseWndPtr( win );
1972 return strlenW(lpString);
1976 /*******************************************************************
1977 * GetWindowTextW (USER32.@)
1979 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
1981 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
1986 /*******************************************************************
1987 * SetWindowText (USER32.@)
1988 * SetWindowTextA (USER32.@)
1990 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
1992 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1996 /*******************************************************************
1997 * SetWindowTextW (USER32.@)
1999 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2001 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2005 /*******************************************************************
2006 * GetWindowTextLengthA (USER32.@)
2008 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2010 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2013 /*******************************************************************
2014 * GetWindowTextLengthW (USER32.@)
2016 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2018 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2022 /*******************************************************************
2023 * IsWindow (USER32.@)
2025 BOOL WINAPI IsWindow( HWND hwnd )
2030 if ((ptr = WIN_GetWndPtr( hwnd )))
2032 if (ptr == BAD_WND_PTR) return FALSE;
2037 /* check other processes */
2038 SERVER_START_REQ( get_window_info )
2041 ret = !SERVER_CALL_ERR();
2048 /***********************************************************************
2049 * GetWindowThreadProcessId (USER32.@)
2051 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2056 if ((ptr = WIN_GetWndPtr( hwnd )))
2058 if (ptr != BAD_WND_PTR)
2060 /* got a valid window */
2062 if (process) *process = GetCurrentProcessId();
2065 else SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2069 /* check other processes */
2070 SERVER_START_REQ( get_window_info )
2073 if (!SERVER_CALL_ERR())
2075 tid = (DWORD)req->tid;
2076 if (process) *process = (DWORD)req->pid;
2084 /*****************************************************************
2085 * GetParent (USER32.@)
2087 HWND WINAPI GetParent( HWND hwnd )
2092 if ((wndPtr = WIN_FindWndPtr(hwnd)))
2094 if (wndPtr->dwStyle & WS_CHILD)
2095 retvalue = wndPtr->parent->hwndSelf;
2096 else if (wndPtr->dwStyle & WS_POPUP)
2097 retvalue = wndPtr->owner;
2098 WIN_ReleaseWndPtr(wndPtr);
2104 /*****************************************************************
2105 * GetAncestor (USER32.@)
2107 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2112 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2113 if (wndPtr->hwndSelf == GetDesktopWindow()) goto done;
2118 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2121 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2122 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2125 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2126 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2127 while (wndPtr && wndPtr->owner)
2129 WND *ptr = WIN_FindWndPtr( wndPtr->owner );
2130 WIN_ReleaseWndPtr( wndPtr );
2135 ret = wndPtr ? wndPtr->hwndSelf : 0;
2137 WIN_ReleaseWndPtr( wndPtr );
2142 /*****************************************************************
2143 * SetParent (USER32.@)
2145 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2151 if (!parent) parent = GetDesktopWindow();
2152 else parent = WIN_GetFullHandle( parent );
2155 if (WIN_GetFullHandle(hwnd) == GetDesktopWindow() || !IsWindow( parent ))
2157 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2161 if (USER_Driver.pSetParent)
2162 return USER_Driver.pSetParent( hwnd, parent );
2164 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2166 dwStyle = wndPtr->dwStyle;
2168 /* Windows hides the window first, then shows it again
2169 * including the WM_SHOWWINDOW messages and all */
2170 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2172 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2173 if (parent != retvalue)
2175 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2177 if (parent != GetDesktopWindow()) /* a child window */
2179 if (!(dwStyle & WS_CHILD))
2181 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2182 if (menu) DestroyMenu( menu );
2186 WIN_ReleaseWndPtr( wndPtr );
2188 /* SetParent additionally needs to make hwnd the topmost window
2189 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2190 WM_WINDOWPOSCHANGED notification messages.
2192 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2193 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2194 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2195 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2196 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2201 /*******************************************************************
2202 * IsChild (USER32.@)
2204 BOOL WINAPI IsChild( HWND parent, HWND child )
2206 HWND *list = WIN_ListParents( child );
2210 if (!list) return FALSE;
2211 parent = WIN_GetFullHandle( parent );
2212 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2213 ret = (list[i] != 0);
2214 HeapFree( GetProcessHeap(), 0, list );
2219 /***********************************************************************
2220 * IsWindowVisible (USER32.@)
2222 BOOL WINAPI IsWindowVisible( HWND hwnd )
2228 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2229 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2230 for (i = 0; list[i]; i++)
2231 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2233 HeapFree( GetProcessHeap(), 0, list );
2238 /***********************************************************************
2239 * WIN_IsWindowDrawable
2241 * hwnd is drawable when it is visible, all parents are not
2242 * minimized, and it is itself not minimized unless we are
2243 * trying to draw its default class icon.
2245 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2251 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2252 if ((wnd->dwStyle & WS_MINIMIZE) &&
2253 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2255 if (!(list = WIN_ListParents( wnd->hwndSelf ))) return TRUE;
2256 for (i = 0; list[i]; i++)
2257 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2260 HeapFree( GetProcessHeap(), 0, list );
2265 /*******************************************************************
2266 * GetTopWindow (USER32.@)
2268 HWND WINAPI GetTopWindow( HWND hwnd )
2270 if (!hwnd) hwnd = GetDesktopWindow();
2271 return GetWindow( hwnd, GW_CHILD );
2275 /*******************************************************************
2276 * GetWindow (USER32.@)
2278 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2282 if (rel == GW_OWNER) /* special case: not fully supported in the server yet */
2284 WND *wndPtr = WIN_FindWndPtr( hwnd );
2285 if (!wndPtr) return 0;
2286 retval = wndPtr->owner;
2287 WIN_ReleaseWndPtr( wndPtr );
2291 SERVER_START_REQ( get_window_tree )
2294 if (!SERVER_CALL_ERR())
2299 retval = req->first_sibling;
2302 retval = req->last_sibling;
2305 retval = req->next_sibling;
2308 retval = req->prev_sibling;
2311 retval = req->first_child;
2321 /***********************************************************************
2322 * WIN_InternalShowOwnedPopups
2324 * Internal version of ShowOwnedPopups; Wine functions should use this
2325 * to avoid interfering with application calls to ShowOwnedPopups
2326 * and to make sure the application can't prevent showing/hiding.
2328 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2332 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2336 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2338 if (!win_array) return TRUE;
2341 * Show windows Lowest first, Highest last to preserve Z-Order
2343 while (win_array[count]) count++;
2344 while (--count >= 0)
2346 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2347 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2349 if (pWnd->dwStyle & WS_POPUP)
2353 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2354 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2357 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2359 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2360 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2365 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2366 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2367 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2370 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2372 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2373 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2374 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2378 WIN_ReleaseWndPtr( pWnd );
2380 HeapFree( GetProcessHeap(), 0, win_array );
2385 /*******************************************************************
2386 * ShowOwnedPopups (USER32.@)
2388 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2392 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2394 if (!win_array) return TRUE;
2396 while (win_array[count]) count++;
2397 while (--count >= 0)
2399 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2400 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2402 if (pWnd->dwStyle & WS_POPUP)
2406 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2408 /* In Windows, ShowOwnedPopups(TRUE) generates
2409 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2410 * regardless of the state of the owner
2412 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2413 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2418 if (IsWindowVisible(pWnd->hwndSelf))
2420 /* In Windows, ShowOwnedPopups(FALSE) generates
2421 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2422 * regardless of the state of the owner
2424 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2425 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2429 WIN_ReleaseWndPtr( pWnd );
2431 HeapFree( GetProcessHeap(), 0, win_array );
2436 /*******************************************************************
2437 * GetLastActivePopup (USER32.@)
2439 HWND WINAPI GetLastActivePopup( HWND hwnd )
2442 WND *wndPtr =WIN_FindWndPtr(hwnd);
2443 if (!wndPtr) return hwnd;
2444 retval = wndPtr->hwndLastActive;
2445 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2446 WIN_ReleaseWndPtr(wndPtr);
2451 /*******************************************************************
2454 * Build an array of all parents of a given window, starting with
2455 * the immediate parent. The array must be freed with HeapFree.
2456 * Returns NULL if window is a top-level window.
2458 HWND *WIN_ListParents( HWND hwnd )
2462 SERVER_START_VAR_REQ( get_window_parents, REQUEST_MAX_VAR_SIZE )
2467 user_handle_t *data = server_data_ptr(req);
2468 int i, count = server_data_size(req) / sizeof(*data);
2469 if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) ))))
2471 for (i = 0; i < count; i++) list[i] = data[i];
2481 /*******************************************************************
2484 * Build an array of the children of a given window. The array must be
2485 * freed with HeapFree. Returns NULL when no windows are found.
2487 HWND *WIN_ListChildren( HWND hwnd )
2489 return list_window_children( hwnd, 0, 0 );
2493 /*******************************************************************
2494 * EnumWindows (USER32.@)
2496 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2502 /* We have to build a list of all windows first, to avoid */
2503 /* unpleasant side-effects, for instance if the callback */
2504 /* function changes the Z-order of the windows. */
2506 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2508 /* Now call the callback function for every window */
2510 iWndsLocks = WIN_SuspendWndsLock();
2511 for (i = 0; list[i]; i++)
2513 /* Make sure that the window still exists */
2514 if (!IsWindow( list[i] )) continue;
2515 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2517 WIN_RestoreWndsLock(iWndsLocks);
2518 HeapFree( GetProcessHeap(), 0, list );
2523 /**********************************************************************
2524 * EnumTaskWindows16 (USER.225)
2526 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2529 TDB *tdb = TASK_GetPtr( hTask );
2530 if (!tdb) return FALSE;
2531 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2535 /**********************************************************************
2536 * EnumThreadWindows (USER32.@)
2538 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2543 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2546 /* Now call the callback function for every window */
2548 iWndsLocks = WIN_SuspendWndsLock();
2549 for (i = 0; list[i]; i++)
2550 if (!func( list[i], lParam )) break;
2551 WIN_RestoreWndsLock(iWndsLocks);
2552 HeapFree( GetProcessHeap(), 0, list );
2557 /**********************************************************************
2558 * WIN_EnumChildWindows
2560 * Helper function for EnumChildWindows().
2562 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2567 for ( ; *list; list++)
2569 /* Make sure that the window still exists */
2570 if (!IsWindow( *list )) continue;
2571 /* skip owned windows */
2572 if (GetWindow( *list, GW_OWNER )) continue;
2573 /* Build children list first */
2574 childList = WIN_ListChildren( *list );
2576 ret = func( *list, lParam );
2580 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2581 HeapFree( GetProcessHeap(), 0, childList );
2583 if (!ret) return FALSE;
2589 /**********************************************************************
2590 * EnumChildWindows (USER32.@)
2592 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2597 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2598 iWndsLocks = WIN_SuspendWndsLock();
2599 WIN_EnumChildWindows( list, func, lParam );
2600 WIN_RestoreWndsLock(iWndsLocks);
2601 HeapFree( GetProcessHeap(), 0, list );
2606 /*******************************************************************
2607 * AnyPopup (USER.52)
2609 BOOL16 WINAPI AnyPopup16(void)
2615 /*******************************************************************
2616 * AnyPopup (USER32.@)
2618 BOOL WINAPI AnyPopup(void)
2622 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2624 if (!list) return FALSE;
2625 for (i = 0; list[i]; i++)
2627 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2629 retvalue = (list[i] != 0);
2630 HeapFree( GetProcessHeap(), 0, list );
2635 /*******************************************************************
2636 * FlashWindow (USER32.@)
2638 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2640 WND *wndPtr = WIN_FindWndPtr(hWnd);
2642 TRACE("%04x\n", hWnd);
2644 if (!wndPtr) return FALSE;
2645 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2647 if (wndPtr->dwStyle & WS_MINIMIZE)
2649 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2651 HDC hDC = GetDC(hWnd);
2653 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2654 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2656 ReleaseDC( hWnd, hDC );
2657 wndPtr->flags |= WIN_NCACTIVATED;
2661 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2662 wndPtr->flags &= ~WIN_NCACTIVATED;
2664 WIN_ReleaseWndPtr(wndPtr);
2670 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2671 else wparam = (hWnd == GetActiveWindow());
2673 WIN_ReleaseWndPtr(wndPtr);
2674 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2680 /*******************************************************************
2681 * GetWindowContextHelpId (USER32.@)
2683 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2686 WND *wnd = WIN_FindWndPtr( hwnd );
2688 retval = wnd->helpContext;
2689 WIN_ReleaseWndPtr(wnd);
2694 /*******************************************************************
2695 * SetWindowContextHelpId (USER32.@)
2697 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2699 WND *wnd = WIN_FindWndPtr( hwnd );
2700 if (!wnd) return FALSE;
2701 wnd->helpContext = id;
2702 WIN_ReleaseWndPtr(wnd);
2707 /*******************************************************************
2710 * recursively find a child that contains spDragInfo->pt point
2711 * and send WM_QUERYDROPOBJECT
2713 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2715 BOOL16 wParam, bResult = 0;
2717 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
2720 if (!ptrDragInfo) return FALSE;
2722 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2724 GetWindowRect(hQueryWnd,&tempRect);
2726 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
2728 if (!IsIconic( hQueryWnd ))
2730 GetClientRect( hQueryWnd, &tempRect );
2731 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
2733 if (PtInRect( &tempRect, pt))
2736 HWND *list = WIN_ListChildren( hQueryWnd );
2742 for (i = 0; list[i]; i++)
2744 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
2746 GetWindowRect( list[i], &tempRect );
2747 if (PtInRect( &tempRect, pt )) break;
2752 if (IsWindowEnabled( list[i] ))
2753 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
2755 HeapFree( GetProcessHeap(), 0, list );
2757 if(bResult) return bResult;
2763 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2765 ptrDragInfo->hScope = hQueryWnd;
2767 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
2768 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
2770 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2776 /*******************************************************************
2777 * DragDetect (USER32.@)
2779 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2784 rect.left = pt.x - wDragWidth;
2785 rect.right = pt.x + wDragWidth;
2787 rect.top = pt.y - wDragHeight;
2788 rect.bottom = pt.y + wDragHeight;
2794 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2796 if( msg.message == WM_LBUTTONUP )
2801 if( msg.message == WM_MOUSEMOVE )
2804 tmp.x = LOWORD(msg.lParam);
2805 tmp.y = HIWORD(msg.lParam);
2806 if( !PtInRect( &rect, tmp ))
2818 /******************************************************************************
2819 * DragObject (USER.464)
2821 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2822 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2825 LPDRAGINFO16 lpDragInfo;
2827 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2828 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
2829 HCURSOR16 hCurrentCursor = 0;
2830 HWND16 hCurrentWnd = 0;
2832 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
2833 spDragInfo = K32WOWGlobalLock16(hDragInfo);
2835 if( !lpDragInfo || !spDragInfo ) return 0L;
2837 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
2839 GlobalFree16(hDragInfo);
2845 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2847 GlobalFree16(hDragInfo);
2851 if( hDragCursor == hCursor ) hDragCursor = 0;
2852 else hCursor = hDragCursor;
2854 hOldCursor = SetCursor(hDragCursor);
2857 lpDragInfo->hWnd = hWnd;
2858 lpDragInfo->hScope = 0;
2859 lpDragInfo->wFlags = wObj;
2860 lpDragInfo->hList = szList; /* near pointer! */
2861 lpDragInfo->hOfStruct = hOfStruct;
2869 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
2871 *(lpDragInfo+1) = *lpDragInfo;
2873 lpDragInfo->pt.x = msg.pt.x;
2874 lpDragInfo->pt.y = msg.pt.y;
2876 /* update DRAGINFO struct */
2877 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
2879 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2880 hCurrentCursor = hCursor;
2883 hCurrentCursor = hBummer;
2884 lpDragInfo->hScope = 0;
2886 if( hCurrentCursor )
2887 SetCursor(hCurrentCursor);
2889 /* send WM_DRAGLOOP */
2890 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2891 (LPARAM) spDragInfo );
2892 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2893 if( hCurrentWnd != lpDragInfo->hScope )
2896 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2897 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
2898 HIWORD(spDragInfo)) );
2899 hCurrentWnd = lpDragInfo->hScope;
2901 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2905 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2907 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2910 ShowCursor( FALSE );
2914 SetCursor( hOldCursor );
2915 if (hDragCursor) DestroyCursor( hDragCursor );
2918 if( hCurrentCursor != hBummer )
2919 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2920 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2923 GlobalFree16(hDragInfo);
2925 return (DWORD)(msg.lParam);
2929 /******************************************************************************
2930 * GetWindowModuleFileNameA (USER32.@)
2932 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
2934 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
2935 hwnd, lpszFileName, cchFileNameMax);
2939 /******************************************************************************
2940 * GetWindowModuleFileNameW (USER32.@)
2942 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
2944 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
2945 hwnd, lpszFileName, cchFileNameMax);