2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include "wine/winbase16.h"
11 #include "wine/winuser16.h"
12 #include "wine/unicode.h"
18 #include "cursoricon.h"
24 #include "stackframe.h"
25 #include "debugtools.h"
27 DEFAULT_DEBUG_CHANNEL(win);
28 DECLARE_DEBUG_CHANNEL(msg);
30 /**********************************************************************/
32 WND_DRIVER *WND_Driver = NULL;
35 static WND *pWndDesktop = NULL;
37 static HWND hwndSysModal = 0;
39 static WORD wDragWidth = 4;
40 static WORD wDragHeight= 3;
43 static SYSLEVEL WIN_SysLevel = { CRITICAL_SECTION_INIT, 2 };
45 /***********************************************************************
48 * Locks access to all WND structures for thread safeness
50 void WIN_LockWnds( void )
52 _EnterSysLevel( &WIN_SysLevel );
55 /***********************************************************************
58 * Unlocks access to all WND structures
60 void WIN_UnlockWnds( void )
62 _LeaveSysLevel( &WIN_SysLevel );
65 /***********************************************************************
68 * Suspend the lock on WND structures.
69 * Returns the number of locks suspended
71 int WIN_SuspendWndsLock( void )
73 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
74 int count = isuspendedLocks;
77 _LeaveSysLevel( &WIN_SysLevel );
79 return isuspendedLocks;
82 /***********************************************************************
85 * Restore the suspended locks on WND structures
87 void WIN_RestoreWndsLock( int ipreviousLocks )
89 while ( ipreviousLocks-- > 0 )
90 _EnterSysLevel( &WIN_SysLevel );
93 /***********************************************************************
96 * Return a pointer to the WND structure corresponding to a HWND.
98 WND * WIN_FindWndPtr( HWND hwnd )
102 if (!hwnd || HIWORD(hwnd)) goto error2;
103 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
104 /* Lock all WND structures for thread safeness*/
106 /*and increment destruction monitoring*/
109 if (ptr->dwMagic != WND_MAGIC) goto error;
110 if (ptr->hwndSelf != hwnd)
112 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
115 /* returns a locked pointer */
118 /* Unlock all WND structures for thread safeness*/
120 /* and decrement destruction monitoring value */
125 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
129 /***********************************************************************
132 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
134 * Returns the locked initialisation pointer
136 WND *WIN_LockWndPtr(WND *initWndPtr)
138 if(!initWndPtr) return 0;
140 /* Lock all WND structures for thread safeness*/
142 /*and increment destruction monitoring*/
143 initWndPtr->irefCount++;
149 /***********************************************************************
152 * Release the pointer to the WND structure.
154 void WIN_ReleaseWndPtr(WND *wndPtr)
158 /*Decrement destruction monitoring value*/
160 /* Check if it's time to release the memory*/
161 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
164 USER_HEAP_FREE( wndPtr->hwndSelf);
165 wndPtr->hwndSelf = 0;
167 else if(wndPtr->irefCount < 0)
169 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
170 ERR("forgot a Lock on %p somewhere\n",wndPtr);
172 /*unlock all WND structures for thread safeness*/
176 /***********************************************************************
179 * Updates the value of oldPtr to newPtr.
181 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
185 tmpWnd = WIN_LockWndPtr(newPtr);
186 WIN_ReleaseWndPtr(*oldPtr);
191 /***********************************************************************
194 * Dump the content of a window structure to stderr.
196 void WIN_DumpWindow( HWND hwnd )
202 if (!(ptr = WIN_FindWndPtr( hwnd )))
204 WARN("%04x is not a window handle\n", hwnd );
208 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
209 strcpy( className, "#NULL#" );
211 TRACE("Window %04x (%p):\n", hwnd, ptr );
212 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
213 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
214 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
215 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
216 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
217 ptr->next, ptr->child, ptr->parent, ptr->owner,
218 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
219 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
220 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
221 ptr->text ? debugstr_w(ptr->text) : "",
222 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
223 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
224 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
225 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
229 DPRINTF( "extra bytes:" );
230 for (i = 0; i < ptr->cbWndExtra; i++)
231 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
235 WIN_ReleaseWndPtr(ptr);
239 /***********************************************************************
242 * Walk the windows tree and print each window on stderr.
244 void WIN_WalkWindows( HWND hwnd, int indent )
249 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
253 WARN("Invalid window handle %04x\n", hwnd );
257 if (!indent) /* first time around */
258 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
259 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
264 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
266 GetClassNameA( ptr->hwndSelf, className, sizeof(className) );
267 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
268 (DWORD)ptr, ptr->hmemTaskQ, className,
269 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
270 ptr->text ? debugstr_w(ptr->text) : "<null>");
272 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
273 WIN_UpdateWndPtr(&ptr,ptr->next);
277 /***********************************************************************
280 * Remove a window from the siblings linked list.
282 BOOL WIN_UnlinkWindow( HWND hwnd )
284 WND *wndPtr, **ppWnd;
287 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
288 else if(!wndPtr->parent)
290 WIN_ReleaseWndPtr(wndPtr);
294 ppWnd = &wndPtr->parent->child;
295 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
298 *ppWnd = wndPtr->next;
301 WIN_ReleaseWndPtr(wndPtr);
306 /***********************************************************************
309 * Insert a window into the siblings linked list.
310 * The window is inserted after the specified window, which can also
311 * be specified as HWND_TOP or HWND_BOTTOM.
313 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
315 WND *wndPtr, **ppWnd;
317 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
318 else if(!wndPtr->parent)
320 WIN_ReleaseWndPtr(wndPtr);
323 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
325 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
326 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
327 while (*ppWnd) ppWnd = &(*ppWnd)->next;
329 else /* Normal case */
331 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
334 WIN_ReleaseWndPtr(wndPtr);
337 ppWnd = &afterPtr->next;
338 WIN_ReleaseWndPtr(afterPtr);
340 wndPtr->next = *ppWnd;
342 WIN_ReleaseWndPtr(wndPtr);
347 /***********************************************************************
348 * WIN_FindWinToRepaint
350 * Find a window that needs repaint.
352 HWND WIN_FindWinToRepaint( HWND hwnd )
357 /* Note: the desktop window never gets WM_PAINT messages
358 * The real reason why is because Windows DesktopWndProc
359 * does ValidateRgn inside WM_ERASEBKGND handler.
361 if (hwnd == GetDesktopWindow()) hwnd = 0;
363 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
365 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
367 if (!(pWnd->dwStyle & WS_VISIBLE))
369 TRACE("skipping window %04x\n",
372 else if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
373 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
376 else if (pWnd->child )
377 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
379 WIN_ReleaseWndPtr(pWnd);
390 hwndRet = pWnd->hwndSelf;
392 /* look among siblings if we got a transparent window */
393 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
394 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
396 WIN_UpdateWndPtr(&pWnd,pWnd->next);
400 hwndRet = pWnd->hwndSelf;
401 WIN_ReleaseWndPtr(pWnd);
403 TRACE("found %04x\n",hwndRet);
408 /***********************************************************************
411 * Destroy storage associated to a window. "Internals" p.358
412 * returns a locked wndPtr->next
414 static WND* WIN_DestroyWindow( WND* wndPtr )
416 HWND hwnd = wndPtr->hwndSelf;
419 TRACE("%04x\n", wndPtr->hwndSelf );
421 /* free child windows */
422 WIN_LockWndPtr(wndPtr->child);
423 while ((pWnd = wndPtr->child))
425 wndPtr->child = WIN_DestroyWindow( pWnd );
426 WIN_ReleaseWndPtr(pWnd);
430 * Clear the update region to make sure no WM_PAINT messages will be
431 * generated for this window while processing the WM_NCDESTROY.
433 RedrawWindow( wndPtr->hwndSelf, NULL, 0,
434 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
437 * Send the WM_NCDESTROY to the window being destroyed.
439 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
441 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
443 WINPOS_CheckInternalPos( wndPtr );
444 if( hwnd == GetCapture()) ReleaseCapture();
446 /* free resources associated with the window */
448 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
449 PROPERTY_RemoveWindowProps( wndPtr );
451 /* toss stale messages from the queue */
453 QUEUE_CleanupWindow( hwnd );
454 wndPtr->hmemTaskQ = 0;
456 if (!(wndPtr->dwStyle & WS_CHILD))
459 DestroyMenu( wndPtr->wIDmenu );
462 if (wndPtr->hSysMenu)
464 DestroyMenu( wndPtr->hSysMenu );
465 wndPtr->hSysMenu = 0;
467 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
468 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
469 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
470 CLASS_RemoveWindow( wndPtr->class );
471 wndPtr->class = NULL;
472 wndPtr->dwMagic = 0; /* Mark it as invalid */
474 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
479 /***********************************************************************
480 * WIN_DestroyThreadWindows
482 * Destroy all children of 'wnd' owned by the current thread.
483 * Return TRUE if something was done.
485 BOOL WIN_DestroyThreadWindows( HWND hwnd )
488 WND *wnd = WIN_FindWndPtr( hwnd );
490 if (!wnd) return FALSE;
493 WND *tmp = WIN_LockWndPtr(wnd->child);
497 if (GetWindowThreadProcessId( tmp->hwndSelf, NULL ) == GetCurrentThreadId())
499 DestroyWindow( tmp->hwndSelf );
503 if (tmp->child && WIN_DestroyThreadWindows( tmp->hwndSelf ))
506 WIN_UpdateWndPtr(&tmp,tmp->next);
508 WIN_ReleaseWndPtr(tmp);
511 WIN_ReleaseWndPtr( wnd );
515 /***********************************************************************
516 * WIN_CreateDesktopWindow
518 * Create the desktop window.
520 BOOL WIN_CreateDesktopWindow(void)
522 struct tagCLASS *class;
530 TRACE("Creating desktop window\n");
533 if (!WINPOS_CreateInternalPosAtom() ||
534 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
535 &wndExtra, &winproc, &clsStyle, &dce )))
538 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
539 if (!hwndDesktop) return FALSE;
540 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
542 pWndDesktop->pDriver = WND_Driver;
543 pWndDesktop->next = NULL;
544 pWndDesktop->child = NULL;
545 pWndDesktop->parent = NULL;
546 pWndDesktop->owner = NULL;
547 pWndDesktop->class = class;
548 pWndDesktop->dwMagic = WND_MAGIC;
549 pWndDesktop->hwndSelf = hwndDesktop;
550 pWndDesktop->hInstance = 0;
551 pWndDesktop->rectWindow.left = 0;
552 pWndDesktop->rectWindow.top = 0;
553 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
554 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
555 pWndDesktop->rectClient = pWndDesktop->rectWindow;
556 pWndDesktop->text = NULL;
557 pWndDesktop->hmemTaskQ = 0;
558 pWndDesktop->hrgnUpdate = 0;
559 pWndDesktop->hwndLastActive = hwndDesktop;
560 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
562 pWndDesktop->dwExStyle = 0;
563 pWndDesktop->clsStyle = clsStyle;
564 pWndDesktop->dce = NULL;
565 pWndDesktop->pVScroll = NULL;
566 pWndDesktop->pHScroll = NULL;
567 pWndDesktop->pProp = NULL;
568 pWndDesktop->wIDmenu = 0;
569 pWndDesktop->helpContext = 0;
570 pWndDesktop->flags = 0;
571 pWndDesktop->hSysMenu = 0;
572 pWndDesktop->userdata = 0;
573 pWndDesktop->winproc = winproc;
574 pWndDesktop->cbWndExtra = wndExtra;
575 pWndDesktop->irefCount = 0;
577 cs.lpCreateParams = NULL;
583 cs.cx = pWndDesktop->rectWindow.right;
584 cs.cy = pWndDesktop->rectWindow.bottom;
585 cs.style = pWndDesktop->dwStyle;
586 cs.dwExStyle = pWndDesktop->dwExStyle;
588 cs.lpszClass = DESKTOP_CLASS_ATOM;
590 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
592 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
597 /***********************************************************************
600 * Fix the coordinates - Helper for WIN_CreateWindowEx.
601 * returns default show mode in sw.
602 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
604 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
606 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
607 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
609 if (cs->style & (WS_CHILD | WS_POPUP))
611 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
612 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
614 else /* overlapped window */
618 GetStartupInfoA( &info );
620 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
622 /* Never believe Microsoft's documentation... CreateWindowEx doc says
623 * that if an overlapped window is created with WS_VISIBLE style bit
624 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
625 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
628 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
629 * 2) it does not ignore the y parameter as the docs claim; instead, it
630 * uses it as second parameter to ShowWindow() unless y is either
631 * CW_USEDEFAULT or CW_USEDEFAULT16.
633 * The fact that we didn't do 2) caused bogus windows pop up when wine
634 * was running apps that were using this obscure feature. Example -
635 * calc.exe that comes with Win98 (only Win98, it's different from
636 * the one that comes with Win95 and NT)
638 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
639 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
640 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
643 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
645 if (info.dwFlags & STARTF_USESIZE)
647 cs->cx = info.dwXSize;
648 cs->cy = info.dwYSize;
650 else /* if no other hint from the app, pick 3/4 of the screen real estate */
653 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
654 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
655 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
662 /***********************************************************************
665 * Implementation of CreateWindowEx().
667 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
668 WINDOWPROCTYPE type )
671 struct tagCLASS *classPtr;
673 HWND hwnd, hwndLinkAfter;
674 POINT maxSize, maxPos, minTrack, maxTrack;
679 BOOL unicode = (type == WIN_PROC_32W);
681 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
682 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
683 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
684 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
685 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
687 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
688 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
690 /* Find the parent window */
694 /* Make sure parent is valid */
695 if (!IsWindow( cs->hwndParent ))
697 WARN("Bad parent %04x\n", cs->hwndParent );
700 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
701 WARN("No parent for child window\n" );
702 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
705 /* Find the window class */
706 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
707 &wndExtra, &winproc, &clsStyle, &dce )))
709 WARN("Bad class '%s'\n", cs->lpszClass );
713 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
715 /* Create the window structure */
717 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
719 TRACE("out of memory\n" );
723 /* Fill the window structure */
725 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
727 wndPtr->child = NULL;
729 if ((cs->style & WS_CHILD) && cs->hwndParent)
731 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
732 wndPtr->owner = NULL;
733 WIN_ReleaseWndPtr(wndPtr->parent);
737 wndPtr->parent = pWndDesktop;
738 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
739 wndPtr->owner = NULL;
742 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
743 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
744 WIN_ReleaseWndPtr(wndPtr->owner);
745 WIN_ReleaseWndPtr(tmpWnd);
750 wndPtr->pDriver = wndPtr->parent->pDriver;
752 wndPtr->class = classPtr;
753 wndPtr->winproc = winproc;
754 wndPtr->dwMagic = WND_MAGIC;
755 wndPtr->hwndSelf = hwnd;
756 wndPtr->hInstance = cs->hInstance;
758 wndPtr->hmemTaskQ = GetFastQueue16();
759 wndPtr->hrgnUpdate = 0;
761 wndPtr->hwndLastActive = hwnd;
762 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
763 wndPtr->dwExStyle = cs->dwExStyle;
764 wndPtr->clsStyle = clsStyle;
766 wndPtr->helpContext = 0;
767 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
768 wndPtr->pVScroll = NULL;
769 wndPtr->pHScroll = NULL;
770 wndPtr->pProp = NULL;
771 wndPtr->userdata = 0;
772 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
773 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
774 wndPtr->cbWndExtra = wndExtra;
775 wndPtr->irefCount = 1;
777 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
779 /* Call the WH_CBT hook */
781 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
782 ? HWND_BOTTOM : HWND_TOP;
784 if (HOOK_IsHooked( WH_CBT ))
790 cbtc.hwndInsertAfter = hwndLinkAfter;
791 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
792 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
795 TRACE("CBT-hook returned 0\n");
796 USER_HEAP_FREE( hwnd );
797 CLASS_RemoveWindow( classPtr );
803 /* Correct the window style */
805 if (!(cs->style & WS_CHILD))
807 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
808 if (!(cs->style & WS_POPUP))
810 wndPtr->dwStyle |= WS_CAPTION;
811 wndPtr->flags |= WIN_NEED_SIZE;
815 /* Get class or window DC if needed */
817 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
818 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
819 else wndPtr->dce = NULL;
821 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
823 wndPtr->rectWindow.left = cs->x;
824 wndPtr->rectWindow.top = cs->y;
825 wndPtr->rectWindow.right = cs->x + cs->cx;
826 wndPtr->rectWindow.bottom = cs->y + cs->cy;
827 wndPtr->rectClient = wndPtr->rectWindow;
829 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
831 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
833 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
834 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
835 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
836 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
837 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
840 if (cs->cx < 0) cs->cx = 0;
841 if (cs->cy < 0) cs->cy = 0;
843 wndPtr->rectWindow.left = cs->x;
844 wndPtr->rectWindow.top = cs->y;
845 wndPtr->rectWindow.right = cs->x + cs->cx;
846 wndPtr->rectWindow.bottom = cs->y + cs->cy;
847 wndPtr->rectClient = wndPtr->rectWindow;
849 /* Set the window menu */
851 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
853 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
856 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
859 if (HIWORD(cs->hInstance))
860 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
862 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
864 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
868 else wndPtr->wIDmenu = (UINT)cs->hMenu;
870 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
872 WARN("aborted by WM_xxCREATE!\n");
873 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
874 CLASS_RemoveWindow( classPtr );
875 WIN_ReleaseWndPtr(wndPtr);
879 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
881 /* Notify the parent window only */
883 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
884 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
885 if( !IsWindow(hwnd) )
892 if (cs->style & WS_VISIBLE)
894 /* in case WS_VISIBLE got set in the meantime */
895 wndPtr->dwStyle &= ~WS_VISIBLE;
896 ShowWindow( hwnd, sw );
899 /* Call WH_SHELL hook */
901 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
902 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
904 TRACE("created window %04x\n", hwnd);
906 WIN_ReleaseWndPtr(wndPtr);
911 /***********************************************************************
912 * CreateWindow (USER.41)
914 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
915 DWORD style, INT16 x, INT16 y, INT16 width,
916 INT16 height, HWND16 parent, HMENU16 menu,
917 HINSTANCE16 instance, LPVOID data )
919 return CreateWindowEx16( 0, className, windowName, style,
920 x, y, width, height, parent, menu, instance, data );
924 /***********************************************************************
925 * CreateWindowEx (USER.452)
927 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
928 LPCSTR windowName, DWORD style, INT16 x,
929 INT16 y, INT16 width, INT16 height,
930 HWND16 parent, HMENU16 menu,
931 HINSTANCE16 instance, LPVOID data )
937 /* Find the class atom */
939 if (HIWORD(className))
941 if (!(classAtom = GlobalFindAtomA( className )))
943 ERR( "bad class name %s\n", debugres_a(className) );
949 classAtom = LOWORD(className);
950 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
952 ERR( "bad atom %x\n", classAtom);
958 /* Fix the coordinates */
960 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
961 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
962 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
963 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
965 /* Create the window */
967 cs.lpCreateParams = data;
968 cs.hInstance = (HINSTANCE)instance;
969 cs.hMenu = (HMENU)menu;
970 cs.hwndParent = (HWND)parent;
972 cs.lpszName = windowName;
973 cs.lpszClass = className;
974 cs.dwExStyle = exStyle;
976 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
980 /***********************************************************************
981 * CreateWindowExA (USER32.@)
983 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
984 LPCSTR windowName, DWORD style, INT x,
985 INT y, INT width, INT height,
986 HWND parent, HMENU menu,
987 HINSTANCE instance, LPVOID data )
994 instance=GetModuleHandleA(NULL);
996 if(exStyle & WS_EX_MDICHILD)
997 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
999 /* Find the class atom */
1001 if (HIWORD(className))
1003 if (!(classAtom = GlobalFindAtomA( className )))
1005 ERR( "bad class name %s\n", debugres_a(className) );
1011 classAtom = LOWORD(className);
1012 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1014 ERR( "bad atom %x\n", classAtom);
1020 /* Create the window */
1022 cs.lpCreateParams = data;
1023 cs.hInstance = instance;
1025 cs.hwndParent = parent;
1031 cs.lpszName = windowName;
1032 cs.lpszClass = className;
1033 cs.dwExStyle = exStyle;
1035 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1039 /***********************************************************************
1040 * CreateWindowExW (USER32.@)
1042 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1043 LPCWSTR windowName, DWORD style, INT x,
1044 INT y, INT width, INT height,
1045 HWND parent, HMENU menu,
1046 HINSTANCE instance, LPVOID data )
1053 instance=GetModuleHandleA(NULL);
1055 if(exStyle & WS_EX_MDICHILD)
1056 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1058 /* Find the class atom */
1060 if (HIWORD(className))
1062 if (!(classAtom = GlobalFindAtomW( className )))
1064 ERR( "bad class name %s\n", debugres_w(className) );
1070 classAtom = LOWORD(className);
1071 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1073 ERR( "bad atom %x\n", classAtom);
1079 /* Create the window */
1081 cs.lpCreateParams = data;
1082 cs.hInstance = instance;
1084 cs.hwndParent = parent;
1090 cs.lpszName = windowName;
1091 cs.lpszClass = className;
1092 cs.dwExStyle = exStyle;
1094 /* Note: we rely on the fact that CREATESTRUCTA and */
1095 /* CREATESTRUCTW have the same layout. */
1096 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1099 /***********************************************************************
1100 * WIN_SendDestroyMsg
1102 static void WIN_SendDestroyMsg( WND* pWnd )
1104 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1105 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1108 * Send the WM_DESTROY to the window.
1110 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1113 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1114 * make sure that the window still exists when we come back.
1116 if (IsWindow(pWnd->hwndSelf))
1118 HWND* pWndArray = NULL;
1123 * Now, if the window has kids, we have to send WM_DESTROY messages
1124 * recursively to it's kids. It seems that those calls can also
1125 * trigger re-entrant calls to DestroyWindow for the kids so we must
1126 * protect against corruption of the list of siblings. We first build
1127 * a list of HWNDs representing all the kids.
1129 pChild = WIN_LockWndPtr(pWnd->child);
1133 WIN_UpdateWndPtr(&pChild,pChild->next);
1137 * If there are no kids, we're done.
1142 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1147 if (pWndArray==NULL)
1151 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1152 * call, our linked list of siblings should be safe.
1155 pChild = WIN_LockWndPtr(pWnd->child);
1158 pWndArray[nKidCount] = pChild->hwndSelf;
1160 WIN_UpdateWndPtr(&pChild,pChild->next);
1164 * Now that we have a list, go through that list again and send the destroy
1165 * message to those windows. We are using the HWND to retrieve the
1166 * WND pointer so we are effectively checking that all the kid windows are
1167 * still valid before sending the message.
1171 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1175 WIN_SendDestroyMsg( pChild );
1176 WIN_ReleaseWndPtr(pChild);
1183 HeapFree(GetProcessHeap(), 0, pWndArray);
1186 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1190 /***********************************************************************
1191 * DestroyWindow (USER.53)
1193 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1195 return DestroyWindow(hwnd);
1199 /***********************************************************************
1200 * DestroyWindow (USER32.@)
1202 BOOL WINAPI DestroyWindow( HWND hwnd )
1207 BOOL bFocusSet = FALSE;
1209 TRACE("(%04x)\n", hwnd);
1211 /* Initialization */
1213 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1214 if (wndPtr == pWndDesktop)
1216 retvalue = FALSE; /* Can't destroy desktop */
1220 /* Look whether the focus is within the tree of windows we will
1224 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1228 SetFocus(GetParent(h));
1234 /* If the focus is on the window we will destroy and it has no parent,
1235 * set the focus to 0.
1237 if (! bFocusSet && (h == hwnd))
1239 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1245 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1251 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1253 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1254 /* FIXME: clean up palette - see "Internals" p.352 */
1257 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1258 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1260 /* Notify the parent window only */
1261 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1262 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1263 if( !IsWindow(hwnd) )
1270 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1272 /* Hide the window */
1274 if (wndPtr->dwStyle & WS_VISIBLE)
1276 ShowWindow( hwnd, SW_HIDE );
1277 if (!IsWindow(hwnd))
1284 /* Recursively destroy owned windows */
1286 if( !(wndPtr->dwStyle & WS_CHILD) )
1290 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1293 if (siblingPtr->owner == wndPtr)
1295 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1298 siblingPtr->owner = NULL;
1300 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1304 DestroyWindow( siblingPtr->hwndSelf );
1305 WIN_ReleaseWndPtr(siblingPtr);
1310 WINPOS_ActivateOtherWindow(wndPtr);
1312 if( wndPtr->owner &&
1313 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1314 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1317 /* Send destroy messages */
1319 WIN_SendDestroyMsg( wndPtr );
1320 if (!IsWindow(hwnd))
1326 /* Unlink now so we won't bother with the children later on */
1328 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1330 /* Destroy the window storage */
1332 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1335 WIN_ReleaseWndPtr(wndPtr);
1340 /***********************************************************************
1341 * CloseWindow (USER.43)
1343 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1345 return CloseWindow( hwnd );
1349 /***********************************************************************
1350 * CloseWindow (USER32.@)
1352 BOOL WINAPI CloseWindow( HWND hwnd )
1354 WND * wndPtr = WIN_FindWndPtr( hwnd );
1357 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1362 ShowWindow( hwnd, SW_MINIMIZE );
1365 WIN_ReleaseWndPtr(wndPtr);
1371 /***********************************************************************
1372 * OpenIcon (USER.44)
1374 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1376 return OpenIcon( hwnd );
1380 /***********************************************************************
1381 * OpenIcon (USER32.@)
1383 BOOL WINAPI OpenIcon( HWND hwnd )
1385 if (!IsIconic( hwnd )) return FALSE;
1386 ShowWindow( hwnd, SW_SHOWNORMAL );
1391 /***********************************************************************
1394 * Implementation of FindWindow() and FindWindowEx().
1396 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1404 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1407 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1413 else if (pWnd->parent != pWndDesktop)
1418 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1422 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1427 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1435 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1437 if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
1438 continue; /* Not the right class */
1440 /* Now check the title */
1444 retvalue = pWnd->hwndSelf;
1447 if (pWnd->text && !strcmpW( pWnd->text, title ))
1449 retvalue = pWnd->hwndSelf;
1454 /* In this case we need to check whether other processes
1455 own a window with the given paramters on the Desktop,
1456 but we don't, so let's at least warn about it */
1457 FIXME("Returning 0 without checking other processes\n");
1459 WIN_ReleaseWndPtr(pWnd);
1465 /***********************************************************************
1466 * FindWindow (USER.50)
1468 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1470 return FindWindowA( className, title );
1474 /***********************************************************************
1475 * FindWindowEx (USER.427)
1477 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1479 return FindWindowExA( parent, child, className, title );
1483 /***********************************************************************
1484 * FindWindowA (USER32.@)
1486 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1488 HWND ret = FindWindowExA( 0, 0, className, title );
1489 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1494 /***********************************************************************
1495 * FindWindowExA (USER32.@)
1497 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1498 LPCSTR className, LPCSTR title )
1506 /* If the atom doesn't exist, then no class */
1507 /* with this name exists either. */
1508 if (!(atom = GlobalFindAtomA( className )))
1510 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1515 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1516 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1517 HeapFree( GetProcessHeap(), 0, buffer );
1522 /***********************************************************************
1523 * FindWindowExW (USER32.@)
1525 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1526 LPCWSTR className, LPCWSTR title )
1532 /* If the atom doesn't exist, then no class */
1533 /* with this name exists either. */
1534 if (!(atom = GlobalFindAtomW( className )))
1536 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1540 return WIN_FindWindow( parent, child, atom, title );
1544 /***********************************************************************
1545 * FindWindowW (USER32.@)
1547 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1549 return FindWindowExW( 0, 0, className, title );
1553 /**********************************************************************
1555 * returns a locked pointer
1557 WND *WIN_GetDesktop(void)
1559 return WIN_LockWndPtr(pWndDesktop);
1561 /**********************************************************************
1562 * WIN_ReleaseDesktop
1563 * unlock the desktop pointer
1565 void WIN_ReleaseDesktop(void)
1567 WIN_ReleaseWndPtr(pWndDesktop);
1571 /**********************************************************************
1572 * GetDesktopWindow (USER.286)
1574 HWND16 WINAPI GetDesktopWindow16(void)
1576 return (HWND16)pWndDesktop->hwndSelf;
1580 /**********************************************************************
1581 * GetDesktopWindow (USER32.@)
1583 HWND WINAPI GetDesktopWindow(void)
1585 if (pWndDesktop) return pWndDesktop->hwndSelf;
1586 ERR( "You need the -desktop option when running with native USER\n" );
1592 /**********************************************************************
1593 * GetDesktopHwnd (USER.278)
1595 * Exactly the same thing as GetDesktopWindow(), but not documented.
1596 * Don't ask me why...
1598 HWND16 WINAPI GetDesktopHwnd16(void)
1600 return (HWND16)pWndDesktop->hwndSelf;
1604 /*******************************************************************
1605 * EnableWindow (USER.34)
1607 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1609 return EnableWindow( hwnd, enable );
1613 /*******************************************************************
1614 * EnableWindow (USER32.@)
1616 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1621 TRACE("( %x, %d )\n", hwnd, enable);
1623 if (USER_Driver.pEnableWindow)
1624 return USER_Driver.pEnableWindow( hwnd, enable );
1626 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1628 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1630 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1632 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1633 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1635 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1637 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1639 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1641 if (hwnd == GetFocus())
1642 SetFocus( 0 ); /* A disabled window can't have the focus */
1644 if (hwnd == GetCapture())
1645 ReleaseCapture(); /* A disabled window can't capture the mouse */
1647 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1649 WIN_ReleaseWndPtr(wndPtr);
1654 /***********************************************************************
1655 * IsWindowEnabled (USER.35)
1657 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1659 return IsWindowEnabled(hWnd);
1663 /***********************************************************************
1664 * IsWindowEnabled (USER32.@)
1666 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1671 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1672 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1673 WIN_ReleaseWndPtr(wndPtr);
1679 /***********************************************************************
1680 * IsWindowUnicode (USER32.@)
1682 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1687 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1688 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1689 WIN_ReleaseWndPtr(wndPtr);
1694 /**********************************************************************
1695 * GetWindowWord (USER.133)
1697 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1699 return GetWindowWord( hwnd, offset );
1703 /**********************************************************************
1704 * GetWindowWord (USER32.@)
1706 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1709 WND * wndPtr = WIN_FindWndPtr( hwnd );
1710 if (!wndPtr) return 0;
1713 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1715 WARN("Invalid offset %d\n", offset );
1719 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1725 if (HIWORD(wndPtr->wIDmenu))
1726 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1728 retvalue = (WORD)wndPtr->wIDmenu;
1730 case GWW_HWNDPARENT:
1731 retvalue = GetParent(hwnd);
1734 if (HIWORD(wndPtr->hInstance))
1735 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1737 retvalue = (WORD)wndPtr->hInstance;
1740 WARN("Invalid offset %d\n", offset );
1745 WIN_ReleaseWndPtr(wndPtr);
1749 /**********************************************************************
1750 * SetWindowWord (USER.134)
1752 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1754 return SetWindowWord( hwnd, offset, newval );
1758 /**********************************************************************
1759 * SetWindowWord (USER32.@)
1761 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1764 WND * wndPtr = WIN_FindWndPtr( hwnd );
1765 if (!wndPtr) return 0;
1768 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1770 WARN("Invalid offset %d\n", offset );
1774 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1778 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1779 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1780 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1783 WARN("Invalid offset %d\n", offset );
1790 WIN_ReleaseWndPtr(wndPtr);
1795 /**********************************************************************
1798 * Helper function for GetWindowLong().
1800 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1803 WND * wndPtr = WIN_FindWndPtr( hwnd );
1804 if (!wndPtr) return 0;
1807 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1809 WARN("Invalid offset %d\n", offset );
1813 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1814 /* Special case for dialog window procedure */
1815 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1817 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1824 case GWL_USERDATA: retvalue = wndPtr->userdata;
1826 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1828 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1830 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1832 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1835 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1837 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1840 WARN("Unknown offset %d\n", offset );
1844 WIN_ReleaseWndPtr(wndPtr);
1849 /**********************************************************************
1852 * Helper function for SetWindowLong().
1854 * 0 is the failure code. However, in the case of failure SetLastError
1855 * must be set to distinguish between a 0 return value and a failure.
1857 * FIXME: The error values for SetLastError may not be right. Can
1858 * someone check with the real thing?
1860 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1861 WINDOWPROCTYPE type )
1864 WND * wndPtr = WIN_FindWndPtr( hwnd );
1867 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1871 /* Is this the right error? */
1872 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1878 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1880 WARN("Invalid offset %d\n", offset );
1882 /* Is this the right error? */
1883 SetLastError( ERROR_OUTOFMEMORY );
1888 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1889 /* Special case for dialog window procedure */
1890 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1892 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1893 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1894 type, WIN_PROC_WINDOW );
1901 ptr = (DWORD*)&wndPtr->wIDmenu;
1904 retval = SetWindowWord( hwnd, offset, newval );
1907 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1908 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1909 type, WIN_PROC_WINDOW );
1912 style.styleOld = wndPtr->dwStyle;
1913 style.styleNew = newval;
1914 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1915 wndPtr->dwStyle = style.styleNew;
1916 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1917 retval = style.styleOld;
1921 ptr = &wndPtr->userdata;
1924 style.styleOld = wndPtr->dwExStyle;
1925 style.styleNew = newval;
1926 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1927 wndPtr->dwExStyle = newval;
1928 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1929 retval = style.styleOld;
1933 WARN("Invalid offset %d\n", offset );
1935 /* Don't think this is right error but it should do */
1936 SetLastError( ERROR_OUTOFMEMORY );
1944 WIN_ReleaseWndPtr(wndPtr);
1949 /**********************************************************************
1950 * GetWindowLong (USER.135)
1952 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1954 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1958 /**********************************************************************
1959 * GetWindowLongA (USER32.@)
1961 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1963 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1967 /**********************************************************************
1968 * GetWindowLongW (USER32.@)
1970 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1972 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1976 /**********************************************************************
1977 * SetWindowLong (USER.136)
1979 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1981 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1985 /**********************************************************************
1986 * SetWindowLongA (USER32.@)
1988 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1990 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1994 /**********************************************************************
1995 * SetWindowLongW (USER32.@) Set window attribute
1997 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1998 * value in a window's extra memory.
2000 * The _hwnd_ parameter specifies the window. is the handle to a
2001 * window that has extra memory. The _newval_ parameter contains the
2002 * new attribute or extra memory value. If positive, the _offset_
2003 * parameter is the byte-addressed location in the window's extra
2004 * memory to set. If negative, _offset_ specifies the window
2005 * attribute to set, and should be one of the following values:
2007 * GWL_EXSTYLE The window's extended window style
2009 * GWL_STYLE The window's window style.
2011 * GWL_WNDPROC Pointer to the window's window procedure.
2013 * GWL_HINSTANCE The window's pplication instance handle.
2015 * GWL_ID The window's identifier.
2017 * GWL_USERDATA The window's user-specified data.
2019 * If the window is a dialog box, the _offset_ parameter can be one of
2020 * the following values:
2022 * DWL_DLGPROC The address of the window's dialog box procedure.
2024 * DWL_MSGRESULT The return value of a message
2025 * that the dialog box procedure processed.
2027 * DWL_USER Application specific information.
2031 * If successful, returns the previous value located at _offset_. Otherwise,
2036 * Extra memory for a window class is specified by a nonzero cbWndExtra
2037 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2038 * time of class creation.
2040 * Using GWL_WNDPROC to set a new window procedure effectively creates
2041 * a window subclass. Use CallWindowProc() in the new windows procedure
2042 * to pass messages to the superclass's window procedure.
2044 * The user data is reserved for use by the application which created
2047 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2048 * instead, call the EnableWindow() function to change the window's
2051 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2052 * SetParent() instead.
2055 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2056 * it sends WM_STYLECHANGING before changing the settings
2057 * and WM_STYLECHANGED afterwards.
2058 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2062 * GWL_STYLE does not dispatch WM_STYLE... messages.
2069 LONG WINAPI SetWindowLongW(
2070 HWND hwnd, /* [in] window to alter */
2071 INT offset, /* [in] offset, in bytes, of location to alter */
2072 LONG newval /* [in] new value of location */
2074 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2078 /*******************************************************************
2079 * GetWindowText (USER.36)
2081 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2083 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2087 /*******************************************************************
2088 * GetWindowTextA (USER32.@)
2090 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2092 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2096 /*******************************************************************
2097 * InternalGetWindowText (USER32.@)
2099 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2101 WND *win = WIN_FindWndPtr( hwnd );
2103 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2104 else lpString[0] = 0;
2105 WIN_ReleaseWndPtr( win );
2106 return strlenW(lpString);
2110 /*******************************************************************
2111 * GetWindowTextW (USER32.@)
2113 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2115 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2120 /*******************************************************************
2121 * SetWindowText (USER.37)
2123 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2125 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2129 /*******************************************************************
2130 * SetWindowText (USER32.@)
2132 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2134 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2138 /*******************************************************************
2139 * SetWindowTextW (USER32.@)
2141 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2143 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2147 /*******************************************************************
2148 * GetWindowTextLength (USER.38)
2150 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2152 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2156 /*******************************************************************
2157 * GetWindowTextLengthA (USER32.@)
2159 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2161 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2164 /*******************************************************************
2165 * GetWindowTextLengthW (USER32.@)
2167 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2169 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2173 /*******************************************************************
2174 * IsWindow (USER.47)
2176 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2178 CURRENT_STACK16->es = USER_HeapSel;
2179 return IsWindow( hwnd );
2183 /*******************************************************************
2184 * IsWindow (USER32.@)
2186 BOOL WINAPI IsWindow( HWND hwnd )
2191 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2192 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2193 WIN_ReleaseWndPtr(wndPtr);
2199 /*****************************************************************
2200 * GetParent (USER.46)
2202 HWND16 WINAPI GetParent16( HWND16 hwnd )
2204 return (HWND16)GetParent( hwnd );
2208 /*****************************************************************
2209 * GetParent (USER32.@)
2211 HWND WINAPI GetParent( HWND hwnd )
2216 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2217 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2220 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2222 retvalue = wndPtr->hwndSelf;
2225 WIN_ReleaseWndPtr(wndPtr);
2230 /*****************************************************************
2233 * Get the top-level parent for a child window.
2234 * returns a locked pointer
2236 WND* WIN_GetTopParentPtr( WND* pWnd )
2238 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2240 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2242 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2247 /*****************************************************************
2250 * Get the top-level parent for a child window.
2252 HWND WIN_GetTopParent( HWND hwnd )
2255 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2256 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2258 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2259 WIN_ReleaseWndPtr(tmpPtr);
2260 WIN_ReleaseWndPtr(wndPtr);
2265 /*****************************************************************
2266 * SetParent (USER.233)
2268 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2270 return SetParent( hwndChild, hwndNewParent );
2274 /*****************************************************************
2275 * SetParent (USER32.@)
2277 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2284 if (hwnd == GetDesktopWindow()) /* sanity check */
2286 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2290 if (USER_Driver.pSetParent)
2291 return USER_Driver.pSetParent( hwnd, parent );
2293 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2295 dwStyle = wndPtr->dwStyle;
2297 if (!parent) parent = GetDesktopWindow();
2299 if (!(pWndParent = WIN_FindWndPtr(parent)))
2301 WIN_ReleaseWndPtr( wndPtr );
2305 /* Windows hides the window first, then shows it again
2306 * including the WM_SHOWWINDOW messages and all */
2307 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2309 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2310 if (pWndParent != wndPtr->parent)
2312 WIN_UnlinkWindow(wndPtr->hwndSelf);
2313 wndPtr->parent = pWndParent;
2315 if (parent != GetDesktopWindow()) /* a child window */
2317 if( !( wndPtr->dwStyle & WS_CHILD ) )
2319 if( wndPtr->wIDmenu != 0)
2321 DestroyMenu( (HMENU) wndPtr->wIDmenu );
2322 wndPtr->wIDmenu = 0;
2326 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
2328 WIN_ReleaseWndPtr( pWndParent );
2329 WIN_ReleaseWndPtr( wndPtr );
2331 /* SetParent additionally needs to make hwnd the topmost window
2332 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2333 WM_WINDOWPOSCHANGED notification messages.
2335 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2336 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2337 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2338 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2339 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2344 /*******************************************************************
2347 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2349 return IsChild(parent,child);
2353 /*******************************************************************
2354 * IsChild (USER32.@)
2356 BOOL WINAPI IsChild( HWND parent, HWND child )
2358 WND * wndPtr = WIN_FindWndPtr( child );
2359 while (wndPtr && wndPtr->parent)
2361 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2362 if (wndPtr->hwndSelf == GetDesktopWindow()) break;
2363 if (wndPtr->hwndSelf == parent)
2365 WIN_ReleaseWndPtr(wndPtr);
2369 WIN_ReleaseWndPtr(wndPtr);
2374 /***********************************************************************
2375 * IsWindowVisible (USER.49)
2377 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2379 return IsWindowVisible(hwnd);
2383 /***********************************************************************
2384 * IsWindowVisible (USER32.@)
2386 BOOL WINAPI IsWindowVisible( HWND hwnd )
2389 WND *wndPtr = WIN_FindWndPtr( hwnd );
2390 while (wndPtr && wndPtr->parent)
2392 if (!(wndPtr->dwStyle & WS_VISIBLE))
2394 WIN_ReleaseWndPtr(wndPtr);
2397 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2399 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2400 WIN_ReleaseWndPtr(wndPtr);
2405 /***********************************************************************
2406 * WIN_IsWindowDrawable
2408 * hwnd is drawable when it is visible, all parents are not
2409 * minimized, and it is itself not minimized unless we are
2410 * trying to draw its default class icon.
2412 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2414 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2415 if ((wnd->dwStyle & WS_MINIMIZE) &&
2416 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2417 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2418 if( wnd->dwStyle & WS_MINIMIZE ||
2419 !(wnd->dwStyle & WS_VISIBLE) ) break;
2420 return (wnd == NULL);
2424 /*******************************************************************
2425 * GetTopWindow (USER.229)
2427 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2429 return GetTopWindow(hwnd);
2433 /*******************************************************************
2434 * GetTopWindow (USER32.@)
2436 HWND WINAPI GetTopWindow( HWND hwnd )
2439 WND * wndPtr = (hwnd) ?
2440 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2442 if (wndPtr && wndPtr->child)
2443 retval = wndPtr->child->hwndSelf;
2445 WIN_ReleaseWndPtr(wndPtr);
2450 /*******************************************************************
2451 * GetWindow (USER.262)
2453 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2455 return GetWindow( hwnd,rel );
2459 /*******************************************************************
2460 * GetWindow (USER32.@)
2462 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2466 WND * wndPtr = WIN_FindWndPtr( hwnd );
2467 if (!wndPtr) return 0;
2471 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2475 if (!wndPtr->parent)
2477 retval = 0; /* Desktop window */
2480 while (wndPtr->next)
2482 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2484 retval = wndPtr->hwndSelf;
2488 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2492 if (!wndPtr->parent)
2494 retval = 0; /* Desktop window */
2497 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2498 if (wndPtr->hwndSelf == hwnd)
2500 retval = 0; /* First in list */
2503 while (wndPtr->next)
2505 if (wndPtr->next->hwndSelf == hwnd)
2507 retval = wndPtr->hwndSelf;
2510 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2516 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2520 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2525 WIN_ReleaseWndPtr(wndPtr);
2530 /*******************************************************************
2531 * GetNextWindow (USER.230)
2533 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2535 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2536 return GetWindow16( hwnd, flag );
2539 /***********************************************************************
2540 * WIN_InternalShowOwnedPopups
2542 * Internal version of ShowOwnedPopups; Wine functions should use this
2543 * to avoid interfering with application calls to ShowOwnedPopups
2544 * and to make sure the application can't prevent showing/hiding.
2546 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2550 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2552 INT totalChild=0, count=0;
2554 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2556 if (!pWnd) return TRUE;
2559 * Show windows Lowest first, Highest last to preserve Z-Order
2561 for (count = totalChild-1 ; count >=0; count--)
2563 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2567 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2568 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2571 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2573 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2574 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2579 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2580 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2581 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2584 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2586 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2587 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2588 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2593 WIN_ReleaseDesktop();
2594 WIN_ReleaseWinArray(pWnd);
2599 /*******************************************************************
2600 * ShowOwnedPopups (USER.265)
2602 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2604 ShowOwnedPopups( owner, fShow );
2608 /*******************************************************************
2609 * ShowOwnedPopups (USER32.@)
2611 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2613 UINT totalChild=0, count=0;
2615 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2617 if (!pWnd) return TRUE;
2619 for (; count < totalChild; count++)
2621 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2625 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2628 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2629 * regardless of the state of the owner
2631 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2632 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2637 if (IsWindowVisible(pWnd[count]->hwndSelf))
2640 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2641 * regardless of the state of the owner
2643 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2644 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2650 WIN_ReleaseDesktop();
2651 WIN_ReleaseWinArray(pWnd);
2656 /*******************************************************************
2657 * GetLastActivePopup (USER.287)
2659 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2661 return GetLastActivePopup( hwnd );
2664 /*******************************************************************
2665 * GetLastActivePopup (USER32.@)
2667 HWND WINAPI GetLastActivePopup( HWND hwnd )
2670 WND *wndPtr =WIN_FindWndPtr(hwnd);
2671 if (!wndPtr) return hwnd;
2672 retval = wndPtr->hwndLastActive;
2673 WIN_ReleaseWndPtr(wndPtr);
2674 if ((retval != hwnd) && (!IsWindow(retval)))
2680 /*******************************************************************
2683 * Build an array of pointers to the children of a given window.
2684 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2685 * when no windows are found.
2687 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2689 /* Future: this function will lock all windows associated with this array */
2691 WND **list, **ppWnd;
2693 UINT count = 0, skipOwned, skipHidden;
2696 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2697 skipOwned = bwaFlags & BWA_SKIPOWNED;
2698 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2699 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2701 /* First count the windows */
2704 wndPtr = WIN_GetDesktop();
2706 pWnd = WIN_LockWndPtr(wndPtr->child);
2709 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2710 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2712 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2717 /* Now build the list of all windows */
2719 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2721 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2723 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2724 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2730 WIN_ReleaseWndPtr(pWnd);
2736 if( pTotal ) *pTotal = count;
2739 /*******************************************************************
2740 * WIN_ReleaseWinArray
2742 void WIN_ReleaseWinArray(WND **wndArray)
2744 /* Future: this function will also unlock all windows associated with wndArray */
2745 HeapFree( GetProcessHeap(), 0, wndArray );
2749 /*******************************************************************
2750 * EnumWindows (USER32.@)
2752 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2754 WND **list, **ppWnd;
2756 /* We have to build a list of all windows first, to avoid */
2757 /* unpleasant side-effects, for instance if the callback */
2758 /* function changes the Z-order of the windows. */
2760 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2762 WIN_ReleaseDesktop();
2766 /* Now call the callback function for every window */
2768 for (ppWnd = list; *ppWnd; ppWnd++)
2770 LRESULT lpEnumFuncRetval;
2772 /* Make sure that the window still exists */
2773 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2775 /* To avoid any deadlocks, all the locks on the windows
2776 structures must be suspended before the control
2777 is passed to the application */
2778 iWndsLocks = WIN_SuspendWndsLock();
2779 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2780 WIN_RestoreWndsLock(iWndsLocks);
2782 if (!lpEnumFuncRetval) break;
2784 WIN_ReleaseWinArray(list);
2785 WIN_ReleaseDesktop();
2790 /**********************************************************************
2791 * WIN_EnumQueueWindows
2793 * Helper for EnumTaskWindows16 and EnumThreadWindows.
2795 static BOOL WIN_EnumQueueWindows( HQUEUE16 queue, WNDENUMPROC func, LPARAM lParam )
2797 WND **list, **ppWnd;
2799 /* This function is the same as EnumWindows(), */
2800 /* except for an added check on the window's task. */
2802 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2804 WIN_ReleaseDesktop();
2808 /* Now call the callback function for every window */
2810 for (ppWnd = list; *ppWnd; ppWnd++)
2814 /* Make sure that the window still exists */
2815 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2816 if ((*ppWnd)->hmemTaskQ != queue) continue;
2818 /* To avoid any deadlocks, all the locks on the windows
2819 structures must be suspended before the control
2820 is passed to the application */
2821 iWndsLocks = WIN_SuspendWndsLock();
2822 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2823 WIN_RestoreWndsLock(iWndsLocks);
2825 if (!funcRetval) break;
2827 WIN_ReleaseWinArray(list);
2828 WIN_ReleaseDesktop();
2833 /**********************************************************************
2834 * EnumTaskWindows16 (USER.225)
2836 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2839 HQUEUE16 queue = GetTaskQueue16( hTask );
2840 if (!queue) return FALSE;
2841 return WIN_EnumQueueWindows( queue, (WNDENUMPROC)func, lParam );
2845 /**********************************************************************
2846 * EnumThreadWindows (USER32.@)
2848 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2850 HQUEUE16 queue = GetThreadQueue16( id );
2851 if (!queue) return FALSE;
2852 return WIN_EnumQueueWindows( queue, func, lParam );
2856 /**********************************************************************
2857 * WIN_EnumChildWindows
2859 * Helper function for EnumChildWindows().
2861 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2866 for ( ; *ppWnd; ppWnd++)
2870 /* Make sure that the window still exists */
2871 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2872 /* Build children list first */
2873 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2875 /* To avoid any deadlocks, all the locks on the windows
2876 structures must be suspended before the control
2877 is passed to the application */
2878 iWndsLocks = WIN_SuspendWndsLock();
2879 ret = func( (*ppWnd)->hwndSelf, lParam );
2880 WIN_RestoreWndsLock(iWndsLocks);
2884 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2885 WIN_ReleaseWinArray(childList);
2887 if (!ret) return FALSE;
2893 /**********************************************************************
2894 * EnumChildWindows (USER32.@)
2896 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2899 WND **list, *pParent;
2901 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2902 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2904 WIN_ReleaseWndPtr(pParent);
2907 WIN_EnumChildWindows( list, func, lParam );
2908 WIN_ReleaseWinArray(list);
2909 WIN_ReleaseWndPtr(pParent);
2914 /*******************************************************************
2915 * AnyPopup (USER.52)
2917 BOOL16 WINAPI AnyPopup16(void)
2923 /*******************************************************************
2924 * AnyPopup (USER32.@)
2926 BOOL WINAPI AnyPopup(void)
2928 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2933 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2938 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2942 WIN_ReleaseWndPtr(wndPtr);
2947 /*******************************************************************
2948 * FlashWindow (USER.105)
2950 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2952 return FlashWindow( hWnd, bInvert );
2956 /*******************************************************************
2957 * FlashWindow (USER32.@)
2959 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2961 WND *wndPtr = WIN_FindWndPtr(hWnd);
2963 TRACE("%04x\n", hWnd);
2965 if (!wndPtr) return FALSE;
2967 if (wndPtr->dwStyle & WS_MINIMIZE)
2969 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2971 HDC hDC = GetDC(hWnd);
2973 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2974 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2976 ReleaseDC( hWnd, hDC );
2977 wndPtr->flags |= WIN_NCACTIVATED;
2981 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2982 wndPtr->flags &= ~WIN_NCACTIVATED;
2984 WIN_ReleaseWndPtr(wndPtr);
2990 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2991 else wparam = (hWnd == GetActiveWindow());
2993 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2994 WIN_ReleaseWndPtr(wndPtr);
3000 /*******************************************************************
3001 * SetSysModalWindow (USER.188)
3003 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3005 HWND hWndOldModal = hwndSysModal;
3006 hwndSysModal = hWnd;
3007 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3008 return hWndOldModal;
3012 /*******************************************************************
3013 * GetSysModalWindow (USER.189)
3015 HWND16 WINAPI GetSysModalWindow16(void)
3017 return hwndSysModal;
3021 /*******************************************************************
3022 * GetWindowContextHelpId (USER32.@)
3024 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3027 WND *wnd = WIN_FindWndPtr( hwnd );
3029 retval = wnd->helpContext;
3030 WIN_ReleaseWndPtr(wnd);
3035 /*******************************************************************
3036 * SetWindowContextHelpId (USER32.@)
3038 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3040 WND *wnd = WIN_FindWndPtr( hwnd );
3041 if (!wnd) return FALSE;
3042 wnd->helpContext = id;
3043 WIN_ReleaseWndPtr(wnd);
3048 /*******************************************************************
3051 * recursively find a child that contains spDragInfo->pt point
3052 * and send WM_QUERYDROPOBJECT
3054 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3056 BOOL16 wParam, bResult = 0;
3058 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3059 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3062 if( !ptrQueryWnd || !ptrDragInfo )
3065 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3067 GetWindowRect(hQueryWnd,&tempRect);
3069 if( !PtInRect(&tempRect,pt) ||
3070 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3073 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3075 tempRect = ptrQueryWnd->rectClient;
3076 if(ptrQueryWnd->parent)
3077 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3078 (LPPOINT)&tempRect, 2 );
3080 if (PtInRect( &tempRect, pt))
3084 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3086 if( ptrWnd->dwStyle & WS_VISIBLE )
3088 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3089 if (PtInRect( &tempRect, pt )) break;
3095 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3096 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3097 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3098 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3099 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3101 WIN_ReleaseWndPtr(ptrWnd);
3111 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3113 ptrDragInfo->hScope = hQueryWnd;
3115 bResult = ( bNoSend )
3116 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3117 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3118 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3120 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3123 WIN_ReleaseWndPtr(ptrQueryWnd);
3128 /*******************************************************************
3129 * DragDetect (USER.465)
3131 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3134 CONV_POINT16TO32( &pt, &pt32 );
3135 return DragDetect( hWnd, pt32 );
3138 /*******************************************************************
3139 * DragDetect (USER32.@)
3141 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3146 rect.left = pt.x - wDragWidth;
3147 rect.right = pt.x + wDragWidth;
3149 rect.top = pt.y - wDragHeight;
3150 rect.bottom = pt.y + wDragHeight;
3156 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3158 if( msg.message == WM_LBUTTONUP )
3163 if( msg.message == WM_MOUSEMOVE )
3166 tmp.x = LOWORD(msg.lParam);
3167 tmp.y = HIWORD(msg.lParam);
3168 if( !PtInRect( &rect, tmp ))
3180 /******************************************************************************
3181 * DragObject (USER.464)
3183 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3184 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3187 LPDRAGINFO16 lpDragInfo;
3189 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3190 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3191 WND *wndPtr = WIN_FindWndPtr(hWnd);
3192 HCURSOR16 hCurrentCursor = 0;
3193 HWND16 hCurrentWnd = 0;
3195 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3196 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3198 if( !lpDragInfo || !spDragInfo )
3200 WIN_ReleaseWndPtr(wndPtr);
3204 hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO));
3206 if( !hBummer || !wndPtr )
3208 GlobalFree16(hDragInfo);
3209 WIN_ReleaseWndPtr(wndPtr);
3215 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3217 GlobalFree16(hDragInfo);
3218 WIN_ReleaseWndPtr(wndPtr);
3222 if( hDragCursor == hCursor ) hDragCursor = 0;
3223 else hCursor = hDragCursor;
3225 hOldCursor = SetCursor(hDragCursor);
3228 lpDragInfo->hWnd = hWnd;
3229 lpDragInfo->hScope = 0;
3230 lpDragInfo->wFlags = wObj;
3231 lpDragInfo->hList = szList; /* near pointer! */
3232 lpDragInfo->hOfStruct = hOfStruct;
3240 do{ WaitMessage(); }
3241 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3243 *(lpDragInfo+1) = *lpDragInfo;
3245 lpDragInfo->pt.x = msg.pt.x;
3246 lpDragInfo->pt.y = msg.pt.y;
3248 /* update DRAGINFO struct */
3249 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3251 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3252 hCurrentCursor = hCursor;
3255 hCurrentCursor = hBummer;
3256 lpDragInfo->hScope = 0;
3258 if( hCurrentCursor )
3259 SetCursor(hCurrentCursor);
3261 /* send WM_DRAGLOOP */
3262 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3263 (LPARAM) spDragInfo );
3264 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3265 if( hCurrentWnd != lpDragInfo->hScope )
3268 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3269 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3270 HIWORD(spDragInfo)) );
3271 hCurrentWnd = lpDragInfo->hScope;
3273 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3277 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3279 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3282 ShowCursor( FALSE );
3286 SetCursor( hOldCursor );
3287 if (hDragCursor) DestroyCursor( hDragCursor );
3290 if( hCurrentCursor != hBummer )
3291 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3292 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3295 GlobalFree16(hDragInfo);
3296 WIN_ReleaseWndPtr(wndPtr);
3298 return (DWORD)(msg.lParam);
3302 /******************************************************************************
3303 * GetWindowModuleFileNameA (USER32.@)
3305 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3307 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3308 hwnd, lpszFileName, cchFileNameMax);
3312 /******************************************************************************
3313 * GetWindowModuleFileNameW (USER32.@)
3315 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3317 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3318 hwnd, lpszFileName, cchFileNameMax);