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"
19 #include "cursoricon.h"
25 #include "stackframe.h"
26 #include "debugtools.h"
28 DEFAULT_DEBUG_CHANNEL(win);
29 DECLARE_DEBUG_CHANNEL(msg);
31 /**********************************************************************/
33 WND_DRIVER *WND_Driver = NULL;
36 static WND *pWndDesktop = NULL;
38 static HWND hwndSysModal = 0;
40 static WORD wDragWidth = 4;
41 static WORD wDragHeight= 3;
44 static SYSLEVEL WIN_SysLevel = { CRITICAL_SECTION_INIT, 2 };
46 /***********************************************************************
49 * Locks access to all WND structures for thread safeness
51 void WIN_LockWnds( void )
53 _EnterSysLevel( &WIN_SysLevel );
56 /***********************************************************************
59 * Unlocks access to all WND structures
61 void WIN_UnlockWnds( void )
63 _LeaveSysLevel( &WIN_SysLevel );
66 /***********************************************************************
69 * Suspend the lock on WND structures.
70 * Returns the number of locks suspended
72 int WIN_SuspendWndsLock( void )
74 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
75 int count = isuspendedLocks;
78 _LeaveSysLevel( &WIN_SysLevel );
80 return isuspendedLocks;
83 /***********************************************************************
86 * Restore the suspended locks on WND structures
88 void WIN_RestoreWndsLock( int ipreviousLocks )
90 while ( ipreviousLocks-- > 0 )
91 _EnterSysLevel( &WIN_SysLevel );
94 /***********************************************************************
97 * Return a pointer to the WND structure corresponding to a HWND.
99 WND * WIN_FindWndPtr( HWND hwnd )
103 if (!hwnd || HIWORD(hwnd)) goto error2;
104 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
105 /* Lock all WND structures for thread safeness*/
107 /*and increment destruction monitoring*/
110 if (ptr->dwMagic != WND_MAGIC) goto error;
111 if (ptr->hwndSelf != hwnd)
113 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
116 /* returns a locked pointer */
119 /* Unlock all WND structures for thread safeness*/
121 /* and decrement destruction monitoring value */
126 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
130 /***********************************************************************
133 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
135 * Returns the locked initialisation pointer
137 WND *WIN_LockWndPtr(WND *initWndPtr)
139 if(!initWndPtr) return 0;
141 /* Lock all WND structures for thread safeness*/
143 /*and increment destruction monitoring*/
144 initWndPtr->irefCount++;
150 /***********************************************************************
153 * Release the pointer to the WND structure.
155 void WIN_ReleaseWndPtr(WND *wndPtr)
159 /*Decrement destruction monitoring value*/
161 /* Check if it's time to release the memory*/
162 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
165 USER_HEAP_FREE( wndPtr->hwndSelf);
166 wndPtr->hwndSelf = 0;
168 else if(wndPtr->irefCount < 0)
170 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
171 ERR("forgot a Lock on %p somewhere\n",wndPtr);
173 /*unlock all WND structures for thread safeness*/
177 /***********************************************************************
180 * Updates the value of oldPtr to newPtr.
182 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
186 tmpWnd = WIN_LockWndPtr(newPtr);
187 WIN_ReleaseWndPtr(*oldPtr);
192 /***********************************************************************
195 * Dump the content of a window structure to stderr.
197 void WIN_DumpWindow( HWND hwnd )
203 if (!(ptr = WIN_FindWndPtr( hwnd )))
205 WARN("%04x is not a window handle\n", hwnd );
209 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
210 strcpy( className, "#NULL#" );
212 TRACE("Window %04x (%p):\n", hwnd, ptr );
213 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
214 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
215 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
216 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
217 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
218 ptr->next, ptr->child, ptr->parent, ptr->owner,
219 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
220 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
221 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
222 ptr->text ? debugstr_w(ptr->text) : "",
223 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
224 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
225 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
226 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
230 DPRINTF( "extra bytes:" );
231 for (i = 0; i < ptr->cbWndExtra; i++)
232 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
236 WIN_ReleaseWndPtr(ptr);
240 /***********************************************************************
243 * Walk the windows tree and print each window on stderr.
245 void WIN_WalkWindows( HWND hwnd, int indent )
250 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
254 WARN("Invalid window handle %04x\n", hwnd );
258 if (!indent) /* first time around */
259 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
260 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
265 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
267 GetClassNameA( ptr->hwndSelf, className, sizeof(className) );
268 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
269 (DWORD)ptr, ptr->hmemTaskQ, className,
270 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
271 ptr->text ? debugstr_w(ptr->text) : "<null>");
273 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
274 WIN_UpdateWndPtr(&ptr,ptr->next);
278 /***********************************************************************
281 * Remove a window from the siblings linked list.
283 BOOL WIN_UnlinkWindow( HWND hwnd )
285 WND *wndPtr, **ppWnd;
288 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
289 else if(!wndPtr->parent)
291 WIN_ReleaseWndPtr(wndPtr);
295 ppWnd = &wndPtr->parent->child;
296 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
299 *ppWnd = wndPtr->next;
302 WIN_ReleaseWndPtr(wndPtr);
307 /***********************************************************************
310 * Insert a window into the siblings linked list.
311 * The window is inserted after the specified window, which can also
312 * be specified as HWND_TOP or HWND_BOTTOM.
314 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
316 WND *wndPtr, **ppWnd;
318 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
319 else if(!wndPtr->parent)
321 WIN_ReleaseWndPtr(wndPtr);
324 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
326 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
327 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
328 while (*ppWnd) ppWnd = &(*ppWnd)->next;
330 else /* Normal case */
332 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
335 WIN_ReleaseWndPtr(wndPtr);
338 ppWnd = &afterPtr->next;
339 WIN_ReleaseWndPtr(afterPtr);
341 wndPtr->next = *ppWnd;
343 WIN_ReleaseWndPtr(wndPtr);
348 /***********************************************************************
349 * WIN_FindWinToRepaint
351 * Find a window that needs repaint.
353 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
358 /* Note: the desktop window never gets WM_PAINT messages
359 * The real reason why is because Windows DesktopWndProc
360 * does ValidateRgn inside WM_ERASEBKGND handler.
362 if (hwnd == GetDesktopWindow()) hwnd = 0;
364 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
366 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
368 if (!(pWnd->dwStyle & WS_VISIBLE))
370 TRACE("skipping window %04x\n",
373 else if ((pWnd->hmemTaskQ == hQueue) &&
374 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
377 else if (pWnd->child )
378 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
380 WIN_ReleaseWndPtr(pWnd);
391 hwndRet = pWnd->hwndSelf;
393 /* look among siblings if we got a transparent window */
394 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
395 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
397 WIN_UpdateWndPtr(&pWnd,pWnd->next);
401 hwndRet = pWnd->hwndSelf;
402 WIN_ReleaseWndPtr(pWnd);
404 TRACE("found %04x\n",hwndRet);
409 /***********************************************************************
412 * Destroy storage associated to a window. "Internals" p.358
413 * returns a locked wndPtr->next
415 static WND* WIN_DestroyWindow( WND* wndPtr )
417 HWND hwnd = wndPtr->hwndSelf;
420 TRACE("%04x\n", wndPtr->hwndSelf );
422 /* free child windows */
423 WIN_LockWndPtr(wndPtr->child);
424 while ((pWnd = wndPtr->child))
426 wndPtr->child = WIN_DestroyWindow( pWnd );
427 WIN_ReleaseWndPtr(pWnd);
431 * Clear the update region to make sure no WM_PAINT messages will be
432 * generated for this window while processing the WM_NCDESTROY.
434 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
436 if (wndPtr->hrgnUpdate > 1)
437 DeleteObject( wndPtr->hrgnUpdate );
439 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
441 wndPtr->hrgnUpdate = 0;
445 * Send the WM_NCDESTROY to the window being destroyed.
447 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
449 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
451 WINPOS_CheckInternalPos( wndPtr );
452 if( hwnd == GetCapture()) ReleaseCapture();
454 /* free resources associated with the window */
456 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
457 PROPERTY_RemoveWindowProps( wndPtr );
459 /* toss stale messages from the queue */
461 QUEUE_CleanupWindow( hwnd );
462 wndPtr->hmemTaskQ = 0;
464 if (!(wndPtr->dwStyle & WS_CHILD))
467 DestroyMenu( wndPtr->wIDmenu );
470 if (wndPtr->hSysMenu)
472 DestroyMenu( wndPtr->hSysMenu );
473 wndPtr->hSysMenu = 0;
475 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
476 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
477 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
478 CLASS_RemoveWindow( wndPtr->class );
479 wndPtr->class = NULL;
480 wndPtr->dwMagic = 0; /* Mark it as invalid */
482 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
487 /***********************************************************************
488 * WIN_ResetQueueWindows
490 * Reset the queue of all the children of a given window.
491 * Return TRUE if something was done.
493 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
497 if (hNew) /* Set a new queue */
499 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
501 if (wnd->hmemTaskQ == hQueue)
503 wnd->hmemTaskQ = hNew;
508 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
512 else /* Queue is being destroyed */
516 WND *tmp = WIN_LockWndPtr(wnd->child);
521 if (tmp->hmemTaskQ == hQueue)
523 DestroyWindow( tmp->hwndSelf );
527 tmp2 = WIN_LockWndPtr(tmp->child);
528 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
532 WIN_UpdateWndPtr(&tmp,tmp->next);
534 WIN_ReleaseWndPtr(tmp2);
536 WIN_ReleaseWndPtr(tmp);
543 /***********************************************************************
544 * WIN_CreateDesktopWindow
546 * Create the desktop window.
548 BOOL WIN_CreateDesktopWindow(void)
550 struct tagCLASS *class;
558 TRACE("Creating desktop window\n");
561 if (!WINPOS_CreateInternalPosAtom() ||
562 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
563 &wndExtra, &winproc, &clsStyle, &dce )))
566 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
567 if (!hwndDesktop) return FALSE;
568 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
570 pWndDesktop->pDriver = WND_Driver;
571 pWndDesktop->next = NULL;
572 pWndDesktop->child = NULL;
573 pWndDesktop->parent = NULL;
574 pWndDesktop->owner = NULL;
575 pWndDesktop->class = class;
576 pWndDesktop->dwMagic = WND_MAGIC;
577 pWndDesktop->hwndSelf = hwndDesktop;
578 pWndDesktop->hInstance = 0;
579 pWndDesktop->rectWindow.left = 0;
580 pWndDesktop->rectWindow.top = 0;
581 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
582 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
583 pWndDesktop->rectClient = pWndDesktop->rectWindow;
584 pWndDesktop->text = NULL;
585 pWndDesktop->hmemTaskQ = 0;
586 pWndDesktop->hrgnUpdate = 0;
587 pWndDesktop->hwndLastActive = hwndDesktop;
588 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
590 pWndDesktop->dwExStyle = 0;
591 pWndDesktop->clsStyle = clsStyle;
592 pWndDesktop->dce = NULL;
593 pWndDesktop->pVScroll = NULL;
594 pWndDesktop->pHScroll = NULL;
595 pWndDesktop->pProp = NULL;
596 pWndDesktop->wIDmenu = 0;
597 pWndDesktop->helpContext = 0;
598 pWndDesktop->flags = 0;
599 pWndDesktop->hSysMenu = 0;
600 pWndDesktop->userdata = 0;
601 pWndDesktop->winproc = winproc;
602 pWndDesktop->cbWndExtra = wndExtra;
603 pWndDesktop->irefCount = 0;
605 cs.lpCreateParams = NULL;
611 cs.cx = pWndDesktop->rectWindow.right;
612 cs.cy = pWndDesktop->rectWindow.bottom;
613 cs.style = pWndDesktop->dwStyle;
614 cs.dwExStyle = pWndDesktop->dwExStyle;
616 cs.lpszClass = DESKTOP_CLASS_ATOM;
618 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs )) return FALSE;
620 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
625 /***********************************************************************
628 * Fix the coordinates - Helper for WIN_CreateWindowEx.
629 * returns default show mode in sw.
630 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
632 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
634 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
635 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
637 if (cs->style & (WS_CHILD | WS_POPUP))
639 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
640 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
642 else /* overlapped window */
646 GetStartupInfoA( &info );
648 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
650 /* Never believe Microsoft's documentation... CreateWindowEx doc says
651 * that if an overlapped window is created with WS_VISIBLE style bit
652 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
653 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
656 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
657 * 2) it does not ignore the y parameter as the docs claim; instead, it
658 * uses it as second parameter to ShowWindow() unless y is either
659 * CW_USEDEFAULT or CW_USEDEFAULT16.
661 * The fact that we didn't do 2) caused bogus windows pop up when wine
662 * was running apps that were using this obscure feature. Example -
663 * calc.exe that comes with Win98 (only Win98, it's different from
664 * the one that comes with Win95 and NT)
666 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
667 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
668 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
671 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
673 if (info.dwFlags & STARTF_USESIZE)
675 cs->cx = info.dwXSize;
676 cs->cy = info.dwYSize;
678 else /* if no other hint from the app, pick 3/4 of the screen real estate */
681 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
682 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
683 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
690 /***********************************************************************
693 * Implementation of CreateWindowEx().
695 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
696 WINDOWPROCTYPE type )
699 struct tagCLASS *classPtr;
701 HWND hwnd, hwndLinkAfter;
702 POINT maxSize, maxPos, minTrack, maxTrack;
708 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
709 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
710 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
711 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
712 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
714 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
715 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
717 /* Find the parent window */
721 /* Make sure parent is valid */
722 if (!IsWindow( cs->hwndParent ))
724 WARN("Bad parent %04x\n", cs->hwndParent );
727 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
728 WARN("No parent for child window\n" );
729 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
732 /* Find the window class */
733 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
734 &wndExtra, &winproc, &clsStyle, &dce )))
736 WARN("Bad class '%s'\n", cs->lpszClass );
740 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
742 /* Create the window structure */
744 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
746 TRACE("out of memory\n" );
750 /* Fill the window structure */
752 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
754 wndPtr->child = NULL;
756 if ((cs->style & WS_CHILD) && cs->hwndParent)
758 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
759 wndPtr->owner = NULL;
760 WIN_ReleaseWndPtr(wndPtr->parent);
764 wndPtr->parent = pWndDesktop;
765 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
766 wndPtr->owner = NULL;
769 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
770 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
771 WIN_ReleaseWndPtr(wndPtr->owner);
772 WIN_ReleaseWndPtr(tmpWnd);
777 wndPtr->pDriver = wndPtr->parent->pDriver;
779 wndPtr->class = classPtr;
780 wndPtr->winproc = winproc;
781 wndPtr->dwMagic = WND_MAGIC;
782 wndPtr->hwndSelf = hwnd;
783 wndPtr->hInstance = cs->hInstance;
785 wndPtr->hmemTaskQ = GetFastQueue16();
786 wndPtr->hrgnUpdate = 0;
788 wndPtr->hwndLastActive = hwnd;
789 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
790 wndPtr->dwExStyle = cs->dwExStyle;
791 wndPtr->clsStyle = clsStyle;
793 wndPtr->helpContext = 0;
794 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
795 wndPtr->pVScroll = NULL;
796 wndPtr->pHScroll = NULL;
797 wndPtr->pProp = NULL;
798 wndPtr->userdata = 0;
799 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
800 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
801 wndPtr->cbWndExtra = wndExtra;
802 wndPtr->irefCount = 1;
804 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
806 /* Call the WH_CBT hook */
808 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
809 ? HWND_BOTTOM : HWND_TOP;
811 if (HOOK_IsHooked( WH_CBT ))
817 cbtc.hwndInsertAfter = hwndLinkAfter;
818 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
819 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
822 TRACE("CBT-hook returned 0\n");
823 USER_HEAP_FREE( hwnd );
824 CLASS_RemoveWindow( classPtr );
830 /* Correct the window style */
832 if (!(cs->style & WS_CHILD))
834 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
835 if (!(cs->style & WS_POPUP))
837 wndPtr->dwStyle |= WS_CAPTION;
838 wndPtr->flags |= WIN_NEED_SIZE;
842 /* Get class or window DC if needed */
844 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
845 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
846 else wndPtr->dce = NULL;
848 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
850 wndPtr->rectWindow.left = cs->x;
851 wndPtr->rectWindow.top = cs->y;
852 wndPtr->rectWindow.right = cs->x + cs->cx;
853 wndPtr->rectWindow.bottom = cs->y + cs->cy;
854 wndPtr->rectClient = wndPtr->rectWindow;
856 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
858 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
860 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
861 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
862 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
863 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
864 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
867 if (cs->cx < 0) cs->cx = 0;
868 if (cs->cy < 0) cs->cy = 0;
870 wndPtr->rectWindow.left = cs->x;
871 wndPtr->rectWindow.top = cs->y;
872 wndPtr->rectWindow.right = cs->x + cs->cx;
873 wndPtr->rectWindow.bottom = cs->y + cs->cy;
874 wndPtr->rectClient = wndPtr->rectWindow;
876 /* Set the window menu */
878 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
880 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
883 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
886 if (HIWORD(cs->hInstance))
887 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
889 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
891 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
895 else wndPtr->wIDmenu = (UINT)cs->hMenu;
897 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs ))
899 WARN("aborted by WM_xxCREATE!\n");
900 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
901 CLASS_RemoveWindow( classPtr );
902 WIN_ReleaseWndPtr(wndPtr);
906 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
908 /* Notify the parent window only */
910 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
911 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
912 if( !IsWindow(hwnd) )
919 if (cs->style & WS_VISIBLE)
921 /* in case WS_VISIBLE got set in the meantime */
922 wndPtr->dwStyle &= ~WS_VISIBLE;
923 ShowWindow( hwnd, sw );
926 /* Call WH_SHELL hook */
928 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
929 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
931 TRACE("created window %04x\n", hwnd);
933 WIN_ReleaseWndPtr(wndPtr);
938 /***********************************************************************
939 * CreateWindow (USER.41)
941 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
942 DWORD style, INT16 x, INT16 y, INT16 width,
943 INT16 height, HWND16 parent, HMENU16 menu,
944 HINSTANCE16 instance, LPVOID data )
946 return CreateWindowEx16( 0, className, windowName, style,
947 x, y, width, height, parent, menu, instance, data );
951 /***********************************************************************
952 * CreateWindowEx (USER.452)
954 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
955 LPCSTR windowName, DWORD style, INT16 x,
956 INT16 y, INT16 width, INT16 height,
957 HWND16 parent, HMENU16 menu,
958 HINSTANCE16 instance, LPVOID data )
964 /* Find the class atom */
966 if (HIWORD(className))
968 if (!(classAtom = GlobalFindAtomA( className )))
970 ERR( "bad class name %s\n", debugres_a(className) );
976 classAtom = LOWORD(className);
977 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
979 ERR( "bad atom %x\n", classAtom);
985 /* Fix the coordinates */
987 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
988 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
989 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
990 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
992 /* Create the window */
994 cs.lpCreateParams = data;
995 cs.hInstance = (HINSTANCE)instance;
996 cs.hMenu = (HMENU)menu;
997 cs.hwndParent = (HWND)parent;
999 cs.lpszName = windowName;
1000 cs.lpszClass = className;
1001 cs.dwExStyle = exStyle;
1003 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
1007 /***********************************************************************
1008 * CreateWindowExA (USER32.@)
1010 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1011 LPCSTR windowName, DWORD style, INT x,
1012 INT y, INT width, INT height,
1013 HWND parent, HMENU menu,
1014 HINSTANCE instance, LPVOID data )
1021 instance=GetModuleHandleA(NULL);
1023 if(exStyle & WS_EX_MDICHILD)
1024 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1026 /* Find the class atom */
1028 if (HIWORD(className))
1030 if (!(classAtom = GlobalFindAtomA( className )))
1032 ERR( "bad class name %s\n", debugres_a(className) );
1038 classAtom = LOWORD(className);
1039 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1041 ERR( "bad atom %x\n", classAtom);
1047 /* Create the window */
1049 cs.lpCreateParams = data;
1050 cs.hInstance = instance;
1052 cs.hwndParent = parent;
1058 cs.lpszName = windowName;
1059 cs.lpszClass = className;
1060 cs.dwExStyle = exStyle;
1062 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1066 /***********************************************************************
1067 * CreateWindowExW (USER32.@)
1069 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1070 LPCWSTR windowName, DWORD style, INT x,
1071 INT y, INT width, INT height,
1072 HWND parent, HMENU menu,
1073 HINSTANCE instance, LPVOID data )
1080 instance=GetModuleHandleA(NULL);
1082 if(exStyle & WS_EX_MDICHILD)
1083 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1085 /* Find the class atom */
1087 if (HIWORD(className))
1089 if (!(classAtom = GlobalFindAtomW( className )))
1091 ERR( "bad class name %s\n", debugres_w(className) );
1097 classAtom = LOWORD(className);
1098 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1100 ERR( "bad atom %x\n", classAtom);
1106 /* Create the window */
1108 cs.lpCreateParams = data;
1109 cs.hInstance = instance;
1111 cs.hwndParent = parent;
1117 cs.lpszName = windowName;
1118 cs.lpszClass = className;
1119 cs.dwExStyle = exStyle;
1121 /* Note: we rely on the fact that CREATESTRUCTA and */
1122 /* CREATESTRUCTW have the same layout. */
1123 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1126 /***********************************************************************
1127 * WIN_SendDestroyMsg
1129 static void WIN_SendDestroyMsg( WND* pWnd )
1131 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1132 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1135 * Send the WM_DESTROY to the window.
1137 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1140 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1141 * make sure that the window still exists when we come back.
1143 if (IsWindow(pWnd->hwndSelf))
1145 HWND* pWndArray = NULL;
1150 * Now, if the window has kids, we have to send WM_DESTROY messages
1151 * recursively to it's kids. It seems that those calls can also
1152 * trigger re-entrant calls to DestroyWindow for the kids so we must
1153 * protect against corruption of the list of siblings. We first build
1154 * a list of HWNDs representing all the kids.
1156 pChild = WIN_LockWndPtr(pWnd->child);
1160 WIN_UpdateWndPtr(&pChild,pChild->next);
1164 * If there are no kids, we're done.
1169 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1174 if (pWndArray==NULL)
1178 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1179 * call, our linked list of siblings should be safe.
1182 pChild = WIN_LockWndPtr(pWnd->child);
1185 pWndArray[nKidCount] = pChild->hwndSelf;
1187 WIN_UpdateWndPtr(&pChild,pChild->next);
1191 * Now that we have a list, go through that list again and send the destroy
1192 * message to those windows. We are using the HWND to retrieve the
1193 * WND pointer so we are effectively checking that all the kid windows are
1194 * still valid before sending the message.
1198 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1202 WIN_SendDestroyMsg( pChild );
1203 WIN_ReleaseWndPtr(pChild);
1210 HeapFree(GetProcessHeap(), 0, pWndArray);
1213 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1217 /***********************************************************************
1218 * DestroyWindow (USER.53)
1220 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1222 return DestroyWindow(hwnd);
1226 /***********************************************************************
1227 * DestroyWindow (USER32.@)
1229 BOOL WINAPI DestroyWindow( HWND hwnd )
1234 BOOL bFocusSet = FALSE;
1236 TRACE("(%04x)\n", hwnd);
1238 /* Initialization */
1240 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1241 if (wndPtr == pWndDesktop)
1243 retvalue = FALSE; /* Can't destroy desktop */
1247 /* Look whether the focus is within the tree of windows we will
1251 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1255 SetFocus(GetParent(h));
1261 /* If the focus is on the window we will destroy and it has no parent,
1262 * set the focus to 0.
1264 if (! bFocusSet && (h == hwnd))
1266 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1272 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1278 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1280 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1281 /* FIXME: clean up palette - see "Internals" p.352 */
1284 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1285 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1287 /* Notify the parent window only */
1288 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1289 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1290 if( !IsWindow(hwnd) )
1297 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1299 /* Hide the window */
1301 if (wndPtr->dwStyle & WS_VISIBLE)
1303 ShowWindow( hwnd, SW_HIDE );
1304 if (!IsWindow(hwnd))
1311 /* Recursively destroy owned windows */
1313 if( !(wndPtr->dwStyle & WS_CHILD) )
1317 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1320 if (siblingPtr->owner == wndPtr)
1322 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1325 siblingPtr->owner = NULL;
1327 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1331 DestroyWindow( siblingPtr->hwndSelf );
1332 WIN_ReleaseWndPtr(siblingPtr);
1337 WINPOS_ActivateOtherWindow(wndPtr);
1339 if( wndPtr->owner &&
1340 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1341 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1344 /* Send destroy messages */
1346 WIN_SendDestroyMsg( wndPtr );
1347 if (!IsWindow(hwnd))
1353 /* Unlink now so we won't bother with the children later on */
1355 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1357 /* Destroy the window storage */
1359 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1362 WIN_ReleaseWndPtr(wndPtr);
1367 /***********************************************************************
1368 * CloseWindow (USER.43)
1370 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1372 return CloseWindow( hwnd );
1376 /***********************************************************************
1377 * CloseWindow (USER32.@)
1379 BOOL WINAPI CloseWindow( HWND hwnd )
1381 WND * wndPtr = WIN_FindWndPtr( hwnd );
1384 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1389 ShowWindow( hwnd, SW_MINIMIZE );
1392 WIN_ReleaseWndPtr(wndPtr);
1398 /***********************************************************************
1399 * OpenIcon (USER.44)
1401 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1403 return OpenIcon( hwnd );
1407 /***********************************************************************
1408 * OpenIcon (USER32.@)
1410 BOOL WINAPI OpenIcon( HWND hwnd )
1412 if (!IsIconic( hwnd )) return FALSE;
1413 ShowWindow( hwnd, SW_SHOWNORMAL );
1418 /***********************************************************************
1421 * Implementation of FindWindow() and FindWindowEx().
1423 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1431 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1434 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1440 else if (pWnd->parent != pWndDesktop)
1445 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1449 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1454 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1462 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1464 if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
1465 continue; /* Not the right class */
1467 /* Now check the title */
1471 retvalue = pWnd->hwndSelf;
1474 if (pWnd->text && !strcmpW( pWnd->text, title ))
1476 retvalue = pWnd->hwndSelf;
1481 /* In this case we need to check whether other processes
1482 own a window with the given paramters on the Desktop,
1483 but we don't, so let's at least warn about it */
1484 FIXME("Returning 0 without checking other processes\n");
1486 WIN_ReleaseWndPtr(pWnd);
1492 /***********************************************************************
1493 * FindWindow (USER.50)
1495 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1497 return FindWindowA( className, title );
1501 /***********************************************************************
1502 * FindWindowEx (USER.427)
1504 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1506 return FindWindowExA( parent, child, className, title );
1510 /***********************************************************************
1511 * FindWindowA (USER32.@)
1513 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1515 HWND ret = FindWindowExA( 0, 0, className, title );
1516 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1521 /***********************************************************************
1522 * FindWindowExA (USER32.@)
1524 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1525 LPCSTR className, LPCSTR title )
1533 /* If the atom doesn't exist, then no class */
1534 /* with this name exists either. */
1535 if (!(atom = GlobalFindAtomA( className )))
1537 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1542 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1543 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1544 HeapFree( GetProcessHeap(), 0, buffer );
1549 /***********************************************************************
1550 * FindWindowExW (USER32.@)
1552 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1553 LPCWSTR className, LPCWSTR title )
1559 /* If the atom doesn't exist, then no class */
1560 /* with this name exists either. */
1561 if (!(atom = GlobalFindAtomW( className )))
1563 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1567 return WIN_FindWindow( parent, child, atom, title );
1571 /***********************************************************************
1572 * FindWindowW (USER32.@)
1574 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1576 return FindWindowExW( 0, 0, className, title );
1580 /**********************************************************************
1582 * returns a locked pointer
1584 WND *WIN_GetDesktop(void)
1586 return WIN_LockWndPtr(pWndDesktop);
1588 /**********************************************************************
1589 * WIN_ReleaseDesktop
1590 * unlock the desktop pointer
1592 void WIN_ReleaseDesktop(void)
1594 WIN_ReleaseWndPtr(pWndDesktop);
1598 /**********************************************************************
1599 * GetDesktopWindow (USER.286)
1601 HWND16 WINAPI GetDesktopWindow16(void)
1603 return (HWND16)pWndDesktop->hwndSelf;
1607 /**********************************************************************
1608 * GetDesktopWindow (USER32.@)
1610 HWND WINAPI GetDesktopWindow(void)
1612 if (pWndDesktop) return pWndDesktop->hwndSelf;
1613 ERR( "You need the -desktop option when running with native USER\n" );
1619 /**********************************************************************
1620 * GetDesktopHwnd (USER.278)
1622 * Exactly the same thing as GetDesktopWindow(), but not documented.
1623 * Don't ask me why...
1625 HWND16 WINAPI GetDesktopHwnd16(void)
1627 return (HWND16)pWndDesktop->hwndSelf;
1631 /*******************************************************************
1632 * EnableWindow (USER.34)
1634 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1636 return EnableWindow( hwnd, enable );
1640 /*******************************************************************
1641 * EnableWindow (USER32.@)
1643 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1648 TRACE("( %x, %d )\n", hwnd, enable);
1650 if (USER_Driver.pEnableWindow)
1651 return USER_Driver.pEnableWindow( hwnd, enable );
1653 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1655 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1657 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1659 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1660 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1662 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1664 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1666 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1668 if (hwnd == GetFocus())
1669 SetFocus( 0 ); /* A disabled window can't have the focus */
1671 if (hwnd == GetCapture())
1672 ReleaseCapture(); /* A disabled window can't capture the mouse */
1674 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1676 WIN_ReleaseWndPtr(wndPtr);
1681 /***********************************************************************
1682 * IsWindowEnabled (USER.35)
1684 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1686 return IsWindowEnabled(hWnd);
1690 /***********************************************************************
1691 * IsWindowEnabled (USER32.@)
1693 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1698 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1699 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1700 WIN_ReleaseWndPtr(wndPtr);
1706 /***********************************************************************
1707 * IsWindowUnicode (USER32.@)
1709 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1714 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1715 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1716 WIN_ReleaseWndPtr(wndPtr);
1721 /**********************************************************************
1722 * GetWindowWord (USER.133)
1724 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1726 return GetWindowWord( hwnd, offset );
1730 /**********************************************************************
1731 * GetWindowWord (USER32.@)
1733 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1736 WND * wndPtr = WIN_FindWndPtr( hwnd );
1737 if (!wndPtr) return 0;
1740 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1742 WARN("Invalid offset %d\n", offset );
1746 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1752 if (HIWORD(wndPtr->wIDmenu))
1753 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1755 retvalue = (WORD)wndPtr->wIDmenu;
1757 case GWW_HWNDPARENT:
1758 retvalue = GetParent(hwnd);
1761 if (HIWORD(wndPtr->hInstance))
1762 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1764 retvalue = (WORD)wndPtr->hInstance;
1767 WARN("Invalid offset %d\n", offset );
1772 WIN_ReleaseWndPtr(wndPtr);
1776 /**********************************************************************
1777 * SetWindowWord (USER.134)
1779 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1781 return SetWindowWord( hwnd, offset, newval );
1785 /**********************************************************************
1786 * SetWindowWord (USER32.@)
1788 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1791 WND * wndPtr = WIN_FindWndPtr( hwnd );
1792 if (!wndPtr) return 0;
1795 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1797 WARN("Invalid offset %d\n", offset );
1801 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1805 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1806 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1807 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1810 WARN("Invalid offset %d\n", offset );
1817 WIN_ReleaseWndPtr(wndPtr);
1822 /**********************************************************************
1825 * Helper function for GetWindowLong().
1827 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1830 WND * wndPtr = WIN_FindWndPtr( hwnd );
1831 if (!wndPtr) return 0;
1834 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1836 WARN("Invalid offset %d\n", offset );
1840 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1841 /* Special case for dialog window procedure */
1842 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1844 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1851 case GWL_USERDATA: retvalue = wndPtr->userdata;
1853 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1855 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1857 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1859 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1862 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1864 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1867 WARN("Unknown offset %d\n", offset );
1871 WIN_ReleaseWndPtr(wndPtr);
1876 /**********************************************************************
1879 * Helper function for SetWindowLong().
1881 * 0 is the failure code. However, in the case of failure SetLastError
1882 * must be set to distinguish between a 0 return value and a failure.
1884 * FIXME: The error values for SetLastError may not be right. Can
1885 * someone check with the real thing?
1887 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1888 WINDOWPROCTYPE type )
1891 WND * wndPtr = WIN_FindWndPtr( hwnd );
1894 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1898 /* Is this the right error? */
1899 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1905 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1907 WARN("Invalid offset %d\n", offset );
1909 /* Is this the right error? */
1910 SetLastError( ERROR_OUTOFMEMORY );
1915 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1916 /* Special case for dialog window procedure */
1917 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1919 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1920 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1921 type, WIN_PROC_WINDOW );
1928 ptr = (DWORD*)&wndPtr->wIDmenu;
1931 retval = SetWindowWord( hwnd, offset, newval );
1934 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1935 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1936 type, WIN_PROC_WINDOW );
1939 style.styleOld = wndPtr->dwStyle;
1940 style.styleNew = newval;
1941 if (wndPtr->flags & WIN_ISWIN32)
1942 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1943 wndPtr->dwStyle = style.styleNew;
1944 if (wndPtr->flags & WIN_ISWIN32)
1945 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1946 retval = style.styleOld;
1950 ptr = &wndPtr->userdata;
1953 style.styleOld = wndPtr->dwExStyle;
1954 style.styleNew = newval;
1955 if (wndPtr->flags & WIN_ISWIN32)
1956 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1957 wndPtr->dwExStyle = newval;
1958 if (wndPtr->flags & WIN_ISWIN32)
1959 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1960 retval = style.styleOld;
1964 WARN("Invalid offset %d\n", offset );
1966 /* Don't think this is right error but it should do */
1967 SetLastError( ERROR_OUTOFMEMORY );
1975 WIN_ReleaseWndPtr(wndPtr);
1980 /**********************************************************************
1981 * GetWindowLong (USER.135)
1983 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1985 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1989 /**********************************************************************
1990 * GetWindowLongA (USER32.@)
1992 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1994 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1998 /**********************************************************************
1999 * GetWindowLongW (USER32.@)
2001 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2003 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2007 /**********************************************************************
2008 * SetWindowLong (USER.136)
2010 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2012 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2016 /**********************************************************************
2017 * SetWindowLongA (USER32.@)
2019 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2021 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2025 /**********************************************************************
2026 * SetWindowLongW (USER32.@) Set window attribute
2028 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2029 * value in a window's extra memory.
2031 * The _hwnd_ parameter specifies the window. is the handle to a
2032 * window that has extra memory. The _newval_ parameter contains the
2033 * new attribute or extra memory value. If positive, the _offset_
2034 * parameter is the byte-addressed location in the window's extra
2035 * memory to set. If negative, _offset_ specifies the window
2036 * attribute to set, and should be one of the following values:
2038 * GWL_EXSTYLE The window's extended window style
2040 * GWL_STYLE The window's window style.
2042 * GWL_WNDPROC Pointer to the window's window procedure.
2044 * GWL_HINSTANCE The window's pplication instance handle.
2046 * GWL_ID The window's identifier.
2048 * GWL_USERDATA The window's user-specified data.
2050 * If the window is a dialog box, the _offset_ parameter can be one of
2051 * the following values:
2053 * DWL_DLGPROC The address of the window's dialog box procedure.
2055 * DWL_MSGRESULT The return value of a message
2056 * that the dialog box procedure processed.
2058 * DWL_USER Application specific information.
2062 * If successful, returns the previous value located at _offset_. Otherwise,
2067 * Extra memory for a window class is specified by a nonzero cbWndExtra
2068 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2069 * time of class creation.
2071 * Using GWL_WNDPROC to set a new window procedure effectively creates
2072 * a window subclass. Use CallWindowProc() in the new windows procedure
2073 * to pass messages to the superclass's window procedure.
2075 * The user data is reserved for use by the application which created
2078 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2079 * instead, call the EnableWindow() function to change the window's
2082 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2083 * SetParent() instead.
2086 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2087 * it sends WM_STYLECHANGING before changing the settings
2088 * and WM_STYLECHANGED afterwards.
2089 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2093 * GWL_STYLE does not dispatch WM_STYLE... messages.
2100 LONG WINAPI SetWindowLongW(
2101 HWND hwnd, /* [in] window to alter */
2102 INT offset, /* [in] offset, in bytes, of location to alter */
2103 LONG newval /* [in] new value of location */
2105 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2109 /*******************************************************************
2110 * GetWindowText (USER.36)
2112 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2114 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2118 /*******************************************************************
2119 * GetWindowTextA (USER32.@)
2121 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2123 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2127 /*******************************************************************
2128 * InternalGetWindowText (USER32.@)
2130 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2132 WND *win = WIN_FindWndPtr( hwnd );
2134 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2135 else lpString[0] = 0;
2136 WIN_ReleaseWndPtr( win );
2137 return strlenW(lpString);
2141 /*******************************************************************
2142 * GetWindowTextW (USER32.@)
2144 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2146 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2151 /*******************************************************************
2152 * SetWindowText (USER.37)
2154 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2156 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2160 /*******************************************************************
2161 * SetWindowText (USER32.@)
2163 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2165 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2169 /*******************************************************************
2170 * SetWindowTextW (USER32.@)
2172 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2174 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2178 /*******************************************************************
2179 * GetWindowTextLength (USER.38)
2181 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2183 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2187 /*******************************************************************
2188 * GetWindowTextLengthA (USER32.@)
2190 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2192 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2195 /*******************************************************************
2196 * GetWindowTextLengthW (USER32.@)
2198 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2200 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2204 /*******************************************************************
2205 * IsWindow (USER.47)
2207 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2209 CURRENT_STACK16->es = USER_HeapSel;
2210 return IsWindow( hwnd );
2214 /*******************************************************************
2215 * IsWindow (USER32.@)
2217 BOOL WINAPI IsWindow( HWND hwnd )
2222 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2223 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2224 WIN_ReleaseWndPtr(wndPtr);
2230 /*****************************************************************
2231 * GetParent (USER.46)
2233 HWND16 WINAPI GetParent16( HWND16 hwnd )
2235 return (HWND16)GetParent( hwnd );
2239 /*****************************************************************
2240 * GetParent (USER32.@)
2242 HWND WINAPI GetParent( HWND hwnd )
2247 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2248 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2251 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2253 retvalue = wndPtr->hwndSelf;
2256 WIN_ReleaseWndPtr(wndPtr);
2261 /*****************************************************************
2264 * Get the top-level parent for a child window.
2265 * returns a locked pointer
2267 WND* WIN_GetTopParentPtr( WND* pWnd )
2269 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2271 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2273 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2278 /*****************************************************************
2281 * Get the top-level parent for a child window.
2283 HWND WIN_GetTopParent( HWND hwnd )
2286 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2287 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2289 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2290 WIN_ReleaseWndPtr(tmpPtr);
2291 WIN_ReleaseWndPtr(wndPtr);
2296 /*****************************************************************
2297 * SetParent (USER.233)
2299 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2301 return SetParent( hwndChild, hwndNewParent );
2305 /*****************************************************************
2306 * SetParent (USER32.@)
2308 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2315 if (hwnd == GetDesktopWindow()) /* sanity check */
2317 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2321 if (USER_Driver.pSetParent)
2322 return USER_Driver.pSetParent( hwnd, parent );
2324 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2326 dwStyle = wndPtr->dwStyle;
2328 if (!parent) parent = GetDesktopWindow();
2330 if (!(pWndParent = WIN_FindWndPtr(parent)))
2332 WIN_ReleaseWndPtr( wndPtr );
2336 /* Windows hides the window first, then shows it again
2337 * including the WM_SHOWWINDOW messages and all */
2338 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2340 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2341 if (pWndParent != wndPtr->parent)
2343 WIN_UnlinkWindow(wndPtr->hwndSelf);
2344 wndPtr->parent = pWndParent;
2346 if (parent != GetDesktopWindow()) /* a child window */
2348 if( !( wndPtr->dwStyle & WS_CHILD ) )
2350 if( wndPtr->wIDmenu != 0)
2352 DestroyMenu( (HMENU) wndPtr->wIDmenu );
2353 wndPtr->wIDmenu = 0;
2357 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
2359 WIN_ReleaseWndPtr( pWndParent );
2360 WIN_ReleaseWndPtr( wndPtr );
2362 /* SetParent additionally needs to make hwnd the topmost window
2363 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2364 WM_WINDOWPOSCHANGED notification messages.
2366 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2367 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2368 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2369 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2370 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2375 /*******************************************************************
2378 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2380 return IsChild(parent,child);
2384 /*******************************************************************
2385 * IsChild (USER32.@)
2387 BOOL WINAPI IsChild( HWND parent, HWND child )
2389 WND * wndPtr = WIN_FindWndPtr( child );
2390 while (wndPtr && wndPtr->parent)
2392 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2393 if (wndPtr->hwndSelf == GetDesktopWindow()) break;
2394 if (wndPtr->hwndSelf == parent)
2396 WIN_ReleaseWndPtr(wndPtr);
2400 WIN_ReleaseWndPtr(wndPtr);
2405 /***********************************************************************
2406 * IsWindowVisible (USER.49)
2408 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2410 return IsWindowVisible(hwnd);
2414 /***********************************************************************
2415 * IsWindowVisible (USER32.@)
2417 BOOL WINAPI IsWindowVisible( HWND hwnd )
2420 WND *wndPtr = WIN_FindWndPtr( hwnd );
2421 while (wndPtr && wndPtr->parent)
2423 if (!(wndPtr->dwStyle & WS_VISIBLE))
2425 WIN_ReleaseWndPtr(wndPtr);
2428 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2430 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2431 WIN_ReleaseWndPtr(wndPtr);
2436 /***********************************************************************
2437 * WIN_IsWindowDrawable
2439 * hwnd is drawable when it is visible, all parents are not
2440 * minimized, and it is itself not minimized unless we are
2441 * trying to draw its default class icon.
2443 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2445 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2446 if ((wnd->dwStyle & WS_MINIMIZE) &&
2447 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2448 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2449 if( wnd->dwStyle & WS_MINIMIZE ||
2450 !(wnd->dwStyle & WS_VISIBLE) ) break;
2451 return (wnd == NULL);
2455 /*******************************************************************
2456 * GetTopWindow (USER.229)
2458 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2460 return GetTopWindow(hwnd);
2464 /*******************************************************************
2465 * GetTopWindow (USER32.@)
2467 HWND WINAPI GetTopWindow( HWND hwnd )
2470 WND * wndPtr = (hwnd) ?
2471 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2473 if (wndPtr && wndPtr->child)
2474 retval = wndPtr->child->hwndSelf;
2476 WIN_ReleaseWndPtr(wndPtr);
2481 /*******************************************************************
2482 * GetWindow (USER.262)
2484 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2486 return GetWindow( hwnd,rel );
2490 /*******************************************************************
2491 * GetWindow (USER32.@)
2493 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2497 WND * wndPtr = WIN_FindWndPtr( hwnd );
2498 if (!wndPtr) return 0;
2502 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2506 if (!wndPtr->parent)
2508 retval = 0; /* Desktop window */
2511 while (wndPtr->next)
2513 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2515 retval = wndPtr->hwndSelf;
2519 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2523 if (!wndPtr->parent)
2525 retval = 0; /* Desktop window */
2528 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2529 if (wndPtr->hwndSelf == hwnd)
2531 retval = 0; /* First in list */
2534 while (wndPtr->next)
2536 if (wndPtr->next->hwndSelf == hwnd)
2538 retval = wndPtr->hwndSelf;
2541 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2547 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2551 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2556 WIN_ReleaseWndPtr(wndPtr);
2561 /*******************************************************************
2562 * GetNextWindow (USER.230)
2564 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2566 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2567 return GetWindow16( hwnd, flag );
2570 /***********************************************************************
2571 * WIN_InternalShowOwnedPopups
2573 * Internal version of ShowOwnedPopups; Wine functions should use this
2574 * to avoid interfering with application calls to ShowOwnedPopups
2575 * and to make sure the application can't prevent showing/hiding.
2577 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2581 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2583 INT totalChild=0, count=0;
2585 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2587 if (!pWnd) return TRUE;
2590 * Show windows Lowest first, Highest last to preserve Z-Order
2592 for (count = totalChild-1 ; count >=0; count--)
2594 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2598 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2599 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2602 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2604 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2605 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2610 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2611 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2612 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2615 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2617 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2618 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2619 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2624 WIN_ReleaseDesktop();
2625 WIN_ReleaseWinArray(pWnd);
2630 /*******************************************************************
2631 * ShowOwnedPopups (USER.265)
2633 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2635 ShowOwnedPopups( owner, fShow );
2639 /*******************************************************************
2640 * ShowOwnedPopups (USER32.@)
2642 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2644 UINT totalChild=0, count=0;
2646 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2648 if (!pWnd) return TRUE;
2650 for (; count < totalChild; count++)
2652 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2656 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2659 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2660 * regardless of the state of the owner
2662 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2663 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2668 if (IsWindowVisible(pWnd[count]->hwndSelf))
2671 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2672 * regardless of the state of the owner
2674 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2675 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2681 WIN_ReleaseDesktop();
2682 WIN_ReleaseWinArray(pWnd);
2687 /*******************************************************************
2688 * GetLastActivePopup (USER.287)
2690 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2692 return GetLastActivePopup( hwnd );
2695 /*******************************************************************
2696 * GetLastActivePopup (USER32.@)
2698 HWND WINAPI GetLastActivePopup( HWND hwnd )
2701 WND *wndPtr =WIN_FindWndPtr(hwnd);
2702 if (!wndPtr) return hwnd;
2703 retval = wndPtr->hwndLastActive;
2704 WIN_ReleaseWndPtr(wndPtr);
2705 if ((retval != hwnd) && (!IsWindow(retval)))
2711 /*******************************************************************
2714 * Build an array of pointers to the children of a given window.
2715 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2716 * when no windows are found.
2718 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2720 /* Future: this function will lock all windows associated with this array */
2722 WND **list, **ppWnd;
2724 UINT count = 0, skipOwned, skipHidden;
2727 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2728 skipOwned = bwaFlags & BWA_SKIPOWNED;
2729 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2730 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2732 /* First count the windows */
2735 wndPtr = WIN_GetDesktop();
2737 pWnd = WIN_LockWndPtr(wndPtr->child);
2740 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2741 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2743 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2748 /* Now build the list of all windows */
2750 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2752 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2754 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2755 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2761 WIN_ReleaseWndPtr(pWnd);
2767 if( pTotal ) *pTotal = count;
2770 /*******************************************************************
2771 * WIN_ReleaseWinArray
2773 void WIN_ReleaseWinArray(WND **wndArray)
2775 /* Future: this function will also unlock all windows associated with wndArray */
2776 HeapFree( GetProcessHeap(), 0, wndArray );
2780 /*******************************************************************
2781 * EnumWindows (USER32.@)
2783 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2785 WND **list, **ppWnd;
2787 /* We have to build a list of all windows first, to avoid */
2788 /* unpleasant side-effects, for instance if the callback */
2789 /* function changes the Z-order of the windows. */
2791 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2793 WIN_ReleaseDesktop();
2797 /* Now call the callback function for every window */
2799 for (ppWnd = list; *ppWnd; ppWnd++)
2801 LRESULT lpEnumFuncRetval;
2803 /* Make sure that the window still exists */
2804 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2806 /* To avoid any deadlocks, all the locks on the windows
2807 structures must be suspended before the control
2808 is passed to the application */
2809 iWndsLocks = WIN_SuspendWndsLock();
2810 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2811 WIN_RestoreWndsLock(iWndsLocks);
2813 if (!lpEnumFuncRetval) break;
2815 WIN_ReleaseWinArray(list);
2816 WIN_ReleaseDesktop();
2821 /**********************************************************************
2822 * WIN_EnumQueueWindows
2824 * Helper for EnumTaskWindows16 and EnumThreadWindows.
2826 static BOOL WIN_EnumQueueWindows( HQUEUE16 queue, WNDENUMPROC func, LPARAM lParam )
2828 WND **list, **ppWnd;
2830 /* This function is the same as EnumWindows(), */
2831 /* except for an added check on the window's task. */
2833 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2835 WIN_ReleaseDesktop();
2839 /* Now call the callback function for every window */
2841 for (ppWnd = list; *ppWnd; ppWnd++)
2845 /* Make sure that the window still exists */
2846 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2847 if ((*ppWnd)->hmemTaskQ != queue) continue;
2849 /* To avoid any deadlocks, all the locks on the windows
2850 structures must be suspended before the control
2851 is passed to the application */
2852 iWndsLocks = WIN_SuspendWndsLock();
2853 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2854 WIN_RestoreWndsLock(iWndsLocks);
2856 if (!funcRetval) break;
2858 WIN_ReleaseWinArray(list);
2859 WIN_ReleaseDesktop();
2864 /**********************************************************************
2865 * EnumTaskWindows16 (USER.225)
2867 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2870 HQUEUE16 queue = GetTaskQueue16( hTask );
2871 if (!queue) return FALSE;
2872 return WIN_EnumQueueWindows( queue, (WNDENUMPROC)func, lParam );
2876 /**********************************************************************
2877 * EnumThreadWindows (USER32.@)
2879 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2881 HQUEUE16 queue = GetThreadQueue16( id );
2882 if (!queue) return FALSE;
2883 return WIN_EnumQueueWindows( queue, func, lParam );
2887 /**********************************************************************
2888 * WIN_EnumChildWindows
2890 * Helper function for EnumChildWindows().
2892 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2897 for ( ; *ppWnd; ppWnd++)
2901 /* Make sure that the window still exists */
2902 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2903 /* Build children list first */
2904 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2906 /* To avoid any deadlocks, all the locks on the windows
2907 structures must be suspended before the control
2908 is passed to the application */
2909 iWndsLocks = WIN_SuspendWndsLock();
2910 ret = func( (*ppWnd)->hwndSelf, lParam );
2911 WIN_RestoreWndsLock(iWndsLocks);
2915 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2916 WIN_ReleaseWinArray(childList);
2918 if (!ret) return FALSE;
2924 /**********************************************************************
2925 * EnumChildWindows (USER32.@)
2927 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2930 WND **list, *pParent;
2932 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2933 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2935 WIN_ReleaseWndPtr(pParent);
2938 WIN_EnumChildWindows( list, func, lParam );
2939 WIN_ReleaseWinArray(list);
2940 WIN_ReleaseWndPtr(pParent);
2945 /*******************************************************************
2946 * AnyPopup (USER.52)
2948 BOOL16 WINAPI AnyPopup16(void)
2954 /*******************************************************************
2955 * AnyPopup (USER32.@)
2957 BOOL WINAPI AnyPopup(void)
2959 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2964 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2969 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2973 WIN_ReleaseWndPtr(wndPtr);
2978 /*******************************************************************
2979 * FlashWindow (USER.105)
2981 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2983 return FlashWindow( hWnd, bInvert );
2987 /*******************************************************************
2988 * FlashWindow (USER32.@)
2990 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2992 WND *wndPtr = WIN_FindWndPtr(hWnd);
2994 TRACE("%04x\n", hWnd);
2996 if (!wndPtr) return FALSE;
2998 if (wndPtr->dwStyle & WS_MINIMIZE)
3000 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3002 HDC hDC = GetDC(hWnd);
3004 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3005 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3007 ReleaseDC( hWnd, hDC );
3008 wndPtr->flags |= WIN_NCACTIVATED;
3012 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3013 wndPtr->flags &= ~WIN_NCACTIVATED;
3015 WIN_ReleaseWndPtr(wndPtr);
3021 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3022 else wparam = (hWnd == GetActiveWindow());
3024 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3025 WIN_ReleaseWndPtr(wndPtr);
3031 /*******************************************************************
3032 * SetSysModalWindow (USER.188)
3034 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3036 HWND hWndOldModal = hwndSysModal;
3037 hwndSysModal = hWnd;
3038 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3039 return hWndOldModal;
3043 /*******************************************************************
3044 * GetSysModalWindow (USER.189)
3046 HWND16 WINAPI GetSysModalWindow16(void)
3048 return hwndSysModal;
3052 /*******************************************************************
3053 * GetWindowContextHelpId (USER32.@)
3055 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3058 WND *wnd = WIN_FindWndPtr( hwnd );
3060 retval = wnd->helpContext;
3061 WIN_ReleaseWndPtr(wnd);
3066 /*******************************************************************
3067 * SetWindowContextHelpId (USER32.@)
3069 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3071 WND *wnd = WIN_FindWndPtr( hwnd );
3072 if (!wnd) return FALSE;
3073 wnd->helpContext = id;
3074 WIN_ReleaseWndPtr(wnd);
3079 /*******************************************************************
3082 * recursively find a child that contains spDragInfo->pt point
3083 * and send WM_QUERYDROPOBJECT
3085 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3087 BOOL16 wParam, bResult = 0;
3089 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3090 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3093 if( !ptrQueryWnd || !ptrDragInfo )
3096 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3098 GetWindowRect(hQueryWnd,&tempRect);
3100 if( !PtInRect(&tempRect,pt) ||
3101 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3104 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3106 tempRect = ptrQueryWnd->rectClient;
3107 if(ptrQueryWnd->parent)
3108 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3109 (LPPOINT)&tempRect, 2 );
3111 if (PtInRect( &tempRect, pt))
3115 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3117 if( ptrWnd->dwStyle & WS_VISIBLE )
3119 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3120 if (PtInRect( &tempRect, pt )) break;
3126 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3127 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3128 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3129 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3130 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3132 WIN_ReleaseWndPtr(ptrWnd);
3142 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3144 ptrDragInfo->hScope = hQueryWnd;
3146 bResult = ( bNoSend )
3147 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3148 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3149 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3151 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3154 WIN_ReleaseWndPtr(ptrQueryWnd);
3159 /*******************************************************************
3160 * DragDetect (USER.465)
3162 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3165 CONV_POINT16TO32( &pt, &pt32 );
3166 return DragDetect( hWnd, pt32 );
3169 /*******************************************************************
3170 * DragDetect (USER32.@)
3172 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3177 rect.left = pt.x - wDragWidth;
3178 rect.right = pt.x + wDragWidth;
3180 rect.top = pt.y - wDragHeight;
3181 rect.bottom = pt.y + wDragHeight;
3187 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3189 if( msg.message == WM_LBUTTONUP )
3194 if( msg.message == WM_MOUSEMOVE )
3197 tmp.x = LOWORD(msg.lParam);
3198 tmp.y = HIWORD(msg.lParam);
3199 if( !PtInRect( &rect, tmp ))
3211 /******************************************************************************
3212 * DragObject (USER.464)
3214 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3215 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3218 LPDRAGINFO16 lpDragInfo;
3220 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3221 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3222 WND *wndPtr = WIN_FindWndPtr(hWnd);
3223 HCURSOR16 hCurrentCursor = 0;
3224 HWND16 hCurrentWnd = 0;
3226 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3227 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3229 if( !lpDragInfo || !spDragInfo )
3231 WIN_ReleaseWndPtr(wndPtr);
3235 hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO));
3237 if( !hBummer || !wndPtr )
3239 GlobalFree16(hDragInfo);
3240 WIN_ReleaseWndPtr(wndPtr);
3246 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3248 GlobalFree16(hDragInfo);
3249 WIN_ReleaseWndPtr(wndPtr);
3253 if( hDragCursor == hCursor ) hDragCursor = 0;
3254 else hCursor = hDragCursor;
3256 hOldCursor = SetCursor(hDragCursor);
3259 lpDragInfo->hWnd = hWnd;
3260 lpDragInfo->hScope = 0;
3261 lpDragInfo->wFlags = wObj;
3262 lpDragInfo->hList = szList; /* near pointer! */
3263 lpDragInfo->hOfStruct = hOfStruct;
3271 do{ WaitMessage(); }
3272 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3274 *(lpDragInfo+1) = *lpDragInfo;
3276 lpDragInfo->pt.x = msg.pt.x;
3277 lpDragInfo->pt.y = msg.pt.y;
3279 /* update DRAGINFO struct */
3280 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3282 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3283 hCurrentCursor = hCursor;
3286 hCurrentCursor = hBummer;
3287 lpDragInfo->hScope = 0;
3289 if( hCurrentCursor )
3290 SetCursor(hCurrentCursor);
3292 /* send WM_DRAGLOOP */
3293 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3294 (LPARAM) spDragInfo );
3295 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3296 if( hCurrentWnd != lpDragInfo->hScope )
3299 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3300 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3301 HIWORD(spDragInfo)) );
3302 hCurrentWnd = lpDragInfo->hScope;
3304 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3308 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3310 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3313 ShowCursor( FALSE );
3317 SetCursor( hOldCursor );
3318 if (hDragCursor) DestroyCursor( hDragCursor );
3321 if( hCurrentCursor != hBummer )
3322 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3323 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3326 GlobalFree16(hDragInfo);
3327 WIN_ReleaseWndPtr(wndPtr);
3329 return (DWORD)(msg.lParam);
3333 /******************************************************************************
3334 * GetWindowModuleFileNameA (USER32.@)
3336 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3338 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3339 hwnd, lpszFileName, cchFileNameMax);
3343 /******************************************************************************
3344 * GetWindowModuleFileNameW (USER32.@)
3346 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3348 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3349 hwnd, lpszFileName, cchFileNameMax);