2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include "wine/winbase16.h"
11 #include "wine/winuser16.h"
12 #include "wine/unicode.h"
18 #include "cursoricon.h"
25 #include "stackframe.h"
26 #include "debugtools.h"
28 DEFAULT_DEBUG_CHANNEL(win);
29 DECLARE_DEBUG_CHANNEL(msg);
31 /**********************************************************************/
34 static WND *pWndDesktop = NULL;
36 static HWND hwndSysModal = 0;
38 static WORD wDragWidth = 4;
39 static WORD wDragHeight= 3;
42 extern SYSLEVEL USER_SysLevel; /* FIXME */
44 /***********************************************************************
47 * Suspend the lock on WND structures.
48 * Returns the number of locks suspended
50 int WIN_SuspendWndsLock( void )
52 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
53 int count = isuspendedLocks;
56 _LeaveSysLevel( &USER_SysLevel );
58 return isuspendedLocks;
61 /***********************************************************************
64 * Restore the suspended locks on WND structures
66 void WIN_RestoreWndsLock( int ipreviousLocks )
68 while ( ipreviousLocks-- > 0 )
69 _EnterSysLevel( &USER_SysLevel );
72 /***********************************************************************
75 * Return a pointer to the WND structure corresponding to a HWND.
77 WND * WIN_FindWndPtr( HWND hwnd )
81 if (!hwnd || HIWORD(hwnd)) goto error2;
82 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
83 /* Lock all WND structures for thread safeness*/
85 /*and increment destruction monitoring*/
88 if (ptr->dwMagic != WND_MAGIC) goto error;
89 if (ptr->hwndSelf != hwnd)
91 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
94 /* returns a locked pointer */
97 /* Unlock all WND structures for thread safeness*/
99 /* and decrement destruction monitoring value */
104 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
108 /***********************************************************************
111 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
113 * Returns the locked initialisation pointer
115 WND *WIN_LockWndPtr(WND *initWndPtr)
117 if(!initWndPtr) return 0;
119 /* Lock all WND structures for thread safeness*/
121 /*and increment destruction monitoring*/
122 initWndPtr->irefCount++;
128 /***********************************************************************
131 * Release the pointer to the WND structure.
133 void WIN_ReleaseWndPtr(WND *wndPtr)
137 /*Decrement destruction monitoring value*/
139 /* Check if it's time to release the memory*/
140 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
143 USER_HEAP_FREE( wndPtr->hwndSelf);
144 wndPtr->hwndSelf = 0;
146 else if(wndPtr->irefCount < 0)
148 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
149 ERR("forgot a Lock on %p somewhere\n",wndPtr);
151 /*unlock all WND structures for thread safeness*/
155 /***********************************************************************
158 * Updates the value of oldPtr to newPtr.
160 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
164 tmpWnd = WIN_LockWndPtr(newPtr);
165 WIN_ReleaseWndPtr(*oldPtr);
170 /***********************************************************************
173 * Dump the content of a window structure to stderr.
175 void WIN_DumpWindow( HWND hwnd )
181 if (!(ptr = WIN_FindWndPtr( hwnd )))
183 WARN("%04x is not a window handle\n", hwnd );
187 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
188 strcpy( className, "#NULL#" );
190 TRACE("Window %04x (%p):\n", hwnd, ptr );
191 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
192 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
193 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
194 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
195 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
196 ptr->next, ptr->child, ptr->parent, ptr->owner,
197 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
198 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
199 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
200 ptr->text ? debugstr_w(ptr->text) : "",
201 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
202 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
203 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
204 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
208 DPRINTF( "extra bytes:" );
209 for (i = 0; i < ptr->cbWndExtra; i++)
210 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
214 WIN_ReleaseWndPtr(ptr);
218 /***********************************************************************
221 * Remove a window from the siblings linked list.
223 BOOL WIN_UnlinkWindow( HWND hwnd )
225 WND *wndPtr, **ppWnd;
228 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
229 else if(!wndPtr->parent)
231 WIN_ReleaseWndPtr(wndPtr);
235 ppWnd = &wndPtr->parent->child;
236 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
239 *ppWnd = wndPtr->next;
242 WIN_ReleaseWndPtr(wndPtr);
247 /***********************************************************************
250 * Insert a window into the siblings linked list.
251 * The window is inserted after the specified window, which can also
252 * be specified as HWND_TOP or HWND_BOTTOM.
254 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
256 WND *wndPtr, **ppWnd;
258 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
259 else if(!wndPtr->parent)
261 WIN_ReleaseWndPtr(wndPtr);
264 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
266 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
267 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
268 while (*ppWnd) ppWnd = &(*ppWnd)->next;
270 else /* Normal case */
272 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
275 WIN_ReleaseWndPtr(wndPtr);
278 ppWnd = &afterPtr->next;
279 WIN_ReleaseWndPtr(afterPtr);
281 wndPtr->next = *ppWnd;
283 WIN_ReleaseWndPtr(wndPtr);
288 /***********************************************************************
289 * WIN_FindWinToRepaint
291 * Find a window that needs repaint.
293 HWND WIN_FindWinToRepaint( HWND hwnd )
298 /* Note: the desktop window never gets WM_PAINT messages
299 * The real reason why is because Windows DesktopWndProc
300 * does ValidateRgn inside WM_ERASEBKGND handler.
302 if (hwnd == GetDesktopWindow()) hwnd = 0;
304 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
306 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
308 if (!(pWnd->dwStyle & WS_VISIBLE))
310 TRACE("skipping window %04x\n",
313 else if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
314 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
317 else if (pWnd->child )
318 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
320 WIN_ReleaseWndPtr(pWnd);
331 hwndRet = pWnd->hwndSelf;
333 /* look among siblings if we got a transparent window */
334 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
335 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
337 WIN_UpdateWndPtr(&pWnd,pWnd->next);
341 hwndRet = pWnd->hwndSelf;
342 WIN_ReleaseWndPtr(pWnd);
344 TRACE("found %04x\n",hwndRet);
349 /***********************************************************************
352 * Destroy storage associated to a window. "Internals" p.358
353 * returns a locked wndPtr->next
355 static WND* WIN_DestroyWindow( WND* wndPtr )
357 HWND hwnd = wndPtr->hwndSelf;
360 TRACE("%04x\n", wndPtr->hwndSelf );
362 /* free child windows */
363 WIN_LockWndPtr(wndPtr->child);
364 while ((pWnd = wndPtr->child))
366 wndPtr->child = WIN_DestroyWindow( pWnd );
367 WIN_ReleaseWndPtr(pWnd);
371 * Clear the update region to make sure no WM_PAINT messages will be
372 * generated for this window while processing the WM_NCDESTROY.
374 RedrawWindow( wndPtr->hwndSelf, NULL, 0,
375 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
378 * Send the WM_NCDESTROY to the window being destroyed.
380 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
382 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
384 WINPOS_CheckInternalPos( hwnd );
385 if( hwnd == GetCapture()) ReleaseCapture();
387 /* free resources associated with the window */
389 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
390 PROPERTY_RemoveWindowProps( wndPtr );
392 /* toss stale messages from the queue */
394 QUEUE_CleanupWindow( hwnd );
395 wndPtr->hmemTaskQ = 0;
397 if (!(wndPtr->dwStyle & WS_CHILD))
400 DestroyMenu( wndPtr->wIDmenu );
403 if (wndPtr->hSysMenu)
405 DestroyMenu( wndPtr->hSysMenu );
406 wndPtr->hSysMenu = 0;
408 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
409 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
410 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
411 CLASS_RemoveWindow( wndPtr->class );
412 wndPtr->class = NULL;
413 wndPtr->dwMagic = 0; /* Mark it as invalid */
415 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
420 /***********************************************************************
421 * WIN_DestroyThreadWindows
423 * Destroy all children of 'wnd' owned by the current thread.
424 * Return TRUE if something was done.
426 BOOL WIN_DestroyThreadWindows( HWND hwnd )
429 WND *wnd = WIN_FindWndPtr( hwnd );
431 if (!wnd) return FALSE;
434 WND *tmp = WIN_LockWndPtr(wnd->child);
438 if (GetWindowThreadProcessId( tmp->hwndSelf, NULL ) == GetCurrentThreadId())
440 DestroyWindow( tmp->hwndSelf );
444 if (tmp->child && WIN_DestroyThreadWindows( tmp->hwndSelf ))
447 WIN_UpdateWndPtr(&tmp,tmp->next);
449 WIN_ReleaseWndPtr(tmp);
452 WIN_ReleaseWndPtr( wnd );
456 /***********************************************************************
457 * WIN_CreateDesktopWindow
459 * Create the desktop window.
461 BOOL WIN_CreateDesktopWindow(void)
463 struct tagCLASS *class;
471 TRACE("Creating desktop window\n");
474 if (!WINPOS_CreateInternalPosAtom() ||
475 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
476 &wndExtra, &winproc, &clsStyle, &dce )))
479 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
480 if (!hwndDesktop) return FALSE;
481 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
483 pWndDesktop->next = NULL;
484 pWndDesktop->child = NULL;
485 pWndDesktop->parent = NULL;
486 pWndDesktop->owner = NULL;
487 pWndDesktop->class = class;
488 pWndDesktop->dwMagic = WND_MAGIC;
489 pWndDesktop->hwndSelf = hwndDesktop;
490 pWndDesktop->hInstance = 0;
491 pWndDesktop->rectWindow.left = 0;
492 pWndDesktop->rectWindow.top = 0;
493 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
494 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
495 pWndDesktop->rectClient = pWndDesktop->rectWindow;
496 pWndDesktop->text = NULL;
497 pWndDesktop->hmemTaskQ = 0;
498 pWndDesktop->hrgnUpdate = 0;
499 pWndDesktop->hwndLastActive = hwndDesktop;
500 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
502 pWndDesktop->dwExStyle = 0;
503 pWndDesktop->clsStyle = clsStyle;
504 pWndDesktop->dce = NULL;
505 pWndDesktop->pVScroll = NULL;
506 pWndDesktop->pHScroll = NULL;
507 pWndDesktop->pProp = NULL;
508 pWndDesktop->wIDmenu = 0;
509 pWndDesktop->helpContext = 0;
510 pWndDesktop->flags = 0;
511 pWndDesktop->hSysMenu = 0;
512 pWndDesktop->userdata = 0;
513 pWndDesktop->winproc = winproc;
514 pWndDesktop->cbWndExtra = wndExtra;
515 pWndDesktop->irefCount = 0;
517 cs.lpCreateParams = NULL;
523 cs.cx = pWndDesktop->rectWindow.right;
524 cs.cy = pWndDesktop->rectWindow.bottom;
525 cs.style = pWndDesktop->dwStyle;
526 cs.dwExStyle = pWndDesktop->dwExStyle;
528 cs.lpszClass = DESKTOP_CLASS_ATOM;
530 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
532 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
537 /***********************************************************************
540 * Fix the coordinates - Helper for WIN_CreateWindowEx.
541 * returns default show mode in sw.
542 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
544 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
546 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
547 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
549 if (cs->style & (WS_CHILD | WS_POPUP))
551 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
552 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
554 else /* overlapped window */
558 GetStartupInfoA( &info );
560 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
562 /* Never believe Microsoft's documentation... CreateWindowEx doc says
563 * that if an overlapped window is created with WS_VISIBLE style bit
564 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
565 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
568 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
569 * 2) it does not ignore the y parameter as the docs claim; instead, it
570 * uses it as second parameter to ShowWindow() unless y is either
571 * CW_USEDEFAULT or CW_USEDEFAULT16.
573 * The fact that we didn't do 2) caused bogus windows pop up when wine
574 * was running apps that were using this obscure feature. Example -
575 * calc.exe that comes with Win98 (only Win98, it's different from
576 * the one that comes with Win95 and NT)
578 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
579 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
580 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
583 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
585 if (info.dwFlags & STARTF_USESIZE)
587 cs->cx = info.dwXSize;
588 cs->cy = info.dwYSize;
590 else /* if no other hint from the app, pick 3/4 of the screen real estate */
593 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
594 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
595 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
602 /***********************************************************************
605 * Implementation of CreateWindowEx().
607 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
608 WINDOWPROCTYPE type )
611 struct tagCLASS *classPtr;
613 HWND hwnd, hwndLinkAfter;
614 POINT maxSize, maxPos, minTrack, maxTrack;
619 BOOL unicode = (type == WIN_PROC_32W);
621 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
622 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
623 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
624 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
625 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
627 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
628 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
630 /* Find the parent window */
634 /* Make sure parent is valid */
635 if (!IsWindow( cs->hwndParent ))
637 WARN("Bad parent %04x\n", cs->hwndParent );
640 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
641 WARN("No parent for child window\n" );
642 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
645 /* Find the window class */
646 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
647 &wndExtra, &winproc, &clsStyle, &dce )))
649 WARN("Bad class '%s'\n", cs->lpszClass );
653 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
655 /* Correct the window style - stage 1
657 * These are patches that appear to affect both the style loaded into the
658 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
660 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
661 * why does the user get to set it?
664 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
665 * tested for WS_POPUP
667 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
668 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
669 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
670 cs->dwExStyle |= WS_EX_WINDOWEDGE;
672 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
674 /* Create the window structure */
676 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
678 TRACE("out of memory\n" );
682 /* Fill the window structure */
684 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
686 wndPtr->child = NULL;
688 if ((cs->style & WS_CHILD) && cs->hwndParent)
690 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
691 wndPtr->owner = NULL;
692 WIN_ReleaseWndPtr(wndPtr->parent);
696 wndPtr->parent = pWndDesktop;
697 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
698 wndPtr->owner = NULL;
701 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
702 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
703 WIN_ReleaseWndPtr(wndPtr->owner);
704 WIN_ReleaseWndPtr(tmpWnd);
709 wndPtr->class = classPtr;
710 wndPtr->winproc = winproc;
711 wndPtr->dwMagic = WND_MAGIC;
712 wndPtr->hwndSelf = hwnd;
713 wndPtr->hInstance = cs->hInstance;
715 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
716 wndPtr->hrgnUpdate = 0;
718 wndPtr->hwndLastActive = hwnd;
719 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
720 wndPtr->dwExStyle = cs->dwExStyle;
721 wndPtr->clsStyle = clsStyle;
723 wndPtr->helpContext = 0;
724 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
725 wndPtr->pVScroll = NULL;
726 wndPtr->pHScroll = NULL;
727 wndPtr->pProp = NULL;
728 wndPtr->userdata = 0;
729 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
730 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
731 wndPtr->cbWndExtra = wndExtra;
732 wndPtr->irefCount = 1;
734 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
736 /* Call the WH_CBT hook */
738 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
739 ? HWND_BOTTOM : HWND_TOP;
741 if (HOOK_IsHooked( WH_CBT ))
747 cbtc.hwndInsertAfter = hwndLinkAfter;
748 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
749 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
752 TRACE("CBT-hook returned 0\n");
753 USER_HEAP_FREE( hwnd );
754 CLASS_RemoveWindow( classPtr );
760 /* Correct the window style - stage 2 */
762 if (!(cs->style & WS_CHILD))
764 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
765 if (!(cs->style & WS_POPUP))
767 wndPtr->dwStyle |= WS_CAPTION;
768 wndPtr->flags |= WIN_NEED_SIZE;
772 /* Get class or window DC if needed */
774 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
775 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
776 else wndPtr->dce = NULL;
778 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
780 wndPtr->rectWindow.left = cs->x;
781 wndPtr->rectWindow.top = cs->y;
782 wndPtr->rectWindow.right = cs->x + cs->cx;
783 wndPtr->rectWindow.bottom = cs->y + cs->cy;
784 wndPtr->rectClient = wndPtr->rectWindow;
786 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
788 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
790 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
791 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
792 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
793 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
794 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
797 if (cs->cx < 0) cs->cx = 0;
798 if (cs->cy < 0) cs->cy = 0;
800 wndPtr->rectWindow.left = cs->x;
801 wndPtr->rectWindow.top = cs->y;
802 wndPtr->rectWindow.right = cs->x + cs->cx;
803 wndPtr->rectWindow.bottom = cs->y + cs->cy;
804 wndPtr->rectClient = wndPtr->rectWindow;
806 /* Set the window menu */
808 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
810 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
813 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
816 if (HIWORD(cs->hInstance))
817 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
819 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
821 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
825 else wndPtr->wIDmenu = (UINT)cs->hMenu;
827 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
829 WARN("aborted by WM_xxCREATE!\n");
830 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
831 CLASS_RemoveWindow( classPtr );
832 WIN_ReleaseWndPtr(wndPtr);
836 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
838 /* Notify the parent window only */
840 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
841 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
842 if( !IsWindow(hwnd) )
849 if (cs->style & WS_VISIBLE)
851 /* in case WS_VISIBLE got set in the meantime */
852 wndPtr->dwStyle &= ~WS_VISIBLE;
853 ShowWindow( hwnd, sw );
856 /* Call WH_SHELL hook */
858 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
859 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
861 TRACE("created window %04x\n", hwnd);
863 WIN_ReleaseWndPtr(wndPtr);
868 /***********************************************************************
869 * CreateWindow (USER.41)
871 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
872 DWORD style, INT16 x, INT16 y, INT16 width,
873 INT16 height, HWND16 parent, HMENU16 menu,
874 HINSTANCE16 instance, LPVOID data )
876 return CreateWindowEx16( 0, className, windowName, style,
877 x, y, width, height, parent, menu, instance, data );
881 /***********************************************************************
882 * CreateWindowEx (USER.452)
884 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
885 LPCSTR windowName, DWORD style, INT16 x,
886 INT16 y, INT16 width, INT16 height,
887 HWND16 parent, HMENU16 menu,
888 HINSTANCE16 instance, LPVOID data )
894 /* Find the class atom */
896 if (HIWORD(className))
898 if (!(classAtom = GlobalFindAtomA( className )))
900 ERR( "bad class name %s\n", debugres_a(className) );
906 classAtom = LOWORD(className);
907 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
909 ERR( "bad atom %x\n", classAtom);
915 /* Fix the coordinates */
917 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
918 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
919 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
920 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
922 /* Create the window */
924 cs.lpCreateParams = data;
925 cs.hInstance = (HINSTANCE)instance;
926 cs.hMenu = (HMENU)menu;
927 cs.hwndParent = (HWND)parent;
929 cs.lpszName = windowName;
930 cs.lpszClass = className;
931 cs.dwExStyle = exStyle;
933 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
937 /***********************************************************************
938 * CreateWindowExA (USER32.@)
940 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
941 LPCSTR windowName, DWORD style, INT x,
942 INT y, INT width, INT height,
943 HWND parent, HMENU menu,
944 HINSTANCE instance, LPVOID data )
951 instance=GetModuleHandleA(NULL);
953 if(exStyle & WS_EX_MDICHILD)
954 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
956 /* Find the class atom */
958 if (HIWORD(className))
960 if (!(classAtom = GlobalFindAtomA( className )))
962 ERR( "bad class name %s\n", debugres_a(className) );
968 classAtom = LOWORD(className);
969 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
971 ERR( "bad atom %x\n", classAtom);
977 /* Create the window */
979 cs.lpCreateParams = data;
980 cs.hInstance = instance;
982 cs.hwndParent = parent;
988 cs.lpszName = windowName;
989 cs.lpszClass = className;
990 cs.dwExStyle = exStyle;
992 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
996 /***********************************************************************
997 * CreateWindowExW (USER32.@)
999 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1000 LPCWSTR windowName, DWORD style, INT x,
1001 INT y, INT width, INT height,
1002 HWND parent, HMENU menu,
1003 HINSTANCE instance, LPVOID data )
1010 instance=GetModuleHandleA(NULL);
1012 if(exStyle & WS_EX_MDICHILD)
1013 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1015 /* Find the class atom */
1017 if (HIWORD(className))
1019 if (!(classAtom = GlobalFindAtomW( className )))
1021 ERR( "bad class name %s\n", debugres_w(className) );
1027 classAtom = LOWORD(className);
1028 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1030 ERR( "bad atom %x\n", classAtom);
1036 /* Create the window */
1038 cs.lpCreateParams = data;
1039 cs.hInstance = instance;
1041 cs.hwndParent = parent;
1047 cs.lpszName = windowName;
1048 cs.lpszClass = className;
1049 cs.dwExStyle = exStyle;
1051 /* Note: we rely on the fact that CREATESTRUCTA and */
1052 /* CREATESTRUCTW have the same layout. */
1053 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1056 /***********************************************************************
1057 * WIN_SendDestroyMsg
1059 static void WIN_SendDestroyMsg( WND* pWnd )
1061 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1062 if (USER_Driver.pResetSelectionOwner)
1063 USER_Driver.pResetSelectionOwner( pWnd->hwndSelf, TRUE );
1066 * Send the WM_DESTROY to the window.
1068 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1071 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1072 * make sure that the window still exists when we come back.
1074 if (IsWindow(pWnd->hwndSelf))
1076 HWND* pWndArray = NULL;
1081 * Now, if the window has kids, we have to send WM_DESTROY messages
1082 * recursively to it's kids. It seems that those calls can also
1083 * trigger re-entrant calls to DestroyWindow for the kids so we must
1084 * protect against corruption of the list of siblings. We first build
1085 * a list of HWNDs representing all the kids.
1087 pChild = WIN_LockWndPtr(pWnd->child);
1091 WIN_UpdateWndPtr(&pChild,pChild->next);
1095 * If there are no kids, we're done.
1100 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1105 if (pWndArray==NULL)
1109 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1110 * call, our linked list of siblings should be safe.
1113 pChild = WIN_LockWndPtr(pWnd->child);
1116 pWndArray[nKidCount] = pChild->hwndSelf;
1118 WIN_UpdateWndPtr(&pChild,pChild->next);
1122 * Now that we have a list, go through that list again and send the destroy
1123 * message to those windows. We are using the HWND to retrieve the
1124 * WND pointer so we are effectively checking that all the kid windows are
1125 * still valid before sending the message.
1129 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1133 WIN_SendDestroyMsg( pChild );
1134 WIN_ReleaseWndPtr(pChild);
1141 HeapFree(GetProcessHeap(), 0, pWndArray);
1144 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1148 /***********************************************************************
1149 * DestroyWindow (USER.53)
1151 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1153 return DestroyWindow(hwnd);
1157 /***********************************************************************
1158 * DestroyWindow (USER32.@)
1160 BOOL WINAPI DestroyWindow( HWND hwnd )
1165 BOOL bFocusSet = FALSE;
1167 TRACE("(%04x)\n", hwnd);
1169 /* Initialization */
1171 if (hwnd == GetDesktopWindow()) return FALSE; /* Can't destroy desktop */
1172 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1174 /* Look whether the focus is within the tree of windows we will
1178 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1182 SetFocus(GetParent(h));
1188 /* If the focus is on the window we will destroy and it has no parent,
1189 * set the focus to 0.
1191 if (! bFocusSet && (h == hwnd))
1193 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1199 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1205 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1207 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1208 /* FIXME: clean up palette - see "Internals" p.352 */
1211 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1212 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1214 /* Notify the parent window only */
1215 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1216 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1217 if( !IsWindow(hwnd) )
1224 if (USER_Driver.pResetSelectionOwner)
1225 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1227 /* Hide the window */
1229 if (wndPtr->dwStyle & WS_VISIBLE)
1231 ShowWindow( hwnd, SW_HIDE );
1232 if (!IsWindow(hwnd))
1239 /* Recursively destroy owned windows */
1241 if( !(wndPtr->dwStyle & WS_CHILD) )
1245 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1248 if (siblingPtr->owner == wndPtr)
1250 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1253 siblingPtr->owner = NULL;
1255 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1259 DestroyWindow( siblingPtr->hwndSelf );
1260 WIN_ReleaseWndPtr(siblingPtr);
1265 WINPOS_ActivateOtherWindow(wndPtr->hwndSelf);
1267 if( wndPtr->owner &&
1268 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1269 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1272 /* Send destroy messages */
1274 WIN_SendDestroyMsg( wndPtr );
1275 if (!IsWindow(hwnd))
1281 /* Unlink now so we won't bother with the children later on */
1283 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1285 /* Destroy the window storage */
1287 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1290 WIN_ReleaseWndPtr(wndPtr);
1295 /***********************************************************************
1296 * CloseWindow (USER.43)
1298 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1300 return CloseWindow( hwnd );
1304 /***********************************************************************
1305 * CloseWindow (USER32.@)
1307 BOOL WINAPI CloseWindow( HWND hwnd )
1309 WND * wndPtr = WIN_FindWndPtr( hwnd );
1312 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1317 ShowWindow( hwnd, SW_MINIMIZE );
1320 WIN_ReleaseWndPtr(wndPtr);
1326 /***********************************************************************
1327 * OpenIcon (USER.44)
1329 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1331 return OpenIcon( hwnd );
1335 /***********************************************************************
1336 * OpenIcon (USER32.@)
1338 BOOL WINAPI OpenIcon( HWND hwnd )
1340 if (!IsIconic( hwnd )) return FALSE;
1341 ShowWindow( hwnd, SW_SHOWNORMAL );
1346 /***********************************************************************
1349 * Implementation of FindWindow() and FindWindowEx().
1351 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1359 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1362 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1368 else if (pWnd->parent != pWndDesktop)
1373 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1377 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1382 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1390 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1392 if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
1393 continue; /* Not the right class */
1395 /* Now check the title */
1399 retvalue = pWnd->hwndSelf;
1402 if (pWnd->text && !strcmpW( pWnd->text, title ))
1404 retvalue = pWnd->hwndSelf;
1409 /* In this case we need to check whether other processes
1410 own a window with the given paramters on the Desktop,
1411 but we don't, so let's at least warn about it */
1412 FIXME("Returning 0 without checking other processes\n");
1414 WIN_ReleaseWndPtr(pWnd);
1420 /***********************************************************************
1421 * FindWindow (USER.50)
1423 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1425 return FindWindowA( className, title );
1429 /***********************************************************************
1430 * FindWindowEx (USER.427)
1432 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1434 return FindWindowExA( parent, child, className, title );
1438 /***********************************************************************
1439 * FindWindowA (USER32.@)
1441 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1443 HWND ret = FindWindowExA( 0, 0, className, title );
1444 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1449 /***********************************************************************
1450 * FindWindowExA (USER32.@)
1452 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1453 LPCSTR className, LPCSTR title )
1461 /* If the atom doesn't exist, then no class */
1462 /* with this name exists either. */
1463 if (!(atom = GlobalFindAtomA( className )))
1465 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1470 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1471 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1472 HeapFree( GetProcessHeap(), 0, buffer );
1477 /***********************************************************************
1478 * FindWindowExW (USER32.@)
1480 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1481 LPCWSTR className, LPCWSTR title )
1487 /* If the atom doesn't exist, then no class */
1488 /* with this name exists either. */
1489 if (!(atom = GlobalFindAtomW( className )))
1491 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1495 return WIN_FindWindow( parent, child, atom, title );
1499 /***********************************************************************
1500 * FindWindowW (USER32.@)
1502 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1504 return FindWindowExW( 0, 0, className, title );
1508 /**********************************************************************
1509 * GetDesktopWindow (USER.286)
1511 HWND16 WINAPI GetDesktopWindow16(void)
1513 return (HWND16)pWndDesktop->hwndSelf;
1517 /**********************************************************************
1518 * GetDesktopWindow (USER32.@)
1520 HWND WINAPI GetDesktopWindow(void)
1522 if (pWndDesktop) return pWndDesktop->hwndSelf;
1523 ERR( "You need the -desktop option when running with native USER\n" );
1529 /**********************************************************************
1530 * GetDesktopHwnd (USER.278)
1532 * Exactly the same thing as GetDesktopWindow(), but not documented.
1533 * Don't ask me why...
1535 HWND16 WINAPI GetDesktopHwnd16(void)
1537 return (HWND16)pWndDesktop->hwndSelf;
1541 /*******************************************************************
1542 * EnableWindow (USER.34)
1544 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1546 return EnableWindow( hwnd, enable );
1550 /*******************************************************************
1551 * EnableWindow (USER32.@)
1553 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1558 TRACE("( %x, %d )\n", hwnd, enable);
1560 if (USER_Driver.pEnableWindow)
1561 return USER_Driver.pEnableWindow( hwnd, enable );
1563 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1565 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1567 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1569 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1570 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1572 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1574 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1576 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1578 if (hwnd == GetFocus())
1579 SetFocus( 0 ); /* A disabled window can't have the focus */
1581 if (hwnd == GetCapture())
1582 ReleaseCapture(); /* A disabled window can't capture the mouse */
1584 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1586 WIN_ReleaseWndPtr(wndPtr);
1591 /***********************************************************************
1592 * IsWindowEnabled (USER.35)
1594 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1596 return IsWindowEnabled(hWnd);
1600 /***********************************************************************
1601 * IsWindowEnabled (USER32.@)
1603 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1608 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1609 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1610 WIN_ReleaseWndPtr(wndPtr);
1616 /***********************************************************************
1617 * IsWindowUnicode (USER32.@)
1619 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1624 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1625 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1626 WIN_ReleaseWndPtr(wndPtr);
1631 /**********************************************************************
1632 * GetWindowWord (USER.133)
1634 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1636 return GetWindowWord( hwnd, offset );
1640 /**********************************************************************
1641 * GetWindowWord (USER32.@)
1643 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1646 WND * wndPtr = WIN_FindWndPtr( hwnd );
1647 if (!wndPtr) return 0;
1650 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1652 WARN("Invalid offset %d\n", offset );
1656 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1662 if (HIWORD(wndPtr->wIDmenu))
1663 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1665 retvalue = (WORD)wndPtr->wIDmenu;
1667 case GWW_HWNDPARENT:
1668 retvalue = GetParent(hwnd);
1671 if (HIWORD(wndPtr->hInstance))
1672 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1674 retvalue = (WORD)wndPtr->hInstance;
1677 WARN("Invalid offset %d\n", offset );
1682 WIN_ReleaseWndPtr(wndPtr);
1686 /**********************************************************************
1687 * SetWindowWord (USER.134)
1689 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1691 return SetWindowWord( hwnd, offset, newval );
1695 /**********************************************************************
1696 * SetWindowWord (USER32.@)
1698 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1701 WND * wndPtr = WIN_FindWndPtr( hwnd );
1702 if (!wndPtr) return 0;
1705 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1707 WARN("Invalid offset %d\n", offset );
1711 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1715 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1716 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1717 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1720 WARN("Invalid offset %d\n", offset );
1727 WIN_ReleaseWndPtr(wndPtr);
1732 /**********************************************************************
1735 * Helper function for GetWindowLong().
1737 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1740 WND * wndPtr = WIN_FindWndPtr( hwnd );
1741 if (!wndPtr) return 0;
1744 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1746 WARN("Invalid offset %d\n", offset );
1750 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1751 /* Special case for dialog window procedure */
1752 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1754 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1761 case GWL_USERDATA: retvalue = wndPtr->userdata;
1763 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1765 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1767 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1769 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1772 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1774 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1777 WARN("Unknown offset %d\n", offset );
1781 WIN_ReleaseWndPtr(wndPtr);
1786 /**********************************************************************
1789 * Helper function for SetWindowLong().
1791 * 0 is the failure code. However, in the case of failure SetLastError
1792 * must be set to distinguish between a 0 return value and a failure.
1794 * FIXME: The error values for SetLastError may not be right. Can
1795 * someone check with the real thing?
1797 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1798 WINDOWPROCTYPE type )
1801 WND * wndPtr = WIN_FindWndPtr( hwnd );
1804 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1808 /* Is this the right error? */
1809 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1815 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1817 WARN("Invalid offset %d\n", offset );
1819 /* Is this the right error? */
1820 SetLastError( ERROR_OUTOFMEMORY );
1825 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1826 /* Special case for dialog window procedure */
1827 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1829 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1830 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1831 type, WIN_PROC_WINDOW );
1838 ptr = (DWORD*)&wndPtr->wIDmenu;
1841 retval = SetWindowWord( hwnd, offset, newval );
1844 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1845 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1846 type, WIN_PROC_WINDOW );
1849 style.styleOld = wndPtr->dwStyle;
1850 style.styleNew = newval;
1851 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1852 wndPtr->dwStyle = style.styleNew;
1853 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1854 retval = style.styleOld;
1858 ptr = &wndPtr->userdata;
1861 style.styleOld = wndPtr->dwExStyle;
1862 style.styleNew = newval;
1863 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1864 wndPtr->dwExStyle = newval;
1865 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1866 retval = style.styleOld;
1870 WARN("Invalid offset %d\n", offset );
1872 /* Don't think this is right error but it should do */
1873 SetLastError( ERROR_OUTOFMEMORY );
1881 WIN_ReleaseWndPtr(wndPtr);
1886 /**********************************************************************
1887 * GetWindowLong (USER.135)
1889 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1891 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1895 /**********************************************************************
1896 * GetWindowLongA (USER32.@)
1898 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1900 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1904 /**********************************************************************
1905 * GetWindowLongW (USER32.@)
1907 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1909 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1913 /**********************************************************************
1914 * SetWindowLong (USER.136)
1916 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1918 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1922 /**********************************************************************
1923 * SetWindowLongA (USER32.@)
1925 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1927 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1931 /**********************************************************************
1932 * SetWindowLongW (USER32.@) Set window attribute
1934 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1935 * value in a window's extra memory.
1937 * The _hwnd_ parameter specifies the window. is the handle to a
1938 * window that has extra memory. The _newval_ parameter contains the
1939 * new attribute or extra memory value. If positive, the _offset_
1940 * parameter is the byte-addressed location in the window's extra
1941 * memory to set. If negative, _offset_ specifies the window
1942 * attribute to set, and should be one of the following values:
1944 * GWL_EXSTYLE The window's extended window style
1946 * GWL_STYLE The window's window style.
1948 * GWL_WNDPROC Pointer to the window's window procedure.
1950 * GWL_HINSTANCE The window's pplication instance handle.
1952 * GWL_ID The window's identifier.
1954 * GWL_USERDATA The window's user-specified data.
1956 * If the window is a dialog box, the _offset_ parameter can be one of
1957 * the following values:
1959 * DWL_DLGPROC The address of the window's dialog box procedure.
1961 * DWL_MSGRESULT The return value of a message
1962 * that the dialog box procedure processed.
1964 * DWL_USER Application specific information.
1968 * If successful, returns the previous value located at _offset_. Otherwise,
1973 * Extra memory for a window class is specified by a nonzero cbWndExtra
1974 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1975 * time of class creation.
1977 * Using GWL_WNDPROC to set a new window procedure effectively creates
1978 * a window subclass. Use CallWindowProc() in the new windows procedure
1979 * to pass messages to the superclass's window procedure.
1981 * The user data is reserved for use by the application which created
1984 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1985 * instead, call the EnableWindow() function to change the window's
1988 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1989 * SetParent() instead.
1992 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1993 * it sends WM_STYLECHANGING before changing the settings
1994 * and WM_STYLECHANGED afterwards.
1995 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1999 * GWL_STYLE does not dispatch WM_STYLE... messages.
2006 LONG WINAPI SetWindowLongW(
2007 HWND hwnd, /* [in] window to alter */
2008 INT offset, /* [in] offset, in bytes, of location to alter */
2009 LONG newval /* [in] new value of location */
2011 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2015 /*******************************************************************
2016 * GetWindowText (USER.36)
2018 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2020 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2024 /*******************************************************************
2025 * GetWindowTextA (USER32.@)
2027 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2029 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2033 /*******************************************************************
2034 * InternalGetWindowText (USER32.@)
2036 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2038 WND *win = WIN_FindWndPtr( hwnd );
2040 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2041 else lpString[0] = 0;
2042 WIN_ReleaseWndPtr( win );
2043 return strlenW(lpString);
2047 /*******************************************************************
2048 * GetWindowTextW (USER32.@)
2050 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2052 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2057 /*******************************************************************
2058 * SetWindowText (USER.37)
2060 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2062 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2066 /*******************************************************************
2067 * SetWindowText (USER32.@)
2068 * SetWindowTextA (USER32.@)
2070 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2072 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2076 /*******************************************************************
2077 * SetWindowTextW (USER32.@)
2079 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2081 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2085 /*******************************************************************
2086 * GetWindowTextLength (USER.38)
2088 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2090 return (INT16)GetWindowTextLengthA( hwnd );
2094 /*******************************************************************
2095 * GetWindowTextLengthA (USER32.@)
2097 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2099 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2102 /*******************************************************************
2103 * GetWindowTextLengthW (USER32.@)
2105 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2107 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2111 /*******************************************************************
2112 * IsWindow (USER.47)
2114 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2116 CURRENT_STACK16->es = USER_HeapSel;
2117 return IsWindow( hwnd );
2121 /*******************************************************************
2122 * IsWindow (USER32.@)
2124 BOOL WINAPI IsWindow( HWND hwnd )
2129 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2130 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2131 WIN_ReleaseWndPtr(wndPtr);
2137 /*****************************************************************
2138 * GetParent (USER.46)
2140 HWND16 WINAPI GetParent16( HWND16 hwnd )
2142 return (HWND16)GetParent( hwnd );
2146 /*****************************************************************
2147 * GetParent (USER32.@)
2149 HWND WINAPI GetParent( HWND hwnd )
2154 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2155 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2158 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2160 retvalue = wndPtr->hwndSelf;
2163 WIN_ReleaseWndPtr(wndPtr);
2168 /*****************************************************************
2171 * Get the top-level parent for a child window.
2172 * returns a locked pointer
2174 WND* WIN_GetTopParentPtr( WND* pWnd )
2176 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2178 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2180 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2185 /*****************************************************************
2188 * Get the top-level parent for a child window.
2190 HWND WIN_GetTopParent( HWND hwnd )
2193 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2194 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2196 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2197 WIN_ReleaseWndPtr(tmpPtr);
2198 WIN_ReleaseWndPtr(wndPtr);
2203 /*****************************************************************
2204 * SetParent (USER.233)
2206 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2208 return SetParent( hwndChild, hwndNewParent );
2212 /*****************************************************************
2213 * SetParent (USER32.@)
2215 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2222 if (hwnd == GetDesktopWindow()) /* sanity check */
2224 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2228 if (USER_Driver.pSetParent)
2229 return USER_Driver.pSetParent( hwnd, parent );
2231 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2233 dwStyle = wndPtr->dwStyle;
2235 if (!parent) parent = GetDesktopWindow();
2237 if (!(pWndParent = WIN_FindWndPtr(parent)))
2239 WIN_ReleaseWndPtr( wndPtr );
2243 /* Windows hides the window first, then shows it again
2244 * including the WM_SHOWWINDOW messages and all */
2245 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2247 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2248 if (pWndParent != wndPtr->parent)
2250 WIN_UnlinkWindow(wndPtr->hwndSelf);
2251 wndPtr->parent = pWndParent;
2253 if (parent != GetDesktopWindow()) /* a child window */
2255 if( !( wndPtr->dwStyle & WS_CHILD ) )
2257 if( wndPtr->wIDmenu != 0)
2259 DestroyMenu( (HMENU) wndPtr->wIDmenu );
2260 wndPtr->wIDmenu = 0;
2264 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
2266 WIN_ReleaseWndPtr( pWndParent );
2267 WIN_ReleaseWndPtr( wndPtr );
2269 /* SetParent additionally needs to make hwnd the topmost window
2270 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2271 WM_WINDOWPOSCHANGED notification messages.
2273 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2274 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2275 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2276 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2277 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2282 /*******************************************************************
2285 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2287 return IsChild(parent,child);
2291 /*******************************************************************
2292 * IsChild (USER32.@)
2294 BOOL WINAPI IsChild( HWND parent, HWND child )
2296 WND * wndPtr = WIN_FindWndPtr( child );
2297 while (wndPtr && wndPtr->parent)
2299 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2300 if (wndPtr->hwndSelf == GetDesktopWindow()) break;
2301 if (wndPtr->hwndSelf == parent)
2303 WIN_ReleaseWndPtr(wndPtr);
2307 WIN_ReleaseWndPtr(wndPtr);
2312 /***********************************************************************
2313 * IsWindowVisible (USER.49)
2315 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2317 return IsWindowVisible(hwnd);
2321 /***********************************************************************
2322 * IsWindowVisible (USER32.@)
2324 BOOL WINAPI IsWindowVisible( HWND hwnd )
2327 WND *wndPtr = WIN_FindWndPtr( hwnd );
2328 while (wndPtr && wndPtr->parent)
2330 if (!(wndPtr->dwStyle & WS_VISIBLE))
2332 WIN_ReleaseWndPtr(wndPtr);
2335 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2337 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2338 WIN_ReleaseWndPtr(wndPtr);
2343 /***********************************************************************
2344 * WIN_IsWindowDrawable
2346 * hwnd is drawable when it is visible, all parents are not
2347 * minimized, and it is itself not minimized unless we are
2348 * trying to draw its default class icon.
2350 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2352 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2353 if ((wnd->dwStyle & WS_MINIMIZE) &&
2354 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2355 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2356 if( wnd->dwStyle & WS_MINIMIZE ||
2357 !(wnd->dwStyle & WS_VISIBLE) ) break;
2358 return (wnd == NULL);
2362 /*******************************************************************
2363 * GetTopWindow (USER.229)
2365 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2367 return GetTopWindow(hwnd);
2371 /*******************************************************************
2372 * GetTopWindow (USER32.@)
2374 HWND WINAPI GetTopWindow( HWND hwnd )
2376 if (!hwnd) hwnd = GetDesktopWindow();
2377 return GetWindow( hwnd, GW_CHILD );
2381 /*******************************************************************
2382 * GetWindow (USER.262)
2384 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2386 return GetWindow( hwnd,rel );
2390 /*******************************************************************
2391 * GetWindow (USER32.@)
2393 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2397 WND * wndPtr = WIN_FindWndPtr( hwnd );
2398 if (!wndPtr) return 0;
2402 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2406 if (!wndPtr->parent)
2408 retval = 0; /* Desktop window */
2411 while (wndPtr->next)
2413 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2415 retval = wndPtr->hwndSelf;
2419 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2423 if (!wndPtr->parent)
2425 retval = 0; /* Desktop window */
2428 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2429 if (wndPtr->hwndSelf == hwnd)
2431 retval = 0; /* First in list */
2434 while (wndPtr->next)
2436 if (wndPtr->next->hwndSelf == hwnd)
2438 retval = wndPtr->hwndSelf;
2441 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2447 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2451 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2456 WIN_ReleaseWndPtr(wndPtr);
2461 /*******************************************************************
2462 * GetNextWindow (USER.230)
2464 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2466 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2467 return GetWindow16( hwnd, flag );
2470 /***********************************************************************
2471 * WIN_InternalShowOwnedPopups
2473 * Internal version of ShowOwnedPopups; Wine functions should use this
2474 * to avoid interfering with application calls to ShowOwnedPopups
2475 * and to make sure the application can't prevent showing/hiding.
2477 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2481 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2484 HWND *win_array = WIN_BuildWinArray( GetDesktopWindow() );
2486 if (!win_array) return TRUE;
2489 * Show windows Lowest first, Highest last to preserve Z-Order
2491 while (win_array[count]) count++;
2492 while (--count >= 0)
2494 WND *pWnd = WIN_FindWndPtr( win_array[count] );
2495 if (!pWnd) continue;
2497 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) && (pWnd->dwStyle & WS_POPUP))
2501 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2502 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2505 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2507 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2508 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2513 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2514 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2515 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2518 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2520 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2521 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2522 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2526 WIN_ReleaseWndPtr( pWnd );
2528 WIN_ReleaseWinArray( win_array );
2533 /*******************************************************************
2534 * ShowOwnedPopups (USER.265)
2536 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2538 ShowOwnedPopups( owner, fShow );
2542 /*******************************************************************
2543 * ShowOwnedPopups (USER32.@)
2545 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2549 HWND *win_array = WIN_BuildWinArray(GetDesktopWindow());
2551 if (!win_array) return TRUE;
2553 while (win_array[count]) count++;
2554 while (--count >= 0)
2556 WND *pWnd = WIN_FindWndPtr( win_array[count] );
2557 if (!pWnd) continue;
2559 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) && (pWnd->dwStyle & WS_POPUP))
2563 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2565 /* In Windows, ShowOwnedPopups(TRUE) generates
2566 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2567 * regardless of the state of the owner
2569 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2570 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2575 if (IsWindowVisible(pWnd->hwndSelf))
2577 /* In Windows, ShowOwnedPopups(FALSE) generates
2578 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2579 * regardless of the state of the owner
2581 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2582 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2586 WIN_ReleaseWndPtr( pWnd );
2588 WIN_ReleaseWinArray( win_array );
2593 /*******************************************************************
2594 * GetLastActivePopup (USER.287)
2596 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2598 return GetLastActivePopup( hwnd );
2601 /*******************************************************************
2602 * GetLastActivePopup (USER32.@)
2604 HWND WINAPI GetLastActivePopup( HWND hwnd )
2607 WND *wndPtr =WIN_FindWndPtr(hwnd);
2608 if (!wndPtr) return hwnd;
2609 retval = wndPtr->hwndLastActive;
2610 WIN_ReleaseWndPtr(wndPtr);
2611 if ((retval != hwnd) && (!IsWindow(retval)))
2617 /*******************************************************************
2620 * Build an array of pointers to the children of a given window.
2621 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2622 * when no windows are found.
2624 HWND *WIN_BuildWinArray( HWND hwnd )
2626 /* Future: this function will lock all windows associated with this array */
2627 WND *pWnd, *wndPtr = WIN_FindWndPtr( hwnd );
2631 /* First count the windows */
2633 if (!wndPtr) return NULL;
2635 pWnd = WIN_LockWndPtr(wndPtr->child);
2639 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2644 /* Now build the list of all windows */
2646 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1))))
2648 for (pWnd = WIN_LockWndPtr(wndPtr->child), phwnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2650 *phwnd++ = pWnd->hwndSelf;
2653 WIN_ReleaseWndPtr(pWnd);
2659 WIN_ReleaseWndPtr( wndPtr );
2663 /*******************************************************************
2664 * WIN_ReleaseWinArray
2666 void WIN_ReleaseWinArray(HWND *wndArray)
2668 if (wndArray) HeapFree( GetProcessHeap(), 0, wndArray );
2671 /*******************************************************************
2672 * EnumWindows (USER32.@)
2674 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2680 /* We have to build a list of all windows first, to avoid */
2681 /* unpleasant side-effects, for instance if the callback */
2682 /* function changes the Z-order of the windows. */
2684 if (!(list = WIN_BuildWinArray( GetDesktopWindow() ))) return FALSE;
2686 /* Now call the callback function for every window */
2688 iWndsLocks = WIN_SuspendWndsLock();
2689 for (i = 0; list[i]; i++)
2691 /* Make sure that the window still exists */
2692 if (!IsWindow( list[i] )) continue;
2693 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2695 WIN_RestoreWndsLock(iWndsLocks);
2696 WIN_ReleaseWinArray(list);
2701 /**********************************************************************
2702 * EnumTaskWindows16 (USER.225)
2704 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2707 TDB *tdb = TASK_GetPtr( hTask );
2708 if (!tdb) return FALSE;
2709 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2713 /**********************************************************************
2714 * EnumThreadWindows (USER32.@)
2716 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2721 if (!(list = WIN_BuildWinArray( GetDesktopWindow() ))) return FALSE;
2723 /* Now call the callback function for every window */
2725 iWndsLocks = WIN_SuspendWndsLock();
2726 for (i = 0; list[i]; i++)
2728 if (GetWindowThreadProcessId( list[i], NULL ) != id) continue;
2729 if (!func( list[i], lParam )) break;
2731 WIN_RestoreWndsLock(iWndsLocks);
2732 WIN_ReleaseWinArray(list);
2737 /**********************************************************************
2738 * WIN_EnumChildWindows
2740 * Helper function for EnumChildWindows().
2742 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2747 for ( ; *list; list++)
2749 /* Make sure that the window still exists */
2750 if (!IsWindow( *list )) continue;
2751 /* skip owned windows */
2752 if (GetWindow( *list, GW_OWNER )) continue;
2753 /* Build children list first */
2754 childList = WIN_BuildWinArray( *list );
2756 ret = func( *list, lParam );
2760 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2761 WIN_ReleaseWinArray(childList);
2763 if (!ret) return FALSE;
2769 /**********************************************************************
2770 * EnumChildWindows (USER32.@)
2772 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2777 if (!(list = WIN_BuildWinArray( parent ))) return FALSE;
2778 iWndsLocks = WIN_SuspendWndsLock();
2779 WIN_EnumChildWindows( list, func, lParam );
2780 WIN_RestoreWndsLock(iWndsLocks);
2781 WIN_ReleaseWinArray(list);
2786 /*******************************************************************
2787 * AnyPopup (USER.52)
2789 BOOL16 WINAPI AnyPopup16(void)
2795 /*******************************************************************
2796 * AnyPopup (USER32.@)
2798 BOOL WINAPI AnyPopup(void)
2800 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2805 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2810 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2814 WIN_ReleaseWndPtr(wndPtr);
2819 /*******************************************************************
2820 * FlashWindow (USER.105)
2822 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2824 return FlashWindow( hWnd, bInvert );
2828 /*******************************************************************
2829 * FlashWindow (USER32.@)
2831 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2833 WND *wndPtr = WIN_FindWndPtr(hWnd);
2835 TRACE("%04x\n", hWnd);
2837 if (!wndPtr) return FALSE;
2839 if (wndPtr->dwStyle & WS_MINIMIZE)
2841 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2843 HDC hDC = GetDC(hWnd);
2845 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2846 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2848 ReleaseDC( hWnd, hDC );
2849 wndPtr->flags |= WIN_NCACTIVATED;
2853 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2854 wndPtr->flags &= ~WIN_NCACTIVATED;
2856 WIN_ReleaseWndPtr(wndPtr);
2862 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2863 else wparam = (hWnd == GetActiveWindow());
2865 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2866 WIN_ReleaseWndPtr(wndPtr);
2872 /*******************************************************************
2873 * SetSysModalWindow (USER.188)
2875 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2877 HWND hWndOldModal = hwndSysModal;
2878 hwndSysModal = hWnd;
2879 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2880 return hWndOldModal;
2884 /*******************************************************************
2885 * GetSysModalWindow (USER.189)
2887 HWND16 WINAPI GetSysModalWindow16(void)
2889 return hwndSysModal;
2893 /*******************************************************************
2894 * GetWindowContextHelpId (USER32.@)
2896 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2899 WND *wnd = WIN_FindWndPtr( hwnd );
2901 retval = wnd->helpContext;
2902 WIN_ReleaseWndPtr(wnd);
2907 /*******************************************************************
2908 * SetWindowContextHelpId (USER32.@)
2910 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2912 WND *wnd = WIN_FindWndPtr( hwnd );
2913 if (!wnd) return FALSE;
2914 wnd->helpContext = id;
2915 WIN_ReleaseWndPtr(wnd);
2920 /*******************************************************************
2923 * recursively find a child that contains spDragInfo->pt point
2924 * and send WM_QUERYDROPOBJECT
2926 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2928 BOOL16 wParam, bResult = 0;
2930 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
2933 if (!ptrDragInfo) return FALSE;
2935 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2937 GetWindowRect(hQueryWnd,&tempRect);
2939 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
2941 if (!IsIconic( hQueryWnd ))
2943 WND *ptrWnd, *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd);
2945 tempRect = ptrQueryWnd->rectClient;
2946 if(ptrQueryWnd->parent)
2947 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
2948 (LPPOINT)&tempRect, 2 );
2950 if (PtInRect( &tempRect, pt))
2954 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
2956 if( ptrWnd->dwStyle & WS_VISIBLE )
2958 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
2959 if (PtInRect( &tempRect, pt )) break;
2965 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
2966 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2967 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2968 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2969 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2971 WIN_ReleaseWndPtr(ptrWnd);
2976 WIN_ReleaseWndPtr(ptrQueryWnd);
2981 WIN_ReleaseWndPtr(ptrQueryWnd);
2985 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2987 ptrDragInfo->hScope = hQueryWnd;
2989 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
2990 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
2992 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2998 /*******************************************************************
2999 * DragDetect (USER.465)
3001 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3004 CONV_POINT16TO32( &pt, &pt32 );
3005 return DragDetect( hWnd, pt32 );
3008 /*******************************************************************
3009 * DragDetect (USER32.@)
3011 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3016 rect.left = pt.x - wDragWidth;
3017 rect.right = pt.x + wDragWidth;
3019 rect.top = pt.y - wDragHeight;
3020 rect.bottom = pt.y + wDragHeight;
3026 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3028 if( msg.message == WM_LBUTTONUP )
3033 if( msg.message == WM_MOUSEMOVE )
3036 tmp.x = LOWORD(msg.lParam);
3037 tmp.y = HIWORD(msg.lParam);
3038 if( !PtInRect( &rect, tmp ))
3050 /******************************************************************************
3051 * DragObject (USER.464)
3053 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3054 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3057 LPDRAGINFO16 lpDragInfo;
3059 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3060 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3061 HCURSOR16 hCurrentCursor = 0;
3062 HWND16 hCurrentWnd = 0;
3064 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3065 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3067 if( !lpDragInfo || !spDragInfo ) return 0L;
3069 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3071 GlobalFree16(hDragInfo);
3077 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3079 GlobalFree16(hDragInfo);
3083 if( hDragCursor == hCursor ) hDragCursor = 0;
3084 else hCursor = hDragCursor;
3086 hOldCursor = SetCursor(hDragCursor);
3089 lpDragInfo->hWnd = hWnd;
3090 lpDragInfo->hScope = 0;
3091 lpDragInfo->wFlags = wObj;
3092 lpDragInfo->hList = szList; /* near pointer! */
3093 lpDragInfo->hOfStruct = hOfStruct;
3101 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3103 *(lpDragInfo+1) = *lpDragInfo;
3105 lpDragInfo->pt.x = msg.pt.x;
3106 lpDragInfo->pt.y = msg.pt.y;
3108 /* update DRAGINFO struct */
3109 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3111 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3112 hCurrentCursor = hCursor;
3115 hCurrentCursor = hBummer;
3116 lpDragInfo->hScope = 0;
3118 if( hCurrentCursor )
3119 SetCursor(hCurrentCursor);
3121 /* send WM_DRAGLOOP */
3122 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3123 (LPARAM) spDragInfo );
3124 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3125 if( hCurrentWnd != lpDragInfo->hScope )
3128 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3129 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3130 HIWORD(spDragInfo)) );
3131 hCurrentWnd = lpDragInfo->hScope;
3133 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3137 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3139 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3142 ShowCursor( FALSE );
3146 SetCursor( hOldCursor );
3147 if (hDragCursor) DestroyCursor( hDragCursor );
3150 if( hCurrentCursor != hBummer )
3151 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3152 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3155 GlobalFree16(hDragInfo);
3157 return (DWORD)(msg.lParam);
3161 /******************************************************************************
3162 * GetWindowModuleFileNameA (USER32.@)
3164 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3166 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3167 hwnd, lpszFileName, cchFileNameMax);
3171 /******************************************************************************
3172 * GetWindowModuleFileNameW (USER32.@)
3174 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3176 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3177 hwnd, lpszFileName, cchFileNameMax);