2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
9 #include "wine/winbase16.h"
16 #include "sysmetrics.h"
17 #include "cursoricon.h"
21 #include "nonclient.h"
24 #include "shm_main_blk.h"
26 #include "clipboard.h"
37 /**********************************************************************/
39 WND_DRIVER *WND_Driver = NULL;
42 static WND *pWndDesktop = NULL;
44 static HWND hwndSysModal = 0;
46 static WORD wDragWidth = 4;
47 static WORD wDragHeight= 3;
50 static CRITICAL_SECTION WIN_CritSection;
52 /***********************************************************************
55 * Locks access to all WND structures for thread safeness
59 EnterCriticalSection(&WIN_CritSection);
62 /***********************************************************************
65 * Unlocks access to all WND structures
69 LeaveCriticalSection(&WIN_CritSection);
71 /***********************************************************************
74 * Suspend the lock on WND structures.
75 * Returns the number of locks suspended
77 int WIN_SuspendWndsLock()
79 int isuspendedLocks = 0;
81 /* make sure that the lock is not suspended by different thread than
83 if(WIN_CritSection.OwningThread != GetCurrentThreadId())
87 /* set the value of isuspendedlock to the actual recursion count
88 of the critical section */
89 isuspendedLocks = WIN_CritSection.RecursionCount;
90 /* set the recursion count of the critical section to 1
91 so the owning thread will be able to leave it */
92 WIN_CritSection.RecursionCount = 1;
93 /* leave critical section*/
96 return isuspendedLocks;
99 /***********************************************************************
100 * WIN_RestoreWndsLock
102 * Restore the suspended locks on WND structures
104 void WIN_RestoreWndsLock(int ipreviousLocks)
110 /* restore the lock */
112 /* set the recursion count of the critical section to the
113 value of suspended locks (given by WIN_SuspendWndsLock())*/
114 WIN_CritSection.RecursionCount = ipreviousLocks;
118 /***********************************************************************
121 * Return a pointer to the WND structure corresponding to a HWND.
123 WND * WIN_FindWndPtr( HWND hwnd )
127 if (!hwnd || HIWORD(hwnd)) goto error2;
128 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
129 /* Lock all WND structures for thread safeness*/
131 /*and increment destruction monitoring*/
134 if (ptr->dwMagic != WND_MAGIC) goto error;
135 if (ptr->hwndSelf != hwnd)
137 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
140 /* returns a locked pointer */
143 /* Unlock all WND structures for thread safeness*/
145 /* and decrement destruction monitoring value */
150 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
154 /***********************************************************************
157 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
159 * Returns the locked initialisation pointer
161 WND *WIN_LockWndPtr(WND *initWndPtr)
163 if(!initWndPtr) return 0;
165 /* Lock all WND structures for thread safeness*/
167 /*and increment destruction monitoring*/
168 initWndPtr->irefCount++;
174 /***********************************************************************
177 * Release the pointer to the WND structure.
179 void WIN_ReleaseWndPtr(WND *wndPtr)
183 /*Decrement destruction monitoring value*/
185 /* Check if it's time to release the memory*/
186 /* Check if it's time to release the memory*/
187 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
190 USER_HEAP_FREE( wndPtr->hwndSelf);
192 else if(wndPtr->irefCount < 0)
194 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
195 TRACE(win,"forgot a Lock on %p somewhere\n",wndPtr);
197 /*unlock all WND structures for thread safeness*/
201 /***********************************************************************
204 * Updates the value of oldPtr to newPtr.
206 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
210 tmpWnd = WIN_LockWndPtr(newPtr);
211 WIN_ReleaseWndPtr(*oldPtr);
216 /***********************************************************************
219 * Dump the content of a window structure to stderr.
221 void WIN_DumpWindow( HWND hwnd )
227 if (!(ptr = WIN_FindWndPtr( hwnd )))
229 WARN( win, "%04x is not a window handle\n", hwnd );
233 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
234 strcpy( className, "#NULL#" );
236 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
237 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
238 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
239 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
240 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
241 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
242 ptr->next, ptr->child, ptr->parent, ptr->owner,
243 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
244 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
245 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
246 ptr->text ? ptr->text : "",
247 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
248 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
249 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
250 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
252 if (ptr->class->cbWndExtra)
254 DUMP( "extra bytes:" );
255 for (i = 0; i < ptr->class->cbWndExtra; i++)
256 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
260 WIN_ReleaseWndPtr(ptr);
264 /***********************************************************************
267 * Walk the windows tree and print each window on stderr.
269 void WIN_WalkWindows( HWND hwnd, int indent )
274 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
278 WARN( win, "Invalid window handle %04x\n", hwnd );
282 if (!indent) /* first time around */
283 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
284 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
289 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
291 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
293 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
294 (DWORD)ptr, ptr->hmemTaskQ, className,
295 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
296 ptr->text?ptr->text:"<null>");
298 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
299 WIN_UpdateWndPtr(&ptr,ptr->next);
305 /***********************************************************************
308 * Remove a window from the siblings linked list.
310 BOOL WIN_UnlinkWindow( HWND hwnd )
312 WND *wndPtr, **ppWnd;
315 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
316 else if(!wndPtr->parent)
318 WIN_ReleaseWndPtr(wndPtr);
322 ppWnd = &wndPtr->parent->child;
323 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
326 *ppWnd = wndPtr->next;
329 WIN_ReleaseWndPtr(wndPtr);
334 /***********************************************************************
337 * Insert a window into the siblings linked list.
338 * The window is inserted after the specified window, which can also
339 * be specified as HWND_TOP or HWND_BOTTOM.
341 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
343 WND *wndPtr, **ppWnd;
345 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
346 else if(!wndPtr->parent)
348 WIN_ReleaseWndPtr(wndPtr);
351 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
353 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
354 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
355 while (*ppWnd) ppWnd = &(*ppWnd)->next;
357 else /* Normal case */
359 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
362 WIN_ReleaseWndPtr(wndPtr);
365 ppWnd = &afterPtr->next;
366 WIN_ReleaseWndPtr(afterPtr);
368 wndPtr->next = *ppWnd;
370 WIN_ReleaseWndPtr(wndPtr);
375 /***********************************************************************
376 * WIN_FindWinToRepaint
378 * Find a window that needs repaint.
380 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
385 /* Note: the desktop window never gets WM_PAINT messages
386 * The real reason why is because Windows DesktopWndProc
387 * does ValidateRgn inside WM_ERASEBKGND handler.
390 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
392 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
394 if (!(pWnd->dwStyle & WS_VISIBLE))
396 TRACE(win, "skipping window %04x\n",
399 else if ((pWnd->hmemTaskQ == hQueue) &&
400 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
403 else if (pWnd->child )
404 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
406 WIN_ReleaseWndPtr(pWnd);
417 hwndRet = pWnd->hwndSelf;
419 /* look among siblings if we got a transparent window */
420 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
421 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
423 WIN_UpdateWndPtr(&pWnd,pWnd->next);
427 hwndRet = pWnd->hwndSelf;
428 WIN_ReleaseWndPtr(pWnd);
430 TRACE(win,"found %04x\n",hwndRet);
435 /***********************************************************************
438 * Destroy storage associated to a window. "Internals" p.358
439 * returns a locked wndPtr->next
441 static WND* WIN_DestroyWindow( WND* wndPtr )
443 HWND hwnd = wndPtr->hwndSelf;
446 TRACE(win, "%04x\n", wndPtr->hwndSelf );
450 DDE_DestroyWindow(wndPtr->hwndSelf);
451 #endif /* CONFIG_IPC */
453 /* free child windows */
454 WIN_LockWndPtr(wndPtr->child);
455 while ((pWnd = wndPtr->child))
457 wndPtr->child = WIN_DestroyWindow( pWnd );
458 WIN_ReleaseWndPtr(pWnd);
462 * Clear the update region to make sure no WM_PAINT messages will be
463 * generated for this window while processing the WM_NCDESTROY.
465 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
467 if (wndPtr->hrgnUpdate > 1)
468 DeleteObject( wndPtr->hrgnUpdate );
470 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
472 wndPtr->hrgnUpdate = 0;
476 * Send the WM_NCDESTROY to the window being destroyed.
478 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
480 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
482 WINPOS_CheckInternalPos( wndPtr );
483 if( hwnd == GetCapture()) ReleaseCapture();
485 /* free resources associated with the window */
487 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
488 PROPERTY_RemoveWindowProps( wndPtr );
490 wndPtr->dwMagic = 0; /* Mark it as invalid */
492 /* toss stale messages from the queue */
494 if( wndPtr->hmemTaskQ )
496 BOOL bPostQuit = FALSE;
497 WPARAM wQuitParam = 0;
498 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
501 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
503 if( qmsg->msg.message == WM_QUIT )
506 wQuitParam = qmsg->msg.wParam;
508 QUEUE_RemoveMsg(msgQ, qmsg);
513 /* repost WM_QUIT to make sure this app exits its message loop */
514 if( bPostQuit ) PostQuitMessage(wQuitParam);
515 wndPtr->hmemTaskQ = 0;
518 if (!(wndPtr->dwStyle & WS_CHILD))
519 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
520 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
521 wndPtr->pDriver->pDestroyWindow( wndPtr );
522 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
523 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
524 wndPtr->hwndSelf = 0;
525 wndPtr->class->cWindows--;
526 wndPtr->class = NULL;
528 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
530 wndPtr->pDriver->pFinalize(wndPtr);
535 /***********************************************************************
536 * WIN_ResetQueueWindows
538 * Reset the queue of all the children of a given window.
539 * Return TRUE if something was done.
541 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
545 if (hNew) /* Set a new queue */
547 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
549 if (wnd->hmemTaskQ == hQueue)
551 wnd->hmemTaskQ = hNew;
556 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
560 else /* Queue is being destroyed */
564 WND *tmp = WIN_LockWndPtr(wnd->child);
569 if (tmp->hmemTaskQ == hQueue)
571 DestroyWindow( tmp->hwndSelf );
575 tmp2 = WIN_LockWndPtr(tmp->child);
576 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
580 WIN_UpdateWndPtr(&tmp,tmp->next);
582 WIN_ReleaseWndPtr(tmp2);
584 WIN_ReleaseWndPtr(tmp);
591 /***********************************************************************
592 * WIN_CreateDesktopWindow
594 * Create the desktop window.
596 BOOL WIN_CreateDesktopWindow(void)
602 TRACE(win,"Creating desktop window\n");
605 /* Initialisation of the critical section for thread safeness */
606 InitializeCriticalSection(&WIN_CritSection);
607 MakeCriticalSectionGlobal(&WIN_CritSection);
609 if (!ICONTITLE_Init() ||
610 !WINPOS_CreateInternalPosAtom() ||
611 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
614 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
615 if (!hwndDesktop) return FALSE;
616 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
618 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
619 pDesktop->pDriver = DESKTOP_Driver;
620 pWndDesktop->pDriver = WND_Driver;
622 pDesktop->pDriver->pInitialize(pDesktop);
623 pWndDesktop->pDriver->pInitialize(pWndDesktop);
625 pWndDesktop->next = NULL;
626 pWndDesktop->child = NULL;
627 pWndDesktop->parent = NULL;
628 pWndDesktop->owner = NULL;
629 pWndDesktop->class = class;
630 pWndDesktop->dwMagic = WND_MAGIC;
631 pWndDesktop->hwndSelf = hwndDesktop;
632 pWndDesktop->hInstance = 0;
633 pWndDesktop->rectWindow.left = 0;
634 pWndDesktop->rectWindow.top = 0;
635 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
636 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
637 pWndDesktop->rectClient = pWndDesktop->rectWindow;
638 pWndDesktop->text = NULL;
639 pWndDesktop->hmemTaskQ = GetFastQueue16();
640 pWndDesktop->hrgnUpdate = 0;
641 pWndDesktop->hwndLastActive = hwndDesktop;
642 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
644 pWndDesktop->dwExStyle = 0;
645 pWndDesktop->dce = NULL;
646 pWndDesktop->pVScroll = NULL;
647 pWndDesktop->pHScroll = NULL;
648 pWndDesktop->pProp = NULL;
649 pWndDesktop->wIDmenu = 0;
650 pWndDesktop->helpContext = 0;
651 pWndDesktop->flags = 0;
652 pWndDesktop->hSysMenu = 0;
653 pWndDesktop->userdata = 0;
654 pWndDesktop->winproc = (WNDPROC16)class->winproc;
655 pWndDesktop->irefCount = 0;
657 /* FIXME: How do we know if it should be Unicode or not */
658 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
661 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
662 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
667 /***********************************************************************
670 * Implementation of CreateWindowEx().
672 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
673 BOOL win32, BOOL unicode )
678 HWND16 hwnd, hwndLinkAfter;
679 POINT maxSize, maxPos, minTrack, maxTrack;
680 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
683 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
684 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
685 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
686 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
687 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
689 /* Find the parent window */
693 /* Make sure parent is valid */
694 if (!IsWindow( cs->hwndParent ))
696 WARN( win, "Bad parent %04x\n", cs->hwndParent );
699 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
700 WARN( win, "No parent for child window\n" );
701 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
704 /* Find the window class */
705 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
707 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
708 WARN( win, "Bad class '%s'\n", buffer );
712 /* Fix the lpszClass field: from existing programs, it seems ok to call a CreateWindowXXX
713 * with an atom as the class name, put some programs expect to have a *REAL* string in
714 * lpszClass when the CREATESTRUCT is sent with WM_CREATE
716 if ( !HIWORD(cs->lpszClass) ) {
718 GlobalGetAtomNameW( classAtom, (LPWSTR)buffer, sizeof(buffer) );
720 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
722 cs->lpszClass = buffer;
725 /* Fix the coordinates */
727 if (cs->x == CW_USEDEFAULT)
729 PDB *pdb = PROCESS_Current();
730 if ( !(cs->style & (WS_CHILD | WS_POPUP))
731 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
733 cs->x = pdb->env_db->startup_info->dwX;
734 cs->y = pdb->env_db->startup_info->dwY;
742 if (cs->cx == CW_USEDEFAULT)
744 PDB *pdb = PROCESS_Current();
745 if ( !(cs->style & (WS_CHILD | WS_POPUP))
746 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
748 cs->cx = pdb->env_db->startup_info->dwXSize;
749 cs->cy = pdb->env_db->startup_info->dwYSize;
753 cs->cx = 600; /* FIXME */
758 /* Create the window structure */
760 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
761 - sizeof(wndPtr->wExtra) )))
763 TRACE(win, "out of memory\n" );
767 /* Fill the window structure */
769 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
771 wndPtr->child = NULL;
773 if ((cs->style & WS_CHILD) && cs->hwndParent)
775 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
776 wndPtr->owner = NULL;
777 WIN_ReleaseWndPtr(wndPtr->parent);
781 wndPtr->parent = pWndDesktop;
782 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
783 wndPtr->owner = NULL;
786 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
787 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
788 WIN_ReleaseWndPtr(wndPtr->owner);
789 WIN_ReleaseWndPtr(tmpWnd);
793 wndPtr->pDriver = wndPtr->parent->pDriver;
794 wndPtr->pDriver->pInitialize(wndPtr);
796 wndPtr->class = classPtr;
797 wndPtr->winproc = classPtr->winproc;
798 wndPtr->dwMagic = WND_MAGIC;
799 wndPtr->hwndSelf = hwnd;
800 wndPtr->hInstance = cs->hInstance;
802 wndPtr->hmemTaskQ = GetFastQueue16();
803 wndPtr->hrgnUpdate = 0;
804 wndPtr->hwndLastActive = hwnd;
805 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
806 wndPtr->dwExStyle = cs->dwExStyle;
808 wndPtr->helpContext = 0;
809 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
810 wndPtr->pVScroll = NULL;
811 wndPtr->pHScroll = NULL;
812 wndPtr->pProp = NULL;
813 wndPtr->userdata = 0;
814 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
815 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
816 wndPtr->irefCount = 1;
818 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
820 /* Call the WH_CBT hook */
822 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
823 ? HWND_BOTTOM : HWND_TOP;
825 if (HOOK_IsHooked( WH_CBT ))
831 cbtc.hwndInsertAfter = hwndLinkAfter;
832 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
833 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
836 TRACE(win, "CBT-hook returned 0\n");
837 wndPtr->pDriver->pFinalize(wndPtr);
838 USER_HEAP_FREE( hwnd );
844 /* Increment class window counter */
846 classPtr->cWindows++;
848 /* Correct the window style */
850 if (!(cs->style & WS_CHILD))
852 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
853 if (!(cs->style & WS_POPUP))
855 wndPtr->dwStyle |= WS_CAPTION;
856 wndPtr->flags |= WIN_NEED_SIZE;
859 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
861 /* Get class or window DC if needed */
863 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
864 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
865 else wndPtr->dce = NULL;
867 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
869 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
871 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
872 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
873 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
874 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
875 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
878 if(cs->style & WS_CHILD)
880 if(cs->cx < 0) cs->cx = 0;
881 if(cs->cy < 0) cs->cy = 0;
885 if (cs->cx <= 0) cs->cx = 1;
886 if (cs->cy <= 0) cs->cy = 1;
889 wndPtr->rectWindow.left = cs->x;
890 wndPtr->rectWindow.top = cs->y;
891 wndPtr->rectWindow.right = cs->x + cs->cx;
892 wndPtr->rectWindow.bottom = cs->y + cs->cy;
893 wndPtr->rectClient = wndPtr->rectWindow;
895 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
901 /* Set the window menu */
903 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
905 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
908 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
909 if (classPtr->menuNameA)
910 cs->hMenu = HIWORD(classPtr->menuNameA) ?
911 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
912 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
914 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
917 if (HIWORD(cs->hInstance))
918 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
920 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
922 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
927 else wndPtr->wIDmenu = (UINT)cs->hMenu;
929 /* Send the WM_CREATE message
930 * Perhaps we shouldn't allow width/height changes as well.
931 * See p327 in "Internals".
934 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
936 localSend32 = unicode ? SendMessageW : SendMessageA;
937 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
939 /* Insert the window in the linked list */
941 WIN_LinkWindow( hwnd, hwndLinkAfter );
943 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
944 NULL, NULL, 0, &wndPtr->rectClient );
945 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
946 maxPos.y - wndPtr->rectWindow.top);
947 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
949 /* Send the size messages */
951 if (!(wndPtr->flags & WIN_NEED_SIZE))
954 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
955 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
956 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
957 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
958 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
959 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
960 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
961 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
962 SendMessageA( hwnd, WM_MOVE, 0,
963 MAKELONG( wndPtr->rectClient.left,
964 wndPtr->rectClient.top ) );
967 /* Show the window, maximizing or minimizing if needed */
969 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
972 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
973 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
974 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
975 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
976 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
977 : SWP_NOZORDER | SWP_FRAMECHANGED;
978 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
979 newPos.right, newPos.bottom, swFlag );
982 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
984 /* Notify the parent window only */
986 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
987 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
988 if( !IsWindow(hwnd) )
995 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
997 /* Call WH_SHELL hook */
999 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1000 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1002 TRACE(win, "created window %04x\n", hwnd);
1006 WIN_UnlinkWindow( hwnd );
1009 /* Abort window creation */
1011 WARN(win, "aborted by WM_xxCREATE!\n");
1012 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1015 WIN_ReleaseWndPtr(wndPtr);
1021 /***********************************************************************
1022 * CreateWindow16 (USER.41)
1024 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1025 DWORD style, INT16 x, INT16 y, INT16 width,
1026 INT16 height, HWND16 parent, HMENU16 menu,
1027 HINSTANCE16 instance, LPVOID data )
1029 return CreateWindowEx16( 0, className, windowName, style,
1030 x, y, width, height, parent, menu, instance, data );
1034 /***********************************************************************
1035 * CreateWindowEx16 (USER.452)
1037 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1038 LPCSTR windowName, DWORD style, INT16 x,
1039 INT16 y, INT16 width, INT16 height,
1040 HWND16 parent, HMENU16 menu,
1041 HINSTANCE16 instance, LPVOID data )
1046 /* Find the class atom */
1048 if (!(classAtom = GlobalFindAtomA( className )))
1050 fprintf( stderr, "CreateWindowEx16: bad class name " );
1051 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1052 else fprintf( stderr, "'%s'\n", className );
1056 /* Fix the coordinates */
1058 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1059 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1060 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1061 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1063 /* Create the window */
1065 cs.lpCreateParams = data;
1066 cs.hInstance = (HINSTANCE)instance;
1067 cs.hMenu = (HMENU)menu;
1068 cs.hwndParent = (HWND)parent;
1070 cs.lpszName = windowName;
1071 cs.lpszClass = className;
1072 cs.dwExStyle = exStyle;
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 )
1089 if(exStyle & WS_EX_MDICHILD)
1090 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1091 /* Find the class atom */
1093 if (!(classAtom = GlobalFindAtomA( className )))
1095 fprintf( stderr, "CreateWindowEx32A: bad class name " );
1096 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1097 else fprintf( stderr, "'%s'\n", className );
1101 /* Create the window */
1103 cs.lpCreateParams = data;
1104 cs.hInstance = instance;
1106 cs.hwndParent = parent;
1112 cs.lpszName = windowName;
1113 cs.lpszClass = className;
1114 cs.dwExStyle = exStyle;
1115 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1119 /***********************************************************************
1120 * CreateWindowEx32W (USER32.84)
1122 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1123 LPCWSTR windowName, DWORD style, INT x,
1124 INT y, INT width, INT height,
1125 HWND parent, HMENU menu,
1126 HINSTANCE instance, LPVOID data )
1131 if(exStyle & WS_EX_MDICHILD)
1132 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1134 /* Find the class atom */
1136 if (!(classAtom = GlobalFindAtomW( className )))
1138 if (HIWORD(className))
1140 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
1141 WARN( win, "Bad class name '%s'\n",cn);
1142 HeapFree( GetProcessHeap(), 0, cn );
1145 WARN( win, "Bad class name %p\n", className );
1149 /* Create the window */
1151 cs.lpCreateParams = data;
1152 cs.hInstance = instance;
1154 cs.hwndParent = parent;
1160 cs.lpszName = windowName;
1161 cs.lpszClass = className;
1162 cs.dwExStyle = exStyle;
1163 /* Note: we rely on the fact that CREATESTRUCT32A and */
1164 /* CREATESTRUCT32W have the same layout. */
1165 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1169 /***********************************************************************
1172 static void WIN_CheckFocus( WND* pWnd )
1174 if( GetFocus16() == pWnd->hwndSelf )
1175 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1178 /***********************************************************************
1179 * WIN_SendDestroyMsg
1181 static void WIN_SendDestroyMsg( WND* pWnd )
1183 WIN_CheckFocus(pWnd);
1185 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1186 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1189 * Send the WM_DESTROY to the window.
1191 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1194 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1195 * make sure that the window still exists when we come back.
1197 if (IsWindow(pWnd->hwndSelf))
1199 HWND* pWndArray = NULL;
1204 * Now, if the window has kids, we have to send WM_DESTROY messages
1205 * recursively to it's kids. It seems that those calls can also
1206 * trigger re-entrant calls to DestroyWindow for the kids so we must
1207 * protect against corruption of the list of siblings. We first build
1208 * a list of HWNDs representing all the kids.
1210 pChild = WIN_LockWndPtr(pWnd->child);
1214 WIN_UpdateWndPtr(&pChild,pChild->next);
1218 * If there are no kids, we're done.
1223 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1228 if (pWndArray==NULL)
1232 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1233 * call, our linked list of siblings should be safe.
1236 pChild = WIN_LockWndPtr(pWnd->child);
1239 pWndArray[nKidCount] = pChild->hwndSelf;
1241 WIN_UpdateWndPtr(&pChild,pChild->next);
1245 * Now that we have a list, go through that list again and send the destroy
1246 * message to those windows. We are using the HWND to retrieve the
1247 * WND pointer so we are effectively checking that all the kid windows are
1248 * still valid before sending the message.
1252 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1256 WIN_SendDestroyMsg( pChild );
1257 WIN_ReleaseWndPtr(pChild);
1264 HeapFree(GetProcessHeap(), 0, pWndArray);
1265 WIN_CheckFocus(pWnd);
1268 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
1272 /***********************************************************************
1273 * DestroyWindow16 (USER.53)
1275 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1277 return DestroyWindow(hwnd);
1281 /***********************************************************************
1282 * DestroyWindow32 (USER32.135)
1284 BOOL WINAPI DestroyWindow( HWND hwnd )
1289 TRACE(win, "(%04x)\n", hwnd);
1291 /* Initialization */
1293 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1294 if (wndPtr == pWndDesktop)
1296 WIN_ReleaseWndPtr(wndPtr);
1297 return FALSE; /* Can't destroy desktop */
1302 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1308 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1310 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1311 /* FIXME: clean up palette - see "Internals" p.352 */
1314 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1315 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1317 /* Notify the parent window only */
1318 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1319 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1320 if( !IsWindow(hwnd) )
1327 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1329 /* Hide the window */
1331 if (wndPtr->dwStyle & WS_VISIBLE)
1333 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1334 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1335 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1336 if (!IsWindow(hwnd))
1343 /* Recursively destroy owned windows */
1345 if( !(wndPtr->dwStyle & WS_CHILD) )
1347 /* make sure top menu popup doesn't get destroyed */
1348 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1352 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1355 if (siblingPtr->owner == wndPtr)
1357 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1360 siblingPtr->owner = NULL;
1362 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1366 DestroyWindow( siblingPtr->hwndSelf );
1367 WIN_ReleaseWndPtr(siblingPtr);
1372 if( !Options.managed || EVENT_CheckFocus() )
1373 WINPOS_ActivateOtherWindow(wndPtr);
1375 if( wndPtr->owner &&
1376 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1377 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1380 /* Send destroy messages */
1382 WIN_SendDestroyMsg( wndPtr );
1383 if (!IsWindow(hwnd))
1389 /* Unlink now so we won't bother with the children later on */
1391 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1393 /* Destroy the window storage */
1395 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1398 WIN_ReleaseWndPtr(wndPtr);
1403 /***********************************************************************
1404 * CloseWindow16 (USER.43)
1406 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1408 return CloseWindow( hwnd );
1412 /***********************************************************************
1413 * CloseWindow32 (USER32.56)
1415 BOOL WINAPI CloseWindow( HWND hwnd )
1417 WND * wndPtr = WIN_FindWndPtr( hwnd );
1420 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1425 ShowWindow( hwnd, SW_MINIMIZE );
1428 WIN_ReleaseWndPtr(wndPtr);
1434 /***********************************************************************
1435 * OpenIcon16 (USER.44)
1437 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1439 return OpenIcon( hwnd );
1443 /***********************************************************************
1444 * OpenIcon32 (USER32.410)
1446 BOOL WINAPI OpenIcon( HWND hwnd )
1448 if (!IsIconic( hwnd )) return FALSE;
1449 ShowWindow( hwnd, SW_SHOWNORMAL );
1454 /***********************************************************************
1457 * Implementation of FindWindow() and FindWindowEx().
1459 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1464 CLASS *pClass = NULL;
1468 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1471 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1477 else if (pWnd->parent != pWndDesktop)
1482 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1486 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1491 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1499 /* For a child window, all siblings will have the same hInstance, */
1500 /* so we can look for the class once and for all. */
1502 if (className && (pWnd->dwStyle & WS_CHILD))
1504 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1512 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1514 if (className && !(pWnd->dwStyle & WS_CHILD))
1516 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1517 continue; /* Skip this window */
1520 if (pClass && (pWnd->class != pClass))
1521 continue; /* Not the right class */
1523 /* Now check the title */
1527 retvalue = pWnd->hwndSelf;
1530 if (pWnd->text && !strcmp( pWnd->text, title ))
1532 retvalue = pWnd->hwndSelf;
1538 WIN_ReleaseWndPtr(pWnd);
1544 /***********************************************************************
1545 * FindWindow16 (USER.50)
1547 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1549 return FindWindowEx16( 0, 0, className, title );
1553 /***********************************************************************
1554 * FindWindowEx16 (USER.427)
1556 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1557 SEGPTR className, LPCSTR title )
1561 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1562 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1563 title ? title : "");
1567 /* If the atom doesn't exist, then no class */
1568 /* with this name exists either. */
1569 if (!(atom = GlobalFindAtom16( className ))) return 0;
1571 return WIN_FindWindow( parent, child, atom, 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 return pWndDesktop->hwndSelf;
1680 /**********************************************************************
1681 * GetDesktopHwnd (USER.278)
1683 * Exactly the same thing as GetDesktopWindow(), but not documented.
1684 * Don't ask me why...
1686 HWND16 WINAPI GetDesktopHwnd16(void)
1688 return (HWND16)pWndDesktop->hwndSelf;
1692 /*******************************************************************
1693 * EnableWindow16 (USER.34)
1695 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1697 return EnableWindow( hwnd, enable );
1701 /*******************************************************************
1702 * EnableWindow32 (USER32.172)
1704 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1709 TRACE(win,"EnableWindow32: ( %x, %d )\n", hwnd, enable);
1711 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1712 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1715 wndPtr->dwStyle &= ~WS_DISABLED;
1717 if( wndPtr->flags & WIN_NATIVE )
1718 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1720 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1724 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1726 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1728 /* Disable window */
1729 wndPtr->dwStyle |= WS_DISABLED;
1731 if( wndPtr->flags & WIN_NATIVE )
1732 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1734 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
1736 SetFocus( 0 ); /* A disabled window can't have the focus */
1738 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
1740 ReleaseCapture(); /* A disabled window can't capture the mouse */
1742 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1746 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1748 WIN_ReleaseWndPtr(wndPtr);
1753 /***********************************************************************
1754 * IsWindowEnabled16 (USER.35)
1756 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1758 return IsWindowEnabled(hWnd);
1762 /***********************************************************************
1763 * IsWindowEnabled32 (USER32.349)
1765 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1770 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1771 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1772 WIN_ReleaseWndPtr(wndPtr);
1778 /***********************************************************************
1779 * IsWindowUnicode (USER32.350)
1781 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1786 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1787 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1788 WIN_ReleaseWndPtr(wndPtr);
1793 /**********************************************************************
1794 * GetWindowWord16 (USER.133)
1796 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1798 return GetWindowWord( hwnd, offset );
1802 /**********************************************************************
1803 * GetWindowWord32 (USER32.314)
1805 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1808 WND * wndPtr = WIN_FindWndPtr( hwnd );
1809 if (!wndPtr) return 0;
1812 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1814 WARN( win, "Invalid offset %d\n", offset );
1818 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1824 if (HIWORD(wndPtr->wIDmenu))
1825 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1827 retvalue = (WORD)wndPtr->wIDmenu;
1829 case GWW_HWNDPARENT:
1830 retvalue = GetParent(hwnd);
1833 if (HIWORD(wndPtr->hInstance))
1834 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1836 retvalue = (WORD)wndPtr->hInstance;
1839 WARN( win, "Invalid offset %d\n", offset );
1844 WIN_ReleaseWndPtr(wndPtr);
1849 /**********************************************************************
1850 * WIN_GetWindowInstance
1852 HINSTANCE WIN_GetWindowInstance( HWND hwnd )
1855 WND * wndPtr = WIN_FindWndPtr( hwnd );
1856 if (!wndPtr) return (HINSTANCE)0;
1857 WIN_ReleaseWndPtr(wndPtr);
1858 return wndPtr->hInstance;
1863 /**********************************************************************
1864 * SetWindowWord16 (USER.134)
1866 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1868 return SetWindowWord( hwnd, offset, newval );
1872 /**********************************************************************
1873 * SetWindowWord32 (USER32.524)
1875 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1878 WND * wndPtr = WIN_FindWndPtr( hwnd );
1879 if (!wndPtr) return 0;
1882 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1884 WARN( win, "Invalid offset %d\n", offset );
1888 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1892 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1893 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1894 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1897 WARN( win, "Invalid offset %d\n", offset );
1904 WIN_ReleaseWndPtr(wndPtr);
1909 /**********************************************************************
1912 * Helper function for GetWindowLong().
1914 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1917 WND * wndPtr = WIN_FindWndPtr( hwnd );
1918 if (!wndPtr) return 0;
1921 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1923 WARN( win, "Invalid offset %d\n", offset );
1927 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1928 /* Special case for dialog window procedure */
1929 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1931 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1938 case GWL_USERDATA: retvalue = wndPtr->userdata;
1940 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1942 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1944 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1946 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1949 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1951 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1954 WARN( win, "Unknown offset %d\n", offset );
1958 WIN_ReleaseWndPtr(wndPtr);
1963 /**********************************************************************
1966 * Helper function for SetWindowLong().
1968 * 0 is the failure code. However, in the case of failure SetLastError
1969 * must be set to distinguish between a 0 return value and a failure.
1971 * FIXME: The error values for SetLastError may not be right. Can
1972 * someone check with the real thing?
1974 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1975 WINDOWPROCTYPE type )
1978 WND * wndPtr = WIN_FindWndPtr( hwnd );
1981 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1985 /* Is this the right error? */
1986 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1992 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1994 WARN( win, "Invalid offset %d\n", offset );
1996 /* Is this the right error? */
1997 SetLastError( ERROR_OUTOFMEMORY );
2002 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2003 /* Special case for dialog window procedure */
2004 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2006 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2007 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2008 type, WIN_PROC_WINDOW );
2015 ptr = (DWORD*)&wndPtr->wIDmenu;
2018 retval = SetWindowWord( hwnd, offset, newval );
2021 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2022 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2023 type, WIN_PROC_WINDOW );
2026 style.styleOld = wndPtr->dwStyle;
2027 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2028 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2030 if (wndPtr->flags & WIN_ISWIN32)
2031 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2032 wndPtr->dwStyle = style.styleNew;
2033 if (wndPtr->flags & WIN_ISWIN32)
2034 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2035 retval = style.styleOld;
2039 ptr = &wndPtr->userdata;
2042 style.styleOld = wndPtr->dwExStyle;
2043 style.styleNew = newval;
2044 if (wndPtr->flags & WIN_ISWIN32)
2045 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2046 wndPtr->dwExStyle = newval;
2047 if (wndPtr->flags & WIN_ISWIN32)
2048 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2049 retval = style.styleOld;
2053 WARN( win, "Invalid offset %d\n", offset );
2055 /* Don't think this is right error but it should do */
2056 SetLastError( ERROR_OUTOFMEMORY );
2064 WIN_ReleaseWndPtr(wndPtr);
2069 /**********************************************************************
2070 * GetWindowLong16 (USER.135)
2072 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2074 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2078 /**********************************************************************
2079 * GetWindowLong32A (USER32.305)
2081 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2083 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2087 /**********************************************************************
2088 * GetWindowLong32W (USER32.306)
2090 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2092 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2096 /**********************************************************************
2097 * SetWindowLong16 (USER.136)
2099 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2101 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2105 /**********************************************************************
2106 * SetWindowLong32A (USER32.517)
2108 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2110 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2114 /**********************************************************************
2115 * SetWindowLong32W (USER32.518) Set window attribute
2117 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2118 * value in a window's extra memory.
2120 * The _hwnd_ parameter specifies the window. is the handle to a
2121 * window that has extra memory. The _newval_ parameter contains the
2122 * new attribute or extra memory value. If positive, the _offset_
2123 * parameter is the byte-addressed location in the window's extra
2124 * memory to set. If negative, _offset_ specifies the window
2125 * attribute to set, and should be one of the following values:
2127 * GWL_EXSTYLE The window's extended window style
2129 * GWL_STYLE The window's window style.
2131 * GWL_WNDPROC Pointer to the window's window procedure.
2133 * GWL_HINSTANCE The window's pplication instance handle.
2135 * GWL_ID The window's identifier.
2137 * GWL_USERDATA The window's user-specified data.
2139 * If the window is a dialog box, the _offset_ parameter can be one of
2140 * the following values:
2142 * DWL_DLGPROC The address of the window's dialog box procedure.
2144 * DWL_MSGRESULT The return value of a message
2145 * that the dialog box procedure processed.
2147 * DWL_USER Application specific information.
2151 * If successful, returns the previous value located at _offset_. Otherwise,
2156 * Extra memory for a window class is specified by a nonzero cbWndExtra
2157 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2158 * time of class creation.
2160 * Using GWL_WNDPROC to set a new window procedure effectively creates
2161 * a window subclass. Use CallWindowProc() in the new windows procedure
2162 * to pass messages to the superclass's window procedure.
2164 * The user data is reserved for use by the application which created
2167 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2168 * instead, call the EnableWindow() function to change the window's
2171 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2172 * SetParent() instead.
2175 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2176 * it sends WM_STYLECHANGING before changing the settings
2177 * and WM_STYLECHANGED afterwards.
2178 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2182 * GWL_STYLE does not dispatch WM_STYLE... messages.
2189 LONG WINAPI SetWindowLongW(
2190 HWND hwnd, /* window to alter */
2191 INT offset, /* offset, in bytes, of location to alter */
2192 LONG newval /* new value of location */
2194 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2198 /*******************************************************************
2199 * GetWindowText16 (USER.36)
2201 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2203 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2207 /*******************************************************************
2208 * GetWindowText32A (USER32.309)
2210 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2212 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2216 /*******************************************************************
2217 * InternalGetWindowText (USER32.326)
2219 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2221 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2222 return GetWindowTextW(hwnd,lpString,nMaxCount);
2226 /*******************************************************************
2227 * GetWindowText32W (USER32.312)
2229 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2231 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2236 /*******************************************************************
2237 * SetWindowText16 (USER.37)
2239 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2241 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2245 /*******************************************************************
2246 * SetWindowText32A (USER32.521)
2248 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2250 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2254 /*******************************************************************
2255 * SetWindowText32W (USER32.523)
2257 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2259 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2263 /*******************************************************************
2264 * GetWindowTextLength16 (USER.38)
2266 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2268 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2272 /*******************************************************************
2273 * GetWindowTextLength32A (USER32.310)
2275 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2277 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2280 /*******************************************************************
2281 * GetWindowTextLength32W (USER32.311)
2283 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2285 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2289 /*******************************************************************
2290 * IsWindow16 (USER.47)
2292 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2294 return IsWindow( hwnd );
2297 void WINAPI WIN16_IsWindow16( CONTEXT *context )
2299 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
2300 HWND16 hwnd = (HWND16)stack[2];
2302 AX_reg(context) = IsWindow( hwnd );
2303 ES_reg(context) = USER_HeapSel;
2307 /*******************************************************************
2308 * IsWindow32 (USER32.348)
2310 BOOL WINAPI IsWindow( HWND hwnd )
2315 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2316 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2317 WIN_ReleaseWndPtr(wndPtr);
2323 /*****************************************************************
2324 * GetParent16 (USER.46)
2326 HWND16 WINAPI GetParent16( HWND16 hwnd )
2328 return (HWND16)GetParent( hwnd );
2332 /*****************************************************************
2333 * GetParent32 (USER32.278)
2335 HWND WINAPI GetParent( HWND hwnd )
2340 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2341 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2343 WIN_ReleaseWndPtr(wndPtr);
2346 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2347 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2349 WIN_ReleaseWndPtr(wndPtr);
2354 /*****************************************************************
2357 * Get the top-level parent for a child window.
2358 * returns a locked pointer
2360 WND* WIN_GetTopParentPtr( WND* pWnd )
2362 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2364 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2366 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2371 /*****************************************************************
2374 * Get the top-level parent for a child window.
2376 HWND WIN_GetTopParent( HWND hwnd )
2379 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2380 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2382 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2383 WIN_ReleaseWndPtr(tmpPtr);
2384 WIN_ReleaseWndPtr(wndPtr);
2389 /*****************************************************************
2390 * SetParent16 (USER.233)
2392 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2394 return SetParent( hwndChild, hwndNewParent );
2398 /*****************************************************************
2399 * SetParent32 (USER32.495)
2401 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2410 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2412 dwStyle = wndPtr->dwStyle;
2414 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2415 : WIN_LockWndPtr(pWndDesktop);
2417 /* Windows hides the window first, then shows it again
2418 * including the WM_SHOWWINDOW messages and all */
2419 if (dwStyle & WS_VISIBLE)
2420 ShowWindow( hwndChild, SW_HIDE );
2422 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2424 /* SetParent32 additionally needs to make hwndChild the topmost window
2425 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2426 WM_WINDOWPOSCHANGED notification messages.
2428 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2429 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2430 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2431 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2433 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2435 WIN_ReleaseWndPtr(pWndOldParent);
2436 WIN_ReleaseWndPtr(pWndNewParent);
2437 WIN_ReleaseWndPtr(wndPtr);
2443 /*******************************************************************
2444 * IsChild16 (USER.48)
2446 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2448 return IsChild(parent,child);
2452 /*******************************************************************
2453 * IsChild32 (USER32.339)
2455 BOOL WINAPI IsChild( HWND parent, HWND child )
2457 WND * wndPtr = WIN_FindWndPtr( child );
2458 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2460 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2461 if (wndPtr->hwndSelf == parent)
2463 WIN_ReleaseWndPtr(wndPtr);
2467 WIN_ReleaseWndPtr(wndPtr);
2472 /***********************************************************************
2473 * IsWindowVisible16 (USER.49)
2475 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2477 return IsWindowVisible(hwnd);
2481 /***********************************************************************
2482 * IsWindowVisible32 (USER32.351)
2484 BOOL WINAPI IsWindowVisible( HWND hwnd )
2487 WND *wndPtr = WIN_FindWndPtr( hwnd );
2488 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2490 if (!(wndPtr->dwStyle & WS_VISIBLE))
2492 WIN_ReleaseWndPtr(wndPtr);
2495 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2497 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2498 WIN_ReleaseWndPtr(wndPtr);
2504 /***********************************************************************
2505 * WIN_IsWindowDrawable
2507 * hwnd is drawable when it is visible, all parents are not
2508 * minimized, and it is itself not minimized unless we are
2509 * trying to draw its default class icon.
2511 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2513 if( (wnd->dwStyle & WS_MINIMIZE &&
2514 icon && wnd->class->hIcon) ||
2515 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2516 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2517 if( wnd->dwStyle & WS_MINIMIZE ||
2518 !(wnd->dwStyle & WS_VISIBLE) ) break;
2519 return (wnd == NULL);
2523 /*******************************************************************
2524 * GetTopWindow16 (USER.229)
2526 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2528 return GetTopWindow(hwnd);
2532 /*******************************************************************
2533 * GetTopWindow32 (USER.229)
2535 HWND WINAPI GetTopWindow( HWND hwnd )
2538 WND * wndPtr = WIN_FindWndPtr( hwnd );
2539 if (wndPtr && wndPtr->child)
2541 retval = wndPtr->child->hwndSelf;
2544 WIN_ReleaseWndPtr(wndPtr);
2549 /*******************************************************************
2550 * GetWindow16 (USER.262)
2552 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2554 return GetWindow( hwnd,rel );
2558 /*******************************************************************
2559 * GetWindow32 (USER32.302)
2561 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2565 WND * wndPtr = WIN_FindWndPtr( hwnd );
2566 if (!wndPtr) return 0;
2570 if (wndPtr->parent) retval = wndPtr->parent->child->hwndSelf;
2575 if (!wndPtr->parent)
2577 retval = 0; /* Desktop window */
2580 while (wndPtr->next)
2582 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2584 retval = wndPtr->hwndSelf;
2588 if (!wndPtr->next) retval = 0;
2589 else retval = wndPtr->next->hwndSelf;
2593 if (!wndPtr->parent)
2595 retval = 0; /* Desktop window */
2598 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2599 if (wndPtr->hwndSelf == hwnd)
2601 retval = 0; /* First in list */
2604 while (wndPtr->next)
2606 if (wndPtr->next->hwndSelf == hwnd)
2608 retval = wndPtr->hwndSelf;
2611 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2617 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2621 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2626 WIN_ReleaseWndPtr(wndPtr);
2631 /*******************************************************************
2632 * GetNextWindow16 (USER.230)
2634 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2636 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2637 return GetWindow16( hwnd, flag );
2640 /*******************************************************************
2641 * ShowOwnedPopups16 (USER.265)
2643 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2645 ShowOwnedPopups( owner, fShow );
2649 /*******************************************************************
2650 * ShowOwnedPopups32 (USER32.531)
2652 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2655 pWnd = WIN_LockWndPtr(pWndDesktop->child);
2658 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2659 (pWnd->dwStyle & WS_POPUP))
2660 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2661 WIN_UpdateWndPtr(&pWnd,pWnd->next);
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 )
2682 wndPtr = WIN_FindWndPtr(hwnd);
2683 if (!wndPtr) return hwnd;
2684 retval = wndPtr->hwndLastActive;
2685 WIN_ReleaseWndPtr(wndPtr);
2690 /*******************************************************************
2693 * Build an array of pointers to the children of a given window.
2694 * The array must be freed with HeapFree(SystemHeap). Return NULL
2695 * when no windows are found.
2697 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2699 /* Future : this function will lock all windows associated with this array */
2701 WND **list, **ppWnd;
2703 UINT count = 0, skipOwned, skipHidden;
2706 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2707 skipOwned = bwaFlags & BWA_SKIPOWNED;
2708 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2709 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2711 /* First count the windows */
2714 wndPtr = WIN_GetDesktop();
2716 pWnd = WIN_LockWndPtr(wndPtr->child);
2719 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2720 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2722 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2727 /* Now build the list of all windows */
2729 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2731 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2733 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2734 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2740 WIN_ReleaseWndPtr(pWnd);
2746 if( pTotal ) *pTotal = count;
2749 /*******************************************************************
2750 * WIN_ReleaseWinArray
2752 void WIN_ReleaseWinArray(WND **wndArray)
2754 /* Future : this function will also unlock all windows associated with wndArray */
2755 HeapFree( SystemHeap, 0, wndArray );
2759 /*******************************************************************
2760 * EnumWindows16 (USER.54)
2762 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2764 WND **list, **ppWnd;
2766 /* We have to build a list of all windows first, to avoid */
2767 /* unpleasant side-effects, for instance if the callback */
2768 /* function changes the Z-order of the windows. */
2770 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2772 WIN_ReleaseDesktop();
2776 /* Now call the callback function for every window */
2778 for (ppWnd = list; *ppWnd; ppWnd++)
2780 LRESULT lpEnumFuncRetval;
2782 /* Make sure that the window still exists */
2783 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2785 /* To avoid any deadlocks, all the locks on the windows
2786 structures must be suspended before the control
2787 is passed to the application */
2788 iWndsLocks = WIN_SuspendWndsLock();
2789 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2790 WIN_RestoreWndsLock(iWndsLocks);
2792 if (!lpEnumFuncRetval) break;
2794 WIN_ReleaseWinArray(list);
2795 WIN_ReleaseDesktop();
2800 /*******************************************************************
2801 * EnumWindows32 (USER32.193)
2803 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2805 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2809 /**********************************************************************
2810 * EnumTaskWindows16 (USER.225)
2812 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2815 WND **list, **ppWnd;
2817 /* This function is the same as EnumWindows(), */
2818 /* except for an added check on the window's task. */
2820 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2822 WIN_ReleaseDesktop();
2826 /* Now call the callback function for every window */
2828 for (ppWnd = list; *ppWnd; ppWnd++)
2832 /* Make sure that the window still exists */
2833 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2834 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2836 /* To avoid any deadlocks, all the locks on the windows
2837 structures must be suspended before the control
2838 is passed to the application */
2839 iWndsLocks = WIN_SuspendWndsLock();
2840 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2841 WIN_RestoreWndsLock(iWndsLocks);
2843 if (!funcRetval) break;
2845 WIN_ReleaseWinArray(list);
2846 WIN_ReleaseDesktop();
2851 /**********************************************************************
2852 * EnumThreadWindows (USER32.190)
2854 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2856 THDB *tdb = THREAD_IdToTHDB(id);
2858 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2862 /**********************************************************************
2863 * WIN_EnumChildWindows
2865 * Helper function for EnumChildWindows().
2867 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2873 for ( ; *ppWnd; ppWnd++)
2877 /* Make sure that the window still exists */
2878 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2879 /* Build children list first */
2880 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2882 /* To avoid any deadlocks, all the locks on the windows
2883 structures must be suspended before the control
2884 is passed to the application */
2885 iWndsLocks = WIN_SuspendWndsLock();
2886 ret = func( (*ppWnd)->hwndSelf, lParam );
2887 WIN_RestoreWndsLock(iWndsLocks);
2891 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2892 WIN_ReleaseWinArray(childList);
2894 if (!ret) return FALSE;
2900 /**********************************************************************
2901 * EnumChildWindows16 (USER.55)
2903 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2906 WND **list, *pParent;
2908 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2909 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2911 WIN_ReleaseWndPtr(pParent);
2914 WIN_EnumChildWindows( list, func, lParam );
2915 WIN_ReleaseWinArray(list);
2916 WIN_ReleaseWndPtr(pParent);
2921 /**********************************************************************
2922 * EnumChildWindows32 (USER32.178)
2924 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2927 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2932 /*******************************************************************
2933 * AnyPopup16 (USER.52)
2935 BOOL16 WINAPI AnyPopup16(void)
2941 /*******************************************************************
2942 * AnyPopup32 (USER32.4)
2944 BOOL WINAPI AnyPopup(void)
2946 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2951 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2956 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2960 WIN_ReleaseWndPtr(wndPtr);
2965 /*******************************************************************
2966 * FlashWindow16 (USER.105)
2968 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2970 return FlashWindow( hWnd, bInvert );
2974 /*******************************************************************
2975 * FlashWindow32 (USER32.202)
2977 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2979 WND *wndPtr = WIN_FindWndPtr(hWnd);
2981 TRACE(win,"%04x\n", hWnd);
2983 if (!wndPtr) return FALSE;
2985 if (wndPtr->dwStyle & WS_MINIMIZE)
2987 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2989 HDC hDC = GetDC(hWnd);
2991 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2992 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2994 ReleaseDC( hWnd, hDC );
2995 wndPtr->flags |= WIN_NCACTIVATED;
2999 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3000 RDW_UPDATENOW | RDW_FRAME, 0 );
3001 wndPtr->flags &= ~WIN_NCACTIVATED;
3003 WIN_ReleaseWndPtr(wndPtr);
3009 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3010 else wparam = (hWnd == GetActiveWindow());
3012 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3013 WIN_ReleaseWndPtr(wndPtr);
3019 /*******************************************************************
3020 * SetSysModalWindow16 (USER.188)
3022 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3024 HWND hWndOldModal = hwndSysModal;
3025 hwndSysModal = hWnd;
3026 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3027 return hWndOldModal;
3031 /*******************************************************************
3032 * GetSysModalWindow16 (USER.52)
3034 HWND16 WINAPI GetSysModalWindow16(void)
3036 return hwndSysModal;
3040 /*******************************************************************
3041 * GetWindowContextHelpId (USER32.303)
3043 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3046 WND *wnd = WIN_FindWndPtr( hwnd );
3048 retval = wnd->helpContext;
3049 WIN_ReleaseWndPtr(wnd);
3054 /*******************************************************************
3055 * SetWindowContextHelpId (USER32.515)
3057 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3059 WND *wnd = WIN_FindWndPtr( hwnd );
3060 if (!wnd) return FALSE;
3061 wnd->helpContext = id;
3062 WIN_ReleaseWndPtr(wnd);
3067 /*******************************************************************
3070 * recursively find a child that contains spDragInfo->pt point
3071 * and send WM_QUERYDROPOBJECT
3073 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3075 BOOL16 wParam,bResult = 0;
3077 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3078 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3081 if( !ptrQueryWnd || !ptrDragInfo )
3083 WIN_ReleaseWndPtr(ptrQueryWnd);
3087 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3089 GetWindowRect(hQueryWnd,&tempRect);
3091 if( !PtInRect(&tempRect,pt) ||
3092 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3094 WIN_ReleaseWndPtr(ptrQueryWnd);
3098 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3100 tempRect = ptrQueryWnd->rectClient;
3101 if(ptrQueryWnd->dwStyle & WS_CHILD)
3102 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3103 (LPPOINT)&tempRect, 2 );
3105 if (PtInRect( &tempRect, pt))
3109 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3111 if( ptrWnd->dwStyle & WS_VISIBLE )
3113 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3114 if (PtInRect( &tempRect, pt )) break;
3120 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
3121 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3122 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3123 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3124 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3126 WIN_ReleaseWndPtr(ptrWnd);
3131 WIN_ReleaseWndPtr(ptrQueryWnd);
3139 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3141 ptrDragInfo->hScope = hQueryWnd;
3143 bResult = ( bNoSend )
3144 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3145 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3146 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3148 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3150 WIN_ReleaseWndPtr(ptrQueryWnd);
3155 /*******************************************************************
3156 * DragDetect (USER.465)
3158 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3161 CONV_POINT16TO32( &pt, &pt32 );
3162 return DragDetect( hWnd, pt32 );
3165 /*******************************************************************
3166 * DragDetect32 (USER32.151)
3168 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3173 rect.left = pt.x - wDragWidth;
3174 rect.right = pt.x + wDragWidth;
3176 rect.top = pt.y - wDragHeight;
3177 rect.bottom = pt.y + wDragHeight;
3183 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3185 if( msg.message == WM_LBUTTONUP )
3190 if( msg.message == WM_MOUSEMOVE )
3192 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3204 /******************************************************************************
3205 * DragObject16 (USER.464)
3207 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3208 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3211 LPDRAGINFO lpDragInfo;
3213 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3214 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3215 WND *wndPtr = WIN_FindWndPtr(hWnd);
3216 HCURSOR16 hCurrentCursor = 0;
3217 HWND16 hCurrentWnd = 0;
3219 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3220 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3222 if( !lpDragInfo || !spDragInfo )
3224 WIN_ReleaseWndPtr(wndPtr);
3228 hBummer = LoadCursor16(0, IDC_BUMMER16);
3230 if( !hBummer || !wndPtr )
3232 GlobalFree16(hDragInfo);
3233 WIN_ReleaseWndPtr(wndPtr);
3239 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3241 GlobalFree16(hDragInfo);
3242 WIN_ReleaseWndPtr(wndPtr);
3246 if( hDragCursor == hCursor ) hDragCursor = 0;
3247 else hCursor = hDragCursor;
3249 hOldCursor = SetCursor(hDragCursor);
3252 lpDragInfo->hWnd = hWnd;
3253 lpDragInfo->hScope = 0;
3254 lpDragInfo->wFlags = wObj;
3255 lpDragInfo->hList = szList; /* near pointer! */
3256 lpDragInfo->hOfStruct = hOfStruct;
3264 do{ WaitMessage(); }
3265 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3267 *(lpDragInfo+1) = *lpDragInfo;
3269 lpDragInfo->pt = msg.pt;
3271 /* update DRAGINFO struct */
3272 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
3274 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3275 hCurrentCursor = hCursor;
3278 hCurrentCursor = hBummer;
3279 lpDragInfo->hScope = 0;
3281 if( hCurrentCursor )
3282 SetCursor(hCurrentCursor);
3284 /* send WM_DRAGLOOP */
3285 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3286 (LPARAM) spDragInfo );
3287 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3288 if( hCurrentWnd != lpDragInfo->hScope )
3291 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3292 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3293 HIWORD(spDragInfo)) );
3294 hCurrentWnd = lpDragInfo->hScope;
3296 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3300 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3302 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3305 ShowCursor( FALSE );
3309 SetCursor( hOldCursor );
3310 if (hDragCursor) DestroyCursor( hDragCursor );
3313 if( hCurrentCursor != hBummer )
3314 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3315 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3318 GlobalFree16(hDragInfo);
3319 WIN_ReleaseWndPtr(wndPtr);
3321 return (DWORD)(msg.lParam);