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"
24 #include "stackframe.h"
25 #include "debugtools.h"
27 DEFAULT_DEBUG_CHANNEL(win);
28 DECLARE_DEBUG_CHANNEL(msg);
30 /**********************************************************************/
33 static WND *pWndDesktop = NULL;
35 static HWND hwndSysModal = 0;
37 static WORD wDragWidth = 4;
38 static WORD wDragHeight= 3;
41 static SYSLEVEL WIN_SysLevel = { CRITICAL_SECTION_INIT, 2 };
43 /***********************************************************************
46 * Locks access to all WND structures for thread safeness
48 void WIN_LockWnds( void )
50 _EnterSysLevel( &WIN_SysLevel );
53 /***********************************************************************
56 * Unlocks access to all WND structures
58 void WIN_UnlockWnds( void )
60 _LeaveSysLevel( &WIN_SysLevel );
63 /***********************************************************************
66 * Suspend the lock on WND structures.
67 * Returns the number of locks suspended
69 int WIN_SuspendWndsLock( void )
71 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
72 int count = isuspendedLocks;
75 _LeaveSysLevel( &WIN_SysLevel );
77 return isuspendedLocks;
80 /***********************************************************************
83 * Restore the suspended locks on WND structures
85 void WIN_RestoreWndsLock( int ipreviousLocks )
87 while ( ipreviousLocks-- > 0 )
88 _EnterSysLevel( &WIN_SysLevel );
91 /***********************************************************************
94 * Return a pointer to the WND structure corresponding to a HWND.
96 WND * WIN_FindWndPtr( HWND hwnd )
100 if (!hwnd || HIWORD(hwnd)) goto error2;
101 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
102 /* Lock all WND structures for thread safeness*/
104 /*and increment destruction monitoring*/
107 if (ptr->dwMagic != WND_MAGIC) goto error;
108 if (ptr->hwndSelf != hwnd)
110 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
113 /* returns a locked pointer */
116 /* Unlock all WND structures for thread safeness*/
118 /* and decrement destruction monitoring value */
123 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
127 /***********************************************************************
130 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
132 * Returns the locked initialisation pointer
134 WND *WIN_LockWndPtr(WND *initWndPtr)
136 if(!initWndPtr) return 0;
138 /* Lock all WND structures for thread safeness*/
140 /*and increment destruction monitoring*/
141 initWndPtr->irefCount++;
147 /***********************************************************************
150 * Release the pointer to the WND structure.
152 void WIN_ReleaseWndPtr(WND *wndPtr)
156 /*Decrement destruction monitoring value*/
158 /* Check if it's time to release the memory*/
159 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
162 USER_HEAP_FREE( wndPtr->hwndSelf);
163 wndPtr->hwndSelf = 0;
165 else if(wndPtr->irefCount < 0)
167 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
168 ERR("forgot a Lock on %p somewhere\n",wndPtr);
170 /*unlock all WND structures for thread safeness*/
174 /***********************************************************************
177 * Updates the value of oldPtr to newPtr.
179 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
183 tmpWnd = WIN_LockWndPtr(newPtr);
184 WIN_ReleaseWndPtr(*oldPtr);
189 /***********************************************************************
192 * Dump the content of a window structure to stderr.
194 void WIN_DumpWindow( HWND hwnd )
200 if (!(ptr = WIN_FindWndPtr( hwnd )))
202 WARN("%04x is not a window handle\n", hwnd );
206 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
207 strcpy( className, "#NULL#" );
209 TRACE("Window %04x (%p):\n", hwnd, ptr );
210 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
211 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
212 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
213 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
214 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
215 ptr->next, ptr->child, ptr->parent, ptr->owner,
216 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
217 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
218 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
219 ptr->text ? debugstr_w(ptr->text) : "",
220 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
221 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
222 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
223 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
227 DPRINTF( "extra bytes:" );
228 for (i = 0; i < ptr->cbWndExtra; i++)
229 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
233 WIN_ReleaseWndPtr(ptr);
237 /***********************************************************************
240 * Walk the windows tree and print each window on stderr.
242 void WIN_WalkWindows( HWND hwnd, int indent )
247 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
251 WARN("Invalid window handle %04x\n", hwnd );
255 if (!indent) /* first time around */
256 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
257 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
262 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
264 GetClassNameA( ptr->hwndSelf, className, sizeof(className) );
265 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
266 (DWORD)ptr, ptr->hmemTaskQ, className,
267 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
268 ptr->text ? debugstr_w(ptr->text) : "<null>");
270 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
271 WIN_UpdateWndPtr(&ptr,ptr->next);
275 /***********************************************************************
278 * Remove a window from the siblings linked list.
280 BOOL WIN_UnlinkWindow( HWND hwnd )
282 WND *wndPtr, **ppWnd;
285 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
286 else if(!wndPtr->parent)
288 WIN_ReleaseWndPtr(wndPtr);
292 ppWnd = &wndPtr->parent->child;
293 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
296 *ppWnd = wndPtr->next;
299 WIN_ReleaseWndPtr(wndPtr);
304 /***********************************************************************
307 * Insert a window into the siblings linked list.
308 * The window is inserted after the specified window, which can also
309 * be specified as HWND_TOP or HWND_BOTTOM.
311 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
313 WND *wndPtr, **ppWnd;
315 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
316 else if(!wndPtr->parent)
318 WIN_ReleaseWndPtr(wndPtr);
321 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
323 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
324 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
325 while (*ppWnd) ppWnd = &(*ppWnd)->next;
327 else /* Normal case */
329 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
332 WIN_ReleaseWndPtr(wndPtr);
335 ppWnd = &afterPtr->next;
336 WIN_ReleaseWndPtr(afterPtr);
338 wndPtr->next = *ppWnd;
340 WIN_ReleaseWndPtr(wndPtr);
345 /***********************************************************************
346 * WIN_FindWinToRepaint
348 * Find a window that needs repaint.
350 HWND WIN_FindWinToRepaint( HWND hwnd )
355 /* Note: the desktop window never gets WM_PAINT messages
356 * The real reason why is because Windows DesktopWndProc
357 * does ValidateRgn inside WM_ERASEBKGND handler.
359 if (hwnd == GetDesktopWindow()) hwnd = 0;
361 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
363 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
365 if (!(pWnd->dwStyle & WS_VISIBLE))
367 TRACE("skipping window %04x\n",
370 else if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
371 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
374 else if (pWnd->child )
375 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
377 WIN_ReleaseWndPtr(pWnd);
388 hwndRet = pWnd->hwndSelf;
390 /* look among siblings if we got a transparent window */
391 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
392 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
394 WIN_UpdateWndPtr(&pWnd,pWnd->next);
398 hwndRet = pWnd->hwndSelf;
399 WIN_ReleaseWndPtr(pWnd);
401 TRACE("found %04x\n",hwndRet);
406 /***********************************************************************
409 * Destroy storage associated to a window. "Internals" p.358
410 * returns a locked wndPtr->next
412 static WND* WIN_DestroyWindow( WND* wndPtr )
414 HWND hwnd = wndPtr->hwndSelf;
417 TRACE("%04x\n", wndPtr->hwndSelf );
419 /* free child windows */
420 WIN_LockWndPtr(wndPtr->child);
421 while ((pWnd = wndPtr->child))
423 wndPtr->child = WIN_DestroyWindow( pWnd );
424 WIN_ReleaseWndPtr(pWnd);
428 * Clear the update region to make sure no WM_PAINT messages will be
429 * generated for this window while processing the WM_NCDESTROY.
431 RedrawWindow( wndPtr->hwndSelf, NULL, 0,
432 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
435 * Send the WM_NCDESTROY to the window being destroyed.
437 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
439 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
441 WINPOS_CheckInternalPos( wndPtr );
442 if( hwnd == GetCapture()) ReleaseCapture();
444 /* free resources associated with the window */
446 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
447 PROPERTY_RemoveWindowProps( wndPtr );
449 /* toss stale messages from the queue */
451 QUEUE_CleanupWindow( hwnd );
452 wndPtr->hmemTaskQ = 0;
454 if (!(wndPtr->dwStyle & WS_CHILD))
457 DestroyMenu( wndPtr->wIDmenu );
460 if (wndPtr->hSysMenu)
462 DestroyMenu( wndPtr->hSysMenu );
463 wndPtr->hSysMenu = 0;
465 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
466 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
467 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
468 CLASS_RemoveWindow( wndPtr->class );
469 wndPtr->class = NULL;
470 wndPtr->dwMagic = 0; /* Mark it as invalid */
472 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
477 /***********************************************************************
478 * WIN_DestroyThreadWindows
480 * Destroy all children of 'wnd' owned by the current thread.
481 * Return TRUE if something was done.
483 BOOL WIN_DestroyThreadWindows( HWND hwnd )
486 WND *wnd = WIN_FindWndPtr( hwnd );
488 if (!wnd) return FALSE;
491 WND *tmp = WIN_LockWndPtr(wnd->child);
495 if (GetWindowThreadProcessId( tmp->hwndSelf, NULL ) == GetCurrentThreadId())
497 DestroyWindow( tmp->hwndSelf );
501 if (tmp->child && WIN_DestroyThreadWindows( tmp->hwndSelf ))
504 WIN_UpdateWndPtr(&tmp,tmp->next);
506 WIN_ReleaseWndPtr(tmp);
509 WIN_ReleaseWndPtr( wnd );
513 /***********************************************************************
514 * WIN_CreateDesktopWindow
516 * Create the desktop window.
518 BOOL WIN_CreateDesktopWindow(void)
520 struct tagCLASS *class;
528 TRACE("Creating desktop window\n");
531 if (!WINPOS_CreateInternalPosAtom() ||
532 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
533 &wndExtra, &winproc, &clsStyle, &dce )))
536 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
537 if (!hwndDesktop) return FALSE;
538 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
540 pWndDesktop->next = NULL;
541 pWndDesktop->child = NULL;
542 pWndDesktop->parent = NULL;
543 pWndDesktop->owner = NULL;
544 pWndDesktop->class = class;
545 pWndDesktop->dwMagic = WND_MAGIC;
546 pWndDesktop->hwndSelf = hwndDesktop;
547 pWndDesktop->hInstance = 0;
548 pWndDesktop->rectWindow.left = 0;
549 pWndDesktop->rectWindow.top = 0;
550 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
551 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
552 pWndDesktop->rectClient = pWndDesktop->rectWindow;
553 pWndDesktop->text = NULL;
554 pWndDesktop->hmemTaskQ = 0;
555 pWndDesktop->hrgnUpdate = 0;
556 pWndDesktop->hwndLastActive = hwndDesktop;
557 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
559 pWndDesktop->dwExStyle = 0;
560 pWndDesktop->clsStyle = clsStyle;
561 pWndDesktop->dce = NULL;
562 pWndDesktop->pVScroll = NULL;
563 pWndDesktop->pHScroll = NULL;
564 pWndDesktop->pProp = NULL;
565 pWndDesktop->wIDmenu = 0;
566 pWndDesktop->helpContext = 0;
567 pWndDesktop->flags = 0;
568 pWndDesktop->hSysMenu = 0;
569 pWndDesktop->userdata = 0;
570 pWndDesktop->winproc = winproc;
571 pWndDesktop->cbWndExtra = wndExtra;
572 pWndDesktop->irefCount = 0;
574 cs.lpCreateParams = NULL;
580 cs.cx = pWndDesktop->rectWindow.right;
581 cs.cy = pWndDesktop->rectWindow.bottom;
582 cs.style = pWndDesktop->dwStyle;
583 cs.dwExStyle = pWndDesktop->dwExStyle;
585 cs.lpszClass = DESKTOP_CLASS_ATOM;
587 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
589 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
594 /***********************************************************************
597 * Fix the coordinates - Helper for WIN_CreateWindowEx.
598 * returns default show mode in sw.
599 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
601 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
603 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
604 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
606 if (cs->style & (WS_CHILD | WS_POPUP))
608 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
609 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
611 else /* overlapped window */
615 GetStartupInfoA( &info );
617 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
619 /* Never believe Microsoft's documentation... CreateWindowEx doc says
620 * that if an overlapped window is created with WS_VISIBLE style bit
621 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
622 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
625 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
626 * 2) it does not ignore the y parameter as the docs claim; instead, it
627 * uses it as second parameter to ShowWindow() unless y is either
628 * CW_USEDEFAULT or CW_USEDEFAULT16.
630 * The fact that we didn't do 2) caused bogus windows pop up when wine
631 * was running apps that were using this obscure feature. Example -
632 * calc.exe that comes with Win98 (only Win98, it's different from
633 * the one that comes with Win95 and NT)
635 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
636 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
637 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
640 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
642 if (info.dwFlags & STARTF_USESIZE)
644 cs->cx = info.dwXSize;
645 cs->cy = info.dwYSize;
647 else /* if no other hint from the app, pick 3/4 of the screen real estate */
650 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
651 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
652 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
659 /***********************************************************************
662 * Implementation of CreateWindowEx().
664 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
665 WINDOWPROCTYPE type )
668 struct tagCLASS *classPtr;
670 HWND hwnd, hwndLinkAfter;
671 POINT maxSize, maxPos, minTrack, maxTrack;
676 BOOL unicode = (type == WIN_PROC_32W);
678 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
679 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
680 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
681 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
682 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
684 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
685 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
687 /* Find the parent window */
691 /* Make sure parent is valid */
692 if (!IsWindow( cs->hwndParent ))
694 WARN("Bad parent %04x\n", cs->hwndParent );
697 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
698 WARN("No parent for child window\n" );
699 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
702 /* Find the window class */
703 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
704 &wndExtra, &winproc, &clsStyle, &dce )))
706 WARN("Bad class '%s'\n", cs->lpszClass );
710 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
712 /* Correct the window style - stage 1
714 * These are patches that appear to affect both the style loaded into the
715 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
717 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
718 * why does the user get to set it?
721 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
722 * tested for WS_POPUP
724 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
725 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
726 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
727 cs->dwExStyle |= WS_EX_WINDOWEDGE;
729 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
731 /* Create the window structure */
733 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
735 TRACE("out of memory\n" );
739 /* Fill the window structure */
741 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
743 wndPtr->child = NULL;
745 if ((cs->style & WS_CHILD) && cs->hwndParent)
747 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
748 wndPtr->owner = NULL;
749 WIN_ReleaseWndPtr(wndPtr->parent);
753 wndPtr->parent = pWndDesktop;
754 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
755 wndPtr->owner = NULL;
758 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
759 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
760 WIN_ReleaseWndPtr(wndPtr->owner);
761 WIN_ReleaseWndPtr(tmpWnd);
766 wndPtr->class = classPtr;
767 wndPtr->winproc = winproc;
768 wndPtr->dwMagic = WND_MAGIC;
769 wndPtr->hwndSelf = hwnd;
770 wndPtr->hInstance = cs->hInstance;
772 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
773 wndPtr->hrgnUpdate = 0;
775 wndPtr->hwndLastActive = hwnd;
776 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
777 wndPtr->dwExStyle = cs->dwExStyle;
778 wndPtr->clsStyle = clsStyle;
780 wndPtr->helpContext = 0;
781 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
782 wndPtr->pVScroll = NULL;
783 wndPtr->pHScroll = NULL;
784 wndPtr->pProp = NULL;
785 wndPtr->userdata = 0;
786 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
787 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
788 wndPtr->cbWndExtra = wndExtra;
789 wndPtr->irefCount = 1;
791 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
793 /* Call the WH_CBT hook */
795 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
796 ? HWND_BOTTOM : HWND_TOP;
798 if (HOOK_IsHooked( WH_CBT ))
804 cbtc.hwndInsertAfter = hwndLinkAfter;
805 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
806 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
809 TRACE("CBT-hook returned 0\n");
810 USER_HEAP_FREE( hwnd );
811 CLASS_RemoveWindow( classPtr );
817 /* Correct the window style - stage 2 */
819 if (!(cs->style & WS_CHILD))
821 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
822 if (!(cs->style & WS_POPUP))
824 wndPtr->dwStyle |= WS_CAPTION;
825 wndPtr->flags |= WIN_NEED_SIZE;
829 /* Get class or window DC if needed */
831 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
832 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
833 else wndPtr->dce = NULL;
835 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
837 wndPtr->rectWindow.left = cs->x;
838 wndPtr->rectWindow.top = cs->y;
839 wndPtr->rectWindow.right = cs->x + cs->cx;
840 wndPtr->rectWindow.bottom = cs->y + cs->cy;
841 wndPtr->rectClient = wndPtr->rectWindow;
843 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
845 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
847 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
848 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
849 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
850 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
851 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
854 if (cs->cx < 0) cs->cx = 0;
855 if (cs->cy < 0) cs->cy = 0;
857 wndPtr->rectWindow.left = cs->x;
858 wndPtr->rectWindow.top = cs->y;
859 wndPtr->rectWindow.right = cs->x + cs->cx;
860 wndPtr->rectWindow.bottom = cs->y + cs->cy;
861 wndPtr->rectClient = wndPtr->rectWindow;
863 /* Set the window menu */
865 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
867 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
870 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
873 if (HIWORD(cs->hInstance))
874 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
876 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
878 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
882 else wndPtr->wIDmenu = (UINT)cs->hMenu;
884 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
886 WARN("aborted by WM_xxCREATE!\n");
887 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
888 CLASS_RemoveWindow( classPtr );
889 WIN_ReleaseWndPtr(wndPtr);
893 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
895 /* Notify the parent window only */
897 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
898 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
899 if( !IsWindow(hwnd) )
906 if (cs->style & WS_VISIBLE)
908 /* in case WS_VISIBLE got set in the meantime */
909 wndPtr->dwStyle &= ~WS_VISIBLE;
910 ShowWindow( hwnd, sw );
913 /* Call WH_SHELL hook */
915 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
916 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
918 TRACE("created window %04x\n", hwnd);
920 WIN_ReleaseWndPtr(wndPtr);
925 /***********************************************************************
926 * CreateWindow (USER.41)
928 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
929 DWORD style, INT16 x, INT16 y, INT16 width,
930 INT16 height, HWND16 parent, HMENU16 menu,
931 HINSTANCE16 instance, LPVOID data )
933 return CreateWindowEx16( 0, className, windowName, style,
934 x, y, width, height, parent, menu, instance, data );
938 /***********************************************************************
939 * CreateWindowEx (USER.452)
941 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
942 LPCSTR windowName, DWORD style, INT16 x,
943 INT16 y, INT16 width, INT16 height,
944 HWND16 parent, HMENU16 menu,
945 HINSTANCE16 instance, LPVOID data )
951 /* Find the class atom */
953 if (HIWORD(className))
955 if (!(classAtom = GlobalFindAtomA( className )))
957 ERR( "bad class name %s\n", debugres_a(className) );
963 classAtom = LOWORD(className);
964 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
966 ERR( "bad atom %x\n", classAtom);
972 /* Fix the coordinates */
974 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
975 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
976 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
977 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
979 /* Create the window */
981 cs.lpCreateParams = data;
982 cs.hInstance = (HINSTANCE)instance;
983 cs.hMenu = (HMENU)menu;
984 cs.hwndParent = (HWND)parent;
986 cs.lpszName = windowName;
987 cs.lpszClass = className;
988 cs.dwExStyle = exStyle;
990 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
994 /***********************************************************************
995 * CreateWindowExA (USER32.@)
997 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
998 LPCSTR windowName, DWORD style, INT x,
999 INT y, INT width, INT height,
1000 HWND parent, HMENU menu,
1001 HINSTANCE instance, LPVOID data )
1008 instance=GetModuleHandleA(NULL);
1010 if(exStyle & WS_EX_MDICHILD)
1011 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1013 /* Find the class atom */
1015 if (HIWORD(className))
1017 if (!(classAtom = GlobalFindAtomA( className )))
1019 ERR( "bad class name %s\n", debugres_a(className) );
1025 classAtom = LOWORD(className);
1026 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1028 ERR( "bad atom %x\n", classAtom);
1034 /* Create the window */
1036 cs.lpCreateParams = data;
1037 cs.hInstance = instance;
1039 cs.hwndParent = parent;
1045 cs.lpszName = windowName;
1046 cs.lpszClass = className;
1047 cs.dwExStyle = exStyle;
1049 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1053 /***********************************************************************
1054 * CreateWindowExW (USER32.@)
1056 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1057 LPCWSTR windowName, DWORD style, INT x,
1058 INT y, INT width, INT height,
1059 HWND parent, HMENU menu,
1060 HINSTANCE instance, LPVOID data )
1067 instance=GetModuleHandleA(NULL);
1069 if(exStyle & WS_EX_MDICHILD)
1070 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1072 /* Find the class atom */
1074 if (HIWORD(className))
1076 if (!(classAtom = GlobalFindAtomW( className )))
1078 ERR( "bad class name %s\n", debugres_w(className) );
1084 classAtom = LOWORD(className);
1085 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1087 ERR( "bad atom %x\n", classAtom);
1093 /* Create the window */
1095 cs.lpCreateParams = data;
1096 cs.hInstance = instance;
1098 cs.hwndParent = parent;
1104 cs.lpszName = windowName;
1105 cs.lpszClass = className;
1106 cs.dwExStyle = exStyle;
1108 /* Note: we rely on the fact that CREATESTRUCTA and */
1109 /* CREATESTRUCTW have the same layout. */
1110 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1113 /***********************************************************************
1114 * WIN_SendDestroyMsg
1116 static void WIN_SendDestroyMsg( WND* pWnd )
1118 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1119 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1122 * Send the WM_DESTROY to the window.
1124 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1127 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1128 * make sure that the window still exists when we come back.
1130 if (IsWindow(pWnd->hwndSelf))
1132 HWND* pWndArray = NULL;
1137 * Now, if the window has kids, we have to send WM_DESTROY messages
1138 * recursively to it's kids. It seems that those calls can also
1139 * trigger re-entrant calls to DestroyWindow for the kids so we must
1140 * protect against corruption of the list of siblings. We first build
1141 * a list of HWNDs representing all the kids.
1143 pChild = WIN_LockWndPtr(pWnd->child);
1147 WIN_UpdateWndPtr(&pChild,pChild->next);
1151 * If there are no kids, we're done.
1156 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1161 if (pWndArray==NULL)
1165 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1166 * call, our linked list of siblings should be safe.
1169 pChild = WIN_LockWndPtr(pWnd->child);
1172 pWndArray[nKidCount] = pChild->hwndSelf;
1174 WIN_UpdateWndPtr(&pChild,pChild->next);
1178 * Now that we have a list, go through that list again and send the destroy
1179 * message to those windows. We are using the HWND to retrieve the
1180 * WND pointer so we are effectively checking that all the kid windows are
1181 * still valid before sending the message.
1185 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1189 WIN_SendDestroyMsg( pChild );
1190 WIN_ReleaseWndPtr(pChild);
1197 HeapFree(GetProcessHeap(), 0, pWndArray);
1200 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1204 /***********************************************************************
1205 * DestroyWindow (USER.53)
1207 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1209 return DestroyWindow(hwnd);
1213 /***********************************************************************
1214 * DestroyWindow (USER32.@)
1216 BOOL WINAPI DestroyWindow( HWND hwnd )
1221 BOOL bFocusSet = FALSE;
1223 TRACE("(%04x)\n", hwnd);
1225 /* Initialization */
1227 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1228 if (wndPtr == pWndDesktop)
1230 retvalue = FALSE; /* Can't destroy desktop */
1234 /* Look whether the focus is within the tree of windows we will
1238 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1242 SetFocus(GetParent(h));
1248 /* If the focus is on the window we will destroy and it has no parent,
1249 * set the focus to 0.
1251 if (! bFocusSet && (h == hwnd))
1253 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1259 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1265 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1267 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1268 /* FIXME: clean up palette - see "Internals" p.352 */
1271 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1272 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1274 /* Notify the parent window only */
1275 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1276 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1277 if( !IsWindow(hwnd) )
1284 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1286 /* Hide the window */
1288 if (wndPtr->dwStyle & WS_VISIBLE)
1290 ShowWindow( hwnd, SW_HIDE );
1291 if (!IsWindow(hwnd))
1298 /* Recursively destroy owned windows */
1300 if( !(wndPtr->dwStyle & WS_CHILD) )
1304 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1307 if (siblingPtr->owner == wndPtr)
1309 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1312 siblingPtr->owner = NULL;
1314 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1318 DestroyWindow( siblingPtr->hwndSelf );
1319 WIN_ReleaseWndPtr(siblingPtr);
1324 WINPOS_ActivateOtherWindow(wndPtr);
1326 if( wndPtr->owner &&
1327 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1328 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1331 /* Send destroy messages */
1333 WIN_SendDestroyMsg( wndPtr );
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 (USER.43)
1357 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1359 return CloseWindow( hwnd );
1363 /***********************************************************************
1364 * CloseWindow (USER32.@)
1366 BOOL WINAPI CloseWindow( HWND hwnd )
1368 WND * wndPtr = WIN_FindWndPtr( hwnd );
1371 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1376 ShowWindow( hwnd, SW_MINIMIZE );
1379 WIN_ReleaseWndPtr(wndPtr);
1385 /***********************************************************************
1386 * OpenIcon (USER.44)
1388 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1390 return OpenIcon( hwnd );
1394 /***********************************************************************
1395 * OpenIcon (USER32.@)
1397 BOOL WINAPI OpenIcon( HWND hwnd )
1399 if (!IsIconic( hwnd )) return FALSE;
1400 ShowWindow( hwnd, SW_SHOWNORMAL );
1405 /***********************************************************************
1408 * Implementation of FindWindow() and FindWindowEx().
1410 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1418 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1421 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1427 else if (pWnd->parent != pWndDesktop)
1432 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1436 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1441 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1449 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1451 if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
1452 continue; /* Not the right class */
1454 /* Now check the title */
1458 retvalue = pWnd->hwndSelf;
1461 if (pWnd->text && !strcmpW( pWnd->text, title ))
1463 retvalue = pWnd->hwndSelf;
1468 /* In this case we need to check whether other processes
1469 own a window with the given paramters on the Desktop,
1470 but we don't, so let's at least warn about it */
1471 FIXME("Returning 0 without checking other processes\n");
1473 WIN_ReleaseWndPtr(pWnd);
1479 /***********************************************************************
1480 * FindWindow (USER.50)
1482 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1484 return FindWindowA( className, title );
1488 /***********************************************************************
1489 * FindWindowEx (USER.427)
1491 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1493 return FindWindowExA( parent, child, className, title );
1497 /***********************************************************************
1498 * FindWindowA (USER32.@)
1500 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1502 HWND ret = FindWindowExA( 0, 0, className, title );
1503 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1508 /***********************************************************************
1509 * FindWindowExA (USER32.@)
1511 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1512 LPCSTR className, LPCSTR title )
1520 /* If the atom doesn't exist, then no class */
1521 /* with this name exists either. */
1522 if (!(atom = GlobalFindAtomA( className )))
1524 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1529 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1530 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1531 HeapFree( GetProcessHeap(), 0, buffer );
1536 /***********************************************************************
1537 * FindWindowExW (USER32.@)
1539 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1540 LPCWSTR className, LPCWSTR title )
1546 /* If the atom doesn't exist, then no class */
1547 /* with this name exists either. */
1548 if (!(atom = GlobalFindAtomW( className )))
1550 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1554 return WIN_FindWindow( parent, child, atom, title );
1558 /***********************************************************************
1559 * FindWindowW (USER32.@)
1561 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1563 return FindWindowExW( 0, 0, className, title );
1567 /**********************************************************************
1569 * returns a locked pointer
1571 WND *WIN_GetDesktop(void)
1573 return WIN_LockWndPtr(pWndDesktop);
1575 /**********************************************************************
1576 * WIN_ReleaseDesktop
1577 * unlock the desktop pointer
1579 void WIN_ReleaseDesktop(void)
1581 WIN_ReleaseWndPtr(pWndDesktop);
1585 /**********************************************************************
1586 * GetDesktopWindow (USER.286)
1588 HWND16 WINAPI GetDesktopWindow16(void)
1590 return (HWND16)pWndDesktop->hwndSelf;
1594 /**********************************************************************
1595 * GetDesktopWindow (USER32.@)
1597 HWND WINAPI GetDesktopWindow(void)
1599 if (pWndDesktop) return pWndDesktop->hwndSelf;
1600 ERR( "You need the -desktop option when running with native USER\n" );
1606 /**********************************************************************
1607 * GetDesktopHwnd (USER.278)
1609 * Exactly the same thing as GetDesktopWindow(), but not documented.
1610 * Don't ask me why...
1612 HWND16 WINAPI GetDesktopHwnd16(void)
1614 return (HWND16)pWndDesktop->hwndSelf;
1618 /*******************************************************************
1619 * EnableWindow (USER.34)
1621 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1623 return EnableWindow( hwnd, enable );
1627 /*******************************************************************
1628 * EnableWindow (USER32.@)
1630 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1635 TRACE("( %x, %d )\n", hwnd, enable);
1637 if (USER_Driver.pEnableWindow)
1638 return USER_Driver.pEnableWindow( hwnd, enable );
1640 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1642 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1644 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1646 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1647 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1649 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1651 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1653 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1655 if (hwnd == GetFocus())
1656 SetFocus( 0 ); /* A disabled window can't have the focus */
1658 if (hwnd == GetCapture())
1659 ReleaseCapture(); /* A disabled window can't capture the mouse */
1661 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1663 WIN_ReleaseWndPtr(wndPtr);
1668 /***********************************************************************
1669 * IsWindowEnabled (USER.35)
1671 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1673 return IsWindowEnabled(hWnd);
1677 /***********************************************************************
1678 * IsWindowEnabled (USER32.@)
1680 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1685 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1686 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1687 WIN_ReleaseWndPtr(wndPtr);
1693 /***********************************************************************
1694 * IsWindowUnicode (USER32.@)
1696 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1701 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1702 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1703 WIN_ReleaseWndPtr(wndPtr);
1708 /**********************************************************************
1709 * GetWindowWord (USER.133)
1711 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1713 return GetWindowWord( hwnd, offset );
1717 /**********************************************************************
1718 * GetWindowWord (USER32.@)
1720 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1723 WND * wndPtr = WIN_FindWndPtr( hwnd );
1724 if (!wndPtr) return 0;
1727 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1729 WARN("Invalid offset %d\n", offset );
1733 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1739 if (HIWORD(wndPtr->wIDmenu))
1740 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1742 retvalue = (WORD)wndPtr->wIDmenu;
1744 case GWW_HWNDPARENT:
1745 retvalue = GetParent(hwnd);
1748 if (HIWORD(wndPtr->hInstance))
1749 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1751 retvalue = (WORD)wndPtr->hInstance;
1754 WARN("Invalid offset %d\n", offset );
1759 WIN_ReleaseWndPtr(wndPtr);
1763 /**********************************************************************
1764 * SetWindowWord (USER.134)
1766 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1768 return SetWindowWord( hwnd, offset, newval );
1772 /**********************************************************************
1773 * SetWindowWord (USER32.@)
1775 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1778 WND * wndPtr = WIN_FindWndPtr( hwnd );
1779 if (!wndPtr) return 0;
1782 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1784 WARN("Invalid offset %d\n", offset );
1788 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1792 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1793 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1794 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1797 WARN("Invalid offset %d\n", offset );
1804 WIN_ReleaseWndPtr(wndPtr);
1809 /**********************************************************************
1812 * Helper function for GetWindowLong().
1814 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1817 WND * wndPtr = WIN_FindWndPtr( hwnd );
1818 if (!wndPtr) return 0;
1821 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1823 WARN("Invalid offset %d\n", offset );
1827 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1828 /* Special case for dialog window procedure */
1829 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1831 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1838 case GWL_USERDATA: retvalue = wndPtr->userdata;
1840 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1842 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1844 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1846 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1849 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1851 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1854 WARN("Unknown offset %d\n", offset );
1858 WIN_ReleaseWndPtr(wndPtr);
1863 /**********************************************************************
1866 * Helper function for SetWindowLong().
1868 * 0 is the failure code. However, in the case of failure SetLastError
1869 * must be set to distinguish between a 0 return value and a failure.
1871 * FIXME: The error values for SetLastError may not be right. Can
1872 * someone check with the real thing?
1874 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1875 WINDOWPROCTYPE type )
1878 WND * wndPtr = WIN_FindWndPtr( hwnd );
1881 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1885 /* Is this the right error? */
1886 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1892 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1894 WARN("Invalid offset %d\n", offset );
1896 /* Is this the right error? */
1897 SetLastError( ERROR_OUTOFMEMORY );
1902 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1903 /* Special case for dialog window procedure */
1904 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1906 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1907 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1908 type, WIN_PROC_WINDOW );
1915 ptr = (DWORD*)&wndPtr->wIDmenu;
1918 retval = SetWindowWord( hwnd, offset, newval );
1921 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1922 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1923 type, WIN_PROC_WINDOW );
1926 style.styleOld = wndPtr->dwStyle;
1927 style.styleNew = newval;
1928 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1929 wndPtr->dwStyle = style.styleNew;
1930 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1931 retval = style.styleOld;
1935 ptr = &wndPtr->userdata;
1938 style.styleOld = wndPtr->dwExStyle;
1939 style.styleNew = newval;
1940 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1941 wndPtr->dwExStyle = newval;
1942 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1943 retval = style.styleOld;
1947 WARN("Invalid offset %d\n", offset );
1949 /* Don't think this is right error but it should do */
1950 SetLastError( ERROR_OUTOFMEMORY );
1958 WIN_ReleaseWndPtr(wndPtr);
1963 /**********************************************************************
1964 * GetWindowLong (USER.135)
1966 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1968 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1972 /**********************************************************************
1973 * GetWindowLongA (USER32.@)
1975 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1977 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1981 /**********************************************************************
1982 * GetWindowLongW (USER32.@)
1984 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1986 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1990 /**********************************************************************
1991 * SetWindowLong (USER.136)
1993 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1995 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1999 /**********************************************************************
2000 * SetWindowLongA (USER32.@)
2002 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2004 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2008 /**********************************************************************
2009 * SetWindowLongW (USER32.@) Set window attribute
2011 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2012 * value in a window's extra memory.
2014 * The _hwnd_ parameter specifies the window. is the handle to a
2015 * window that has extra memory. The _newval_ parameter contains the
2016 * new attribute or extra memory value. If positive, the _offset_
2017 * parameter is the byte-addressed location in the window's extra
2018 * memory to set. If negative, _offset_ specifies the window
2019 * attribute to set, and should be one of the following values:
2021 * GWL_EXSTYLE The window's extended window style
2023 * GWL_STYLE The window's window style.
2025 * GWL_WNDPROC Pointer to the window's window procedure.
2027 * GWL_HINSTANCE The window's pplication instance handle.
2029 * GWL_ID The window's identifier.
2031 * GWL_USERDATA The window's user-specified data.
2033 * If the window is a dialog box, the _offset_ parameter can be one of
2034 * the following values:
2036 * DWL_DLGPROC The address of the window's dialog box procedure.
2038 * DWL_MSGRESULT The return value of a message
2039 * that the dialog box procedure processed.
2041 * DWL_USER Application specific information.
2045 * If successful, returns the previous value located at _offset_. Otherwise,
2050 * Extra memory for a window class is specified by a nonzero cbWndExtra
2051 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2052 * time of class creation.
2054 * Using GWL_WNDPROC to set a new window procedure effectively creates
2055 * a window subclass. Use CallWindowProc() in the new windows procedure
2056 * to pass messages to the superclass's window procedure.
2058 * The user data is reserved for use by the application which created
2061 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2062 * instead, call the EnableWindow() function to change the window's
2065 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2066 * SetParent() instead.
2069 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2070 * it sends WM_STYLECHANGING before changing the settings
2071 * and WM_STYLECHANGED afterwards.
2072 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2076 * GWL_STYLE does not dispatch WM_STYLE... messages.
2083 LONG WINAPI SetWindowLongW(
2084 HWND hwnd, /* [in] window to alter */
2085 INT offset, /* [in] offset, in bytes, of location to alter */
2086 LONG newval /* [in] new value of location */
2088 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2092 /*******************************************************************
2093 * GetWindowText (USER.36)
2095 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2097 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2101 /*******************************************************************
2102 * GetWindowTextA (USER32.@)
2104 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2106 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2110 /*******************************************************************
2111 * InternalGetWindowText (USER32.@)
2113 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2115 WND *win = WIN_FindWndPtr( hwnd );
2117 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2118 else lpString[0] = 0;
2119 WIN_ReleaseWndPtr( win );
2120 return strlenW(lpString);
2124 /*******************************************************************
2125 * GetWindowTextW (USER32.@)
2127 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2129 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2134 /*******************************************************************
2135 * SetWindowText (USER.37)
2137 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2139 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2143 /*******************************************************************
2144 * SetWindowText (USER32.@)
2145 * SetWindowTextA (USER32.@)
2147 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2149 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2153 /*******************************************************************
2154 * SetWindowTextW (USER32.@)
2156 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2158 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2162 /*******************************************************************
2163 * GetWindowTextLength (USER.38)
2165 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2167 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2171 /*******************************************************************
2172 * GetWindowTextLengthA (USER32.@)
2174 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2176 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2179 /*******************************************************************
2180 * GetWindowTextLengthW (USER32.@)
2182 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2184 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2188 /*******************************************************************
2189 * IsWindow (USER.47)
2191 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2193 CURRENT_STACK16->es = USER_HeapSel;
2194 return IsWindow( hwnd );
2198 /*******************************************************************
2199 * IsWindow (USER32.@)
2201 BOOL WINAPI IsWindow( HWND hwnd )
2206 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2207 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2208 WIN_ReleaseWndPtr(wndPtr);
2214 /*****************************************************************
2215 * GetParent (USER.46)
2217 HWND16 WINAPI GetParent16( HWND16 hwnd )
2219 return (HWND16)GetParent( hwnd );
2223 /*****************************************************************
2224 * GetParent (USER32.@)
2226 HWND WINAPI GetParent( HWND hwnd )
2231 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2232 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2235 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2237 retvalue = wndPtr->hwndSelf;
2240 WIN_ReleaseWndPtr(wndPtr);
2245 /*****************************************************************
2248 * Get the top-level parent for a child window.
2249 * returns a locked pointer
2251 WND* WIN_GetTopParentPtr( WND* pWnd )
2253 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2255 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2257 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2262 /*****************************************************************
2265 * Get the top-level parent for a child window.
2267 HWND WIN_GetTopParent( HWND hwnd )
2270 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2271 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2273 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2274 WIN_ReleaseWndPtr(tmpPtr);
2275 WIN_ReleaseWndPtr(wndPtr);
2280 /*****************************************************************
2281 * SetParent (USER.233)
2283 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2285 return SetParent( hwndChild, hwndNewParent );
2289 /*****************************************************************
2290 * SetParent (USER32.@)
2292 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2299 if (hwnd == GetDesktopWindow()) /* sanity check */
2301 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2305 if (USER_Driver.pSetParent)
2306 return USER_Driver.pSetParent( hwnd, parent );
2308 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2310 dwStyle = wndPtr->dwStyle;
2312 if (!parent) parent = GetDesktopWindow();
2314 if (!(pWndParent = WIN_FindWndPtr(parent)))
2316 WIN_ReleaseWndPtr( wndPtr );
2320 /* Windows hides the window first, then shows it again
2321 * including the WM_SHOWWINDOW messages and all */
2322 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2324 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2325 if (pWndParent != wndPtr->parent)
2327 WIN_UnlinkWindow(wndPtr->hwndSelf);
2328 wndPtr->parent = pWndParent;
2330 if (parent != GetDesktopWindow()) /* a child window */
2332 if( !( wndPtr->dwStyle & WS_CHILD ) )
2334 if( wndPtr->wIDmenu != 0)
2336 DestroyMenu( (HMENU) wndPtr->wIDmenu );
2337 wndPtr->wIDmenu = 0;
2341 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
2343 WIN_ReleaseWndPtr( pWndParent );
2344 WIN_ReleaseWndPtr( wndPtr );
2346 /* SetParent additionally needs to make hwnd the topmost window
2347 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2348 WM_WINDOWPOSCHANGED notification messages.
2350 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2351 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2352 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2353 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2354 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2359 /*******************************************************************
2362 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2364 return IsChild(parent,child);
2368 /*******************************************************************
2369 * IsChild (USER32.@)
2371 BOOL WINAPI IsChild( HWND parent, HWND child )
2373 WND * wndPtr = WIN_FindWndPtr( child );
2374 while (wndPtr && wndPtr->parent)
2376 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2377 if (wndPtr->hwndSelf == GetDesktopWindow()) break;
2378 if (wndPtr->hwndSelf == parent)
2380 WIN_ReleaseWndPtr(wndPtr);
2384 WIN_ReleaseWndPtr(wndPtr);
2389 /***********************************************************************
2390 * IsWindowVisible (USER.49)
2392 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2394 return IsWindowVisible(hwnd);
2398 /***********************************************************************
2399 * IsWindowVisible (USER32.@)
2401 BOOL WINAPI IsWindowVisible( HWND hwnd )
2404 WND *wndPtr = WIN_FindWndPtr( hwnd );
2405 while (wndPtr && wndPtr->parent)
2407 if (!(wndPtr->dwStyle & WS_VISIBLE))
2409 WIN_ReleaseWndPtr(wndPtr);
2412 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2414 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2415 WIN_ReleaseWndPtr(wndPtr);
2420 /***********************************************************************
2421 * WIN_IsWindowDrawable
2423 * hwnd is drawable when it is visible, all parents are not
2424 * minimized, and it is itself not minimized unless we are
2425 * trying to draw its default class icon.
2427 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2429 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2430 if ((wnd->dwStyle & WS_MINIMIZE) &&
2431 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2432 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2433 if( wnd->dwStyle & WS_MINIMIZE ||
2434 !(wnd->dwStyle & WS_VISIBLE) ) break;
2435 return (wnd == NULL);
2439 /*******************************************************************
2440 * GetTopWindow (USER.229)
2442 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2444 return GetTopWindow(hwnd);
2448 /*******************************************************************
2449 * GetTopWindow (USER32.@)
2451 HWND WINAPI GetTopWindow( HWND hwnd )
2454 WND * wndPtr = (hwnd) ?
2455 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2457 if (wndPtr && wndPtr->child)
2458 retval = wndPtr->child->hwndSelf;
2460 WIN_ReleaseWndPtr(wndPtr);
2465 /*******************************************************************
2466 * GetWindow (USER.262)
2468 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2470 return GetWindow( hwnd,rel );
2474 /*******************************************************************
2475 * GetWindow (USER32.@)
2477 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2481 WND * wndPtr = WIN_FindWndPtr( hwnd );
2482 if (!wndPtr) return 0;
2486 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2490 if (!wndPtr->parent)
2492 retval = 0; /* Desktop window */
2495 while (wndPtr->next)
2497 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2499 retval = wndPtr->hwndSelf;
2503 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2507 if (!wndPtr->parent)
2509 retval = 0; /* Desktop window */
2512 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2513 if (wndPtr->hwndSelf == hwnd)
2515 retval = 0; /* First in list */
2518 while (wndPtr->next)
2520 if (wndPtr->next->hwndSelf == hwnd)
2522 retval = wndPtr->hwndSelf;
2525 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2531 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2535 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2540 WIN_ReleaseWndPtr(wndPtr);
2545 /*******************************************************************
2546 * GetNextWindow (USER.230)
2548 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2550 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2551 return GetWindow16( hwnd, flag );
2554 /***********************************************************************
2555 * WIN_InternalShowOwnedPopups
2557 * Internal version of ShowOwnedPopups; Wine functions should use this
2558 * to avoid interfering with application calls to ShowOwnedPopups
2559 * and to make sure the application can't prevent showing/hiding.
2561 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2565 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2567 INT totalChild=0, count=0;
2569 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2571 if (!pWnd) return TRUE;
2574 * Show windows Lowest first, Highest last to preserve Z-Order
2576 for (count = totalChild-1 ; count >=0; count--)
2578 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2582 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2583 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2586 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2588 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2589 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2594 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2595 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2596 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2599 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2601 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2602 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2603 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2608 WIN_ReleaseDesktop();
2609 WIN_ReleaseWinArray(pWnd);
2614 /*******************************************************************
2615 * ShowOwnedPopups (USER.265)
2617 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2619 ShowOwnedPopups( owner, fShow );
2623 /*******************************************************************
2624 * ShowOwnedPopups (USER32.@)
2626 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2628 UINT totalChild=0, count=0;
2630 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2632 if (!pWnd) return TRUE;
2634 for (; count < totalChild; count++)
2636 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2640 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2643 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2644 * regardless of the state of the owner
2646 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2647 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2652 if (IsWindowVisible(pWnd[count]->hwndSelf))
2655 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2656 * regardless of the state of the owner
2658 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2659 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2665 WIN_ReleaseDesktop();
2666 WIN_ReleaseWinArray(pWnd);
2671 /*******************************************************************
2672 * GetLastActivePopup (USER.287)
2674 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2676 return GetLastActivePopup( hwnd );
2679 /*******************************************************************
2680 * GetLastActivePopup (USER32.@)
2682 HWND WINAPI GetLastActivePopup( HWND hwnd )
2685 WND *wndPtr =WIN_FindWndPtr(hwnd);
2686 if (!wndPtr) return hwnd;
2687 retval = wndPtr->hwndLastActive;
2688 WIN_ReleaseWndPtr(wndPtr);
2689 if ((retval != hwnd) && (!IsWindow(retval)))
2695 /*******************************************************************
2698 * Build an array of pointers to the children of a given window.
2699 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2700 * when no windows are found.
2702 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2704 /* Future: this function will lock all windows associated with this array */
2706 WND **list, **ppWnd;
2708 UINT count = 0, skipOwned, skipHidden;
2711 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2712 skipOwned = bwaFlags & BWA_SKIPOWNED;
2713 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2714 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2716 /* First count the windows */
2719 wndPtr = WIN_GetDesktop();
2721 pWnd = WIN_LockWndPtr(wndPtr->child);
2724 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2725 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2727 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2732 /* Now build the list of all windows */
2734 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2736 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2738 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2739 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2745 WIN_ReleaseWndPtr(pWnd);
2751 if( pTotal ) *pTotal = count;
2754 /*******************************************************************
2755 * WIN_ReleaseWinArray
2757 void WIN_ReleaseWinArray(WND **wndArray)
2759 /* Future: this function will also unlock all windows associated with wndArray */
2760 HeapFree( GetProcessHeap(), 0, wndArray );
2764 /*******************************************************************
2765 * EnumWindows (USER32.@)
2767 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2769 WND **list, **ppWnd;
2771 /* We have to build a list of all windows first, to avoid */
2772 /* unpleasant side-effects, for instance if the callback */
2773 /* function changes the Z-order of the windows. */
2775 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2777 WIN_ReleaseDesktop();
2781 /* Now call the callback function for every window */
2783 for (ppWnd = list; *ppWnd; ppWnd++)
2785 LRESULT lpEnumFuncRetval;
2787 /* Make sure that the window still exists */
2788 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2790 /* To avoid any deadlocks, all the locks on the windows
2791 structures must be suspended before the control
2792 is passed to the application */
2793 iWndsLocks = WIN_SuspendWndsLock();
2794 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2795 WIN_RestoreWndsLock(iWndsLocks);
2797 if (!lpEnumFuncRetval) break;
2799 WIN_ReleaseWinArray(list);
2800 WIN_ReleaseDesktop();
2805 /**********************************************************************
2806 * WIN_EnumQueueWindows
2808 * Helper for EnumTaskWindows16 and EnumThreadWindows.
2810 static BOOL WIN_EnumQueueWindows( HQUEUE16 queue, WNDENUMPROC func, LPARAM lParam )
2812 WND **list, **ppWnd;
2814 /* This function is the same as EnumWindows(), */
2815 /* except for an added check on the window's task. */
2817 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2819 WIN_ReleaseDesktop();
2823 /* Now call the callback function for every window */
2825 for (ppWnd = list; *ppWnd; ppWnd++)
2829 /* Make sure that the window still exists */
2830 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2831 if ((*ppWnd)->hmemTaskQ != queue) continue;
2833 /* To avoid any deadlocks, all the locks on the windows
2834 structures must be suspended before the control
2835 is passed to the application */
2836 iWndsLocks = WIN_SuspendWndsLock();
2837 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2838 WIN_RestoreWndsLock(iWndsLocks);
2840 if (!funcRetval) break;
2842 WIN_ReleaseWinArray(list);
2843 WIN_ReleaseDesktop();
2848 /**********************************************************************
2849 * EnumTaskWindows16 (USER.225)
2851 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2854 HQUEUE16 queue = GetTaskQueue16( hTask );
2855 if (!queue) return FALSE;
2856 return WIN_EnumQueueWindows( queue, (WNDENUMPROC)func, lParam );
2860 /**********************************************************************
2861 * EnumThreadWindows (USER32.@)
2863 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2865 HQUEUE16 queue = GetThreadQueue16( id );
2866 if (!queue) return FALSE;
2867 return WIN_EnumQueueWindows( queue, func, lParam );
2871 /**********************************************************************
2872 * WIN_EnumChildWindows
2874 * Helper function for EnumChildWindows().
2876 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2881 for ( ; *ppWnd; ppWnd++)
2885 /* Make sure that the window still exists */
2886 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2887 /* Build children list first */
2888 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2890 /* To avoid any deadlocks, all the locks on the windows
2891 structures must be suspended before the control
2892 is passed to the application */
2893 iWndsLocks = WIN_SuspendWndsLock();
2894 ret = func( (*ppWnd)->hwndSelf, lParam );
2895 WIN_RestoreWndsLock(iWndsLocks);
2899 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2900 WIN_ReleaseWinArray(childList);
2902 if (!ret) return FALSE;
2908 /**********************************************************************
2909 * EnumChildWindows (USER32.@)
2911 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2914 WND **list, *pParent;
2916 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2917 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2919 WIN_ReleaseWndPtr(pParent);
2922 WIN_EnumChildWindows( list, func, lParam );
2923 WIN_ReleaseWinArray(list);
2924 WIN_ReleaseWndPtr(pParent);
2929 /*******************************************************************
2930 * AnyPopup (USER.52)
2932 BOOL16 WINAPI AnyPopup16(void)
2938 /*******************************************************************
2939 * AnyPopup (USER32.@)
2941 BOOL WINAPI AnyPopup(void)
2943 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2948 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2953 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2957 WIN_ReleaseWndPtr(wndPtr);
2962 /*******************************************************************
2963 * FlashWindow (USER.105)
2965 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2967 return FlashWindow( hWnd, bInvert );
2971 /*******************************************************************
2972 * FlashWindow (USER32.@)
2974 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2976 WND *wndPtr = WIN_FindWndPtr(hWnd);
2978 TRACE("%04x\n", hWnd);
2980 if (!wndPtr) return FALSE;
2982 if (wndPtr->dwStyle & WS_MINIMIZE)
2984 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2986 HDC hDC = GetDC(hWnd);
2988 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2989 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2991 ReleaseDC( hWnd, hDC );
2992 wndPtr->flags |= WIN_NCACTIVATED;
2996 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2997 wndPtr->flags &= ~WIN_NCACTIVATED;
2999 WIN_ReleaseWndPtr(wndPtr);
3005 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3006 else wparam = (hWnd == GetActiveWindow());
3008 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3009 WIN_ReleaseWndPtr(wndPtr);
3015 /*******************************************************************
3016 * SetSysModalWindow (USER.188)
3018 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3020 HWND hWndOldModal = hwndSysModal;
3021 hwndSysModal = hWnd;
3022 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3023 return hWndOldModal;
3027 /*******************************************************************
3028 * GetSysModalWindow (USER.189)
3030 HWND16 WINAPI GetSysModalWindow16(void)
3032 return hwndSysModal;
3036 /*******************************************************************
3037 * GetWindowContextHelpId (USER32.@)
3039 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3042 WND *wnd = WIN_FindWndPtr( hwnd );
3044 retval = wnd->helpContext;
3045 WIN_ReleaseWndPtr(wnd);
3050 /*******************************************************************
3051 * SetWindowContextHelpId (USER32.@)
3053 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3055 WND *wnd = WIN_FindWndPtr( hwnd );
3056 if (!wnd) return FALSE;
3057 wnd->helpContext = id;
3058 WIN_ReleaseWndPtr(wnd);
3063 /*******************************************************************
3066 * recursively find a child that contains spDragInfo->pt point
3067 * and send WM_QUERYDROPOBJECT
3069 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3071 BOOL16 wParam, bResult = 0;
3073 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3074 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3077 if( !ptrQueryWnd || !ptrDragInfo )
3080 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3082 GetWindowRect(hQueryWnd,&tempRect);
3084 if( !PtInRect(&tempRect,pt) ||
3085 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3088 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3090 tempRect = ptrQueryWnd->rectClient;
3091 if(ptrQueryWnd->parent)
3092 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3093 (LPPOINT)&tempRect, 2 );
3095 if (PtInRect( &tempRect, pt))
3099 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3101 if( ptrWnd->dwStyle & WS_VISIBLE )
3103 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3104 if (PtInRect( &tempRect, pt )) break;
3110 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3111 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3112 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3113 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3114 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3116 WIN_ReleaseWndPtr(ptrWnd);
3126 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3128 ptrDragInfo->hScope = hQueryWnd;
3130 bResult = ( bNoSend )
3131 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3132 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3133 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3135 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3138 WIN_ReleaseWndPtr(ptrQueryWnd);
3143 /*******************************************************************
3144 * DragDetect (USER.465)
3146 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3149 CONV_POINT16TO32( &pt, &pt32 );
3150 return DragDetect( hWnd, pt32 );
3153 /*******************************************************************
3154 * DragDetect (USER32.@)
3156 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3161 rect.left = pt.x - wDragWidth;
3162 rect.right = pt.x + wDragWidth;
3164 rect.top = pt.y - wDragHeight;
3165 rect.bottom = pt.y + wDragHeight;
3171 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3173 if( msg.message == WM_LBUTTONUP )
3178 if( msg.message == WM_MOUSEMOVE )
3181 tmp.x = LOWORD(msg.lParam);
3182 tmp.y = HIWORD(msg.lParam);
3183 if( !PtInRect( &rect, tmp ))
3195 /******************************************************************************
3196 * DragObject (USER.464)
3198 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3199 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3202 LPDRAGINFO16 lpDragInfo;
3204 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3205 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3206 WND *wndPtr = WIN_FindWndPtr(hWnd);
3207 HCURSOR16 hCurrentCursor = 0;
3208 HWND16 hCurrentWnd = 0;
3210 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3211 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3213 if( !lpDragInfo || !spDragInfo )
3215 WIN_ReleaseWndPtr(wndPtr);
3219 hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO));
3221 if( !hBummer || !wndPtr )
3223 GlobalFree16(hDragInfo);
3224 WIN_ReleaseWndPtr(wndPtr);
3230 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3232 GlobalFree16(hDragInfo);
3233 WIN_ReleaseWndPtr(wndPtr);
3237 if( hDragCursor == hCursor ) hDragCursor = 0;
3238 else hCursor = hDragCursor;
3240 hOldCursor = SetCursor(hDragCursor);
3243 lpDragInfo->hWnd = hWnd;
3244 lpDragInfo->hScope = 0;
3245 lpDragInfo->wFlags = wObj;
3246 lpDragInfo->hList = szList; /* near pointer! */
3247 lpDragInfo->hOfStruct = hOfStruct;
3255 do{ WaitMessage(); }
3256 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3258 *(lpDragInfo+1) = *lpDragInfo;
3260 lpDragInfo->pt.x = msg.pt.x;
3261 lpDragInfo->pt.y = msg.pt.y;
3263 /* update DRAGINFO struct */
3264 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3266 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3267 hCurrentCursor = hCursor;
3270 hCurrentCursor = hBummer;
3271 lpDragInfo->hScope = 0;
3273 if( hCurrentCursor )
3274 SetCursor(hCurrentCursor);
3276 /* send WM_DRAGLOOP */
3277 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3278 (LPARAM) spDragInfo );
3279 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3280 if( hCurrentWnd != lpDragInfo->hScope )
3283 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3284 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3285 HIWORD(spDragInfo)) );
3286 hCurrentWnd = lpDragInfo->hScope;
3288 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3292 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3294 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3297 ShowCursor( FALSE );
3301 SetCursor( hOldCursor );
3302 if (hDragCursor) DestroyCursor( hDragCursor );
3305 if( hCurrentCursor != hBummer )
3306 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3307 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3310 GlobalFree16(hDragInfo);
3311 WIN_ReleaseWndPtr(wndPtr);
3313 return (DWORD)(msg.lParam);
3317 /******************************************************************************
3318 * GetWindowModuleFileNameA (USER32.@)
3320 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3322 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3323 hwnd, lpszFileName, cchFileNameMax);
3327 /******************************************************************************
3328 * GetWindowModuleFileNameW (USER32.@)
3330 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3332 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3333 hwnd, lpszFileName, cchFileNameMax);