2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
9 #include "wine/winbase16.h"
10 #include "wine/winuser16.h"
17 #include "cursoricon.h"
21 #include "nonclient.h"
24 #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 ? 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 GlobalGetAtomName16(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?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))
508 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
509 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
510 wndPtr->pDriver->pDestroyWindow( wndPtr );
511 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
512 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
513 wndPtr->class->cWindows--;
514 wndPtr->class = NULL;
516 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
518 wndPtr->pDriver->pFinalize(wndPtr);
523 /***********************************************************************
524 * WIN_ResetQueueWindows
526 * Reset the queue of all the children of a given window.
527 * Return TRUE if something was done.
529 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
533 if (hNew) /* Set a new queue */
535 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
537 if (wnd->hmemTaskQ == hQueue)
539 wnd->hmemTaskQ = hNew;
544 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
548 else /* Queue is being destroyed */
552 WND *tmp = WIN_LockWndPtr(wnd->child);
557 if (tmp->hmemTaskQ == hQueue)
559 DestroyWindow( tmp->hwndSelf );
563 tmp2 = WIN_LockWndPtr(tmp->child);
564 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
568 WIN_UpdateWndPtr(&tmp,tmp->next);
570 WIN_ReleaseWndPtr(tmp2);
572 WIN_ReleaseWndPtr(tmp);
579 /***********************************************************************
580 * WIN_CreateDesktopWindow
582 * Create the desktop window.
584 BOOL WIN_CreateDesktopWindow(void)
590 TRACE("Creating desktop window\n");
593 if (!ICONTITLE_Init() ||
594 !WINPOS_CreateInternalPosAtom() ||
595 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
598 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
599 if (!hwndDesktop) return FALSE;
600 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
602 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
603 pDesktop->pDriver = DESKTOP_Driver;
604 pWndDesktop->pDriver = WND_Driver;
606 pDesktop->pDriver->pInitialize(pDesktop);
607 pWndDesktop->pDriver->pInitialize(pWndDesktop);
609 pWndDesktop->next = NULL;
610 pWndDesktop->child = NULL;
611 pWndDesktop->parent = NULL;
612 pWndDesktop->owner = NULL;
613 pWndDesktop->class = class;
614 pWndDesktop->dwMagic = WND_MAGIC;
615 pWndDesktop->hwndSelf = hwndDesktop;
616 pWndDesktop->hInstance = 0;
617 pWndDesktop->rectWindow.left = 0;
618 pWndDesktop->rectWindow.top = 0;
619 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
620 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
621 pWndDesktop->rectClient = pWndDesktop->rectWindow;
622 pWndDesktop->text = NULL;
623 pWndDesktop->hmemTaskQ = GetFastQueue16();
624 pWndDesktop->hrgnUpdate = 0;
625 pWndDesktop->hwndLastActive = hwndDesktop;
626 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
628 pWndDesktop->dwExStyle = 0;
629 pWndDesktop->dce = NULL;
630 pWndDesktop->pVScroll = NULL;
631 pWndDesktop->pHScroll = NULL;
632 pWndDesktop->pProp = NULL;
633 pWndDesktop->wIDmenu = 0;
634 pWndDesktop->helpContext = 0;
635 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
636 pWndDesktop->hSysMenu = 0;
637 pWndDesktop->userdata = 0;
638 pWndDesktop->winproc = (WNDPROC16)class->winproc;
639 pWndDesktop->irefCount = 0;
641 /* FIXME: How do we know if it should be Unicode or not */
642 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
645 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
646 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
651 /***********************************************************************
654 * Implementation of CreateWindowEx().
656 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
657 BOOL win32, BOOL unicode )
663 HWND16 hwnd, hwndLinkAfter;
664 POINT maxSize, maxPos, minTrack, maxTrack;
665 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
667 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
668 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
669 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
670 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
671 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
673 /* Find the parent window */
677 /* Make sure parent is valid */
678 if (!IsWindow( cs->hwndParent ))
680 WARN("Bad parent %04x\n", cs->hwndParent );
683 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
684 WARN("No parent for child window\n" );
685 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
688 /* Find the window class */
689 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
692 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
693 WARN("Bad class '%s'\n", buffer );
697 /* Fix the coordinates */
699 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
701 PDB *pdb = PROCESS_Current();
703 /* Never believe Microsoft's documentation... CreateWindowEx doc says
704 * that if an overlapped window is created with WS_VISIBLE style bit
705 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
706 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
709 * 1) not only if checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
710 * 2) it does not ignore the y parameter as the docs claim; instead, it
711 * uses it as second parameter to ShowWindow() unless y is either
712 * CW_USEDEFAULT or CW_USEDEFAULT16.
714 * The fact that we didn't do 2) caused bogus windows pop up when wine
715 * was running apps that were using this obscure feature. Example -
716 * calc.exe that comes with Win98 (only Win98, it's different from
717 * the one that comes with Win95 and NT)
719 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) sw = cs->y;
721 /* We have saved cs->y, now we can trash it */
722 if ( !(cs->style & (WS_CHILD | WS_POPUP))
723 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
725 cs->x = pdb->env_db->startup_info->dwX;
726 cs->y = pdb->env_db->startup_info->dwY;
734 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
736 PDB *pdb = PROCESS_Current();
737 if ( !(cs->style & (WS_CHILD | WS_POPUP))
738 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
740 cs->cx = pdb->env_db->startup_info->dwXSize;
741 cs->cy = pdb->env_db->startup_info->dwYSize;
745 cs->cx = 600; /* FIXME */
750 /* Create the window structure */
752 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
753 - sizeof(wndPtr->wExtra) )))
755 TRACE("out of memory\n" );
759 /* Fill the window structure */
761 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
763 wndPtr->child = NULL;
765 if ((cs->style & WS_CHILD) && cs->hwndParent)
767 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
768 wndPtr->owner = NULL;
769 WIN_ReleaseWndPtr(wndPtr->parent);
773 wndPtr->parent = pWndDesktop;
774 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
775 wndPtr->owner = NULL;
778 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
779 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
780 WIN_ReleaseWndPtr(wndPtr->owner);
781 WIN_ReleaseWndPtr(tmpWnd);
786 wndPtr->pDriver = wndPtr->parent->pDriver;
787 wndPtr->pDriver->pInitialize(wndPtr);
789 wndPtr->class = classPtr;
790 wndPtr->winproc = classPtr->winproc;
791 wndPtr->dwMagic = WND_MAGIC;
792 wndPtr->hwndSelf = hwnd;
793 wndPtr->hInstance = cs->hInstance;
795 wndPtr->hmemTaskQ = GetFastQueue16();
796 wndPtr->hrgnUpdate = 0;
797 wndPtr->hwndLastActive = hwnd;
798 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
799 wndPtr->dwExStyle = cs->dwExStyle;
801 wndPtr->helpContext = 0;
802 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
803 wndPtr->pVScroll = NULL;
804 wndPtr->pHScroll = NULL;
805 wndPtr->pProp = NULL;
806 wndPtr->userdata = 0;
807 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
808 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
809 wndPtr->irefCount = 1;
811 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
813 /* Call the WH_CBT hook */
815 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
816 ? HWND_BOTTOM : HWND_TOP;
818 if (HOOK_IsHooked( WH_CBT ))
824 cbtc.hwndInsertAfter = hwndLinkAfter;
825 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
826 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
829 TRACE("CBT-hook returned 0\n");
830 wndPtr->pDriver->pFinalize(wndPtr);
831 USER_HEAP_FREE( hwnd );
837 /* Increment class window counter */
839 classPtr->cWindows++;
841 /* Correct the window style */
843 if (!(cs->style & WS_CHILD))
845 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
846 if (!(cs->style & WS_POPUP))
848 wndPtr->dwStyle |= WS_CAPTION;
849 wndPtr->flags |= WIN_NEED_SIZE;
853 /* Get class or window DC if needed */
855 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
856 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
857 else wndPtr->dce = NULL;
859 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
861 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
863 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
864 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
865 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
866 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
867 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
870 if(cs->style & WS_CHILD)
872 if(cs->cx < 0) cs->cx = 0;
873 if(cs->cy < 0) cs->cy = 0;
877 if (cs->cx <= 0) cs->cx = 1;
878 if (cs->cy <= 0) cs->cy = 1;
881 wndPtr->rectWindow.left = cs->x;
882 wndPtr->rectWindow.top = cs->y;
883 wndPtr->rectWindow.right = cs->x + cs->cx;
884 wndPtr->rectWindow.bottom = cs->y + cs->cy;
885 wndPtr->rectClient = wndPtr->rectWindow;
887 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
893 /* Set the window menu */
895 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
897 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
900 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
901 if (classPtr->menuNameA)
902 cs->hMenu = HIWORD(classPtr->menuNameA) ?
903 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
904 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
906 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
909 if (HIWORD(cs->hInstance))
910 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
912 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
914 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
919 else wndPtr->wIDmenu = (UINT)cs->hMenu;
921 /* Send the WM_CREATE message
922 * Perhaps we shouldn't allow width/height changes as well.
923 * See p327 in "Internals".
926 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
928 localSend32 = unicode ? SendMessageW : SendMessageA;
929 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
931 /* Insert the window in the linked list */
933 WIN_LinkWindow( hwnd, hwndLinkAfter );
935 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
936 NULL, NULL, 0, &wndPtr->rectClient );
937 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
938 maxPos.y - wndPtr->rectWindow.top);
939 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
941 /* Send the size messages */
943 if (!(wndPtr->flags & WIN_NEED_SIZE))
946 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
947 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
948 WARN("sending bogus WM_SIZE message 0x%08lx\n",
949 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
950 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
951 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
952 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
953 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
954 SendMessageA( hwnd, WM_MOVE, 0,
955 MAKELONG( wndPtr->rectClient.left,
956 wndPtr->rectClient.top ) );
959 /* Show the window, maximizing or minimizing if needed */
961 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
964 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
965 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
966 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
967 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
968 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
969 : SWP_NOZORDER | SWP_FRAMECHANGED;
970 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
971 newPos.right, newPos.bottom, swFlag );
974 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
976 /* Notify the parent window only */
978 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
979 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
980 if( !IsWindow(hwnd) )
987 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
989 /* Call WH_SHELL hook */
991 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
992 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
994 TRACE("created window %04x\n", hwnd);
998 WIN_UnlinkWindow( hwnd );
1001 /* Abort window creation */
1003 WARN("aborted by WM_xxCREATE!\n");
1004 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1007 WIN_ReleaseWndPtr(wndPtr);
1013 /***********************************************************************
1014 * CreateWindow16 (USER.41)
1016 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1017 DWORD style, INT16 x, INT16 y, INT16 width,
1018 INT16 height, HWND16 parent, HMENU16 menu,
1019 HINSTANCE16 instance, LPVOID data )
1021 return CreateWindowEx16( 0, className, windowName, style,
1022 x, y, width, height, parent, menu, instance, data );
1026 /***********************************************************************
1027 * CreateWindowEx16 (USER.452)
1029 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1030 LPCSTR windowName, DWORD style, INT16 x,
1031 INT16 y, INT16 width, INT16 height,
1032 HWND16 parent, HMENU16 menu,
1033 HINSTANCE16 instance, LPVOID data )
1039 /* Find the class atom */
1041 if (!(classAtom = GlobalFindAtomA( className )))
1043 fprintf( stderr, "CreateWindowEx16: bad class name " );
1044 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1045 else fprintf( stderr, "'%s'\n", className );
1049 /* Fix the coordinates */
1051 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1052 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1053 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1054 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1056 /* Create the window */
1058 cs.lpCreateParams = data;
1059 cs.hInstance = (HINSTANCE)instance;
1060 cs.hMenu = (HMENU)menu;
1061 cs.hwndParent = (HWND)parent;
1063 cs.lpszName = windowName;
1064 cs.lpszClass = className;
1065 cs.dwExStyle = exStyle;
1067 /* make sure lpszClass is a string */
1068 if (!HIWORD(cs.lpszClass))
1070 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
1071 cs.lpszClass = buffer;
1073 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1077 /***********************************************************************
1078 * CreateWindowEx32A (USER32.83)
1080 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1081 LPCSTR windowName, DWORD style, INT x,
1082 INT y, INT width, INT height,
1083 HWND parent, HMENU menu,
1084 HINSTANCE instance, LPVOID data )
1091 instance=GetModuleHandleA(NULL);
1093 if(exStyle & WS_EX_MDICHILD)
1094 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1095 /* Find the class atom */
1097 if (!(classAtom = GlobalFindAtomA( className )))
1099 fprintf( stderr, "CreateWindowEx32A: bad class name " );
1100 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1101 else fprintf( stderr, "'%s'\n", className );
1105 /* Create the window */
1107 cs.lpCreateParams = data;
1108 cs.hInstance = instance;
1110 cs.hwndParent = parent;
1116 cs.lpszName = windowName;
1117 cs.lpszClass = className;
1118 cs.dwExStyle = exStyle;
1120 /* make sure lpszClass is a string */
1121 if (!HIWORD(cs.lpszClass))
1123 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
1124 cs.lpszClass = buffer;
1126 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1130 /***********************************************************************
1131 * CreateWindowEx32W (USER32.84)
1133 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1134 LPCWSTR windowName, DWORD style, INT x,
1135 INT y, INT width, INT height,
1136 HWND parent, HMENU menu,
1137 HINSTANCE instance, LPVOID data )
1144 instance=GetModuleHandleA(NULL);
1146 if(exStyle & WS_EX_MDICHILD)
1147 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1149 /* Find the class atom */
1151 if (!(classAtom = GlobalFindAtomW( className )))
1153 if (HIWORD(className))
1155 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
1156 WARN("Bad class name '%s'\n",cn);
1157 HeapFree( GetProcessHeap(), 0, cn );
1160 WARN("Bad class name %p\n", className );
1164 /* Create the window */
1166 cs.lpCreateParams = data;
1167 cs.hInstance = instance;
1169 cs.hwndParent = parent;
1175 cs.lpszName = windowName;
1176 cs.lpszClass = className;
1177 cs.dwExStyle = exStyle;
1179 /* make sure lpszClass is a string */
1180 if (!HIWORD(cs.lpszClass))
1182 GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) );
1183 cs.lpszClass = buffer;
1186 /* Note: we rely on the fact that CREATESTRUCT32A and */
1187 /* CREATESTRUCT32W have the same layout. */
1188 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1192 /***********************************************************************
1195 static void WIN_CheckFocus( WND* pWnd )
1197 if( GetFocus16() == pWnd->hwndSelf )
1198 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1201 /***********************************************************************
1202 * WIN_SendDestroyMsg
1204 static void WIN_SendDestroyMsg( WND* pWnd )
1206 WIN_CheckFocus(pWnd);
1208 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1209 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1212 * Send the WM_DESTROY to the window.
1214 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1217 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1218 * make sure that the window still exists when we come back.
1220 if (IsWindow(pWnd->hwndSelf))
1222 HWND* pWndArray = NULL;
1227 * Now, if the window has kids, we have to send WM_DESTROY messages
1228 * recursively to it's kids. It seems that those calls can also
1229 * trigger re-entrant calls to DestroyWindow for the kids so we must
1230 * protect against corruption of the list of siblings. We first build
1231 * a list of HWNDs representing all the kids.
1233 pChild = WIN_LockWndPtr(pWnd->child);
1237 WIN_UpdateWndPtr(&pChild,pChild->next);
1241 * If there are no kids, we're done.
1246 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1251 if (pWndArray==NULL)
1255 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1256 * call, our linked list of siblings should be safe.
1259 pChild = WIN_LockWndPtr(pWnd->child);
1262 pWndArray[nKidCount] = pChild->hwndSelf;
1264 WIN_UpdateWndPtr(&pChild,pChild->next);
1268 * Now that we have a list, go through that list again and send the destroy
1269 * message to those windows. We are using the HWND to retrieve the
1270 * WND pointer so we are effectively checking that all the kid windows are
1271 * still valid before sending the message.
1275 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1279 WIN_SendDestroyMsg( pChild );
1280 WIN_ReleaseWndPtr(pChild);
1287 HeapFree(GetProcessHeap(), 0, pWndArray);
1288 WIN_CheckFocus(pWnd);
1291 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1295 /***********************************************************************
1296 * DestroyWindow16 (USER.53)
1298 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1300 return DestroyWindow(hwnd);
1304 /***********************************************************************
1305 * DestroyWindow32 (USER32.135)
1307 BOOL WINAPI DestroyWindow( HWND hwnd )
1312 TRACE("(%04x)\n", hwnd);
1314 /* Initialization */
1316 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1317 if (wndPtr == pWndDesktop)
1319 WIN_ReleaseWndPtr(wndPtr);
1320 return FALSE; /* Can't destroy desktop */
1325 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1331 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1333 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1334 /* FIXME: clean up palette - see "Internals" p.352 */
1337 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1338 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1340 /* Notify the parent window only */
1341 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1342 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1343 if( !IsWindow(hwnd) )
1350 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1352 /* Hide the window */
1354 if (wndPtr->dwStyle & WS_VISIBLE)
1356 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1357 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1358 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1359 if (!IsWindow(hwnd))
1366 /* Recursively destroy owned windows */
1368 if( !(wndPtr->dwStyle & WS_CHILD) )
1370 /* make sure top menu popup doesn't get destroyed */
1371 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1375 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1378 if (siblingPtr->owner == wndPtr)
1380 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1383 siblingPtr->owner = NULL;
1385 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1389 DestroyWindow( siblingPtr->hwndSelf );
1390 WIN_ReleaseWndPtr(siblingPtr);
1395 if( !Options.managed || EVENT_CheckFocus() )
1396 WINPOS_ActivateOtherWindow(wndPtr);
1398 if( wndPtr->owner &&
1399 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1400 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1403 /* Send destroy messages */
1405 WIN_SendDestroyMsg( wndPtr );
1406 if (!IsWindow(hwnd))
1412 /* Unlink now so we won't bother with the children later on */
1414 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1416 /* Destroy the window storage */
1418 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1421 WIN_ReleaseWndPtr(wndPtr);
1426 /***********************************************************************
1427 * CloseWindow16 (USER.43)
1429 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1431 return CloseWindow( hwnd );
1435 /***********************************************************************
1436 * CloseWindow32 (USER32.56)
1438 BOOL WINAPI CloseWindow( HWND hwnd )
1440 WND * wndPtr = WIN_FindWndPtr( hwnd );
1443 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1448 ShowWindow( hwnd, SW_MINIMIZE );
1451 WIN_ReleaseWndPtr(wndPtr);
1457 /***********************************************************************
1458 * OpenIcon16 (USER.44)
1460 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1462 return OpenIcon( hwnd );
1466 /***********************************************************************
1467 * OpenIcon32 (USER32.410)
1469 BOOL WINAPI OpenIcon( HWND hwnd )
1471 if (!IsIconic( hwnd )) return FALSE;
1472 ShowWindow( hwnd, SW_SHOWNORMAL );
1477 /***********************************************************************
1480 * Implementation of FindWindow() and FindWindowEx().
1482 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1487 CLASS *pClass = NULL;
1491 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1494 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1500 else if (pWnd->parent != pWndDesktop)
1505 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1509 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1514 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1522 /* For a child window, all siblings will have the same hInstance, */
1523 /* so we can look for the class once and for all. */
1525 if (className && (pWnd->dwStyle & WS_CHILD))
1527 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1535 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1537 if (className && !(pWnd->dwStyle & WS_CHILD))
1539 if (!((pClass = CLASS_FindClassByAtom( className, pWnd->hInstance))
1540 ||(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1542 continue; /* Skip this window */
1545 if (pClass && (pWnd->class != pClass))
1546 continue; /* Not the right class */
1548 /* Now check the title */
1552 retvalue = pWnd->hwndSelf;
1555 if (pWnd->text && !strcmp( pWnd->text, title ))
1557 retvalue = pWnd->hwndSelf;
1563 WIN_ReleaseWndPtr(pWnd);
1569 /***********************************************************************
1570 * FindWindow16 (USER.50)
1572 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1574 return FindWindowEx16( 0, 0, className, title );
1578 /***********************************************************************
1579 * FindWindowEx16 (USER.427)
1581 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1582 SEGPTR className, LPCSTR title )
1586 TRACE("%04x %04x '%s' '%s'\n", parent,
1587 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1588 title ? title : "");
1592 /* If the atom doesn't exist, then no class */
1593 /* with this name exists either. */
1594 if (!(atom = GlobalFindAtom16( className ))) return 0;
1596 return WIN_FindWindow( parent, child, atom, title );
1600 /***********************************************************************
1601 * FindWindow32A (USER32.198)
1603 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1605 HWND ret = FindWindowExA( 0, 0, className, title );
1606 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1611 /***********************************************************************
1612 * FindWindowEx32A (USER32.199)
1614 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1615 LPCSTR className, LPCSTR title )
1621 /* If the atom doesn't exist, then no class */
1622 /* with this name exists either. */
1623 if (!(atom = GlobalFindAtomA( className )))
1625 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1629 return WIN_FindWindow( parent, child, atom, title );
1633 /***********************************************************************
1634 * FindWindowEx32W (USER32.200)
1636 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1637 LPCWSTR className, LPCWSTR title )
1645 /* If the atom doesn't exist, then no class */
1646 /* with this name exists either. */
1647 if (!(atom = GlobalFindAtomW( className )))
1649 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1653 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1654 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1655 HeapFree( GetProcessHeap(), 0, buffer );
1660 /***********************************************************************
1661 * FindWindow32W (USER32.201)
1663 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1665 return FindWindowExW( 0, 0, className, title );
1669 /**********************************************************************
1671 * returns a locked pointer
1673 WND *WIN_GetDesktop(void)
1675 return WIN_LockWndPtr(pWndDesktop);
1677 /**********************************************************************
1678 * WIN_ReleaseDesktop
1679 * unlock the desktop pointer
1681 void WIN_ReleaseDesktop(void)
1683 WIN_ReleaseWndPtr(pWndDesktop);
1687 /**********************************************************************
1688 * GetDesktopWindow16 (USER.286)
1690 HWND16 WINAPI GetDesktopWindow16(void)
1692 return (HWND16)pWndDesktop->hwndSelf;
1696 /**********************************************************************
1697 * GetDesktopWindow32 (USER32.232)
1699 HWND WINAPI GetDesktopWindow(void)
1701 if (pWndDesktop) return pWndDesktop->hwndSelf;
1702 ERR( "You need the -desktop option when running with native USER\n" );
1708 /**********************************************************************
1709 * GetDesktopHwnd (USER.278)
1711 * Exactly the same thing as GetDesktopWindow(), but not documented.
1712 * Don't ask me why...
1714 HWND16 WINAPI GetDesktopHwnd16(void)
1716 return (HWND16)pWndDesktop->hwndSelf;
1720 /*******************************************************************
1721 * EnableWindow16 (USER.34)
1723 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1725 return EnableWindow( hwnd, enable );
1729 /*******************************************************************
1730 * EnableWindow32 (USER32.172)
1732 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1737 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1739 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1740 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1743 wndPtr->dwStyle &= ~WS_DISABLED;
1745 if( wndPtr->flags & WIN_NATIVE )
1746 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1748 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1752 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1754 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1756 /* Disable window */
1757 wndPtr->dwStyle |= WS_DISABLED;
1759 if( wndPtr->flags & WIN_NATIVE )
1760 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1762 if (hwnd == GetFocus())
1764 SetFocus( 0 ); /* A disabled window can't have the focus */
1766 if (hwnd == GetCapture())
1768 ReleaseCapture(); /* A disabled window can't capture the mouse */
1770 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1774 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1776 WIN_ReleaseWndPtr(wndPtr);
1781 /***********************************************************************
1782 * IsWindowEnabled16 (USER.35)
1784 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1786 return IsWindowEnabled(hWnd);
1790 /***********************************************************************
1791 * IsWindowEnabled32 (USER32.349)
1793 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1798 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1799 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1800 WIN_ReleaseWndPtr(wndPtr);
1806 /***********************************************************************
1807 * IsWindowUnicode (USER32.350)
1809 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1814 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1815 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1816 WIN_ReleaseWndPtr(wndPtr);
1821 /**********************************************************************
1822 * GetWindowWord16 (USER.133)
1824 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1826 return GetWindowWord( hwnd, offset );
1830 /**********************************************************************
1831 * GetWindowWord32 (USER32.314)
1833 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1836 WND * wndPtr = WIN_FindWndPtr( hwnd );
1837 if (!wndPtr) return 0;
1840 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1842 WARN("Invalid offset %d\n", offset );
1846 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1852 if (HIWORD(wndPtr->wIDmenu))
1853 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1855 retvalue = (WORD)wndPtr->wIDmenu;
1857 case GWW_HWNDPARENT:
1858 retvalue = GetParent(hwnd);
1861 if (HIWORD(wndPtr->hInstance))
1862 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1864 retvalue = (WORD)wndPtr->hInstance;
1867 WARN("Invalid offset %d\n", offset );
1872 WIN_ReleaseWndPtr(wndPtr);
1876 /**********************************************************************
1877 * SetWindowWord16 (USER.134)
1879 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1881 return SetWindowWord( hwnd, offset, newval );
1885 /**********************************************************************
1886 * SetWindowWord32 (USER32.524)
1888 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1891 WND * wndPtr = WIN_FindWndPtr( hwnd );
1892 if (!wndPtr) return 0;
1895 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1897 WARN("Invalid offset %d\n", offset );
1901 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1905 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1906 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1907 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1910 WARN("Invalid offset %d\n", offset );
1917 WIN_ReleaseWndPtr(wndPtr);
1922 /**********************************************************************
1925 * Helper function for GetWindowLong().
1927 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1930 WND * wndPtr = WIN_FindWndPtr( hwnd );
1931 if (!wndPtr) return 0;
1934 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1936 WARN("Invalid offset %d\n", offset );
1940 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1941 /* Special case for dialog window procedure */
1942 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1944 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1951 case GWL_USERDATA: retvalue = wndPtr->userdata;
1953 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1955 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1957 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1959 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1962 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1964 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1967 WARN("Unknown offset %d\n", offset );
1971 WIN_ReleaseWndPtr(wndPtr);
1976 /**********************************************************************
1979 * Helper function for SetWindowLong().
1981 * 0 is the failure code. However, in the case of failure SetLastError
1982 * must be set to distinguish between a 0 return value and a failure.
1984 * FIXME: The error values for SetLastError may not be right. Can
1985 * someone check with the real thing?
1987 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1988 WINDOWPROCTYPE type )
1991 WND * wndPtr = WIN_FindWndPtr( hwnd );
1994 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1998 /* Is this the right error? */
1999 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2005 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
2007 WARN("Invalid offset %d\n", offset );
2009 /* Is this the right error? */
2010 SetLastError( ERROR_OUTOFMEMORY );
2015 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2016 /* Special case for dialog window procedure */
2017 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2019 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2020 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2021 type, WIN_PROC_WINDOW );
2028 ptr = (DWORD*)&wndPtr->wIDmenu;
2031 retval = SetWindowWord( hwnd, offset, newval );
2034 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2035 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2036 type, WIN_PROC_WINDOW );
2039 style.styleOld = wndPtr->dwStyle;
2040 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2041 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2043 if (wndPtr->flags & WIN_ISWIN32)
2044 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2045 wndPtr->dwStyle = style.styleNew;
2046 if (wndPtr->flags & WIN_ISWIN32)
2047 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2048 retval = style.styleOld;
2052 ptr = &wndPtr->userdata;
2055 style.styleOld = wndPtr->dwExStyle;
2056 style.styleNew = newval;
2057 if (wndPtr->flags & WIN_ISWIN32)
2058 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2059 wndPtr->dwExStyle = newval;
2060 if (wndPtr->flags & WIN_ISWIN32)
2061 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2062 retval = style.styleOld;
2066 WARN("Invalid offset %d\n", offset );
2068 /* Don't think this is right error but it should do */
2069 SetLastError( ERROR_OUTOFMEMORY );
2077 WIN_ReleaseWndPtr(wndPtr);
2082 /**********************************************************************
2083 * GetWindowLong16 (USER.135)
2085 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2087 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2091 /**********************************************************************
2092 * GetWindowLong32A (USER32.305)
2094 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2096 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2100 /**********************************************************************
2101 * GetWindowLong32W (USER32.306)
2103 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2105 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2109 /**********************************************************************
2110 * SetWindowLong16 (USER.136)
2112 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2114 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2118 /**********************************************************************
2119 * SetWindowLong32A (USER32.517)
2121 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2123 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2127 /**********************************************************************
2128 * SetWindowLong32W (USER32.518) Set window attribute
2130 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2131 * value in a window's extra memory.
2133 * The _hwnd_ parameter specifies the window. is the handle to a
2134 * window that has extra memory. The _newval_ parameter contains the
2135 * new attribute or extra memory value. If positive, the _offset_
2136 * parameter is the byte-addressed location in the window's extra
2137 * memory to set. If negative, _offset_ specifies the window
2138 * attribute to set, and should be one of the following values:
2140 * GWL_EXSTYLE The window's extended window style
2142 * GWL_STYLE The window's window style.
2144 * GWL_WNDPROC Pointer to the window's window procedure.
2146 * GWL_HINSTANCE The window's pplication instance handle.
2148 * GWL_ID The window's identifier.
2150 * GWL_USERDATA The window's user-specified data.
2152 * If the window is a dialog box, the _offset_ parameter can be one of
2153 * the following values:
2155 * DWL_DLGPROC The address of the window's dialog box procedure.
2157 * DWL_MSGRESULT The return value of a message
2158 * that the dialog box procedure processed.
2160 * DWL_USER Application specific information.
2164 * If successful, returns the previous value located at _offset_. Otherwise,
2169 * Extra memory for a window class is specified by a nonzero cbWndExtra
2170 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2171 * time of class creation.
2173 * Using GWL_WNDPROC to set a new window procedure effectively creates
2174 * a window subclass. Use CallWindowProc() in the new windows procedure
2175 * to pass messages to the superclass's window procedure.
2177 * The user data is reserved for use by the application which created
2180 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2181 * instead, call the EnableWindow() function to change the window's
2184 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2185 * SetParent() instead.
2188 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2189 * it sends WM_STYLECHANGING before changing the settings
2190 * and WM_STYLECHANGED afterwards.
2191 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2195 * GWL_STYLE does not dispatch WM_STYLE... messages.
2202 LONG WINAPI SetWindowLongW(
2203 HWND hwnd, /* window to alter */
2204 INT offset, /* offset, in bytes, of location to alter */
2205 LONG newval /* new value of location */
2207 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2211 /*******************************************************************
2212 * GetWindowText16 (USER.36)
2214 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2216 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2220 /*******************************************************************
2221 * GetWindowText32A (USER32.309)
2223 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2225 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2229 /*******************************************************************
2230 * InternalGetWindowText (USER32.326)
2232 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2234 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2235 return GetWindowTextW(hwnd,lpString,nMaxCount);
2239 /*******************************************************************
2240 * GetWindowText32W (USER32.312)
2242 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2244 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2249 /*******************************************************************
2250 * SetWindowText16 (USER.37)
2252 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2254 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2258 /*******************************************************************
2259 * SetWindowText32A (USER32.521)
2261 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2263 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2267 /*******************************************************************
2268 * SetWindowText32W (USER32.523)
2270 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2272 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2276 /*******************************************************************
2277 * GetWindowTextLength16 (USER.38)
2279 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2281 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2285 /*******************************************************************
2286 * GetWindowTextLength32A (USER32.310)
2288 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2290 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2293 /*******************************************************************
2294 * GetWindowTextLength32W (USER32.311)
2296 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2298 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2302 /*******************************************************************
2303 * IsWindow16 (USER.47)
2305 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2307 CURRENT_STACK16->es = USER_HeapSel;
2308 return IsWindow( hwnd );
2312 /*******************************************************************
2313 * IsWindow32 (USER32.348)
2315 BOOL WINAPI IsWindow( HWND hwnd )
2320 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2321 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2322 WIN_ReleaseWndPtr(wndPtr);
2328 /*****************************************************************
2329 * GetParent16 (USER.46)
2331 HWND16 WINAPI GetParent16( HWND16 hwnd )
2333 return (HWND16)GetParent( hwnd );
2337 /*****************************************************************
2338 * GetParent32 (USER32.278)
2340 HWND WINAPI GetParent( HWND hwnd )
2345 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2346 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2348 WIN_ReleaseWndPtr(wndPtr);
2351 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2352 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2354 WIN_ReleaseWndPtr(wndPtr);
2359 /*****************************************************************
2362 * Get the top-level parent for a child window.
2363 * returns a locked pointer
2365 WND* WIN_GetTopParentPtr( WND* pWnd )
2367 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2369 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2371 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2376 /*****************************************************************
2379 * Get the top-level parent for a child window.
2381 HWND WIN_GetTopParent( HWND hwnd )
2384 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2385 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2387 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2388 WIN_ReleaseWndPtr(tmpPtr);
2389 WIN_ReleaseWndPtr(wndPtr);
2394 /*****************************************************************
2395 * SetParent16 (USER.233)
2397 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2399 return SetParent( hwndChild, hwndNewParent );
2403 /*****************************************************************
2404 * SetParent32 (USER32.495)
2406 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2415 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2417 dwStyle = wndPtr->dwStyle;
2419 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2420 : WIN_LockWndPtr(pWndDesktop);
2422 /* Windows hides the window first, then shows it again
2423 * including the WM_SHOWWINDOW messages and all */
2424 if (dwStyle & WS_VISIBLE)
2425 ShowWindow( hwndChild, SW_HIDE );
2427 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2429 /* SetParent32 additionally needs to make hwndChild the topmost window
2430 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2431 WM_WINDOWPOSCHANGED notification messages.
2433 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2434 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2435 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2436 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2438 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2440 WIN_ReleaseWndPtr(pWndOldParent);
2441 WIN_ReleaseWndPtr(pWndNewParent);
2442 WIN_ReleaseWndPtr(wndPtr);
2448 /*******************************************************************
2449 * IsChild16 (USER.48)
2451 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2453 return IsChild(parent,child);
2457 /*******************************************************************
2458 * IsChild32 (USER32.339)
2460 BOOL WINAPI IsChild( HWND parent, HWND child )
2462 WND * wndPtr = WIN_FindWndPtr( child );
2463 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2465 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2466 if (wndPtr->hwndSelf == parent)
2468 WIN_ReleaseWndPtr(wndPtr);
2472 WIN_ReleaseWndPtr(wndPtr);
2477 /***********************************************************************
2478 * IsWindowVisible16 (USER.49)
2480 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2482 return IsWindowVisible(hwnd);
2486 /***********************************************************************
2487 * IsWindowVisible32 (USER32.351)
2489 BOOL WINAPI IsWindowVisible( HWND hwnd )
2492 WND *wndPtr = WIN_FindWndPtr( hwnd );
2493 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2495 if (!(wndPtr->dwStyle & WS_VISIBLE))
2497 WIN_ReleaseWndPtr(wndPtr);
2500 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2502 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2503 WIN_ReleaseWndPtr(wndPtr);
2509 /***********************************************************************
2510 * WIN_IsWindowDrawable
2512 * hwnd is drawable when it is visible, all parents are not
2513 * minimized, and it is itself not minimized unless we are
2514 * trying to draw its default class icon.
2516 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2518 if( (wnd->dwStyle & WS_MINIMIZE &&
2519 icon && wnd->class->hIcon) ||
2520 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2521 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2522 if( wnd->dwStyle & WS_MINIMIZE ||
2523 !(wnd->dwStyle & WS_VISIBLE) ) break;
2524 return (wnd == NULL);
2528 /*******************************************************************
2529 * GetTopWindow16 (USER.229)
2531 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2533 return GetTopWindow(hwnd);
2537 /*******************************************************************
2538 * GetTopWindow32 (USER.229)
2540 HWND WINAPI GetTopWindow( HWND hwnd )
2543 WND * wndPtr = NULL;
2546 wndPtr = WIN_FindWndPtr( hwnd );
2548 wndPtr = WIN_GetDesktop();
2550 if (wndPtr && wndPtr->child)
2552 retval = wndPtr->child->hwndSelf;
2555 WIN_ReleaseWndPtr(wndPtr);
2560 /*******************************************************************
2561 * GetWindow16 (USER.262)
2563 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2565 return GetWindow( hwnd,rel );
2569 /*******************************************************************
2570 * GetWindow32 (USER32.302)
2572 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2576 WND * wndPtr = WIN_FindWndPtr( hwnd );
2577 if (!wndPtr) return 0;
2581 if (wndPtr->parent) retval = wndPtr->parent->child->hwndSelf;
2586 if (!wndPtr->parent)
2588 retval = 0; /* Desktop window */
2591 while (wndPtr->next)
2593 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2595 retval = wndPtr->hwndSelf;
2599 if (!wndPtr->next) retval = 0;
2600 else retval = wndPtr->next->hwndSelf;
2604 if (!wndPtr->parent)
2606 retval = 0; /* Desktop window */
2609 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2610 if (wndPtr->hwndSelf == hwnd)
2612 retval = 0; /* First in list */
2615 while (wndPtr->next)
2617 if (wndPtr->next->hwndSelf == hwnd)
2619 retval = wndPtr->hwndSelf;
2622 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2628 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2632 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2637 WIN_ReleaseWndPtr(wndPtr);
2642 /*******************************************************************
2643 * GetNextWindow16 (USER.230)
2645 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2647 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2648 return GetWindow16( hwnd, flag );
2651 /*******************************************************************
2652 * ShowOwnedPopups16 (USER.265)
2654 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2656 ShowOwnedPopups( owner, fShow );
2660 /*******************************************************************
2661 * ShowOwnedPopups32 (USER32.531)
2663 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2665 UINT totalChild=0, count=0;
2667 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2669 if (!pWnd) return TRUE;
2671 for (; count < totalChild; count++)
2673 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2674 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, fShow ? SW_SHOW : SW_HIDE,IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2677 WIN_ReleaseDesktop();
2678 WIN_ReleaseWinArray(pWnd);
2683 /*******************************************************************
2684 * GetLastActivePopup16 (USER.287)
2686 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2688 return GetLastActivePopup( hwnd );
2691 /*******************************************************************
2692 * GetLastActivePopup32 (USER32.256)
2694 HWND WINAPI GetLastActivePopup( HWND hwnd )
2698 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 HeapFree(SystemHeap). 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( SystemHeap, 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( SystemHeap, 0, wndArray );
2775 /*******************************************************************
2776 * EnumWindows16 (USER.54)
2778 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 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 * EnumWindows32 (USER32.193)
2819 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2821 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2825 /**********************************************************************
2826 * EnumTaskWindows16 (USER.225)
2828 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2831 WND **list, **ppWnd;
2833 /* This function is the same as EnumWindows(), */
2834 /* except for an added check on the window's task. */
2836 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2838 WIN_ReleaseDesktop();
2842 /* Now call the callback function for every window */
2844 for (ppWnd = list; *ppWnd; ppWnd++)
2848 /* Make sure that the window still exists */
2849 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2850 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2852 /* To avoid any deadlocks, all the locks on the windows
2853 structures must be suspended before the control
2854 is passed to the application */
2855 iWndsLocks = WIN_SuspendWndsLock();
2856 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2857 WIN_RestoreWndsLock(iWndsLocks);
2859 if (!funcRetval) break;
2861 WIN_ReleaseWinArray(list);
2862 WIN_ReleaseDesktop();
2867 /**********************************************************************
2868 * EnumThreadWindows (USER32.190)
2870 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2872 TEB *teb = THREAD_IdToTEB(id);
2874 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2878 /**********************************************************************
2879 * WIN_EnumChildWindows
2881 * Helper function for EnumChildWindows().
2883 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2889 for ( ; *ppWnd; ppWnd++)
2893 /* Make sure that the window still exists */
2894 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2895 /* Build children list first */
2896 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2898 /* To avoid any deadlocks, all the locks on the windows
2899 structures must be suspended before the control
2900 is passed to the application */
2901 iWndsLocks = WIN_SuspendWndsLock();
2902 ret = func( (*ppWnd)->hwndSelf, lParam );
2903 WIN_RestoreWndsLock(iWndsLocks);
2907 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2908 WIN_ReleaseWinArray(childList);
2910 if (!ret) return FALSE;
2916 /**********************************************************************
2917 * EnumChildWindows16 (USER.55)
2919 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2922 WND **list, *pParent;
2924 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2925 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2927 WIN_ReleaseWndPtr(pParent);
2930 WIN_EnumChildWindows( list, func, lParam );
2931 WIN_ReleaseWinArray(list);
2932 WIN_ReleaseWndPtr(pParent);
2937 /**********************************************************************
2938 * EnumChildWindows32 (USER32.178)
2940 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2943 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2948 /*******************************************************************
2949 * AnyPopup16 (USER.52)
2951 BOOL16 WINAPI AnyPopup16(void)
2957 /*******************************************************************
2958 * AnyPopup32 (USER32.4)
2960 BOOL WINAPI AnyPopup(void)
2962 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2967 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2972 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2976 WIN_ReleaseWndPtr(wndPtr);
2981 /*******************************************************************
2982 * FlashWindow16 (USER.105)
2984 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2986 return FlashWindow( hWnd, bInvert );
2990 /*******************************************************************
2991 * FlashWindow32 (USER32.202)
2993 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2995 WND *wndPtr = WIN_FindWndPtr(hWnd);
2997 TRACE("%04x\n", hWnd);
2999 if (!wndPtr) return FALSE;
3001 if (wndPtr->dwStyle & WS_MINIMIZE)
3003 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3005 HDC hDC = GetDC(hWnd);
3007 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3008 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3010 ReleaseDC( hWnd, hDC );
3011 wndPtr->flags |= WIN_NCACTIVATED;
3015 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3016 RDW_UPDATENOW | RDW_FRAME, 0 );
3017 wndPtr->flags &= ~WIN_NCACTIVATED;
3019 WIN_ReleaseWndPtr(wndPtr);
3025 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3026 else wparam = (hWnd == GetActiveWindow());
3028 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3029 WIN_ReleaseWndPtr(wndPtr);
3035 /*******************************************************************
3036 * SetSysModalWindow16 (USER.188)
3038 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3040 HWND hWndOldModal = hwndSysModal;
3041 hwndSysModal = hWnd;
3042 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3043 return hWndOldModal;
3047 /*******************************************************************
3048 * GetSysModalWindow16 (USER.52)
3050 HWND16 WINAPI GetSysModalWindow16(void)
3052 return hwndSysModal;
3056 /*******************************************************************
3057 * GetWindowContextHelpId (USER32.303)
3059 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3062 WND *wnd = WIN_FindWndPtr( hwnd );
3064 retval = wnd->helpContext;
3065 WIN_ReleaseWndPtr(wnd);
3070 /*******************************************************************
3071 * SetWindowContextHelpId (USER32.515)
3073 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3075 WND *wnd = WIN_FindWndPtr( hwnd );
3076 if (!wnd) return FALSE;
3077 wnd->helpContext = id;
3078 WIN_ReleaseWndPtr(wnd);
3083 /*******************************************************************
3086 * recursively find a child that contains spDragInfo->pt point
3087 * and send WM_QUERYDROPOBJECT
3089 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3091 BOOL16 wParam,bResult = 0;
3093 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3094 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3097 if( !ptrQueryWnd || !ptrDragInfo )
3099 WIN_ReleaseWndPtr(ptrQueryWnd);
3103 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3105 GetWindowRect(hQueryWnd,&tempRect);
3107 if( !PtInRect(&tempRect,pt) ||
3108 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3110 WIN_ReleaseWndPtr(ptrQueryWnd);
3114 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3116 tempRect = ptrQueryWnd->rectClient;
3117 if(ptrQueryWnd->dwStyle & WS_CHILD)
3118 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3119 (LPPOINT)&tempRect, 2 );
3121 if (PtInRect( &tempRect, pt))
3125 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3127 if( ptrWnd->dwStyle & WS_VISIBLE )
3129 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3130 if (PtInRect( &tempRect, pt )) break;
3136 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3137 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3138 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3139 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3140 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3142 WIN_ReleaseWndPtr(ptrWnd);
3147 WIN_ReleaseWndPtr(ptrQueryWnd);
3155 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3157 ptrDragInfo->hScope = hQueryWnd;
3159 bResult = ( bNoSend )
3160 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3161 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3162 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3164 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3166 WIN_ReleaseWndPtr(ptrQueryWnd);
3171 /*******************************************************************
3172 * DragDetect (USER.465)
3174 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3177 CONV_POINT16TO32( &pt, &pt32 );
3178 return DragDetect( hWnd, pt32 );
3181 /*******************************************************************
3182 * DragDetect32 (USER32.151)
3184 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3189 rect.left = pt.x - wDragWidth;
3190 rect.right = pt.x + wDragWidth;
3192 rect.top = pt.y - wDragHeight;
3193 rect.bottom = pt.y + wDragHeight;
3199 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3201 if( msg.message == WM_LBUTTONUP )
3206 if( msg.message == WM_MOUSEMOVE )
3208 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3220 /******************************************************************************
3221 * DragObject16 (USER.464)
3223 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3224 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3227 LPDRAGINFO lpDragInfo;
3229 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3230 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3231 WND *wndPtr = WIN_FindWndPtr(hWnd);
3232 HCURSOR16 hCurrentCursor = 0;
3233 HWND16 hCurrentWnd = 0;
3235 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3236 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3238 if( !lpDragInfo || !spDragInfo )
3240 WIN_ReleaseWndPtr(wndPtr);
3244 hBummer = LoadCursor16(0, IDC_BUMMER16);
3246 if( !hBummer || !wndPtr )
3248 GlobalFree16(hDragInfo);
3249 WIN_ReleaseWndPtr(wndPtr);
3255 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3257 GlobalFree16(hDragInfo);
3258 WIN_ReleaseWndPtr(wndPtr);
3262 if( hDragCursor == hCursor ) hDragCursor = 0;
3263 else hCursor = hDragCursor;
3265 hOldCursor = SetCursor(hDragCursor);
3268 lpDragInfo->hWnd = hWnd;
3269 lpDragInfo->hScope = 0;
3270 lpDragInfo->wFlags = wObj;
3271 lpDragInfo->hList = szList; /* near pointer! */
3272 lpDragInfo->hOfStruct = hOfStruct;
3280 do{ WaitMessage(); }
3281 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3283 *(lpDragInfo+1) = *lpDragInfo;
3285 lpDragInfo->pt = msg.pt;
3287 /* update DRAGINFO struct */
3288 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3290 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3291 hCurrentCursor = hCursor;
3294 hCurrentCursor = hBummer;
3295 lpDragInfo->hScope = 0;
3297 if( hCurrentCursor )
3298 SetCursor(hCurrentCursor);
3300 /* send WM_DRAGLOOP */
3301 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3302 (LPARAM) spDragInfo );
3303 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3304 if( hCurrentWnd != lpDragInfo->hScope )
3307 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3308 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3309 HIWORD(spDragInfo)) );
3310 hCurrentWnd = lpDragInfo->hScope;
3312 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3316 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3318 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3321 ShowCursor( FALSE );
3325 SetCursor( hOldCursor );
3326 if (hDragCursor) DestroyCursor( hDragCursor );
3329 if( hCurrentCursor != hBummer )
3330 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3331 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3334 GlobalFree16(hDragInfo);
3335 WIN_ReleaseWndPtr(wndPtr);
3337 return (DWORD)(msg.lParam);