2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
19 #include "cursoricon.h"
23 #include "nonclient.h"
26 #include "clipboard.h"
34 #include "stackframe.h"
35 #include "debugtools.h"
37 DEFAULT_DEBUG_CHANNEL(win);
38 DECLARE_DEBUG_CHANNEL(msg);
40 /**********************************************************************/
42 WND_DRIVER *WND_Driver = NULL;
45 static WND *pWndDesktop = NULL;
47 static HWND hwndSysModal = 0;
49 static WORD wDragWidth = 4;
50 static WORD wDragHeight= 3;
53 static SYSLEVEL WIN_SysLevel;
55 /***********************************************************************
60 /* Initialisation of the critical section for thread safeness */
61 _CreateSysLevel( &WIN_SysLevel, 2 );
64 /***********************************************************************
67 * Locks access to all WND structures for thread safeness
69 void WIN_LockWnds( void )
71 _EnterSysLevel( &WIN_SysLevel );
74 /***********************************************************************
77 * Unlocks access to all WND structures
79 void WIN_UnlockWnds( void )
81 _LeaveSysLevel( &WIN_SysLevel );
84 /***********************************************************************
87 * Suspend the lock on WND structures.
88 * Returns the number of locks suspended
90 int WIN_SuspendWndsLock( void )
92 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
93 int count = isuspendedLocks;
96 _LeaveSysLevel( &WIN_SysLevel );
98 return isuspendedLocks;
101 /***********************************************************************
102 * WIN_RestoreWndsLock
104 * Restore the suspended locks on WND structures
106 void WIN_RestoreWndsLock( int ipreviousLocks )
108 while ( ipreviousLocks-- > 0 )
109 _EnterSysLevel( &WIN_SysLevel );
112 /***********************************************************************
115 * Return a pointer to the WND structure corresponding to a HWND.
117 WND * WIN_FindWndPtr( HWND hwnd )
121 if (!hwnd || HIWORD(hwnd)) goto error2;
122 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
123 /* Lock all WND structures for thread safeness*/
125 /*and increment destruction monitoring*/
128 if (ptr->dwMagic != WND_MAGIC) goto error;
129 if (ptr->hwndSelf != hwnd)
131 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
134 /* returns a locked pointer */
137 /* Unlock all WND structures for thread safeness*/
139 /* and decrement destruction monitoring value */
144 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
148 /***********************************************************************
151 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
153 * Returns the locked initialisation pointer
155 WND *WIN_LockWndPtr(WND *initWndPtr)
157 if(!initWndPtr) return 0;
159 /* Lock all WND structures for thread safeness*/
161 /*and increment destruction monitoring*/
162 initWndPtr->irefCount++;
168 /***********************************************************************
171 * Release the pointer to the WND structure.
173 void WIN_ReleaseWndPtr(WND *wndPtr)
177 /*Decrement destruction monitoring value*/
179 /* Check if it's time to release the memory*/
180 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
183 USER_HEAP_FREE( wndPtr->hwndSelf);
184 wndPtr->hwndSelf = 0;
186 else if(wndPtr->irefCount < 0)
188 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
189 ERR("forgot a Lock on %p somewhere\n",wndPtr);
191 /*unlock all WND structures for thread safeness*/
195 /***********************************************************************
198 * Updates the value of oldPtr to newPtr.
200 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
204 tmpWnd = WIN_LockWndPtr(newPtr);
205 WIN_ReleaseWndPtr(*oldPtr);
210 /***********************************************************************
213 * Dump the content of a window structure to stderr.
215 void WIN_DumpWindow( HWND hwnd )
221 if (!(ptr = WIN_FindWndPtr( hwnd )))
223 WARN("%04x is not a window handle\n", hwnd );
227 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
228 strcpy( className, "#NULL#" );
230 TRACE("Window %04x (%p):\n", hwnd, ptr );
231 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
232 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
233 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
234 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
235 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
236 ptr->next, ptr->child, ptr->parent, ptr->owner,
237 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
238 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
239 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
240 ptr->text ? debugstr_w(ptr->text) : "",
241 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
242 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
243 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
244 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
246 if (ptr->class->cbWndExtra)
248 DPRINTF( "extra bytes:" );
249 for (i = 0; i < ptr->class->cbWndExtra; i++)
250 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
254 WIN_ReleaseWndPtr(ptr);
258 /***********************************************************************
261 * Walk the windows tree and print each window on stderr.
263 void WIN_WalkWindows( HWND hwnd, int indent )
268 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
272 WARN("Invalid window handle %04x\n", hwnd );
276 if (!indent) /* first time around */
277 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
278 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
283 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
285 GlobalGetAtomNameA(ptr->class->atomName,className,sizeof(className));
287 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
288 (DWORD)ptr, ptr->hmemTaskQ, className,
289 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
290 ptr->text ? debugstr_w(ptr->text) : "<null>");
292 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
293 WIN_UpdateWndPtr(&ptr,ptr->next);
299 /***********************************************************************
302 * Remove a window from the siblings linked list.
304 BOOL WIN_UnlinkWindow( HWND hwnd )
306 WND *wndPtr, **ppWnd;
309 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
310 else if(!wndPtr->parent)
312 WIN_ReleaseWndPtr(wndPtr);
316 ppWnd = &wndPtr->parent->child;
317 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
320 *ppWnd = wndPtr->next;
323 WIN_ReleaseWndPtr(wndPtr);
328 /***********************************************************************
331 * Insert a window into the siblings linked list.
332 * The window is inserted after the specified window, which can also
333 * be specified as HWND_TOP or HWND_BOTTOM.
335 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
337 WND *wndPtr, **ppWnd;
339 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
340 else if(!wndPtr->parent)
342 WIN_ReleaseWndPtr(wndPtr);
345 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
347 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
348 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
349 while (*ppWnd) ppWnd = &(*ppWnd)->next;
351 else /* Normal case */
353 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
356 WIN_ReleaseWndPtr(wndPtr);
359 ppWnd = &afterPtr->next;
360 WIN_ReleaseWndPtr(afterPtr);
362 wndPtr->next = *ppWnd;
364 WIN_ReleaseWndPtr(wndPtr);
369 /***********************************************************************
370 * WIN_FindWinToRepaint
372 * Find a window that needs repaint.
374 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
379 /* Note: the desktop window never gets WM_PAINT messages
380 * The real reason why is because Windows DesktopWndProc
381 * does ValidateRgn inside WM_ERASEBKGND handler.
384 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
386 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
388 if (!(pWnd->dwStyle & WS_VISIBLE))
390 TRACE("skipping window %04x\n",
393 else if ((pWnd->hmemTaskQ == hQueue) &&
394 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
397 else if (pWnd->child )
398 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
400 WIN_ReleaseWndPtr(pWnd);
411 hwndRet = pWnd->hwndSelf;
413 /* look among siblings if we got a transparent window */
414 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
415 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
417 WIN_UpdateWndPtr(&pWnd,pWnd->next);
421 hwndRet = pWnd->hwndSelf;
422 WIN_ReleaseWndPtr(pWnd);
424 TRACE("found %04x\n",hwndRet);
429 /***********************************************************************
432 * Destroy storage associated to a window. "Internals" p.358
433 * returns a locked wndPtr->next
435 static WND* WIN_DestroyWindow( WND* wndPtr )
437 HWND hwnd = wndPtr->hwndSelf;
440 TRACE("%04x\n", wndPtr->hwndSelf );
442 /* free child windows */
443 WIN_LockWndPtr(wndPtr->child);
444 while ((pWnd = wndPtr->child))
446 wndPtr->child = WIN_DestroyWindow( pWnd );
447 WIN_ReleaseWndPtr(pWnd);
451 * Clear the update region to make sure no WM_PAINT messages will be
452 * generated for this window while processing the WM_NCDESTROY.
454 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
456 if (wndPtr->hrgnUpdate > 1)
457 DeleteObject( wndPtr->hrgnUpdate );
459 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
461 wndPtr->hrgnUpdate = 0;
465 * Send the WM_NCDESTROY to the window being destroyed.
467 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
469 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
471 WINPOS_CheckInternalPos( wndPtr );
472 if( hwnd == GetCapture()) ReleaseCapture();
474 /* free resources associated with the window */
476 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
477 PROPERTY_RemoveWindowProps( wndPtr );
479 wndPtr->dwMagic = 0; /* Mark it as invalid */
481 /* toss stale messages from the queue */
483 if( wndPtr->hmemTaskQ )
485 BOOL bPostQuit = FALSE;
486 WPARAM wQuitParam = 0;
487 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
490 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
492 if( qmsg->msg.message == WM_QUIT )
495 wQuitParam = qmsg->msg.wParam;
497 QUEUE_RemoveMsg(msgQ, qmsg);
502 /* repost WM_QUIT to make sure this app exits its message loop */
503 if( bPostQuit ) PostQuitMessage(wQuitParam);
504 wndPtr->hmemTaskQ = 0;
507 if (!(wndPtr->dwStyle & WS_CHILD))
510 DestroyMenu( wndPtr->wIDmenu );
513 if (wndPtr->hSysMenu)
515 DestroyMenu( wndPtr->hSysMenu );
516 wndPtr->hSysMenu = 0;
518 wndPtr->pDriver->pDestroyWindow( wndPtr );
519 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
520 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
521 wndPtr->class->cWindows--;
522 wndPtr->class = NULL;
524 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
526 wndPtr->pDriver->pFinalize(wndPtr);
531 /***********************************************************************
532 * WIN_ResetQueueWindows
534 * Reset the queue of all the children of a given window.
535 * Return TRUE if something was done.
537 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
541 if (hNew) /* Set a new queue */
543 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
545 if (wnd->hmemTaskQ == hQueue)
547 wnd->hmemTaskQ = hNew;
552 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
556 else /* Queue is being destroyed */
560 WND *tmp = WIN_LockWndPtr(wnd->child);
565 if (tmp->hmemTaskQ == hQueue)
567 DestroyWindow( tmp->hwndSelf );
571 tmp2 = WIN_LockWndPtr(tmp->child);
572 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
576 WIN_UpdateWndPtr(&tmp,tmp->next);
578 WIN_ReleaseWndPtr(tmp2);
580 WIN_ReleaseWndPtr(tmp);
587 /***********************************************************************
588 * WIN_CreateDesktopWindow
590 * Create the desktop window.
592 BOOL WIN_CreateDesktopWindow(void)
597 TRACE("Creating desktop window\n");
600 if (!ICONTITLE_Init() ||
601 !WINPOS_CreateInternalPosAtom() ||
602 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
605 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
606 if (!hwndDesktop) return FALSE;
607 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
609 pWndDesktop->pDriver = WND_Driver;
610 pWndDesktop->pDriver->pInitialize(pWndDesktop);
612 pWndDesktop->next = NULL;
613 pWndDesktop->child = NULL;
614 pWndDesktop->parent = NULL;
615 pWndDesktop->owner = NULL;
616 pWndDesktop->class = class;
617 pWndDesktop->dwMagic = WND_MAGIC;
618 pWndDesktop->hwndSelf = hwndDesktop;
619 pWndDesktop->hInstance = 0;
620 pWndDesktop->rectWindow.left = 0;
621 pWndDesktop->rectWindow.top = 0;
622 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
623 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
624 pWndDesktop->rectClient = pWndDesktop->rectWindow;
625 pWndDesktop->text = NULL;
626 pWndDesktop->hmemTaskQ = GetFastQueue16();
627 pWndDesktop->hrgnUpdate = 0;
628 pWndDesktop->hwndLastActive = hwndDesktop;
629 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
631 pWndDesktop->dwExStyle = 0;
632 pWndDesktop->dce = NULL;
633 pWndDesktop->pVScroll = NULL;
634 pWndDesktop->pHScroll = NULL;
635 pWndDesktop->pProp = NULL;
636 pWndDesktop->wIDmenu = 0;
637 pWndDesktop->helpContext = 0;
638 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
639 pWndDesktop->hSysMenu = 0;
640 pWndDesktop->userdata = 0;
641 pWndDesktop->winproc = (WNDPROC16)class->winproc;
642 pWndDesktop->irefCount = 0;
644 /* FIXME: How do we know if it should be Unicode or not */
645 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
648 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
649 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
654 /***********************************************************************
657 * Fix the coordinates - Helper for WIN_CreateWindowEx.
658 * returns default show mode in sw.
659 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
661 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
663 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
664 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
666 if (cs->style & (WS_CHILD | WS_POPUP))
668 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
669 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
671 else /* overlapped window */
675 GetStartupInfoA( &info );
677 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
679 /* Never believe Microsoft's documentation... CreateWindowEx doc says
680 * that if an overlapped window is created with WS_VISIBLE style bit
681 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
682 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
685 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
686 * 2) it does not ignore the y parameter as the docs claim; instead, it
687 * uses it as second parameter to ShowWindow() unless y is either
688 * CW_USEDEFAULT or CW_USEDEFAULT16.
690 * The fact that we didn't do 2) caused bogus windows pop up when wine
691 * was running apps that were using this obscure feature. Example -
692 * calc.exe that comes with Win98 (only Win98, it's different from
693 * the one that comes with Win95 and NT)
695 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
696 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
697 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
700 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
702 if (info.dwFlags & STARTF_USESIZE)
704 cs->cx = info.dwXSize;
705 cs->cy = info.dwYSize;
707 else /* if no other hint from the app, pick 3/4 of the screen real estate */
710 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
711 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
712 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
719 /***********************************************************************
722 * Implementation of CreateWindowEx().
724 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
725 BOOL win32, BOOL unicode )
731 HWND16 hwnd, hwndLinkAfter;
732 POINT maxSize, maxPos, minTrack, maxTrack;
733 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
735 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
736 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
737 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
738 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
739 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
741 /* Find the parent window */
745 /* Make sure parent is valid */
746 if (!IsWindow( cs->hwndParent ))
748 WARN("Bad parent %04x\n", cs->hwndParent );
751 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
752 WARN("No parent for child window\n" );
753 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
756 /* Find the window class */
757 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
759 WARN("Bad class '%s'\n", cs->lpszClass );
763 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
765 /* Create the window structure */
767 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
768 - sizeof(wndPtr->wExtra) )))
770 TRACE("out of memory\n" );
774 /* Fill the window structure */
776 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
778 wndPtr->child = NULL;
780 if ((cs->style & WS_CHILD) && cs->hwndParent)
782 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
783 wndPtr->owner = NULL;
784 WIN_ReleaseWndPtr(wndPtr->parent);
788 wndPtr->parent = pWndDesktop;
789 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
790 wndPtr->owner = NULL;
793 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
794 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
795 WIN_ReleaseWndPtr(wndPtr->owner);
796 WIN_ReleaseWndPtr(tmpWnd);
801 wndPtr->pDriver = wndPtr->parent->pDriver;
802 wndPtr->pDriver->pInitialize(wndPtr);
804 wndPtr->class = classPtr;
805 wndPtr->winproc = classPtr->winproc;
806 wndPtr->dwMagic = WND_MAGIC;
807 wndPtr->hwndSelf = hwnd;
808 wndPtr->hInstance = cs->hInstance;
810 wndPtr->hmemTaskQ = GetFastQueue16();
811 wndPtr->hrgnUpdate = 0;
813 wndPtr->hwndLastActive = hwnd;
814 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
815 wndPtr->dwExStyle = cs->dwExStyle;
817 wndPtr->helpContext = 0;
818 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
819 wndPtr->pVScroll = NULL;
820 wndPtr->pHScroll = NULL;
821 wndPtr->pProp = NULL;
822 wndPtr->userdata = 0;
823 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
824 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
825 wndPtr->irefCount = 1;
827 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
829 /* Call the WH_CBT hook */
831 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
832 ? HWND_BOTTOM : HWND_TOP;
834 if (HOOK_IsHooked( WH_CBT ))
840 cbtc.hwndInsertAfter = hwndLinkAfter;
841 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
842 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
845 TRACE("CBT-hook returned 0\n");
846 wndPtr->pDriver->pFinalize(wndPtr);
847 USER_HEAP_FREE( hwnd );
853 /* Increment class window counter */
855 classPtr->cWindows++;
857 /* Correct the window style */
859 if (!(cs->style & WS_CHILD))
861 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
862 if (!(cs->style & WS_POPUP))
864 wndPtr->dwStyle |= WS_CAPTION;
865 wndPtr->flags |= WIN_NEED_SIZE;
869 /* Get class or window DC if needed */
871 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
872 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
873 else wndPtr->dce = NULL;
875 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
877 wndPtr->rectWindow.left = cs->x;
878 wndPtr->rectWindow.top = cs->y;
879 wndPtr->rectWindow.right = cs->x + cs->cx;
880 wndPtr->rectWindow.bottom = cs->y + cs->cy;
881 wndPtr->rectClient = wndPtr->rectWindow;
883 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
885 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
887 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
888 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
889 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
890 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
891 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
894 if (cs->cx < 0) cs->cx = 0;
895 if (cs->cy < 0) cs->cy = 0;
897 wndPtr->rectWindow.left = cs->x;
898 wndPtr->rectWindow.top = cs->y;
899 wndPtr->rectWindow.right = cs->x + cs->cx;
900 wndPtr->rectWindow.bottom = cs->y + cs->cy;
901 wndPtr->rectClient = wndPtr->rectWindow;
903 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
909 /* Set the window menu */
911 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
913 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
916 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
917 if (classPtr->menuNameA)
918 cs->hMenu = HIWORD(classPtr->menuNameA) ?
919 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
920 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
922 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
925 if (HIWORD(cs->hInstance))
926 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
928 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
930 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
935 else wndPtr->wIDmenu = (UINT)cs->hMenu;
937 /* Send the WM_CREATE message
938 * Perhaps we shouldn't allow width/height changes as well.
939 * See p327 in "Internals".
942 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
944 localSend32 = unicode ? SendMessageW : SendMessageA;
945 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
947 /* Insert the window in the linked list */
949 WIN_LinkWindow( hwnd, hwndLinkAfter );
951 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
952 NULL, NULL, 0, &wndPtr->rectClient );
953 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
954 maxPos.y - wndPtr->rectWindow.top);
955 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
957 /* Send the size messages */
959 if (!(wndPtr->flags & WIN_NEED_SIZE))
962 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
963 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
964 WARN("sending bogus WM_SIZE message 0x%08lx\n",
965 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
966 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
967 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
968 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
969 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
970 SendMessageA( hwnd, WM_MOVE, 0,
971 MAKELONG( wndPtr->rectClient.left,
972 wndPtr->rectClient.top ) );
975 /* Show the window, maximizing or minimizing if needed */
977 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
980 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
981 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
982 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
983 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
984 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
985 : SWP_NOZORDER | SWP_FRAMECHANGED;
986 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
987 newPos.right, newPos.bottom, swFlag );
990 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
992 /* Notify the parent window only */
994 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
995 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
996 if( !IsWindow(hwnd) )
1003 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
1005 /* Call WH_SHELL hook */
1007 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1008 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1010 TRACE("created window %04x\n", hwnd);
1014 WIN_UnlinkWindow( hwnd );
1017 /* Abort window creation */
1019 WARN("aborted by WM_xxCREATE!\n");
1020 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1023 WIN_ReleaseWndPtr(wndPtr);
1029 /***********************************************************************
1030 * CreateWindow16 (USER.41)
1032 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1033 DWORD style, INT16 x, INT16 y, INT16 width,
1034 INT16 height, HWND16 parent, HMENU16 menu,
1035 HINSTANCE16 instance, LPVOID data )
1037 return CreateWindowEx16( 0, className, windowName, style,
1038 x, y, width, height, parent, menu, instance, data );
1042 /***********************************************************************
1043 * CreateWindowEx16 (USER.452)
1045 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1046 LPCSTR windowName, DWORD style, INT16 x,
1047 INT16 y, INT16 width, INT16 height,
1048 HWND16 parent, HMENU16 menu,
1049 HINSTANCE16 instance, LPVOID data )
1055 /* Find the class atom */
1057 if (HIWORD(className))
1059 if (!(classAtom = GlobalFindAtomA( className )))
1061 ERR( "bad class name %s\n", debugres_a(className) );
1067 classAtom = LOWORD(className);
1068 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1070 ERR( "bad atom %x\n", classAtom);
1076 /* Fix the coordinates */
1078 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1079 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1080 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1081 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1083 /* Create the window */
1085 cs.lpCreateParams = data;
1086 cs.hInstance = (HINSTANCE)instance;
1087 cs.hMenu = (HMENU)menu;
1088 cs.hwndParent = (HWND)parent;
1090 cs.lpszName = windowName;
1091 cs.lpszClass = className;
1092 cs.dwExStyle = exStyle;
1094 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1098 /***********************************************************************
1099 * CreateWindowExA (USER32.83)
1101 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1102 LPCSTR windowName, DWORD style, INT x,
1103 INT y, INT width, INT height,
1104 HWND parent, HMENU menu,
1105 HINSTANCE instance, LPVOID data )
1112 instance=GetModuleHandleA(NULL);
1114 if(exStyle & WS_EX_MDICHILD)
1115 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1117 /* Find the class atom */
1119 if (HIWORD(className))
1121 if (!(classAtom = GlobalFindAtomA( className )))
1123 ERR( "bad class name %s\n", debugres_a(className) );
1129 classAtom = LOWORD(className);
1130 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1132 ERR( "bad atom %x\n", classAtom);
1138 /* Create the window */
1140 cs.lpCreateParams = data;
1141 cs.hInstance = instance;
1143 cs.hwndParent = parent;
1149 cs.lpszName = windowName;
1150 cs.lpszClass = className;
1151 cs.dwExStyle = exStyle;
1153 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1157 /***********************************************************************
1158 * CreateWindowExW (USER32.84)
1160 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1161 LPCWSTR windowName, DWORD style, INT x,
1162 INT y, INT width, INT height,
1163 HWND parent, HMENU menu,
1164 HINSTANCE instance, LPVOID data )
1171 instance=GetModuleHandleA(NULL);
1173 if(exStyle & WS_EX_MDICHILD)
1174 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1176 /* Find the class atom */
1178 if (HIWORD(className))
1180 if (!(classAtom = GlobalFindAtomW( className )))
1182 ERR( "bad class name %s\n", debugres_w(className) );
1188 classAtom = LOWORD(className);
1189 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1191 ERR( "bad atom %x\n", classAtom);
1197 /* Create the window */
1199 cs.lpCreateParams = data;
1200 cs.hInstance = instance;
1202 cs.hwndParent = parent;
1208 cs.lpszName = windowName;
1209 cs.lpszClass = className;
1210 cs.dwExStyle = exStyle;
1212 /* Note: we rely on the fact that CREATESTRUCTA and */
1213 /* CREATESTRUCTW have the same layout. */
1214 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1218 /***********************************************************************
1221 static void WIN_CheckFocus( WND* pWnd )
1223 if( GetFocus16() == pWnd->hwndSelf )
1224 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1227 /***********************************************************************
1228 * WIN_SendDestroyMsg
1230 static void WIN_SendDestroyMsg( WND* pWnd )
1232 WIN_CheckFocus(pWnd);
1234 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1235 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1238 * Send the WM_DESTROY to the window.
1240 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1243 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1244 * make sure that the window still exists when we come back.
1246 if (IsWindow(pWnd->hwndSelf))
1248 HWND* pWndArray = NULL;
1253 * Now, if the window has kids, we have to send WM_DESTROY messages
1254 * recursively to it's kids. It seems that those calls can also
1255 * trigger re-entrant calls to DestroyWindow for the kids so we must
1256 * protect against corruption of the list of siblings. We first build
1257 * a list of HWNDs representing all the kids.
1259 pChild = WIN_LockWndPtr(pWnd->child);
1263 WIN_UpdateWndPtr(&pChild,pChild->next);
1267 * If there are no kids, we're done.
1272 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1277 if (pWndArray==NULL)
1281 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1282 * call, our linked list of siblings should be safe.
1285 pChild = WIN_LockWndPtr(pWnd->child);
1288 pWndArray[nKidCount] = pChild->hwndSelf;
1290 WIN_UpdateWndPtr(&pChild,pChild->next);
1294 * Now that we have a list, go through that list again and send the destroy
1295 * message to those windows. We are using the HWND to retrieve the
1296 * WND pointer so we are effectively checking that all the kid windows are
1297 * still valid before sending the message.
1301 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1305 WIN_SendDestroyMsg( pChild );
1306 WIN_ReleaseWndPtr(pChild);
1313 HeapFree(GetProcessHeap(), 0, pWndArray);
1314 WIN_CheckFocus(pWnd);
1317 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1321 /***********************************************************************
1322 * DestroyWindow16 (USER.53)
1324 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1326 return DestroyWindow(hwnd);
1330 /***********************************************************************
1331 * DestroyWindow (USER32.135)
1333 BOOL WINAPI DestroyWindow( HWND hwnd )
1338 TRACE("(%04x)\n", hwnd);
1340 /* Initialization */
1342 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1343 if (wndPtr == pWndDesktop)
1345 retvalue = FALSE; /* Can't destroy desktop */
1351 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1357 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1359 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1360 /* FIXME: clean up palette - see "Internals" p.352 */
1363 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1364 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1366 /* Notify the parent window only */
1367 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1368 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1369 if( !IsWindow(hwnd) )
1376 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1378 /* Hide the window */
1380 if (wndPtr->dwStyle & WS_VISIBLE)
1382 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1383 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1384 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1385 if (!IsWindow(hwnd))
1392 /* Recursively destroy owned windows */
1394 if( !(wndPtr->dwStyle & WS_CHILD) )
1396 /* make sure top menu popup doesn't get destroyed */
1397 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1401 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1404 if (siblingPtr->owner == wndPtr)
1406 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1409 siblingPtr->owner = NULL;
1411 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1415 DestroyWindow( siblingPtr->hwndSelf );
1416 WIN_ReleaseWndPtr(siblingPtr);
1421 if( !Options.managed || EVENT_CheckFocus() )
1422 WINPOS_ActivateOtherWindow(wndPtr);
1424 if( wndPtr->owner &&
1425 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1426 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1429 /* Send destroy messages */
1431 WIN_SendDestroyMsg( wndPtr );
1432 if (!IsWindow(hwnd))
1438 /* Unlink now so we won't bother with the children later on */
1440 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1442 /* Destroy the window storage */
1444 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1447 WIN_ReleaseWndPtr(wndPtr);
1452 /***********************************************************************
1453 * CloseWindow16 (USER.43)
1455 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1457 return CloseWindow( hwnd );
1461 /***********************************************************************
1462 * CloseWindow (USER32.56)
1464 BOOL WINAPI CloseWindow( HWND hwnd )
1466 WND * wndPtr = WIN_FindWndPtr( hwnd );
1469 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1474 ShowWindow( hwnd, SW_MINIMIZE );
1477 WIN_ReleaseWndPtr(wndPtr);
1483 /***********************************************************************
1484 * OpenIcon16 (USER.44)
1486 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1488 return OpenIcon( hwnd );
1492 /***********************************************************************
1493 * OpenIcon (USER32.410)
1495 BOOL WINAPI OpenIcon( HWND hwnd )
1497 if (!IsIconic( hwnd )) return FALSE;
1498 ShowWindow( hwnd, SW_SHOWNORMAL );
1503 /***********************************************************************
1506 * Implementation of FindWindow() and FindWindowEx().
1508 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1516 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1519 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1525 else if (pWnd->parent != pWndDesktop)
1530 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1534 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1539 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1547 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1549 if (className && (pWnd->class->atomName != className))
1550 continue; /* Not the right class */
1552 /* Now check the title */
1556 retvalue = pWnd->hwndSelf;
1559 if (pWnd->text && !lstrcmpW( pWnd->text, title ))
1561 retvalue = pWnd->hwndSelf;
1567 WIN_ReleaseWndPtr(pWnd);
1573 /***********************************************************************
1574 * FindWindow16 (USER.50)
1576 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1578 return FindWindowA( className, title );
1582 /***********************************************************************
1583 * FindWindowEx16 (USER.427)
1585 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1587 return FindWindowExA( parent, child, className, title );
1591 /***********************************************************************
1592 * FindWindowA (USER32.198)
1594 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1596 HWND ret = FindWindowExA( 0, 0, className, title );
1597 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1602 /***********************************************************************
1603 * FindWindowExA (USER32.199)
1605 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1606 LPCSTR className, LPCSTR title )
1614 /* If the atom doesn't exist, then no class */
1615 /* with this name exists either. */
1616 if (!(atom = GlobalFindAtomA( className )))
1618 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1623 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1624 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1625 HeapFree( GetProcessHeap(), 0, buffer );
1630 /***********************************************************************
1631 * FindWindowExW (USER32.200)
1633 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1634 LPCWSTR className, LPCWSTR title )
1640 /* If the atom doesn't exist, then no class */
1641 /* with this name exists either. */
1642 if (!(atom = GlobalFindAtomW( className )))
1644 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1648 return WIN_FindWindow( parent, child, atom, title );
1652 /***********************************************************************
1653 * FindWindowW (USER32.201)
1655 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1657 return FindWindowExW( 0, 0, className, title );
1661 /**********************************************************************
1663 * returns a locked pointer
1665 WND *WIN_GetDesktop(void)
1667 return WIN_LockWndPtr(pWndDesktop);
1669 /**********************************************************************
1670 * WIN_ReleaseDesktop
1671 * unlock the desktop pointer
1673 void WIN_ReleaseDesktop(void)
1675 WIN_ReleaseWndPtr(pWndDesktop);
1679 /**********************************************************************
1680 * GetDesktopWindow16 (USER.286)
1682 HWND16 WINAPI GetDesktopWindow16(void)
1684 return (HWND16)pWndDesktop->hwndSelf;
1688 /**********************************************************************
1689 * GetDesktopWindow (USER32.232)
1691 HWND WINAPI GetDesktopWindow(void)
1693 if (pWndDesktop) return pWndDesktop->hwndSelf;
1694 ERR( "You need the -desktop option when running with native USER\n" );
1700 /**********************************************************************
1701 * GetDesktopHwnd (USER.278)
1703 * Exactly the same thing as GetDesktopWindow(), but not documented.
1704 * Don't ask me why...
1706 HWND16 WINAPI GetDesktopHwnd16(void)
1708 return (HWND16)pWndDesktop->hwndSelf;
1712 /*******************************************************************
1713 * EnableWindow16 (USER.34)
1715 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1717 return EnableWindow( hwnd, enable );
1721 /*******************************************************************
1722 * EnableWindow (USER32.172)
1724 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1729 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1731 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1732 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1735 wndPtr->dwStyle &= ~WS_DISABLED;
1737 if( wndPtr->flags & WIN_NATIVE )
1738 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1740 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1744 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1746 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1748 /* Disable window */
1749 wndPtr->dwStyle |= WS_DISABLED;
1751 if( wndPtr->flags & WIN_NATIVE )
1752 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1754 if (hwnd == GetFocus())
1756 SetFocus( 0 ); /* A disabled window can't have the focus */
1758 if (hwnd == GetCapture())
1760 ReleaseCapture(); /* A disabled window can't capture the mouse */
1762 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1766 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1768 WIN_ReleaseWndPtr(wndPtr);
1773 /***********************************************************************
1774 * IsWindowEnabled16 (USER.35)
1776 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1778 return IsWindowEnabled(hWnd);
1782 /***********************************************************************
1783 * IsWindowEnabled (USER32.349)
1785 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1790 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1791 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1792 WIN_ReleaseWndPtr(wndPtr);
1798 /***********************************************************************
1799 * IsWindowUnicode (USER32.350)
1801 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1806 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1807 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1808 WIN_ReleaseWndPtr(wndPtr);
1813 /**********************************************************************
1814 * GetWindowWord16 (USER.133)
1816 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1818 return GetWindowWord( hwnd, offset );
1822 /**********************************************************************
1823 * GetWindowWord (USER32.314)
1825 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1828 WND * wndPtr = WIN_FindWndPtr( hwnd );
1829 if (!wndPtr) return 0;
1832 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1834 WARN("Invalid offset %d\n", offset );
1838 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1844 if (HIWORD(wndPtr->wIDmenu))
1845 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1847 retvalue = (WORD)wndPtr->wIDmenu;
1849 case GWW_HWNDPARENT:
1850 retvalue = GetParent(hwnd);
1853 if (HIWORD(wndPtr->hInstance))
1854 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1856 retvalue = (WORD)wndPtr->hInstance;
1859 WARN("Invalid offset %d\n", offset );
1864 WIN_ReleaseWndPtr(wndPtr);
1868 /**********************************************************************
1869 * SetWindowWord16 (USER.134)
1871 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1873 return SetWindowWord( hwnd, offset, newval );
1877 /**********************************************************************
1878 * SetWindowWord (USER32.524)
1880 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1883 WND * wndPtr = WIN_FindWndPtr( hwnd );
1884 if (!wndPtr) return 0;
1887 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1889 WARN("Invalid offset %d\n", offset );
1893 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1897 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1898 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1899 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1902 WARN("Invalid offset %d\n", offset );
1909 WIN_ReleaseWndPtr(wndPtr);
1914 /**********************************************************************
1917 * Helper function for GetWindowLong().
1919 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1922 WND * wndPtr = WIN_FindWndPtr( hwnd );
1923 if (!wndPtr) return 0;
1926 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1928 WARN("Invalid offset %d\n", offset );
1932 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1933 /* Special case for dialog window procedure */
1934 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1936 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1943 case GWL_USERDATA: retvalue = wndPtr->userdata;
1945 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1947 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1949 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1951 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1954 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1956 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1959 WARN("Unknown offset %d\n", offset );
1963 WIN_ReleaseWndPtr(wndPtr);
1968 /**********************************************************************
1971 * Helper function for SetWindowLong().
1973 * 0 is the failure code. However, in the case of failure SetLastError
1974 * must be set to distinguish between a 0 return value and a failure.
1976 * FIXME: The error values for SetLastError may not be right. Can
1977 * someone check with the real thing?
1979 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1980 WINDOWPROCTYPE type )
1983 WND * wndPtr = WIN_FindWndPtr( hwnd );
1986 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1990 /* Is this the right error? */
1991 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1997 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1999 WARN("Invalid offset %d\n", offset );
2001 /* Is this the right error? */
2002 SetLastError( ERROR_OUTOFMEMORY );
2007 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2008 /* Special case for dialog window procedure */
2009 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2011 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2012 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2013 type, WIN_PROC_WINDOW );
2020 ptr = (DWORD*)&wndPtr->wIDmenu;
2023 retval = SetWindowWord( hwnd, offset, newval );
2026 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2027 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2028 type, WIN_PROC_WINDOW );
2031 style.styleOld = wndPtr->dwStyle;
2032 newval &= ~(WS_CHILD); /* this bit can't be changed this way */
2033 style.styleNew = newval | (style.styleOld & (WS_CHILD));
2035 if (wndPtr->flags & WIN_ISWIN32)
2036 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2037 wndPtr->dwStyle = style.styleNew;
2038 if (wndPtr->flags & WIN_ISWIN32)
2039 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2040 retval = style.styleOld;
2044 ptr = &wndPtr->userdata;
2047 style.styleOld = wndPtr->dwExStyle;
2048 style.styleNew = newval;
2049 if (wndPtr->flags & WIN_ISWIN32)
2050 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2051 wndPtr->dwExStyle = newval;
2052 if (wndPtr->flags & WIN_ISWIN32)
2053 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2054 retval = style.styleOld;
2058 WARN("Invalid offset %d\n", offset );
2060 /* Don't think this is right error but it should do */
2061 SetLastError( ERROR_OUTOFMEMORY );
2069 WIN_ReleaseWndPtr(wndPtr);
2074 /**********************************************************************
2075 * GetWindowLong16 (USER.135)
2077 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2079 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2083 /**********************************************************************
2084 * GetWindowLongA (USER32.305)
2086 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2088 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2092 /**********************************************************************
2093 * GetWindowLongW (USER32.306)
2095 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2097 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2101 /**********************************************************************
2102 * SetWindowLong16 (USER.136)
2104 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2106 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2110 /**********************************************************************
2111 * SetWindowLongA (USER32.517)
2113 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2115 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2119 /**********************************************************************
2120 * SetWindowLongW (USER32.518) Set window attribute
2122 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2123 * value in a window's extra memory.
2125 * The _hwnd_ parameter specifies the window. is the handle to a
2126 * window that has extra memory. The _newval_ parameter contains the
2127 * new attribute or extra memory value. If positive, the _offset_
2128 * parameter is the byte-addressed location in the window's extra
2129 * memory to set. If negative, _offset_ specifies the window
2130 * attribute to set, and should be one of the following values:
2132 * GWL_EXSTYLE The window's extended window style
2134 * GWL_STYLE The window's window style.
2136 * GWL_WNDPROC Pointer to the window's window procedure.
2138 * GWL_HINSTANCE The window's pplication instance handle.
2140 * GWL_ID The window's identifier.
2142 * GWL_USERDATA The window's user-specified data.
2144 * If the window is a dialog box, the _offset_ parameter can be one of
2145 * the following values:
2147 * DWL_DLGPROC The address of the window's dialog box procedure.
2149 * DWL_MSGRESULT The return value of a message
2150 * that the dialog box procedure processed.
2152 * DWL_USER Application specific information.
2156 * If successful, returns the previous value located at _offset_. Otherwise,
2161 * Extra memory for a window class is specified by a nonzero cbWndExtra
2162 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2163 * time of class creation.
2165 * Using GWL_WNDPROC to set a new window procedure effectively creates
2166 * a window subclass. Use CallWindowProc() in the new windows procedure
2167 * to pass messages to the superclass's window procedure.
2169 * The user data is reserved for use by the application which created
2172 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2173 * instead, call the EnableWindow() function to change the window's
2176 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2177 * SetParent() instead.
2180 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2181 * it sends WM_STYLECHANGING before changing the settings
2182 * and WM_STYLECHANGED afterwards.
2183 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2187 * GWL_STYLE does not dispatch WM_STYLE... messages.
2194 LONG WINAPI SetWindowLongW(
2195 HWND hwnd, /* window to alter */
2196 INT offset, /* offset, in bytes, of location to alter */
2197 LONG newval /* new value of location */
2199 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2203 /*******************************************************************
2204 * GetWindowText16 (USER.36)
2206 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2208 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2212 /*******************************************************************
2213 * GetWindowTextA (USER32.309)
2215 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2217 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2221 /*******************************************************************
2222 * InternalGetWindowText (USER32.326)
2224 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2226 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2227 return GetWindowTextW(hwnd,lpString,nMaxCount);
2231 /*******************************************************************
2232 * GetWindowTextW (USER32.312)
2234 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2236 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2241 /*******************************************************************
2242 * SetWindowText16 (USER.37)
2244 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2246 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2250 /*******************************************************************
2251 * SetWindowTextA (USER32.521)
2253 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2255 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2259 /*******************************************************************
2260 * SetWindowTextW (USER32.523)
2262 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2264 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2268 /*******************************************************************
2269 * GetWindowTextLength16 (USER.38)
2271 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2273 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2277 /*******************************************************************
2278 * GetWindowTextLengthA (USER32.310)
2280 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2282 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2285 /*******************************************************************
2286 * GetWindowTextLengthW (USER32.311)
2288 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2290 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2294 /*******************************************************************
2295 * IsWindow16 (USER.47)
2297 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2299 CURRENT_STACK16->es = USER_HeapSel;
2300 return IsWindow( hwnd );
2304 /*******************************************************************
2305 * IsWindow (USER32.348)
2307 BOOL WINAPI IsWindow( HWND hwnd )
2312 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2313 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2314 WIN_ReleaseWndPtr(wndPtr);
2320 /*****************************************************************
2321 * GetParent16 (USER.46)
2323 HWND16 WINAPI GetParent16( HWND16 hwnd )
2325 return (HWND16)GetParent( hwnd );
2329 /*****************************************************************
2330 * GetParent (USER32.278)
2332 HWND WINAPI GetParent( HWND hwnd )
2337 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2338 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2341 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2343 retvalue = wndPtr->hwndSelf;
2346 WIN_ReleaseWndPtr(wndPtr);
2351 /*****************************************************************
2354 * Get the top-level parent for a child window.
2355 * returns a locked pointer
2357 WND* WIN_GetTopParentPtr( WND* pWnd )
2359 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2361 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2363 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2368 /*****************************************************************
2371 * Get the top-level parent for a child window.
2373 HWND WIN_GetTopParent( HWND hwnd )
2376 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2377 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2379 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2380 WIN_ReleaseWndPtr(tmpPtr);
2381 WIN_ReleaseWndPtr(wndPtr);
2386 /*****************************************************************
2387 * SetParent16 (USER.233)
2389 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2391 return SetParent( hwndChild, hwndNewParent );
2395 /*****************************************************************
2396 * SetParent (USER32.495)
2398 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2407 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2409 dwStyle = wndPtr->dwStyle;
2411 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2412 : WIN_LockWndPtr(pWndDesktop);
2414 /* Windows hides the window first, then shows it again
2415 * including the WM_SHOWWINDOW messages and all */
2416 if (dwStyle & WS_VISIBLE)
2417 ShowWindow( hwndChild, SW_HIDE );
2419 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2421 /* SetParent additionally needs to make hwndChild the topmost window
2422 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2423 WM_WINDOWPOSCHANGED notification messages.
2425 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2426 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2427 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2428 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2430 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2432 WIN_ReleaseWndPtr(pWndOldParent);
2433 WIN_ReleaseWndPtr(pWndNewParent);
2434 WIN_ReleaseWndPtr(wndPtr);
2440 /*******************************************************************
2441 * IsChild16 (USER.48)
2443 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2445 return IsChild(parent,child);
2449 /*******************************************************************
2450 * IsChild (USER32.339)
2452 BOOL WINAPI IsChild( HWND parent, HWND child )
2454 WND * wndPtr = WIN_FindWndPtr( child );
2455 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2457 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2458 if (wndPtr->hwndSelf == parent)
2460 WIN_ReleaseWndPtr(wndPtr);
2464 WIN_ReleaseWndPtr(wndPtr);
2469 /***********************************************************************
2470 * IsWindowVisible16 (USER.49)
2472 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2474 return IsWindowVisible(hwnd);
2478 /***********************************************************************
2479 * IsWindowVisible (USER32.351)
2481 BOOL WINAPI IsWindowVisible( HWND hwnd )
2484 WND *wndPtr = WIN_FindWndPtr( hwnd );
2485 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2487 if (!(wndPtr->dwStyle & WS_VISIBLE))
2489 WIN_ReleaseWndPtr(wndPtr);
2492 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2494 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2495 WIN_ReleaseWndPtr(wndPtr);
2501 /***********************************************************************
2502 * WIN_IsWindowDrawable
2504 * hwnd is drawable when it is visible, all parents are not
2505 * minimized, and it is itself not minimized unless we are
2506 * trying to draw its default class icon.
2508 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2510 if( (wnd->dwStyle & WS_MINIMIZE &&
2511 icon && wnd->class->hIcon) ||
2512 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2513 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2514 if( wnd->dwStyle & WS_MINIMIZE ||
2515 !(wnd->dwStyle & WS_VISIBLE) ) break;
2516 return (wnd == NULL);
2520 /*******************************************************************
2521 * GetTopWindow16 (USER.229)
2523 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2525 return GetTopWindow(hwnd);
2529 /*******************************************************************
2530 * GetTopWindow (USER.229)
2532 HWND WINAPI GetTopWindow( HWND hwnd )
2535 WND * wndPtr = (hwnd) ?
2536 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2538 if (wndPtr && wndPtr->child)
2539 retval = wndPtr->child->hwndSelf;
2541 WIN_ReleaseWndPtr(wndPtr);
2546 /*******************************************************************
2547 * GetWindow16 (USER.262)
2549 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2551 return GetWindow( hwnd,rel );
2555 /*******************************************************************
2556 * GetWindow (USER32.302)
2558 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2562 WND * wndPtr = WIN_FindWndPtr( hwnd );
2563 if (!wndPtr) return 0;
2567 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2571 if (!wndPtr->parent)
2573 retval = 0; /* Desktop window */
2576 while (wndPtr->next)
2578 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2580 retval = wndPtr->hwndSelf;
2584 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2588 if (!wndPtr->parent)
2590 retval = 0; /* Desktop window */
2593 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2594 if (wndPtr->hwndSelf == hwnd)
2596 retval = 0; /* First in list */
2599 while (wndPtr->next)
2601 if (wndPtr->next->hwndSelf == hwnd)
2603 retval = wndPtr->hwndSelf;
2606 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2612 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2616 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2621 WIN_ReleaseWndPtr(wndPtr);
2626 /*******************************************************************
2627 * GetNextWindow16 (USER.230)
2629 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2631 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2632 return GetWindow16( hwnd, flag );
2635 /*******************************************************************
2636 * ShowOwnedPopups16 (USER.265)
2638 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2640 ShowOwnedPopups( owner, fShow );
2644 /*******************************************************************
2645 * ShowOwnedPopups (USER32.531)
2647 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2649 UINT totalChild=0, count=0;
2651 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2653 if (!pWnd) return TRUE;
2655 for (; count < totalChild; count++)
2657 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2661 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2663 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2664 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2669 if (IsWindowVisible(pWnd[count]->hwndSelf))
2671 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2672 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2678 WIN_ReleaseDesktop();
2679 WIN_ReleaseWinArray(pWnd);
2684 /*******************************************************************
2685 * GetLastActivePopup16 (USER.287)
2687 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2689 return GetLastActivePopup( hwnd );
2692 /*******************************************************************
2693 * GetLastActivePopup (USER32.256)
2695 HWND WINAPI GetLastActivePopup( HWND hwnd )
2698 WND *wndPtr =WIN_FindWndPtr(hwnd);
2699 if (!wndPtr) return hwnd;
2700 retval = wndPtr->hwndLastActive;
2701 WIN_ReleaseWndPtr(wndPtr);
2706 /*******************************************************************
2709 * Build an array of pointers to the children of a given window.
2710 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2711 * when no windows are found.
2713 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2715 /* Future: this function will lock all windows associated with this array */
2717 WND **list, **ppWnd;
2719 UINT count = 0, skipOwned, skipHidden;
2722 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2723 skipOwned = bwaFlags & BWA_SKIPOWNED;
2724 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2725 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2727 /* First count the windows */
2730 wndPtr = WIN_GetDesktop();
2732 pWnd = WIN_LockWndPtr(wndPtr->child);
2735 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2736 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2738 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2743 /* Now build the list of all windows */
2745 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2747 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2749 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2750 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2756 WIN_ReleaseWndPtr(pWnd);
2762 if( pTotal ) *pTotal = count;
2765 /*******************************************************************
2766 * WIN_ReleaseWinArray
2768 void WIN_ReleaseWinArray(WND **wndArray)
2770 /* Future: this function will also unlock all windows associated with wndArray */
2771 HeapFree( GetProcessHeap(), 0, wndArray );
2775 /*******************************************************************
2776 * EnumWindows (USER32.193)
2778 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2780 WND **list, **ppWnd;
2782 /* We have to build a list of all windows first, to avoid */
2783 /* unpleasant side-effects, for instance if the callback */
2784 /* function changes the Z-order of the windows. */
2786 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2788 WIN_ReleaseDesktop();
2792 /* Now call the callback function for every window */
2794 for (ppWnd = list; *ppWnd; ppWnd++)
2796 LRESULT lpEnumFuncRetval;
2798 /* Make sure that the window still exists */
2799 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2801 /* To avoid any deadlocks, all the locks on the windows
2802 structures must be suspended before the control
2803 is passed to the application */
2804 iWndsLocks = WIN_SuspendWndsLock();
2805 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2806 WIN_RestoreWndsLock(iWndsLocks);
2808 if (!lpEnumFuncRetval) break;
2810 WIN_ReleaseWinArray(list);
2811 WIN_ReleaseDesktop();
2816 /**********************************************************************
2817 * EnumTaskWindows16 (USER.225)
2819 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2822 WND **list, **ppWnd;
2824 /* This function is the same as EnumWindows(), */
2825 /* except for an added check on the window's task. */
2827 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2829 WIN_ReleaseDesktop();
2833 /* Now call the callback function for every window */
2835 for (ppWnd = list; *ppWnd; ppWnd++)
2839 /* Make sure that the window still exists */
2840 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2841 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2843 /* To avoid any deadlocks, all the locks on the windows
2844 structures must be suspended before the control
2845 is passed to the application */
2846 iWndsLocks = WIN_SuspendWndsLock();
2847 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2848 WIN_RestoreWndsLock(iWndsLocks);
2850 if (!funcRetval) break;
2852 WIN_ReleaseWinArray(list);
2853 WIN_ReleaseDesktop();
2858 /**********************************************************************
2859 * EnumThreadWindows (USER32.190)
2861 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2863 TEB *teb = THREAD_IdToTEB(id);
2865 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2869 /**********************************************************************
2870 * WIN_EnumChildWindows
2872 * Helper function for EnumChildWindows().
2874 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2879 for ( ; *ppWnd; ppWnd++)
2883 /* Make sure that the window still exists */
2884 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2885 /* Build children list first */
2886 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2888 /* To avoid any deadlocks, all the locks on the windows
2889 structures must be suspended before the control
2890 is passed to the application */
2891 iWndsLocks = WIN_SuspendWndsLock();
2892 ret = func( (*ppWnd)->hwndSelf, lParam );
2893 WIN_RestoreWndsLock(iWndsLocks);
2897 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2898 WIN_ReleaseWinArray(childList);
2900 if (!ret) return FALSE;
2906 /**********************************************************************
2907 * EnumChildWindows (USER32.178)
2909 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2912 WND **list, *pParent;
2914 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2915 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2917 WIN_ReleaseWndPtr(pParent);
2920 WIN_EnumChildWindows( list, func, lParam );
2921 WIN_ReleaseWinArray(list);
2922 WIN_ReleaseWndPtr(pParent);
2927 /*******************************************************************
2928 * AnyPopup16 (USER.52)
2930 BOOL16 WINAPI AnyPopup16(void)
2936 /*******************************************************************
2937 * AnyPopup (USER32.4)
2939 BOOL WINAPI AnyPopup(void)
2941 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2946 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2951 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2955 WIN_ReleaseWndPtr(wndPtr);
2960 /*******************************************************************
2961 * FlashWindow16 (USER.105)
2963 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2965 return FlashWindow( hWnd, bInvert );
2969 /*******************************************************************
2970 * FlashWindow (USER32.202)
2972 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2974 WND *wndPtr = WIN_FindWndPtr(hWnd);
2976 TRACE("%04x\n", hWnd);
2978 if (!wndPtr) return FALSE;
2980 if (wndPtr->dwStyle & WS_MINIMIZE)
2982 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2984 HDC hDC = GetDC(hWnd);
2986 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2987 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2989 ReleaseDC( hWnd, hDC );
2990 wndPtr->flags |= WIN_NCACTIVATED;
2994 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2995 RDW_UPDATENOW | RDW_FRAME, 0 );
2996 wndPtr->flags &= ~WIN_NCACTIVATED;
2998 WIN_ReleaseWndPtr(wndPtr);
3004 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3005 else wparam = (hWnd == GetActiveWindow());
3007 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3008 WIN_ReleaseWndPtr(wndPtr);
3014 /*******************************************************************
3015 * SetSysModalWindow16 (USER.188)
3017 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3019 HWND hWndOldModal = hwndSysModal;
3020 hwndSysModal = hWnd;
3021 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3022 return hWndOldModal;
3026 /*******************************************************************
3027 * GetSysModalWindow16 (USER.52)
3029 HWND16 WINAPI GetSysModalWindow16(void)
3031 return hwndSysModal;
3035 /*******************************************************************
3036 * GetWindowContextHelpId (USER32.303)
3038 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3041 WND *wnd = WIN_FindWndPtr( hwnd );
3043 retval = wnd->helpContext;
3044 WIN_ReleaseWndPtr(wnd);
3049 /*******************************************************************
3050 * SetWindowContextHelpId (USER32.515)
3052 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3054 WND *wnd = WIN_FindWndPtr( hwnd );
3055 if (!wnd) return FALSE;
3056 wnd->helpContext = id;
3057 WIN_ReleaseWndPtr(wnd);
3062 /*******************************************************************
3065 * recursively find a child that contains spDragInfo->pt point
3066 * and send WM_QUERYDROPOBJECT
3068 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3070 BOOL16 wParam, bResult = 0;
3072 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3073 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3076 if( !ptrQueryWnd || !ptrDragInfo )
3079 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3081 GetWindowRect(hQueryWnd,&tempRect);
3083 if( !PtInRect(&tempRect,pt) ||
3084 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3087 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3089 tempRect = ptrQueryWnd->rectClient;
3090 if(ptrQueryWnd->dwStyle & WS_CHILD)
3091 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3092 (LPPOINT)&tempRect, 2 );
3094 if (PtInRect( &tempRect, pt))
3098 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3100 if( ptrWnd->dwStyle & WS_VISIBLE )
3102 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3103 if (PtInRect( &tempRect, pt )) break;
3109 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3110 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3111 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3112 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3113 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3115 WIN_ReleaseWndPtr(ptrWnd);
3125 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3127 ptrDragInfo->hScope = hQueryWnd;
3129 bResult = ( bNoSend )
3130 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3131 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3132 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3134 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3137 WIN_ReleaseWndPtr(ptrQueryWnd);
3142 /*******************************************************************
3143 * DragDetect (USER.465)
3145 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3148 CONV_POINT16TO32( &pt, &pt32 );
3149 return DragDetect( hWnd, pt32 );
3152 /*******************************************************************
3153 * DragDetect (USER32.151)
3155 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3160 rect.left = pt.x - wDragWidth;
3161 rect.right = pt.x + wDragWidth;
3163 rect.top = pt.y - wDragHeight;
3164 rect.bottom = pt.y + wDragHeight;
3170 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3172 if( msg.message == WM_LBUTTONUP )
3177 if( msg.message == WM_MOUSEMOVE )
3179 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3191 /******************************************************************************
3192 * DragObject16 (USER.464)
3194 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3195 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3198 LPDRAGINFO lpDragInfo;
3200 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3201 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3202 WND *wndPtr = WIN_FindWndPtr(hWnd);
3203 HCURSOR16 hCurrentCursor = 0;
3204 HWND16 hCurrentWnd = 0;
3206 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3207 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3209 if( !lpDragInfo || !spDragInfo )
3211 WIN_ReleaseWndPtr(wndPtr);
3215 hBummer = LoadCursor16(0, IDC_BUMMER16);
3217 if( !hBummer || !wndPtr )
3219 GlobalFree16(hDragInfo);
3220 WIN_ReleaseWndPtr(wndPtr);
3226 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3228 GlobalFree16(hDragInfo);
3229 WIN_ReleaseWndPtr(wndPtr);
3233 if( hDragCursor == hCursor ) hDragCursor = 0;
3234 else hCursor = hDragCursor;
3236 hOldCursor = SetCursor(hDragCursor);
3239 lpDragInfo->hWnd = hWnd;
3240 lpDragInfo->hScope = 0;
3241 lpDragInfo->wFlags = wObj;
3242 lpDragInfo->hList = szList; /* near pointer! */
3243 lpDragInfo->hOfStruct = hOfStruct;
3251 do{ WaitMessage(); }
3252 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3254 *(lpDragInfo+1) = *lpDragInfo;
3256 lpDragInfo->pt = msg.pt;
3258 /* update DRAGINFO struct */
3259 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3261 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3262 hCurrentCursor = hCursor;
3265 hCurrentCursor = hBummer;
3266 lpDragInfo->hScope = 0;
3268 if( hCurrentCursor )
3269 SetCursor(hCurrentCursor);
3271 /* send WM_DRAGLOOP */
3272 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3273 (LPARAM) spDragInfo );
3274 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3275 if( hCurrentWnd != lpDragInfo->hScope )
3278 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3279 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3280 HIWORD(spDragInfo)) );
3281 hCurrentWnd = lpDragInfo->hScope;
3283 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3287 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3289 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3292 ShowCursor( FALSE );
3296 SetCursor( hOldCursor );
3297 if (hDragCursor) DestroyCursor( hDragCursor );
3300 if( hCurrentCursor != hBummer )
3301 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3302 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3305 GlobalFree16(hDragInfo);
3306 WIN_ReleaseWndPtr(wndPtr);
3308 return (DWORD)(msg.lParam);