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, FALSE )) 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;
707 BOOL unicode = (type == WIN_PROC_32W);
709 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
710 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
711 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
712 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
713 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
715 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
716 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
718 /* Find the parent window */
722 /* Make sure parent is valid */
723 if (!IsWindow( cs->hwndParent ))
725 WARN("Bad parent %04x\n", cs->hwndParent );
728 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
729 WARN("No parent for child window\n" );
730 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
733 /* Find the window class */
734 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
735 &wndExtra, &winproc, &clsStyle, &dce )))
737 WARN("Bad class '%s'\n", cs->lpszClass );
741 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
743 /* Create the window structure */
745 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
747 TRACE("out of memory\n" );
751 /* Fill the window structure */
753 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
755 wndPtr->child = NULL;
757 if ((cs->style & WS_CHILD) && cs->hwndParent)
759 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
760 wndPtr->owner = NULL;
761 WIN_ReleaseWndPtr(wndPtr->parent);
765 wndPtr->parent = pWndDesktop;
766 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
767 wndPtr->owner = NULL;
770 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
771 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
772 WIN_ReleaseWndPtr(wndPtr->owner);
773 WIN_ReleaseWndPtr(tmpWnd);
778 wndPtr->pDriver = wndPtr->parent->pDriver;
780 wndPtr->class = classPtr;
781 wndPtr->winproc = winproc;
782 wndPtr->dwMagic = WND_MAGIC;
783 wndPtr->hwndSelf = hwnd;
784 wndPtr->hInstance = cs->hInstance;
786 wndPtr->hmemTaskQ = GetFastQueue16();
787 wndPtr->hrgnUpdate = 0;
789 wndPtr->hwndLastActive = hwnd;
790 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
791 wndPtr->dwExStyle = cs->dwExStyle;
792 wndPtr->clsStyle = clsStyle;
794 wndPtr->helpContext = 0;
795 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
796 wndPtr->pVScroll = NULL;
797 wndPtr->pHScroll = NULL;
798 wndPtr->pProp = NULL;
799 wndPtr->userdata = 0;
800 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
801 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
802 wndPtr->cbWndExtra = wndExtra;
803 wndPtr->irefCount = 1;
805 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
807 /* Call the WH_CBT hook */
809 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
810 ? HWND_BOTTOM : HWND_TOP;
812 if (HOOK_IsHooked( WH_CBT ))
818 cbtc.hwndInsertAfter = hwndLinkAfter;
819 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
820 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
823 TRACE("CBT-hook returned 0\n");
824 USER_HEAP_FREE( hwnd );
825 CLASS_RemoveWindow( classPtr );
831 /* Correct the window style */
833 if (!(cs->style & WS_CHILD))
835 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
836 if (!(cs->style & WS_POPUP))
838 wndPtr->dwStyle |= WS_CAPTION;
839 wndPtr->flags |= WIN_NEED_SIZE;
843 /* Get class or window DC if needed */
845 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
846 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
847 else wndPtr->dce = NULL;
849 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
851 wndPtr->rectWindow.left = cs->x;
852 wndPtr->rectWindow.top = cs->y;
853 wndPtr->rectWindow.right = cs->x + cs->cx;
854 wndPtr->rectWindow.bottom = cs->y + cs->cy;
855 wndPtr->rectClient = wndPtr->rectWindow;
857 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
859 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
861 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
862 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
863 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
864 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
865 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
868 if (cs->cx < 0) cs->cx = 0;
869 if (cs->cy < 0) cs->cy = 0;
871 wndPtr->rectWindow.left = cs->x;
872 wndPtr->rectWindow.top = cs->y;
873 wndPtr->rectWindow.right = cs->x + cs->cx;
874 wndPtr->rectWindow.bottom = cs->y + cs->cy;
875 wndPtr->rectClient = wndPtr->rectWindow;
877 /* Set the window menu */
879 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
881 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
884 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
887 if (HIWORD(cs->hInstance))
888 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
890 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
892 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
896 else wndPtr->wIDmenu = (UINT)cs->hMenu;
898 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
900 WARN("aborted by WM_xxCREATE!\n");
901 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
902 CLASS_RemoveWindow( classPtr );
903 WIN_ReleaseWndPtr(wndPtr);
907 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
909 /* Notify the parent window only */
911 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
912 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
913 if( !IsWindow(hwnd) )
920 if (cs->style & WS_VISIBLE)
922 /* in case WS_VISIBLE got set in the meantime */
923 wndPtr->dwStyle &= ~WS_VISIBLE;
924 ShowWindow( hwnd, sw );
927 /* Call WH_SHELL hook */
929 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
930 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
932 TRACE("created window %04x\n", hwnd);
934 WIN_ReleaseWndPtr(wndPtr);
939 /***********************************************************************
940 * CreateWindow (USER.41)
942 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
943 DWORD style, INT16 x, INT16 y, INT16 width,
944 INT16 height, HWND16 parent, HMENU16 menu,
945 HINSTANCE16 instance, LPVOID data )
947 return CreateWindowEx16( 0, className, windowName, style,
948 x, y, width, height, parent, menu, instance, data );
952 /***********************************************************************
953 * CreateWindowEx (USER.452)
955 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
956 LPCSTR windowName, DWORD style, INT16 x,
957 INT16 y, INT16 width, INT16 height,
958 HWND16 parent, HMENU16 menu,
959 HINSTANCE16 instance, LPVOID data )
965 /* Find the class atom */
967 if (HIWORD(className))
969 if (!(classAtom = GlobalFindAtomA( className )))
971 ERR( "bad class name %s\n", debugres_a(className) );
977 classAtom = LOWORD(className);
978 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
980 ERR( "bad atom %x\n", classAtom);
986 /* Fix the coordinates */
988 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
989 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
990 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
991 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
993 /* Create the window */
995 cs.lpCreateParams = data;
996 cs.hInstance = (HINSTANCE)instance;
997 cs.hMenu = (HMENU)menu;
998 cs.hwndParent = (HWND)parent;
1000 cs.lpszName = windowName;
1001 cs.lpszClass = className;
1002 cs.dwExStyle = exStyle;
1004 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
1008 /***********************************************************************
1009 * CreateWindowExA (USER32.@)
1011 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1012 LPCSTR windowName, DWORD style, INT x,
1013 INT y, INT width, INT height,
1014 HWND parent, HMENU menu,
1015 HINSTANCE instance, LPVOID data )
1022 instance=GetModuleHandleA(NULL);
1024 if(exStyle & WS_EX_MDICHILD)
1025 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1027 /* Find the class atom */
1029 if (HIWORD(className))
1031 if (!(classAtom = GlobalFindAtomA( className )))
1033 ERR( "bad class name %s\n", debugres_a(className) );
1039 classAtom = LOWORD(className);
1040 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1042 ERR( "bad atom %x\n", classAtom);
1048 /* Create the window */
1050 cs.lpCreateParams = data;
1051 cs.hInstance = instance;
1053 cs.hwndParent = parent;
1059 cs.lpszName = windowName;
1060 cs.lpszClass = className;
1061 cs.dwExStyle = exStyle;
1063 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1067 /***********************************************************************
1068 * CreateWindowExW (USER32.@)
1070 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1071 LPCWSTR windowName, DWORD style, INT x,
1072 INT y, INT width, INT height,
1073 HWND parent, HMENU menu,
1074 HINSTANCE instance, LPVOID data )
1081 instance=GetModuleHandleA(NULL);
1083 if(exStyle & WS_EX_MDICHILD)
1084 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1086 /* Find the class atom */
1088 if (HIWORD(className))
1090 if (!(classAtom = GlobalFindAtomW( className )))
1092 ERR( "bad class name %s\n", debugres_w(className) );
1098 classAtom = LOWORD(className);
1099 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1101 ERR( "bad atom %x\n", classAtom);
1107 /* Create the window */
1109 cs.lpCreateParams = data;
1110 cs.hInstance = instance;
1112 cs.hwndParent = parent;
1118 cs.lpszName = windowName;
1119 cs.lpszClass = className;
1120 cs.dwExStyle = exStyle;
1122 /* Note: we rely on the fact that CREATESTRUCTA and */
1123 /* CREATESTRUCTW have the same layout. */
1124 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1127 /***********************************************************************
1128 * WIN_SendDestroyMsg
1130 static void WIN_SendDestroyMsg( WND* pWnd )
1132 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1133 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1136 * Send the WM_DESTROY to the window.
1138 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1141 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1142 * make sure that the window still exists when we come back.
1144 if (IsWindow(pWnd->hwndSelf))
1146 HWND* pWndArray = NULL;
1151 * Now, if the window has kids, we have to send WM_DESTROY messages
1152 * recursively to it's kids. It seems that those calls can also
1153 * trigger re-entrant calls to DestroyWindow for the kids so we must
1154 * protect against corruption of the list of siblings. We first build
1155 * a list of HWNDs representing all the kids.
1157 pChild = WIN_LockWndPtr(pWnd->child);
1161 WIN_UpdateWndPtr(&pChild,pChild->next);
1165 * If there are no kids, we're done.
1170 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1175 if (pWndArray==NULL)
1179 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1180 * call, our linked list of siblings should be safe.
1183 pChild = WIN_LockWndPtr(pWnd->child);
1186 pWndArray[nKidCount] = pChild->hwndSelf;
1188 WIN_UpdateWndPtr(&pChild,pChild->next);
1192 * Now that we have a list, go through that list again and send the destroy
1193 * message to those windows. We are using the HWND to retrieve the
1194 * WND pointer so we are effectively checking that all the kid windows are
1195 * still valid before sending the message.
1199 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1203 WIN_SendDestroyMsg( pChild );
1204 WIN_ReleaseWndPtr(pChild);
1211 HeapFree(GetProcessHeap(), 0, pWndArray);
1214 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1218 /***********************************************************************
1219 * DestroyWindow (USER.53)
1221 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1223 return DestroyWindow(hwnd);
1227 /***********************************************************************
1228 * DestroyWindow (USER32.@)
1230 BOOL WINAPI DestroyWindow( HWND hwnd )
1235 BOOL bFocusSet = FALSE;
1237 TRACE("(%04x)\n", hwnd);
1239 /* Initialization */
1241 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1242 if (wndPtr == pWndDesktop)
1244 retvalue = FALSE; /* Can't destroy desktop */
1248 /* Look whether the focus is within the tree of windows we will
1252 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1256 SetFocus(GetParent(h));
1262 /* If the focus is on the window we will destroy and it has no parent,
1263 * set the focus to 0.
1265 if (! bFocusSet && (h == hwnd))
1267 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1273 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1279 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1281 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1282 /* FIXME: clean up palette - see "Internals" p.352 */
1285 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1286 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1288 /* Notify the parent window only */
1289 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1290 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1291 if( !IsWindow(hwnd) )
1298 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1300 /* Hide the window */
1302 if (wndPtr->dwStyle & WS_VISIBLE)
1304 ShowWindow( hwnd, SW_HIDE );
1305 if (!IsWindow(hwnd))
1312 /* Recursively destroy owned windows */
1314 if( !(wndPtr->dwStyle & WS_CHILD) )
1318 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1321 if (siblingPtr->owner == wndPtr)
1323 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1326 siblingPtr->owner = NULL;
1328 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1332 DestroyWindow( siblingPtr->hwndSelf );
1333 WIN_ReleaseWndPtr(siblingPtr);
1338 WINPOS_ActivateOtherWindow(wndPtr);
1340 if( wndPtr->owner &&
1341 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1342 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1345 /* Send destroy messages */
1347 WIN_SendDestroyMsg( wndPtr );
1348 if (!IsWindow(hwnd))
1354 /* Unlink now so we won't bother with the children later on */
1356 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1358 /* Destroy the window storage */
1360 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1363 WIN_ReleaseWndPtr(wndPtr);
1368 /***********************************************************************
1369 * CloseWindow (USER.43)
1371 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1373 return CloseWindow( hwnd );
1377 /***********************************************************************
1378 * CloseWindow (USER32.@)
1380 BOOL WINAPI CloseWindow( HWND hwnd )
1382 WND * wndPtr = WIN_FindWndPtr( hwnd );
1385 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1390 ShowWindow( hwnd, SW_MINIMIZE );
1393 WIN_ReleaseWndPtr(wndPtr);
1399 /***********************************************************************
1400 * OpenIcon (USER.44)
1402 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1404 return OpenIcon( hwnd );
1408 /***********************************************************************
1409 * OpenIcon (USER32.@)
1411 BOOL WINAPI OpenIcon( HWND hwnd )
1413 if (!IsIconic( hwnd )) return FALSE;
1414 ShowWindow( hwnd, SW_SHOWNORMAL );
1419 /***********************************************************************
1422 * Implementation of FindWindow() and FindWindowEx().
1424 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1432 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1435 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1441 else if (pWnd->parent != pWndDesktop)
1446 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1450 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1455 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1463 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1465 if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
1466 continue; /* Not the right class */
1468 /* Now check the title */
1472 retvalue = pWnd->hwndSelf;
1475 if (pWnd->text && !strcmpW( pWnd->text, title ))
1477 retvalue = pWnd->hwndSelf;
1482 /* In this case we need to check whether other processes
1483 own a window with the given paramters on the Desktop,
1484 but we don't, so let's at least warn about it */
1485 FIXME("Returning 0 without checking other processes\n");
1487 WIN_ReleaseWndPtr(pWnd);
1493 /***********************************************************************
1494 * FindWindow (USER.50)
1496 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1498 return FindWindowA( className, title );
1502 /***********************************************************************
1503 * FindWindowEx (USER.427)
1505 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1507 return FindWindowExA( parent, child, className, title );
1511 /***********************************************************************
1512 * FindWindowA (USER32.@)
1514 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1516 HWND ret = FindWindowExA( 0, 0, className, title );
1517 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1522 /***********************************************************************
1523 * FindWindowExA (USER32.@)
1525 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1526 LPCSTR className, LPCSTR title )
1534 /* If the atom doesn't exist, then no class */
1535 /* with this name exists either. */
1536 if (!(atom = GlobalFindAtomA( className )))
1538 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1543 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1544 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1545 HeapFree( GetProcessHeap(), 0, buffer );
1550 /***********************************************************************
1551 * FindWindowExW (USER32.@)
1553 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1554 LPCWSTR className, LPCWSTR title )
1560 /* If the atom doesn't exist, then no class */
1561 /* with this name exists either. */
1562 if (!(atom = GlobalFindAtomW( className )))
1564 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1568 return WIN_FindWindow( parent, child, atom, title );
1572 /***********************************************************************
1573 * FindWindowW (USER32.@)
1575 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1577 return FindWindowExW( 0, 0, className, title );
1581 /**********************************************************************
1583 * returns a locked pointer
1585 WND *WIN_GetDesktop(void)
1587 return WIN_LockWndPtr(pWndDesktop);
1589 /**********************************************************************
1590 * WIN_ReleaseDesktop
1591 * unlock the desktop pointer
1593 void WIN_ReleaseDesktop(void)
1595 WIN_ReleaseWndPtr(pWndDesktop);
1599 /**********************************************************************
1600 * GetDesktopWindow (USER.286)
1602 HWND16 WINAPI GetDesktopWindow16(void)
1604 return (HWND16)pWndDesktop->hwndSelf;
1608 /**********************************************************************
1609 * GetDesktopWindow (USER32.@)
1611 HWND WINAPI GetDesktopWindow(void)
1613 if (pWndDesktop) return pWndDesktop->hwndSelf;
1614 ERR( "You need the -desktop option when running with native USER\n" );
1620 /**********************************************************************
1621 * GetDesktopHwnd (USER.278)
1623 * Exactly the same thing as GetDesktopWindow(), but not documented.
1624 * Don't ask me why...
1626 HWND16 WINAPI GetDesktopHwnd16(void)
1628 return (HWND16)pWndDesktop->hwndSelf;
1632 /*******************************************************************
1633 * EnableWindow (USER.34)
1635 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1637 return EnableWindow( hwnd, enable );
1641 /*******************************************************************
1642 * EnableWindow (USER32.@)
1644 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1649 TRACE("( %x, %d )\n", hwnd, enable);
1651 if (USER_Driver.pEnableWindow)
1652 return USER_Driver.pEnableWindow( hwnd, enable );
1654 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1656 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1658 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1660 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1661 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1663 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1665 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1667 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1669 if (hwnd == GetFocus())
1670 SetFocus( 0 ); /* A disabled window can't have the focus */
1672 if (hwnd == GetCapture())
1673 ReleaseCapture(); /* A disabled window can't capture the mouse */
1675 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1677 WIN_ReleaseWndPtr(wndPtr);
1682 /***********************************************************************
1683 * IsWindowEnabled (USER.35)
1685 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1687 return IsWindowEnabled(hWnd);
1691 /***********************************************************************
1692 * IsWindowEnabled (USER32.@)
1694 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1699 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1700 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1701 WIN_ReleaseWndPtr(wndPtr);
1707 /***********************************************************************
1708 * IsWindowUnicode (USER32.@)
1710 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1715 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1716 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1717 WIN_ReleaseWndPtr(wndPtr);
1722 /**********************************************************************
1723 * GetWindowWord (USER.133)
1725 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1727 return GetWindowWord( hwnd, offset );
1731 /**********************************************************************
1732 * GetWindowWord (USER32.@)
1734 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1737 WND * wndPtr = WIN_FindWndPtr( hwnd );
1738 if (!wndPtr) return 0;
1741 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1743 WARN("Invalid offset %d\n", offset );
1747 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1753 if (HIWORD(wndPtr->wIDmenu))
1754 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1756 retvalue = (WORD)wndPtr->wIDmenu;
1758 case GWW_HWNDPARENT:
1759 retvalue = GetParent(hwnd);
1762 if (HIWORD(wndPtr->hInstance))
1763 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1765 retvalue = (WORD)wndPtr->hInstance;
1768 WARN("Invalid offset %d\n", offset );
1773 WIN_ReleaseWndPtr(wndPtr);
1777 /**********************************************************************
1778 * SetWindowWord (USER.134)
1780 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1782 return SetWindowWord( hwnd, offset, newval );
1786 /**********************************************************************
1787 * SetWindowWord (USER32.@)
1789 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1792 WND * wndPtr = WIN_FindWndPtr( hwnd );
1793 if (!wndPtr) return 0;
1796 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1798 WARN("Invalid offset %d\n", offset );
1802 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1806 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1807 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1808 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1811 WARN("Invalid offset %d\n", offset );
1818 WIN_ReleaseWndPtr(wndPtr);
1823 /**********************************************************************
1826 * Helper function for GetWindowLong().
1828 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1831 WND * wndPtr = WIN_FindWndPtr( hwnd );
1832 if (!wndPtr) return 0;
1835 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1837 WARN("Invalid offset %d\n", offset );
1841 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1842 /* Special case for dialog window procedure */
1843 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1845 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1852 case GWL_USERDATA: retvalue = wndPtr->userdata;
1854 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1856 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1858 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1860 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1863 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1865 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1868 WARN("Unknown offset %d\n", offset );
1872 WIN_ReleaseWndPtr(wndPtr);
1877 /**********************************************************************
1880 * Helper function for SetWindowLong().
1882 * 0 is the failure code. However, in the case of failure SetLastError
1883 * must be set to distinguish between a 0 return value and a failure.
1885 * FIXME: The error values for SetLastError may not be right. Can
1886 * someone check with the real thing?
1888 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1889 WINDOWPROCTYPE type )
1892 WND * wndPtr = WIN_FindWndPtr( hwnd );
1895 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1899 /* Is this the right error? */
1900 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1906 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1908 WARN("Invalid offset %d\n", offset );
1910 /* Is this the right error? */
1911 SetLastError( ERROR_OUTOFMEMORY );
1916 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1917 /* Special case for dialog window procedure */
1918 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1920 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1921 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1922 type, WIN_PROC_WINDOW );
1929 ptr = (DWORD*)&wndPtr->wIDmenu;
1932 retval = SetWindowWord( hwnd, offset, newval );
1935 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1936 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1937 type, WIN_PROC_WINDOW );
1940 style.styleOld = wndPtr->dwStyle;
1941 style.styleNew = newval;
1942 if (wndPtr->flags & WIN_ISWIN32)
1943 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1944 wndPtr->dwStyle = style.styleNew;
1945 if (wndPtr->flags & WIN_ISWIN32)
1946 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1947 retval = style.styleOld;
1951 ptr = &wndPtr->userdata;
1954 style.styleOld = wndPtr->dwExStyle;
1955 style.styleNew = newval;
1956 if (wndPtr->flags & WIN_ISWIN32)
1957 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1958 wndPtr->dwExStyle = newval;
1959 if (wndPtr->flags & WIN_ISWIN32)
1960 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1961 retval = style.styleOld;
1965 WARN("Invalid offset %d\n", offset );
1967 /* Don't think this is right error but it should do */
1968 SetLastError( ERROR_OUTOFMEMORY );
1976 WIN_ReleaseWndPtr(wndPtr);
1981 /**********************************************************************
1982 * GetWindowLong (USER.135)
1984 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1986 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1990 /**********************************************************************
1991 * GetWindowLongA (USER32.@)
1993 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1995 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1999 /**********************************************************************
2000 * GetWindowLongW (USER32.@)
2002 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2004 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2008 /**********************************************************************
2009 * SetWindowLong (USER.136)
2011 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2013 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2017 /**********************************************************************
2018 * SetWindowLongA (USER32.@)
2020 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2022 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2026 /**********************************************************************
2027 * SetWindowLongW (USER32.@) Set window attribute
2029 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2030 * value in a window's extra memory.
2032 * The _hwnd_ parameter specifies the window. is the handle to a
2033 * window that has extra memory. The _newval_ parameter contains the
2034 * new attribute or extra memory value. If positive, the _offset_
2035 * parameter is the byte-addressed location in the window's extra
2036 * memory to set. If negative, _offset_ specifies the window
2037 * attribute to set, and should be one of the following values:
2039 * GWL_EXSTYLE The window's extended window style
2041 * GWL_STYLE The window's window style.
2043 * GWL_WNDPROC Pointer to the window's window procedure.
2045 * GWL_HINSTANCE The window's pplication instance handle.
2047 * GWL_ID The window's identifier.
2049 * GWL_USERDATA The window's user-specified data.
2051 * If the window is a dialog box, the _offset_ parameter can be one of
2052 * the following values:
2054 * DWL_DLGPROC The address of the window's dialog box procedure.
2056 * DWL_MSGRESULT The return value of a message
2057 * that the dialog box procedure processed.
2059 * DWL_USER Application specific information.
2063 * If successful, returns the previous value located at _offset_. Otherwise,
2068 * Extra memory for a window class is specified by a nonzero cbWndExtra
2069 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2070 * time of class creation.
2072 * Using GWL_WNDPROC to set a new window procedure effectively creates
2073 * a window subclass. Use CallWindowProc() in the new windows procedure
2074 * to pass messages to the superclass's window procedure.
2076 * The user data is reserved for use by the application which created
2079 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2080 * instead, call the EnableWindow() function to change the window's
2083 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2084 * SetParent() instead.
2087 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2088 * it sends WM_STYLECHANGING before changing the settings
2089 * and WM_STYLECHANGED afterwards.
2090 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2094 * GWL_STYLE does not dispatch WM_STYLE... messages.
2101 LONG WINAPI SetWindowLongW(
2102 HWND hwnd, /* [in] window to alter */
2103 INT offset, /* [in] offset, in bytes, of location to alter */
2104 LONG newval /* [in] new value of location */
2106 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2110 /*******************************************************************
2111 * GetWindowText (USER.36)
2113 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2115 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2119 /*******************************************************************
2120 * GetWindowTextA (USER32.@)
2122 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2124 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2128 /*******************************************************************
2129 * InternalGetWindowText (USER32.@)
2131 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2133 WND *win = WIN_FindWndPtr( hwnd );
2135 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2136 else lpString[0] = 0;
2137 WIN_ReleaseWndPtr( win );
2138 return strlenW(lpString);
2142 /*******************************************************************
2143 * GetWindowTextW (USER32.@)
2145 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2147 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2152 /*******************************************************************
2153 * SetWindowText (USER.37)
2155 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2157 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2161 /*******************************************************************
2162 * SetWindowText (USER32.@)
2164 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2166 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2170 /*******************************************************************
2171 * SetWindowTextW (USER32.@)
2173 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2175 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2179 /*******************************************************************
2180 * GetWindowTextLength (USER.38)
2182 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2184 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2188 /*******************************************************************
2189 * GetWindowTextLengthA (USER32.@)
2191 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2193 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2196 /*******************************************************************
2197 * GetWindowTextLengthW (USER32.@)
2199 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2201 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2205 /*******************************************************************
2206 * IsWindow (USER.47)
2208 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2210 CURRENT_STACK16->es = USER_HeapSel;
2211 return IsWindow( hwnd );
2215 /*******************************************************************
2216 * IsWindow (USER32.@)
2218 BOOL WINAPI IsWindow( HWND hwnd )
2223 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2224 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2225 WIN_ReleaseWndPtr(wndPtr);
2231 /*****************************************************************
2232 * GetParent (USER.46)
2234 HWND16 WINAPI GetParent16( HWND16 hwnd )
2236 return (HWND16)GetParent( hwnd );
2240 /*****************************************************************
2241 * GetParent (USER32.@)
2243 HWND WINAPI GetParent( HWND hwnd )
2248 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2249 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2252 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2254 retvalue = wndPtr->hwndSelf;
2257 WIN_ReleaseWndPtr(wndPtr);
2262 /*****************************************************************
2265 * Get the top-level parent for a child window.
2266 * returns a locked pointer
2268 WND* WIN_GetTopParentPtr( WND* pWnd )
2270 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2272 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2274 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2279 /*****************************************************************
2282 * Get the top-level parent for a child window.
2284 HWND WIN_GetTopParent( HWND hwnd )
2287 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2288 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2290 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2291 WIN_ReleaseWndPtr(tmpPtr);
2292 WIN_ReleaseWndPtr(wndPtr);
2297 /*****************************************************************
2298 * SetParent (USER.233)
2300 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2302 return SetParent( hwndChild, hwndNewParent );
2306 /*****************************************************************
2307 * SetParent (USER32.@)
2309 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2316 if (hwnd == GetDesktopWindow()) /* sanity check */
2318 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2322 if (USER_Driver.pSetParent)
2323 return USER_Driver.pSetParent( hwnd, parent );
2325 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2327 dwStyle = wndPtr->dwStyle;
2329 if (!parent) parent = GetDesktopWindow();
2331 if (!(pWndParent = WIN_FindWndPtr(parent)))
2333 WIN_ReleaseWndPtr( wndPtr );
2337 /* Windows hides the window first, then shows it again
2338 * including the WM_SHOWWINDOW messages and all */
2339 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2341 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2342 if (pWndParent != wndPtr->parent)
2344 WIN_UnlinkWindow(wndPtr->hwndSelf);
2345 wndPtr->parent = pWndParent;
2347 if (parent != GetDesktopWindow()) /* a child window */
2349 if( !( wndPtr->dwStyle & WS_CHILD ) )
2351 if( wndPtr->wIDmenu != 0)
2353 DestroyMenu( (HMENU) wndPtr->wIDmenu );
2354 wndPtr->wIDmenu = 0;
2358 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
2360 WIN_ReleaseWndPtr( pWndParent );
2361 WIN_ReleaseWndPtr( wndPtr );
2363 /* SetParent additionally needs to make hwnd the topmost window
2364 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2365 WM_WINDOWPOSCHANGED notification messages.
2367 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2368 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2369 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2370 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2371 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2376 /*******************************************************************
2379 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2381 return IsChild(parent,child);
2385 /*******************************************************************
2386 * IsChild (USER32.@)
2388 BOOL WINAPI IsChild( HWND parent, HWND child )
2390 WND * wndPtr = WIN_FindWndPtr( child );
2391 while (wndPtr && wndPtr->parent)
2393 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2394 if (wndPtr->hwndSelf == GetDesktopWindow()) break;
2395 if (wndPtr->hwndSelf == parent)
2397 WIN_ReleaseWndPtr(wndPtr);
2401 WIN_ReleaseWndPtr(wndPtr);
2406 /***********************************************************************
2407 * IsWindowVisible (USER.49)
2409 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2411 return IsWindowVisible(hwnd);
2415 /***********************************************************************
2416 * IsWindowVisible (USER32.@)
2418 BOOL WINAPI IsWindowVisible( HWND hwnd )
2421 WND *wndPtr = WIN_FindWndPtr( hwnd );
2422 while (wndPtr && wndPtr->parent)
2424 if (!(wndPtr->dwStyle & WS_VISIBLE))
2426 WIN_ReleaseWndPtr(wndPtr);
2429 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2431 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2432 WIN_ReleaseWndPtr(wndPtr);
2437 /***********************************************************************
2438 * WIN_IsWindowDrawable
2440 * hwnd is drawable when it is visible, all parents are not
2441 * minimized, and it is itself not minimized unless we are
2442 * trying to draw its default class icon.
2444 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2446 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2447 if ((wnd->dwStyle & WS_MINIMIZE) &&
2448 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2449 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2450 if( wnd->dwStyle & WS_MINIMIZE ||
2451 !(wnd->dwStyle & WS_VISIBLE) ) break;
2452 return (wnd == NULL);
2456 /*******************************************************************
2457 * GetTopWindow (USER.229)
2459 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2461 return GetTopWindow(hwnd);
2465 /*******************************************************************
2466 * GetTopWindow (USER32.@)
2468 HWND WINAPI GetTopWindow( HWND hwnd )
2471 WND * wndPtr = (hwnd) ?
2472 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2474 if (wndPtr && wndPtr->child)
2475 retval = wndPtr->child->hwndSelf;
2477 WIN_ReleaseWndPtr(wndPtr);
2482 /*******************************************************************
2483 * GetWindow (USER.262)
2485 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2487 return GetWindow( hwnd,rel );
2491 /*******************************************************************
2492 * GetWindow (USER32.@)
2494 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2498 WND * wndPtr = WIN_FindWndPtr( hwnd );
2499 if (!wndPtr) return 0;
2503 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2507 if (!wndPtr->parent)
2509 retval = 0; /* Desktop window */
2512 while (wndPtr->next)
2514 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2516 retval = wndPtr->hwndSelf;
2520 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2524 if (!wndPtr->parent)
2526 retval = 0; /* Desktop window */
2529 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2530 if (wndPtr->hwndSelf == hwnd)
2532 retval = 0; /* First in list */
2535 while (wndPtr->next)
2537 if (wndPtr->next->hwndSelf == hwnd)
2539 retval = wndPtr->hwndSelf;
2542 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2548 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2552 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2557 WIN_ReleaseWndPtr(wndPtr);
2562 /*******************************************************************
2563 * GetNextWindow (USER.230)
2565 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2567 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2568 return GetWindow16( hwnd, flag );
2571 /***********************************************************************
2572 * WIN_InternalShowOwnedPopups
2574 * Internal version of ShowOwnedPopups; Wine functions should use this
2575 * to avoid interfering with application calls to ShowOwnedPopups
2576 * and to make sure the application can't prevent showing/hiding.
2578 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2582 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2584 INT totalChild=0, count=0;
2586 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2588 if (!pWnd) return TRUE;
2591 * Show windows Lowest first, Highest last to preserve Z-Order
2593 for (count = totalChild-1 ; count >=0; count--)
2595 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2599 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2600 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2603 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2605 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2606 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2611 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2612 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2613 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2616 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2618 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2619 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2620 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2625 WIN_ReleaseDesktop();
2626 WIN_ReleaseWinArray(pWnd);
2631 /*******************************************************************
2632 * ShowOwnedPopups (USER.265)
2634 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2636 ShowOwnedPopups( owner, fShow );
2640 /*******************************************************************
2641 * ShowOwnedPopups (USER32.@)
2643 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2645 UINT totalChild=0, count=0;
2647 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2649 if (!pWnd) return TRUE;
2651 for (; count < totalChild; count++)
2653 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2657 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2660 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2661 * regardless of the state of the owner
2663 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2664 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2669 if (IsWindowVisible(pWnd[count]->hwndSelf))
2672 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2673 * regardless of the state of the owner
2675 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2676 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2682 WIN_ReleaseDesktop();
2683 WIN_ReleaseWinArray(pWnd);
2688 /*******************************************************************
2689 * GetLastActivePopup (USER.287)
2691 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2693 return GetLastActivePopup( hwnd );
2696 /*******************************************************************
2697 * GetLastActivePopup (USER32.@)
2699 HWND WINAPI GetLastActivePopup( HWND hwnd )
2702 WND *wndPtr =WIN_FindWndPtr(hwnd);
2703 if (!wndPtr) return hwnd;
2704 retval = wndPtr->hwndLastActive;
2705 WIN_ReleaseWndPtr(wndPtr);
2706 if ((retval != hwnd) && (!IsWindow(retval)))
2712 /*******************************************************************
2715 * Build an array of pointers to the children of a given window.
2716 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2717 * when no windows are found.
2719 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2721 /* Future: this function will lock all windows associated with this array */
2723 WND **list, **ppWnd;
2725 UINT count = 0, skipOwned, skipHidden;
2728 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2729 skipOwned = bwaFlags & BWA_SKIPOWNED;
2730 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2731 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2733 /* First count the windows */
2736 wndPtr = WIN_GetDesktop();
2738 pWnd = WIN_LockWndPtr(wndPtr->child);
2741 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2742 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2744 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2749 /* Now build the list of all windows */
2751 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2753 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2755 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2756 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2762 WIN_ReleaseWndPtr(pWnd);
2768 if( pTotal ) *pTotal = count;
2771 /*******************************************************************
2772 * WIN_ReleaseWinArray
2774 void WIN_ReleaseWinArray(WND **wndArray)
2776 /* Future: this function will also unlock all windows associated with wndArray */
2777 HeapFree( GetProcessHeap(), 0, wndArray );
2781 /*******************************************************************
2782 * EnumWindows (USER32.@)
2784 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2786 WND **list, **ppWnd;
2788 /* We have to build a list of all windows first, to avoid */
2789 /* unpleasant side-effects, for instance if the callback */
2790 /* function changes the Z-order of the windows. */
2792 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2794 WIN_ReleaseDesktop();
2798 /* Now call the callback function for every window */
2800 for (ppWnd = list; *ppWnd; ppWnd++)
2802 LRESULT lpEnumFuncRetval;
2804 /* Make sure that the window still exists */
2805 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2807 /* To avoid any deadlocks, all the locks on the windows
2808 structures must be suspended before the control
2809 is passed to the application */
2810 iWndsLocks = WIN_SuspendWndsLock();
2811 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2812 WIN_RestoreWndsLock(iWndsLocks);
2814 if (!lpEnumFuncRetval) break;
2816 WIN_ReleaseWinArray(list);
2817 WIN_ReleaseDesktop();
2822 /**********************************************************************
2823 * WIN_EnumQueueWindows
2825 * Helper for EnumTaskWindows16 and EnumThreadWindows.
2827 static BOOL WIN_EnumQueueWindows( HQUEUE16 queue, WNDENUMPROC func, LPARAM lParam )
2829 WND **list, **ppWnd;
2831 /* This function is the same as EnumWindows(), */
2832 /* except for an added check on the window's task. */
2834 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2836 WIN_ReleaseDesktop();
2840 /* Now call the callback function for every window */
2842 for (ppWnd = list; *ppWnd; ppWnd++)
2846 /* Make sure that the window still exists */
2847 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2848 if ((*ppWnd)->hmemTaskQ != queue) continue;
2850 /* To avoid any deadlocks, all the locks on the windows
2851 structures must be suspended before the control
2852 is passed to the application */
2853 iWndsLocks = WIN_SuspendWndsLock();
2854 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2855 WIN_RestoreWndsLock(iWndsLocks);
2857 if (!funcRetval) break;
2859 WIN_ReleaseWinArray(list);
2860 WIN_ReleaseDesktop();
2865 /**********************************************************************
2866 * EnumTaskWindows16 (USER.225)
2868 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2871 HQUEUE16 queue = GetTaskQueue16( hTask );
2872 if (!queue) return FALSE;
2873 return WIN_EnumQueueWindows( queue, (WNDENUMPROC)func, lParam );
2877 /**********************************************************************
2878 * EnumThreadWindows (USER32.@)
2880 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2882 HQUEUE16 queue = GetThreadQueue16( id );
2883 if (!queue) return FALSE;
2884 return WIN_EnumQueueWindows( queue, func, lParam );
2888 /**********************************************************************
2889 * WIN_EnumChildWindows
2891 * Helper function for EnumChildWindows().
2893 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2898 for ( ; *ppWnd; ppWnd++)
2902 /* Make sure that the window still exists */
2903 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2904 /* Build children list first */
2905 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2907 /* To avoid any deadlocks, all the locks on the windows
2908 structures must be suspended before the control
2909 is passed to the application */
2910 iWndsLocks = WIN_SuspendWndsLock();
2911 ret = func( (*ppWnd)->hwndSelf, lParam );
2912 WIN_RestoreWndsLock(iWndsLocks);
2916 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2917 WIN_ReleaseWinArray(childList);
2919 if (!ret) return FALSE;
2925 /**********************************************************************
2926 * EnumChildWindows (USER32.@)
2928 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2931 WND **list, *pParent;
2933 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2934 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2936 WIN_ReleaseWndPtr(pParent);
2939 WIN_EnumChildWindows( list, func, lParam );
2940 WIN_ReleaseWinArray(list);
2941 WIN_ReleaseWndPtr(pParent);
2946 /*******************************************************************
2947 * AnyPopup (USER.52)
2949 BOOL16 WINAPI AnyPopup16(void)
2955 /*******************************************************************
2956 * AnyPopup (USER32.@)
2958 BOOL WINAPI AnyPopup(void)
2960 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2965 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2970 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2974 WIN_ReleaseWndPtr(wndPtr);
2979 /*******************************************************************
2980 * FlashWindow (USER.105)
2982 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2984 return FlashWindow( hWnd, bInvert );
2988 /*******************************************************************
2989 * FlashWindow (USER32.@)
2991 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2993 WND *wndPtr = WIN_FindWndPtr(hWnd);
2995 TRACE("%04x\n", hWnd);
2997 if (!wndPtr) return FALSE;
2999 if (wndPtr->dwStyle & WS_MINIMIZE)
3001 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3003 HDC hDC = GetDC(hWnd);
3005 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3006 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3008 ReleaseDC( hWnd, hDC );
3009 wndPtr->flags |= WIN_NCACTIVATED;
3013 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3014 wndPtr->flags &= ~WIN_NCACTIVATED;
3016 WIN_ReleaseWndPtr(wndPtr);
3022 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3023 else wparam = (hWnd == GetActiveWindow());
3025 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3026 WIN_ReleaseWndPtr(wndPtr);
3032 /*******************************************************************
3033 * SetSysModalWindow (USER.188)
3035 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3037 HWND hWndOldModal = hwndSysModal;
3038 hwndSysModal = hWnd;
3039 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3040 return hWndOldModal;
3044 /*******************************************************************
3045 * GetSysModalWindow (USER.189)
3047 HWND16 WINAPI GetSysModalWindow16(void)
3049 return hwndSysModal;
3053 /*******************************************************************
3054 * GetWindowContextHelpId (USER32.@)
3056 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3059 WND *wnd = WIN_FindWndPtr( hwnd );
3061 retval = wnd->helpContext;
3062 WIN_ReleaseWndPtr(wnd);
3067 /*******************************************************************
3068 * SetWindowContextHelpId (USER32.@)
3070 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3072 WND *wnd = WIN_FindWndPtr( hwnd );
3073 if (!wnd) return FALSE;
3074 wnd->helpContext = id;
3075 WIN_ReleaseWndPtr(wnd);
3080 /*******************************************************************
3083 * recursively find a child that contains spDragInfo->pt point
3084 * and send WM_QUERYDROPOBJECT
3086 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3088 BOOL16 wParam, bResult = 0;
3090 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3091 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3094 if( !ptrQueryWnd || !ptrDragInfo )
3097 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3099 GetWindowRect(hQueryWnd,&tempRect);
3101 if( !PtInRect(&tempRect,pt) ||
3102 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3105 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3107 tempRect = ptrQueryWnd->rectClient;
3108 if(ptrQueryWnd->parent)
3109 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3110 (LPPOINT)&tempRect, 2 );
3112 if (PtInRect( &tempRect, pt))
3116 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3118 if( ptrWnd->dwStyle & WS_VISIBLE )
3120 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3121 if (PtInRect( &tempRect, pt )) break;
3127 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3128 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3129 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3130 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3131 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3133 WIN_ReleaseWndPtr(ptrWnd);
3143 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3145 ptrDragInfo->hScope = hQueryWnd;
3147 bResult = ( bNoSend )
3148 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3149 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3150 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3152 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3155 WIN_ReleaseWndPtr(ptrQueryWnd);
3160 /*******************************************************************
3161 * DragDetect (USER.465)
3163 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3166 CONV_POINT16TO32( &pt, &pt32 );
3167 return DragDetect( hWnd, pt32 );
3170 /*******************************************************************
3171 * DragDetect (USER32.@)
3173 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3178 rect.left = pt.x - wDragWidth;
3179 rect.right = pt.x + wDragWidth;
3181 rect.top = pt.y - wDragHeight;
3182 rect.bottom = pt.y + wDragHeight;
3188 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3190 if( msg.message == WM_LBUTTONUP )
3195 if( msg.message == WM_MOUSEMOVE )
3198 tmp.x = LOWORD(msg.lParam);
3199 tmp.y = HIWORD(msg.lParam);
3200 if( !PtInRect( &rect, tmp ))
3212 /******************************************************************************
3213 * DragObject (USER.464)
3215 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3216 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3219 LPDRAGINFO16 lpDragInfo;
3221 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3222 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3223 WND *wndPtr = WIN_FindWndPtr(hWnd);
3224 HCURSOR16 hCurrentCursor = 0;
3225 HWND16 hCurrentWnd = 0;
3227 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3228 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3230 if( !lpDragInfo || !spDragInfo )
3232 WIN_ReleaseWndPtr(wndPtr);
3236 hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO));
3238 if( !hBummer || !wndPtr )
3240 GlobalFree16(hDragInfo);
3241 WIN_ReleaseWndPtr(wndPtr);
3247 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3249 GlobalFree16(hDragInfo);
3250 WIN_ReleaseWndPtr(wndPtr);
3254 if( hDragCursor == hCursor ) hDragCursor = 0;
3255 else hCursor = hDragCursor;
3257 hOldCursor = SetCursor(hDragCursor);
3260 lpDragInfo->hWnd = hWnd;
3261 lpDragInfo->hScope = 0;
3262 lpDragInfo->wFlags = wObj;
3263 lpDragInfo->hList = szList; /* near pointer! */
3264 lpDragInfo->hOfStruct = hOfStruct;
3272 do{ WaitMessage(); }
3273 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3275 *(lpDragInfo+1) = *lpDragInfo;
3277 lpDragInfo->pt.x = msg.pt.x;
3278 lpDragInfo->pt.y = msg.pt.y;
3280 /* update DRAGINFO struct */
3281 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3283 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3284 hCurrentCursor = hCursor;
3287 hCurrentCursor = hBummer;
3288 lpDragInfo->hScope = 0;
3290 if( hCurrentCursor )
3291 SetCursor(hCurrentCursor);
3293 /* send WM_DRAGLOOP */
3294 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3295 (LPARAM) spDragInfo );
3296 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3297 if( hCurrentWnd != lpDragInfo->hScope )
3300 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3301 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3302 HIWORD(spDragInfo)) );
3303 hCurrentWnd = lpDragInfo->hScope;
3305 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3309 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3311 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3314 ShowCursor( FALSE );
3318 SetCursor( hOldCursor );
3319 if (hDragCursor) DestroyCursor( hDragCursor );
3322 if( hCurrentCursor != hBummer )
3323 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3324 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3327 GlobalFree16(hDragInfo);
3328 WIN_ReleaseWndPtr(wndPtr);
3330 return (DWORD)(msg.lParam);
3334 /******************************************************************************
3335 * GetWindowModuleFileNameA (USER32.@)
3337 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3339 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3340 hwnd, lpszFileName, cchFileNameMax);
3344 /******************************************************************************
3345 * GetWindowModuleFileNameW (USER32.@)
3347 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3349 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3350 hwnd, lpszFileName, cchFileNameMax);