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"
36 #include "stackframe.h"
37 #include "debugtools.h"
39 DEFAULT_DEBUG_CHANNEL(win)
40 DECLARE_DEBUG_CHANNEL(msg)
42 /**********************************************************************/
44 WND_DRIVER *WND_Driver = NULL;
47 static WND *pWndDesktop = NULL;
49 static HWND hwndSysModal = 0;
51 static WORD wDragWidth = 4;
52 static WORD wDragHeight= 3;
55 static SYSLEVEL WIN_SysLevel;
57 /***********************************************************************
62 /* Initialisation of the critical section for thread safeness */
63 _CreateSysLevel( &WIN_SysLevel, 2 );
66 /***********************************************************************
69 * Locks access to all WND structures for thread safeness
71 void WIN_LockWnds( void )
73 _EnterSysLevel( &WIN_SysLevel );
76 /***********************************************************************
79 * Unlocks access to all WND structures
81 void WIN_UnlockWnds( void )
83 _LeaveSysLevel( &WIN_SysLevel );
86 /***********************************************************************
89 * Suspend the lock on WND structures.
90 * Returns the number of locks suspended
92 int WIN_SuspendWndsLock( void )
94 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
95 int count = isuspendedLocks;
98 _LeaveSysLevel( &WIN_SysLevel );
100 return isuspendedLocks;
103 /***********************************************************************
104 * WIN_RestoreWndsLock
106 * Restore the suspended locks on WND structures
108 void WIN_RestoreWndsLock( int ipreviousLocks )
110 while ( ipreviousLocks-- > 0 )
111 _EnterSysLevel( &WIN_SysLevel );
114 /***********************************************************************
117 * Return a pointer to the WND structure corresponding to a HWND.
119 WND * WIN_FindWndPtr( HWND hwnd )
123 if (!hwnd || HIWORD(hwnd)) goto error2;
124 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
125 /* Lock all WND structures for thread safeness*/
127 /*and increment destruction monitoring*/
130 if (ptr->dwMagic != WND_MAGIC) goto error;
131 if (ptr->hwndSelf != hwnd)
133 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
136 /* returns a locked pointer */
139 /* Unlock all WND structures for thread safeness*/
141 /* and decrement destruction monitoring value */
146 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
150 /***********************************************************************
153 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
155 * Returns the locked initialisation pointer
157 WND *WIN_LockWndPtr(WND *initWndPtr)
159 if(!initWndPtr) return 0;
161 /* Lock all WND structures for thread safeness*/
163 /*and increment destruction monitoring*/
164 initWndPtr->irefCount++;
170 /***********************************************************************
173 * Release the pointer to the WND structure.
175 void WIN_ReleaseWndPtr(WND *wndPtr)
179 /*Decrement destruction monitoring value*/
181 /* Check if it's time to release the memory*/
182 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
185 USER_HEAP_FREE( wndPtr->hwndSelf);
186 wndPtr->hwndSelf = 0;
188 else if(wndPtr->irefCount < 0)
190 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
191 ERR("forgot a Lock on %p somewhere\n",wndPtr);
193 /*unlock all WND structures for thread safeness*/
197 /***********************************************************************
200 * Updates the value of oldPtr to newPtr.
202 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
206 tmpWnd = WIN_LockWndPtr(newPtr);
207 WIN_ReleaseWndPtr(*oldPtr);
212 /***********************************************************************
215 * Dump the content of a window structure to stderr.
217 void WIN_DumpWindow( HWND hwnd )
223 if (!(ptr = WIN_FindWndPtr( hwnd )))
225 WARN("%04x is not a window handle\n", hwnd );
229 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
230 strcpy( className, "#NULL#" );
232 TRACE("Window %04x (%p):\n", hwnd, ptr );
233 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
234 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
235 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
236 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
237 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
238 ptr->next, ptr->child, ptr->parent, ptr->owner,
239 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
240 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
241 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
242 ptr->text ? ptr->text : "",
243 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
244 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
245 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
246 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
248 if (ptr->class->cbWndExtra)
250 DPRINTF( "extra bytes:" );
251 for (i = 0; i < ptr->class->cbWndExtra; i++)
252 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
256 WIN_ReleaseWndPtr(ptr);
260 /***********************************************************************
263 * Walk the windows tree and print each window on stderr.
265 void WIN_WalkWindows( HWND hwnd, int indent )
270 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
274 WARN("Invalid window handle %04x\n", hwnd );
278 if (!indent) /* first time around */
279 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
280 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
285 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
287 GlobalGetAtomNameA(ptr->class->atomName,className,sizeof(className));
289 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
290 (DWORD)ptr, ptr->hmemTaskQ, className,
291 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
292 ptr->text?ptr->text:"<null>");
294 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
295 WIN_UpdateWndPtr(&ptr,ptr->next);
301 /***********************************************************************
304 * Remove a window from the siblings linked list.
306 BOOL WIN_UnlinkWindow( HWND hwnd )
308 WND *wndPtr, **ppWnd;
311 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
312 else if(!wndPtr->parent)
314 WIN_ReleaseWndPtr(wndPtr);
318 ppWnd = &wndPtr->parent->child;
319 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
322 *ppWnd = wndPtr->next;
325 WIN_ReleaseWndPtr(wndPtr);
330 /***********************************************************************
333 * Insert a window into the siblings linked list.
334 * The window is inserted after the specified window, which can also
335 * be specified as HWND_TOP or HWND_BOTTOM.
337 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
339 WND *wndPtr, **ppWnd;
341 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
342 else if(!wndPtr->parent)
344 WIN_ReleaseWndPtr(wndPtr);
347 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
349 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
350 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
351 while (*ppWnd) ppWnd = &(*ppWnd)->next;
353 else /* Normal case */
355 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
358 WIN_ReleaseWndPtr(wndPtr);
361 ppWnd = &afterPtr->next;
362 WIN_ReleaseWndPtr(afterPtr);
364 wndPtr->next = *ppWnd;
366 WIN_ReleaseWndPtr(wndPtr);
371 /***********************************************************************
372 * WIN_FindWinToRepaint
374 * Find a window that needs repaint.
376 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
381 /* Note: the desktop window never gets WM_PAINT messages
382 * The real reason why is because Windows DesktopWndProc
383 * does ValidateRgn inside WM_ERASEBKGND handler.
386 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
388 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
390 if (!(pWnd->dwStyle & WS_VISIBLE))
392 TRACE("skipping window %04x\n",
395 else if ((pWnd->hmemTaskQ == hQueue) &&
396 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
399 else if (pWnd->child )
400 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
402 WIN_ReleaseWndPtr(pWnd);
413 hwndRet = pWnd->hwndSelf;
415 /* look among siblings if we got a transparent window */
416 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
417 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
419 WIN_UpdateWndPtr(&pWnd,pWnd->next);
423 hwndRet = pWnd->hwndSelf;
424 WIN_ReleaseWndPtr(pWnd);
426 TRACE("found %04x\n",hwndRet);
431 /***********************************************************************
434 * Destroy storage associated to a window. "Internals" p.358
435 * returns a locked wndPtr->next
437 static WND* WIN_DestroyWindow( WND* wndPtr )
439 HWND hwnd = wndPtr->hwndSelf;
442 TRACE("%04x\n", wndPtr->hwndSelf );
444 /* free child windows */
445 WIN_LockWndPtr(wndPtr->child);
446 while ((pWnd = wndPtr->child))
448 wndPtr->child = WIN_DestroyWindow( pWnd );
449 WIN_ReleaseWndPtr(pWnd);
453 * Clear the update region to make sure no WM_PAINT messages will be
454 * generated for this window while processing the WM_NCDESTROY.
456 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
458 if (wndPtr->hrgnUpdate > 1)
459 DeleteObject( wndPtr->hrgnUpdate );
461 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
463 wndPtr->hrgnUpdate = 0;
467 * Send the WM_NCDESTROY to the window being destroyed.
469 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
471 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
473 WINPOS_CheckInternalPos( wndPtr );
474 if( hwnd == GetCapture()) ReleaseCapture();
476 /* free resources associated with the window */
478 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
479 PROPERTY_RemoveWindowProps( wndPtr );
481 wndPtr->dwMagic = 0; /* Mark it as invalid */
483 /* toss stale messages from the queue */
485 if( wndPtr->hmemTaskQ )
487 BOOL bPostQuit = FALSE;
488 WPARAM wQuitParam = 0;
489 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
492 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
494 if( qmsg->msg.message == WM_QUIT )
497 wQuitParam = qmsg->msg.wParam;
499 QUEUE_RemoveMsg(msgQ, qmsg);
504 /* repost WM_QUIT to make sure this app exits its message loop */
505 if( bPostQuit ) PostQuitMessage(wQuitParam);
506 wndPtr->hmemTaskQ = 0;
509 if (!(wndPtr->dwStyle & WS_CHILD))
510 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
511 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
512 wndPtr->pDriver->pDestroyWindow( wndPtr );
513 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
514 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
515 wndPtr->class->cWindows--;
516 wndPtr->class = NULL;
518 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
520 wndPtr->pDriver->pFinalize(wndPtr);
525 /***********************************************************************
526 * WIN_ResetQueueWindows
528 * Reset the queue of all the children of a given window.
529 * Return TRUE if something was done.
531 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
535 if (hNew) /* Set a new queue */
537 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
539 if (wnd->hmemTaskQ == hQueue)
541 wnd->hmemTaskQ = hNew;
546 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
550 else /* Queue is being destroyed */
554 WND *tmp = WIN_LockWndPtr(wnd->child);
559 if (tmp->hmemTaskQ == hQueue)
561 DestroyWindow( tmp->hwndSelf );
565 tmp2 = WIN_LockWndPtr(tmp->child);
566 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
570 WIN_UpdateWndPtr(&tmp,tmp->next);
572 WIN_ReleaseWndPtr(tmp2);
574 WIN_ReleaseWndPtr(tmp);
581 /***********************************************************************
582 * WIN_CreateDesktopWindow
584 * Create the desktop window.
586 BOOL WIN_CreateDesktopWindow(void)
592 TRACE("Creating desktop window\n");
595 if (!ICONTITLE_Init() ||
596 !WINPOS_CreateInternalPosAtom() ||
597 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
600 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
601 if (!hwndDesktop) return FALSE;
602 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
604 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
605 pDesktop->pDriver = DESKTOP_Driver;
606 pWndDesktop->pDriver = WND_Driver;
608 pDesktop->pDriver->pInitialize(pDesktop);
609 pWndDesktop->pDriver->pInitialize(pWndDesktop);
611 pWndDesktop->next = NULL;
612 pWndDesktop->child = NULL;
613 pWndDesktop->parent = NULL;
614 pWndDesktop->owner = NULL;
615 pWndDesktop->class = class;
616 pWndDesktop->dwMagic = WND_MAGIC;
617 pWndDesktop->hwndSelf = hwndDesktop;
618 pWndDesktop->hInstance = 0;
619 pWndDesktop->rectWindow.left = 0;
620 pWndDesktop->rectWindow.top = 0;
621 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
622 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
623 pWndDesktop->rectClient = pWndDesktop->rectWindow;
624 pWndDesktop->text = NULL;
625 pWndDesktop->hmemTaskQ = GetFastQueue16();
626 pWndDesktop->hrgnUpdate = 0;
627 pWndDesktop->hwndLastActive = hwndDesktop;
628 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
630 pWndDesktop->dwExStyle = 0;
631 pWndDesktop->dce = NULL;
632 pWndDesktop->pVScroll = NULL;
633 pWndDesktop->pHScroll = NULL;
634 pWndDesktop->pProp = NULL;
635 pWndDesktop->wIDmenu = 0;
636 pWndDesktop->helpContext = 0;
637 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
638 pWndDesktop->hSysMenu = 0;
639 pWndDesktop->userdata = 0;
640 pWndDesktop->winproc = (WNDPROC16)class->winproc;
641 pWndDesktop->irefCount = 0;
643 /* FIXME: How do we know if it should be Unicode or not */
644 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
647 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
648 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
653 /***********************************************************************
656 * Implementation of CreateWindowEx().
658 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
659 BOOL win32, BOOL unicode )
665 HWND16 hwnd, hwndLinkAfter;
666 POINT maxSize, maxPos, minTrack, maxTrack;
667 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
669 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
670 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
671 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
672 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
673 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
675 /* Find the parent window */
679 /* Make sure parent is valid */
680 if (!IsWindow( cs->hwndParent ))
682 WARN("Bad parent %04x\n", cs->hwndParent );
685 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
686 WARN("No parent for child window\n" );
687 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
690 /* Find the window class */
691 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
693 WARN("Bad class '%s'\n", cs->lpszClass );
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 it 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 (HIWORD(className))
1043 if (!(classAtom = GlobalFindAtomA( className )))
1045 ERR( "bad class name %s\n", debugres_a(className) );
1051 classAtom = LOWORD(className);
1052 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1054 ERR( "bad atom %x\n", classAtom);
1060 /* Fix the coordinates */
1062 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1063 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1064 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1065 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1067 /* Create the window */
1069 cs.lpCreateParams = data;
1070 cs.hInstance = (HINSTANCE)instance;
1071 cs.hMenu = (HMENU)menu;
1072 cs.hwndParent = (HWND)parent;
1074 cs.lpszName = windowName;
1075 cs.lpszClass = className;
1076 cs.dwExStyle = exStyle;
1078 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1082 /***********************************************************************
1083 * CreateWindowEx32A (USER32.83)
1085 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1086 LPCSTR windowName, DWORD style, INT x,
1087 INT y, INT width, INT height,
1088 HWND parent, HMENU menu,
1089 HINSTANCE instance, LPVOID data )
1096 instance=GetModuleHandleA(NULL);
1098 if(exStyle & WS_EX_MDICHILD)
1099 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1101 /* Find the class atom */
1103 if (HIWORD(className))
1105 if (!(classAtom = GlobalFindAtomA( className )))
1107 ERR( "bad class name %s\n", debugres_a(className) );
1113 classAtom = LOWORD(className);
1114 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1116 ERR( "bad atom %x\n", classAtom);
1122 /* Create the window */
1124 cs.lpCreateParams = data;
1125 cs.hInstance = instance;
1127 cs.hwndParent = parent;
1133 cs.lpszName = windowName;
1134 cs.lpszClass = className;
1135 cs.dwExStyle = exStyle;
1137 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1141 /***********************************************************************
1142 * CreateWindowEx32W (USER32.84)
1144 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1145 LPCWSTR windowName, DWORD style, INT x,
1146 INT y, INT width, INT height,
1147 HWND parent, HMENU menu,
1148 HINSTANCE instance, LPVOID data )
1155 instance=GetModuleHandleA(NULL);
1157 if(exStyle & WS_EX_MDICHILD)
1158 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1160 /* Find the class atom */
1162 if (HIWORD(className))
1164 if (!(classAtom = GlobalFindAtomW( className )))
1166 ERR( "bad class name %s\n", debugres_w(className) );
1172 classAtom = LOWORD(className);
1173 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1175 ERR( "bad atom %x\n", classAtom);
1181 /* Create the window */
1183 cs.lpCreateParams = data;
1184 cs.hInstance = instance;
1186 cs.hwndParent = parent;
1192 cs.lpszName = windowName;
1193 cs.lpszClass = className;
1194 cs.dwExStyle = exStyle;
1196 /* Note: we rely on the fact that CREATESTRUCT32A and */
1197 /* CREATESTRUCT32W have the same layout. */
1198 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1202 /***********************************************************************
1205 static void WIN_CheckFocus( WND* pWnd )
1207 if( GetFocus16() == pWnd->hwndSelf )
1208 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1211 /***********************************************************************
1212 * WIN_SendDestroyMsg
1214 static void WIN_SendDestroyMsg( WND* pWnd )
1216 WIN_CheckFocus(pWnd);
1218 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1219 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1222 * Send the WM_DESTROY to the window.
1224 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1227 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1228 * make sure that the window still exists when we come back.
1230 if (IsWindow(pWnd->hwndSelf))
1232 HWND* pWndArray = NULL;
1237 * Now, if the window has kids, we have to send WM_DESTROY messages
1238 * recursively to it's kids. It seems that those calls can also
1239 * trigger re-entrant calls to DestroyWindow for the kids so we must
1240 * protect against corruption of the list of siblings. We first build
1241 * a list of HWNDs representing all the kids.
1243 pChild = WIN_LockWndPtr(pWnd->child);
1247 WIN_UpdateWndPtr(&pChild,pChild->next);
1251 * If there are no kids, we're done.
1256 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1261 if (pWndArray==NULL)
1265 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1266 * call, our linked list of siblings should be safe.
1269 pChild = WIN_LockWndPtr(pWnd->child);
1272 pWndArray[nKidCount] = pChild->hwndSelf;
1274 WIN_UpdateWndPtr(&pChild,pChild->next);
1278 * Now that we have a list, go through that list again and send the destroy
1279 * message to those windows. We are using the HWND to retrieve the
1280 * WND pointer so we are effectively checking that all the kid windows are
1281 * still valid before sending the message.
1285 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1289 WIN_SendDestroyMsg( pChild );
1290 WIN_ReleaseWndPtr(pChild);
1297 HeapFree(GetProcessHeap(), 0, pWndArray);
1298 WIN_CheckFocus(pWnd);
1301 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1305 /***********************************************************************
1306 * DestroyWindow16 (USER.53)
1308 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1310 return DestroyWindow(hwnd);
1314 /***********************************************************************
1315 * DestroyWindow32 (USER32.135)
1317 BOOL WINAPI DestroyWindow( HWND hwnd )
1322 TRACE("(%04x)\n", hwnd);
1324 /* Initialization */
1326 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1327 if (wndPtr == pWndDesktop)
1329 retvalue = FALSE; /* Can't destroy desktop */
1335 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1341 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1343 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1344 /* FIXME: clean up palette - see "Internals" p.352 */
1347 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1348 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1350 /* Notify the parent window only */
1351 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1352 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1353 if( !IsWindow(hwnd) )
1360 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1362 /* Hide the window */
1364 if (wndPtr->dwStyle & WS_VISIBLE)
1366 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1367 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1368 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1369 if (!IsWindow(hwnd))
1376 /* Recursively destroy owned windows */
1378 if( !(wndPtr->dwStyle & WS_CHILD) )
1380 /* make sure top menu popup doesn't get destroyed */
1381 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1385 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1388 if (siblingPtr->owner == wndPtr)
1390 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1393 siblingPtr->owner = NULL;
1395 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1399 DestroyWindow( siblingPtr->hwndSelf );
1400 WIN_ReleaseWndPtr(siblingPtr);
1405 if( !Options.managed || EVENT_CheckFocus() )
1406 WINPOS_ActivateOtherWindow(wndPtr);
1408 if( wndPtr->owner &&
1409 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1410 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1413 /* Send destroy messages */
1415 WIN_SendDestroyMsg( wndPtr );
1416 if (!IsWindow(hwnd))
1422 /* Unlink now so we won't bother with the children later on */
1424 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1426 /* Destroy the window storage */
1428 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1431 WIN_ReleaseWndPtr(wndPtr);
1436 /***********************************************************************
1437 * CloseWindow16 (USER.43)
1439 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1441 return CloseWindow( hwnd );
1445 /***********************************************************************
1446 * CloseWindow32 (USER32.56)
1448 BOOL WINAPI CloseWindow( HWND hwnd )
1450 WND * wndPtr = WIN_FindWndPtr( hwnd );
1453 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1458 ShowWindow( hwnd, SW_MINIMIZE );
1461 WIN_ReleaseWndPtr(wndPtr);
1467 /***********************************************************************
1468 * OpenIcon16 (USER.44)
1470 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1472 return OpenIcon( hwnd );
1476 /***********************************************************************
1477 * OpenIcon32 (USER32.410)
1479 BOOL WINAPI OpenIcon( HWND hwnd )
1481 if (!IsIconic( hwnd )) return FALSE;
1482 ShowWindow( hwnd, SW_SHOWNORMAL );
1487 /***********************************************************************
1490 * Implementation of FindWindow() and FindWindowEx().
1492 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1500 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1503 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1509 else if (pWnd->parent != pWndDesktop)
1514 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1518 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1523 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1531 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1533 if (className && (pWnd->class->atomName != className))
1534 continue; /* Not the right class */
1536 /* Now check the title */
1540 retvalue = pWnd->hwndSelf;
1543 if (pWnd->text && !strcmp( pWnd->text, title ))
1545 retvalue = pWnd->hwndSelf;
1551 WIN_ReleaseWndPtr(pWnd);
1557 /***********************************************************************
1558 * FindWindow16 (USER.50)
1560 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1562 return FindWindowA( className, title );
1566 /***********************************************************************
1567 * FindWindowEx16 (USER.427)
1569 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1571 return FindWindowExA( parent, child, className, title );
1575 /***********************************************************************
1576 * FindWindow32A (USER32.198)
1578 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1580 HWND ret = FindWindowExA( 0, 0, className, title );
1581 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1586 /***********************************************************************
1587 * FindWindowEx32A (USER32.199)
1589 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1590 LPCSTR className, LPCSTR title )
1596 /* If the atom doesn't exist, then no class */
1597 /* with this name exists either. */
1598 if (!(atom = GlobalFindAtomA( className )))
1600 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1604 return WIN_FindWindow( parent, child, atom, title );
1608 /***********************************************************************
1609 * FindWindowEx32W (USER32.200)
1611 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1612 LPCWSTR className, LPCWSTR title )
1620 /* If the atom doesn't exist, then no class */
1621 /* with this name exists either. */
1622 if (!(atom = GlobalFindAtomW( className )))
1624 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1628 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1629 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1630 HeapFree( GetProcessHeap(), 0, buffer );
1635 /***********************************************************************
1636 * FindWindow32W (USER32.201)
1638 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1640 return FindWindowExW( 0, 0, className, title );
1644 /**********************************************************************
1646 * returns a locked pointer
1648 WND *WIN_GetDesktop(void)
1650 return WIN_LockWndPtr(pWndDesktop);
1652 /**********************************************************************
1653 * WIN_ReleaseDesktop
1654 * unlock the desktop pointer
1656 void WIN_ReleaseDesktop(void)
1658 WIN_ReleaseWndPtr(pWndDesktop);
1662 /**********************************************************************
1663 * GetDesktopWindow16 (USER.286)
1665 HWND16 WINAPI GetDesktopWindow16(void)
1667 return (HWND16)pWndDesktop->hwndSelf;
1671 /**********************************************************************
1672 * GetDesktopWindow32 (USER32.232)
1674 HWND WINAPI GetDesktopWindow(void)
1676 if (pWndDesktop) return pWndDesktop->hwndSelf;
1677 ERR( "You need the -desktop option when running with native USER\n" );
1683 /**********************************************************************
1684 * GetDesktopHwnd (USER.278)
1686 * Exactly the same thing as GetDesktopWindow(), but not documented.
1687 * Don't ask me why...
1689 HWND16 WINAPI GetDesktopHwnd16(void)
1691 return (HWND16)pWndDesktop->hwndSelf;
1695 /*******************************************************************
1696 * EnableWindow16 (USER.34)
1698 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1700 return EnableWindow( hwnd, enable );
1704 /*******************************************************************
1705 * EnableWindow32 (USER32.172)
1707 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1712 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1714 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1715 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1718 wndPtr->dwStyle &= ~WS_DISABLED;
1720 if( wndPtr->flags & WIN_NATIVE )
1721 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1723 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1727 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1729 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1731 /* Disable window */
1732 wndPtr->dwStyle |= WS_DISABLED;
1734 if( wndPtr->flags & WIN_NATIVE )
1735 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1737 if (hwnd == GetFocus())
1739 SetFocus( 0 ); /* A disabled window can't have the focus */
1741 if (hwnd == GetCapture())
1743 ReleaseCapture(); /* A disabled window can't capture the mouse */
1745 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1749 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1751 WIN_ReleaseWndPtr(wndPtr);
1756 /***********************************************************************
1757 * IsWindowEnabled16 (USER.35)
1759 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1761 return IsWindowEnabled(hWnd);
1765 /***********************************************************************
1766 * IsWindowEnabled32 (USER32.349)
1768 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1773 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1774 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1775 WIN_ReleaseWndPtr(wndPtr);
1781 /***********************************************************************
1782 * IsWindowUnicode (USER32.350)
1784 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1789 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1790 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1791 WIN_ReleaseWndPtr(wndPtr);
1796 /**********************************************************************
1797 * GetWindowWord16 (USER.133)
1799 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1801 return GetWindowWord( hwnd, offset );
1805 /**********************************************************************
1806 * GetWindowWord32 (USER32.314)
1808 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1811 WND * wndPtr = WIN_FindWndPtr( hwnd );
1812 if (!wndPtr) return 0;
1815 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1817 WARN("Invalid offset %d\n", offset );
1821 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1827 if (HIWORD(wndPtr->wIDmenu))
1828 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1830 retvalue = (WORD)wndPtr->wIDmenu;
1832 case GWW_HWNDPARENT:
1833 retvalue = GetParent(hwnd);
1836 if (HIWORD(wndPtr->hInstance))
1837 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1839 retvalue = (WORD)wndPtr->hInstance;
1842 WARN("Invalid offset %d\n", offset );
1847 WIN_ReleaseWndPtr(wndPtr);
1851 /**********************************************************************
1852 * SetWindowWord16 (USER.134)
1854 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1856 return SetWindowWord( hwnd, offset, newval );
1860 /**********************************************************************
1861 * SetWindowWord32 (USER32.524)
1863 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1866 WND * wndPtr = WIN_FindWndPtr( hwnd );
1867 if (!wndPtr) return 0;
1870 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1872 WARN("Invalid offset %d\n", offset );
1876 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1880 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1881 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1882 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1885 WARN("Invalid offset %d\n", offset );
1892 WIN_ReleaseWndPtr(wndPtr);
1897 /**********************************************************************
1900 * Helper function for GetWindowLong().
1902 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1905 WND * wndPtr = WIN_FindWndPtr( hwnd );
1906 if (!wndPtr) return 0;
1909 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1911 WARN("Invalid offset %d\n", offset );
1915 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1916 /* Special case for dialog window procedure */
1917 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1919 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1926 case GWL_USERDATA: retvalue = wndPtr->userdata;
1928 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1930 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1932 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1934 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1937 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1939 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1942 WARN("Unknown offset %d\n", offset );
1946 WIN_ReleaseWndPtr(wndPtr);
1951 /**********************************************************************
1954 * Helper function for SetWindowLong().
1956 * 0 is the failure code. However, in the case of failure SetLastError
1957 * must be set to distinguish between a 0 return value and a failure.
1959 * FIXME: The error values for SetLastError may not be right. Can
1960 * someone check with the real thing?
1962 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1963 WINDOWPROCTYPE type )
1966 WND * wndPtr = WIN_FindWndPtr( hwnd );
1969 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1973 /* Is this the right error? */
1974 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1980 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1982 WARN("Invalid offset %d\n", offset );
1984 /* Is this the right error? */
1985 SetLastError( ERROR_OUTOFMEMORY );
1990 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1991 /* Special case for dialog window procedure */
1992 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1994 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1995 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1996 type, WIN_PROC_WINDOW );
2003 ptr = (DWORD*)&wndPtr->wIDmenu;
2006 retval = SetWindowWord( hwnd, offset, newval );
2009 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2010 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2011 type, WIN_PROC_WINDOW );
2014 style.styleOld = wndPtr->dwStyle;
2015 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2016 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2018 if (wndPtr->flags & WIN_ISWIN32)
2019 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2020 wndPtr->dwStyle = style.styleNew;
2021 if (wndPtr->flags & WIN_ISWIN32)
2022 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2023 retval = style.styleOld;
2027 ptr = &wndPtr->userdata;
2030 style.styleOld = wndPtr->dwExStyle;
2031 style.styleNew = newval;
2032 if (wndPtr->flags & WIN_ISWIN32)
2033 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2034 wndPtr->dwExStyle = newval;
2035 if (wndPtr->flags & WIN_ISWIN32)
2036 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2037 retval = style.styleOld;
2041 WARN("Invalid offset %d\n", offset );
2043 /* Don't think this is right error but it should do */
2044 SetLastError( ERROR_OUTOFMEMORY );
2052 WIN_ReleaseWndPtr(wndPtr);
2057 /**********************************************************************
2058 * GetWindowLong16 (USER.135)
2060 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2062 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2066 /**********************************************************************
2067 * GetWindowLong32A (USER32.305)
2069 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2071 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2075 /**********************************************************************
2076 * GetWindowLong32W (USER32.306)
2078 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2080 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2084 /**********************************************************************
2085 * SetWindowLong16 (USER.136)
2087 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2089 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2093 /**********************************************************************
2094 * SetWindowLong32A (USER32.517)
2096 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2098 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2102 /**********************************************************************
2103 * SetWindowLong32W (USER32.518) Set window attribute
2105 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2106 * value in a window's extra memory.
2108 * The _hwnd_ parameter specifies the window. is the handle to a
2109 * window that has extra memory. The _newval_ parameter contains the
2110 * new attribute or extra memory value. If positive, the _offset_
2111 * parameter is the byte-addressed location in the window's extra
2112 * memory to set. If negative, _offset_ specifies the window
2113 * attribute to set, and should be one of the following values:
2115 * GWL_EXSTYLE The window's extended window style
2117 * GWL_STYLE The window's window style.
2119 * GWL_WNDPROC Pointer to the window's window procedure.
2121 * GWL_HINSTANCE The window's pplication instance handle.
2123 * GWL_ID The window's identifier.
2125 * GWL_USERDATA The window's user-specified data.
2127 * If the window is a dialog box, the _offset_ parameter can be one of
2128 * the following values:
2130 * DWL_DLGPROC The address of the window's dialog box procedure.
2132 * DWL_MSGRESULT The return value of a message
2133 * that the dialog box procedure processed.
2135 * DWL_USER Application specific information.
2139 * If successful, returns the previous value located at _offset_. Otherwise,
2144 * Extra memory for a window class is specified by a nonzero cbWndExtra
2145 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2146 * time of class creation.
2148 * Using GWL_WNDPROC to set a new window procedure effectively creates
2149 * a window subclass. Use CallWindowProc() in the new windows procedure
2150 * to pass messages to the superclass's window procedure.
2152 * The user data is reserved for use by the application which created
2155 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2156 * instead, call the EnableWindow() function to change the window's
2159 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2160 * SetParent() instead.
2163 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2164 * it sends WM_STYLECHANGING before changing the settings
2165 * and WM_STYLECHANGED afterwards.
2166 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2170 * GWL_STYLE does not dispatch WM_STYLE... messages.
2177 LONG WINAPI SetWindowLongW(
2178 HWND hwnd, /* window to alter */
2179 INT offset, /* offset, in bytes, of location to alter */
2180 LONG newval /* new value of location */
2182 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2186 /*******************************************************************
2187 * GetWindowText16 (USER.36)
2189 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2191 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2195 /*******************************************************************
2196 * GetWindowText32A (USER32.309)
2198 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2200 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2204 /*******************************************************************
2205 * InternalGetWindowText (USER32.326)
2207 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2209 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2210 return GetWindowTextW(hwnd,lpString,nMaxCount);
2214 /*******************************************************************
2215 * GetWindowText32W (USER32.312)
2217 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2219 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2224 /*******************************************************************
2225 * SetWindowText16 (USER.37)
2227 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2229 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2233 /*******************************************************************
2234 * SetWindowText32A (USER32.521)
2236 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2238 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2242 /*******************************************************************
2243 * SetWindowText32W (USER32.523)
2245 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2247 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2251 /*******************************************************************
2252 * GetWindowTextLength16 (USER.38)
2254 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2256 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2260 /*******************************************************************
2261 * GetWindowTextLength32A (USER32.310)
2263 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2265 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2268 /*******************************************************************
2269 * GetWindowTextLength32W (USER32.311)
2271 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2273 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2277 /*******************************************************************
2278 * IsWindow16 (USER.47)
2280 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2282 CURRENT_STACK16->es = USER_HeapSel;
2283 return IsWindow( hwnd );
2287 /*******************************************************************
2288 * IsWindow32 (USER32.348)
2290 BOOL WINAPI IsWindow( HWND hwnd )
2295 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2296 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2297 WIN_ReleaseWndPtr(wndPtr);
2303 /*****************************************************************
2304 * GetParent16 (USER.46)
2306 HWND16 WINAPI GetParent16( HWND16 hwnd )
2308 return (HWND16)GetParent( hwnd );
2312 /*****************************************************************
2313 * GetParent32 (USER32.278)
2315 HWND WINAPI GetParent( HWND hwnd )
2320 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2321 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2324 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2326 retvalue = wndPtr->hwndSelf;
2329 WIN_ReleaseWndPtr(wndPtr);
2334 /*****************************************************************
2337 * Get the top-level parent for a child window.
2338 * returns a locked pointer
2340 WND* WIN_GetTopParentPtr( WND* pWnd )
2342 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2344 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2346 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2351 /*****************************************************************
2354 * Get the top-level parent for a child window.
2356 HWND WIN_GetTopParent( HWND hwnd )
2359 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2360 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2362 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2363 WIN_ReleaseWndPtr(tmpPtr);
2364 WIN_ReleaseWndPtr(wndPtr);
2369 /*****************************************************************
2370 * SetParent16 (USER.233)
2372 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2374 return SetParent( hwndChild, hwndNewParent );
2378 /*****************************************************************
2379 * SetParent32 (USER32.495)
2381 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2390 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2392 dwStyle = wndPtr->dwStyle;
2394 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2395 : WIN_LockWndPtr(pWndDesktop);
2397 /* Windows hides the window first, then shows it again
2398 * including the WM_SHOWWINDOW messages and all */
2399 if (dwStyle & WS_VISIBLE)
2400 ShowWindow( hwndChild, SW_HIDE );
2402 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2404 /* SetParent32 additionally needs to make hwndChild the topmost window
2405 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2406 WM_WINDOWPOSCHANGED notification messages.
2408 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2409 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2410 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2411 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2413 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2415 WIN_ReleaseWndPtr(pWndOldParent);
2416 WIN_ReleaseWndPtr(pWndNewParent);
2417 WIN_ReleaseWndPtr(wndPtr);
2423 /*******************************************************************
2424 * IsChild16 (USER.48)
2426 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2428 return IsChild(parent,child);
2432 /*******************************************************************
2433 * IsChild32 (USER32.339)
2435 BOOL WINAPI IsChild( HWND parent, HWND child )
2437 WND * wndPtr = WIN_FindWndPtr( child );
2438 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2440 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2441 if (wndPtr->hwndSelf == parent)
2443 WIN_ReleaseWndPtr(wndPtr);
2447 WIN_ReleaseWndPtr(wndPtr);
2452 /***********************************************************************
2453 * IsWindowVisible16 (USER.49)
2455 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2457 return IsWindowVisible(hwnd);
2461 /***********************************************************************
2462 * IsWindowVisible32 (USER32.351)
2464 BOOL WINAPI IsWindowVisible( HWND hwnd )
2467 WND *wndPtr = WIN_FindWndPtr( hwnd );
2468 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2470 if (!(wndPtr->dwStyle & WS_VISIBLE))
2472 WIN_ReleaseWndPtr(wndPtr);
2475 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2477 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2478 WIN_ReleaseWndPtr(wndPtr);
2484 /***********************************************************************
2485 * WIN_IsWindowDrawable
2487 * hwnd is drawable when it is visible, all parents are not
2488 * minimized, and it is itself not minimized unless we are
2489 * trying to draw its default class icon.
2491 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2493 if( (wnd->dwStyle & WS_MINIMIZE &&
2494 icon && wnd->class->hIcon) ||
2495 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2496 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2497 if( wnd->dwStyle & WS_MINIMIZE ||
2498 !(wnd->dwStyle & WS_VISIBLE) ) break;
2499 return (wnd == NULL);
2503 /*******************************************************************
2504 * GetTopWindow16 (USER.229)
2506 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2508 return GetTopWindow(hwnd);
2512 /*******************************************************************
2513 * GetTopWindow32 (USER.229)
2515 HWND WINAPI GetTopWindow( HWND hwnd )
2518 WND * wndPtr = (hwnd) ?
2519 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2521 if (wndPtr && wndPtr->child)
2522 retval = wndPtr->child->hwndSelf;
2524 WIN_ReleaseWndPtr(wndPtr);
2529 /*******************************************************************
2530 * GetWindow16 (USER.262)
2532 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2534 return GetWindow( hwnd,rel );
2538 /*******************************************************************
2539 * GetWindow32 (USER32.302)
2541 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2545 WND * wndPtr = WIN_FindWndPtr( hwnd );
2546 if (!wndPtr) return 0;
2550 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2554 if (!wndPtr->parent)
2556 retval = 0; /* Desktop window */
2559 while (wndPtr->next)
2561 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2563 retval = wndPtr->hwndSelf;
2567 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2571 if (!wndPtr->parent)
2573 retval = 0; /* Desktop window */
2576 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2577 if (wndPtr->hwndSelf == hwnd)
2579 retval = 0; /* First in list */
2582 while (wndPtr->next)
2584 if (wndPtr->next->hwndSelf == hwnd)
2586 retval = wndPtr->hwndSelf;
2589 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2595 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2599 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2604 WIN_ReleaseWndPtr(wndPtr);
2609 /*******************************************************************
2610 * GetNextWindow16 (USER.230)
2612 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2614 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2615 return GetWindow16( hwnd, flag );
2618 /*******************************************************************
2619 * ShowOwnedPopups16 (USER.265)
2621 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2623 ShowOwnedPopups( owner, fShow );
2627 /*******************************************************************
2628 * ShowOwnedPopups32 (USER32.531)
2630 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2632 UINT totalChild=0, count=0;
2634 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2636 if (!pWnd) return TRUE;
2638 for (; count < totalChild; count++)
2640 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2644 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2646 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2647 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2652 if (IsWindowVisible(pWnd[count]->hwndSelf))
2654 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2655 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2661 WIN_ReleaseDesktop();
2662 WIN_ReleaseWinArray(pWnd);
2667 /*******************************************************************
2668 * GetLastActivePopup16 (USER.287)
2670 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2672 return GetLastActivePopup( hwnd );
2675 /*******************************************************************
2676 * GetLastActivePopup32 (USER32.256)
2678 HWND WINAPI GetLastActivePopup( HWND hwnd )
2681 WND *wndPtr =WIN_FindWndPtr(hwnd);
2682 if (!wndPtr) return hwnd;
2683 retval = wndPtr->hwndLastActive;
2684 WIN_ReleaseWndPtr(wndPtr);
2689 /*******************************************************************
2692 * Build an array of pointers to the children of a given window.
2693 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2694 * when no windows are found.
2696 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2698 /* Future: this function will lock all windows associated with this array */
2700 WND **list, **ppWnd;
2702 UINT count = 0, skipOwned, skipHidden;
2705 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2706 skipOwned = bwaFlags & BWA_SKIPOWNED;
2707 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2708 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2710 /* First count the windows */
2713 wndPtr = WIN_GetDesktop();
2715 pWnd = WIN_LockWndPtr(wndPtr->child);
2718 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2719 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2721 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2726 /* Now build the list of all windows */
2728 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2730 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2732 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2733 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2739 WIN_ReleaseWndPtr(pWnd);
2745 if( pTotal ) *pTotal = count;
2748 /*******************************************************************
2749 * WIN_ReleaseWinArray
2751 void WIN_ReleaseWinArray(WND **wndArray)
2753 /* Future: this function will also unlock all windows associated with wndArray */
2754 HeapFree( GetProcessHeap(), 0, wndArray );
2758 /*******************************************************************
2759 * EnumWindows16 (USER.54)
2761 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2763 WND **list, **ppWnd;
2765 /* We have to build a list of all windows first, to avoid */
2766 /* unpleasant side-effects, for instance if the callback */
2767 /* function changes the Z-order of the windows. */
2769 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2771 WIN_ReleaseDesktop();
2775 /* Now call the callback function for every window */
2777 for (ppWnd = list; *ppWnd; ppWnd++)
2779 LRESULT lpEnumFuncRetval;
2781 /* Make sure that the window still exists */
2782 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2784 /* To avoid any deadlocks, all the locks on the windows
2785 structures must be suspended before the control
2786 is passed to the application */
2787 iWndsLocks = WIN_SuspendWndsLock();
2788 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2789 WIN_RestoreWndsLock(iWndsLocks);
2791 if (!lpEnumFuncRetval) break;
2793 WIN_ReleaseWinArray(list);
2794 WIN_ReleaseDesktop();
2799 /*******************************************************************
2800 * EnumWindows32 (USER32.193)
2802 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2804 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2808 /**********************************************************************
2809 * EnumTaskWindows16 (USER.225)
2811 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2814 WND **list, **ppWnd;
2816 /* This function is the same as EnumWindows(), */
2817 /* except for an added check on the window's task. */
2819 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2821 WIN_ReleaseDesktop();
2825 /* Now call the callback function for every window */
2827 for (ppWnd = list; *ppWnd; ppWnd++)
2831 /* Make sure that the window still exists */
2832 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2833 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2835 /* To avoid any deadlocks, all the locks on the windows
2836 structures must be suspended before the control
2837 is passed to the application */
2838 iWndsLocks = WIN_SuspendWndsLock();
2839 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2840 WIN_RestoreWndsLock(iWndsLocks);
2842 if (!funcRetval) break;
2844 WIN_ReleaseWinArray(list);
2845 WIN_ReleaseDesktop();
2850 /**********************************************************************
2851 * EnumThreadWindows (USER32.190)
2853 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2855 TEB *teb = THREAD_IdToTEB(id);
2857 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2861 /**********************************************************************
2862 * WIN_EnumChildWindows
2864 * Helper function for EnumChildWindows().
2866 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2872 for ( ; *ppWnd; ppWnd++)
2876 /* Make sure that the window still exists */
2877 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2878 /* Build children list first */
2879 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2881 /* To avoid any deadlocks, all the locks on the windows
2882 structures must be suspended before the control
2883 is passed to the application */
2884 iWndsLocks = WIN_SuspendWndsLock();
2885 ret = func( (*ppWnd)->hwndSelf, lParam );
2886 WIN_RestoreWndsLock(iWndsLocks);
2890 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2891 WIN_ReleaseWinArray(childList);
2893 if (!ret) return FALSE;
2899 /**********************************************************************
2900 * EnumChildWindows16 (USER.55)
2902 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2905 WND **list, *pParent;
2907 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2908 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2910 WIN_ReleaseWndPtr(pParent);
2913 WIN_EnumChildWindows( list, func, lParam );
2914 WIN_ReleaseWinArray(list);
2915 WIN_ReleaseWndPtr(pParent);
2920 /**********************************************************************
2921 * EnumChildWindows32 (USER32.178)
2923 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2926 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2931 /*******************************************************************
2932 * AnyPopup16 (USER.52)
2934 BOOL16 WINAPI AnyPopup16(void)
2940 /*******************************************************************
2941 * AnyPopup32 (USER32.4)
2943 BOOL WINAPI AnyPopup(void)
2945 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2950 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2955 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2959 WIN_ReleaseWndPtr(wndPtr);
2964 /*******************************************************************
2965 * FlashWindow16 (USER.105)
2967 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2969 return FlashWindow( hWnd, bInvert );
2973 /*******************************************************************
2974 * FlashWindow32 (USER32.202)
2976 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2978 WND *wndPtr = WIN_FindWndPtr(hWnd);
2980 TRACE("%04x\n", hWnd);
2982 if (!wndPtr) return FALSE;
2984 if (wndPtr->dwStyle & WS_MINIMIZE)
2986 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2988 HDC hDC = GetDC(hWnd);
2990 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2991 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2993 ReleaseDC( hWnd, hDC );
2994 wndPtr->flags |= WIN_NCACTIVATED;
2998 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2999 RDW_UPDATENOW | RDW_FRAME, 0 );
3000 wndPtr->flags &= ~WIN_NCACTIVATED;
3002 WIN_ReleaseWndPtr(wndPtr);
3008 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3009 else wparam = (hWnd == GetActiveWindow());
3011 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3012 WIN_ReleaseWndPtr(wndPtr);
3018 /*******************************************************************
3019 * SetSysModalWindow16 (USER.188)
3021 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3023 HWND hWndOldModal = hwndSysModal;
3024 hwndSysModal = hWnd;
3025 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3026 return hWndOldModal;
3030 /*******************************************************************
3031 * GetSysModalWindow16 (USER.52)
3033 HWND16 WINAPI GetSysModalWindow16(void)
3035 return hwndSysModal;
3039 /*******************************************************************
3040 * GetWindowContextHelpId (USER32.303)
3042 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3045 WND *wnd = WIN_FindWndPtr( hwnd );
3047 retval = wnd->helpContext;
3048 WIN_ReleaseWndPtr(wnd);
3053 /*******************************************************************
3054 * SetWindowContextHelpId (USER32.515)
3056 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3058 WND *wnd = WIN_FindWndPtr( hwnd );
3059 if (!wnd) return FALSE;
3060 wnd->helpContext = id;
3061 WIN_ReleaseWndPtr(wnd);
3066 /*******************************************************************
3069 * recursively find a child that contains spDragInfo->pt point
3070 * and send WM_QUERYDROPOBJECT
3072 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3074 BOOL16 wParam, bResult = 0;
3076 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3077 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3080 if( !ptrQueryWnd || !ptrDragInfo )
3083 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3085 GetWindowRect(hQueryWnd,&tempRect);
3087 if( !PtInRect(&tempRect,pt) ||
3088 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3091 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3093 tempRect = ptrQueryWnd->rectClient;
3094 if(ptrQueryWnd->dwStyle & WS_CHILD)
3095 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3096 (LPPOINT)&tempRect, 2 );
3098 if (PtInRect( &tempRect, pt))
3102 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3104 if( ptrWnd->dwStyle & WS_VISIBLE )
3106 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3107 if (PtInRect( &tempRect, pt )) break;
3113 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3114 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3115 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3116 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3117 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3119 WIN_ReleaseWndPtr(ptrWnd);
3129 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3131 ptrDragInfo->hScope = hQueryWnd;
3133 bResult = ( bNoSend )
3134 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3135 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3136 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3138 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3141 WIN_ReleaseWndPtr(ptrQueryWnd);
3146 /*******************************************************************
3147 * DragDetect (USER.465)
3149 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3152 CONV_POINT16TO32( &pt, &pt32 );
3153 return DragDetect( hWnd, pt32 );
3156 /*******************************************************************
3157 * DragDetect32 (USER32.151)
3159 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3164 rect.left = pt.x - wDragWidth;
3165 rect.right = pt.x + wDragWidth;
3167 rect.top = pt.y - wDragHeight;
3168 rect.bottom = pt.y + wDragHeight;
3174 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3176 if( msg.message == WM_LBUTTONUP )
3181 if( msg.message == WM_MOUSEMOVE )
3183 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3195 /******************************************************************************
3196 * DragObject16 (USER.464)
3198 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3199 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3202 LPDRAGINFO lpDragInfo;
3204 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3205 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3206 WND *wndPtr = WIN_FindWndPtr(hWnd);
3207 HCURSOR16 hCurrentCursor = 0;
3208 HWND16 hCurrentWnd = 0;
3210 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3211 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3213 if( !lpDragInfo || !spDragInfo )
3215 WIN_ReleaseWndPtr(wndPtr);
3219 hBummer = LoadCursor16(0, IDC_BUMMER16);
3221 if( !hBummer || !wndPtr )
3223 GlobalFree16(hDragInfo);
3224 WIN_ReleaseWndPtr(wndPtr);
3230 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3232 GlobalFree16(hDragInfo);
3233 WIN_ReleaseWndPtr(wndPtr);
3237 if( hDragCursor == hCursor ) hDragCursor = 0;
3238 else hCursor = hDragCursor;
3240 hOldCursor = SetCursor(hDragCursor);
3243 lpDragInfo->hWnd = hWnd;
3244 lpDragInfo->hScope = 0;
3245 lpDragInfo->wFlags = wObj;
3246 lpDragInfo->hList = szList; /* near pointer! */
3247 lpDragInfo->hOfStruct = hOfStruct;
3255 do{ WaitMessage(); }
3256 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3258 *(lpDragInfo+1) = *lpDragInfo;
3260 lpDragInfo->pt = msg.pt;
3262 /* update DRAGINFO struct */
3263 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3265 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3266 hCurrentCursor = hCursor;
3269 hCurrentCursor = hBummer;
3270 lpDragInfo->hScope = 0;
3272 if( hCurrentCursor )
3273 SetCursor(hCurrentCursor);
3275 /* send WM_DRAGLOOP */
3276 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3277 (LPARAM) spDragInfo );
3278 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3279 if( hCurrentWnd != lpDragInfo->hScope )
3282 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3283 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3284 HIWORD(spDragInfo)) );
3285 hCurrentWnd = lpDragInfo->hScope;
3287 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3291 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3293 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3296 ShowCursor( FALSE );
3300 SetCursor( hOldCursor );
3301 if (hDragCursor) DestroyCursor( hDragCursor );
3304 if( hCurrentCursor != hBummer )
3305 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3306 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3309 GlobalFree16(hDragInfo);
3310 WIN_ReleaseWndPtr(wndPtr);
3312 return (DWORD)(msg.lParam);