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"
25 #include "stackframe.h"
26 #include "debugtools.h"
28 DEFAULT_DEBUG_CHANNEL(win);
29 DECLARE_DEBUG_CHANNEL(msg);
31 /**********************************************************************/
34 static WND *pWndDesktop = NULL;
36 static HWND hwndSysModal = 0;
38 static WORD wDragWidth = 4;
39 static WORD wDragHeight= 3;
42 extern SYSLEVEL USER_SysLevel; /* FIXME */
44 /***********************************************************************
47 * Suspend the lock on WND structures.
48 * Returns the number of locks suspended
50 int WIN_SuspendWndsLock( void )
52 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
53 int count = isuspendedLocks;
56 _LeaveSysLevel( &USER_SysLevel );
58 return isuspendedLocks;
61 /***********************************************************************
64 * Restore the suspended locks on WND structures
66 void WIN_RestoreWndsLock( int ipreviousLocks )
68 while ( ipreviousLocks-- > 0 )
69 _EnterSysLevel( &USER_SysLevel );
72 /***********************************************************************
75 * Return a pointer to the WND structure corresponding to a HWND.
77 WND * WIN_FindWndPtr( HWND hwnd )
81 if (!hwnd || HIWORD(hwnd)) goto error2;
82 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
83 /* Lock all WND structures for thread safeness*/
85 /*and increment destruction monitoring*/
88 if (ptr->dwMagic != WND_MAGIC) goto error;
89 if (ptr->hwndSelf != hwnd)
91 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
94 /* returns a locked pointer */
97 /* Unlock all WND structures for thread safeness*/
99 /* and decrement destruction monitoring value */
104 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
108 /***********************************************************************
111 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
113 * Returns the locked initialisation pointer
115 WND *WIN_LockWndPtr(WND *initWndPtr)
117 if(!initWndPtr) return 0;
119 /* Lock all WND structures for thread safeness*/
121 /*and increment destruction monitoring*/
122 initWndPtr->irefCount++;
128 /***********************************************************************
131 * Release the pointer to the WND structure.
133 void WIN_ReleaseWndPtr(WND *wndPtr)
137 /*Decrement destruction monitoring value*/
139 /* Check if it's time to release the memory*/
140 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
143 USER_HEAP_FREE( wndPtr->hwndSelf);
144 wndPtr->hwndSelf = 0;
146 else if(wndPtr->irefCount < 0)
148 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
149 ERR("forgot a Lock on %p somewhere\n",wndPtr);
151 /*unlock all WND structures for thread safeness*/
155 /***********************************************************************
158 * Updates the value of oldPtr to newPtr.
160 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
164 tmpWnd = WIN_LockWndPtr(newPtr);
165 WIN_ReleaseWndPtr(*oldPtr);
170 /***********************************************************************
173 * Dump the content of a window structure to stderr.
175 void WIN_DumpWindow( HWND hwnd )
181 if (!(ptr = WIN_FindWndPtr( hwnd )))
183 WARN("%04x is not a window handle\n", hwnd );
187 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
188 strcpy( className, "#NULL#" );
190 TRACE("Window %04x (%p):\n", hwnd, ptr );
191 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
192 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
193 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
194 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
195 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
196 ptr->next, ptr->child, ptr->parent, ptr->owner,
197 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
198 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
199 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
200 ptr->text ? debugstr_w(ptr->text) : "",
201 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
202 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
203 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
204 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
208 DPRINTF( "extra bytes:" );
209 for (i = 0; i < ptr->cbWndExtra; i++)
210 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
214 WIN_ReleaseWndPtr(ptr);
218 /***********************************************************************
221 * Remove a window from the siblings linked list.
223 BOOL WIN_UnlinkWindow( HWND hwnd )
225 WND *wndPtr, **ppWnd;
228 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
229 else if(!wndPtr->parent)
231 WIN_ReleaseWndPtr(wndPtr);
235 ppWnd = &wndPtr->parent->child;
236 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
239 *ppWnd = wndPtr->next;
242 WIN_ReleaseWndPtr(wndPtr);
247 /***********************************************************************
250 * Insert a window into the siblings linked list.
251 * The window is inserted after the specified window, which can also
252 * be specified as HWND_TOP or HWND_BOTTOM.
254 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
256 WND *wndPtr, **ppWnd;
258 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
259 else if(!wndPtr->parent)
261 WIN_ReleaseWndPtr(wndPtr);
264 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
266 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
267 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
268 while (*ppWnd) ppWnd = &(*ppWnd)->next;
270 else /* Normal case */
272 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
275 WIN_ReleaseWndPtr(wndPtr);
278 ppWnd = &afterPtr->next;
279 WIN_ReleaseWndPtr(afterPtr);
281 wndPtr->next = *ppWnd;
283 WIN_ReleaseWndPtr(wndPtr);
288 /***********************************************************************
289 * WIN_FindWinToRepaint
291 * Find a window that needs repaint.
293 HWND WIN_FindWinToRepaint( HWND hwnd )
298 /* Note: the desktop window never gets WM_PAINT messages
299 * The real reason why is because Windows DesktopWndProc
300 * does ValidateRgn inside WM_ERASEBKGND handler.
302 if (hwnd == GetDesktopWindow()) hwnd = 0;
304 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
306 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
308 if (!(pWnd->dwStyle & WS_VISIBLE))
310 TRACE("skipping window %04x\n",
313 else if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
314 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
317 else if (pWnd->child )
318 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
320 WIN_ReleaseWndPtr(pWnd);
331 hwndRet = pWnd->hwndSelf;
333 /* look among siblings if we got a transparent window */
334 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
335 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
337 WIN_UpdateWndPtr(&pWnd,pWnd->next);
341 hwndRet = pWnd->hwndSelf;
342 WIN_ReleaseWndPtr(pWnd);
344 TRACE("found %04x\n",hwndRet);
349 /***********************************************************************
352 * Destroy storage associated to a window. "Internals" p.358
353 * returns a locked wndPtr->next
355 static WND* WIN_DestroyWindow( WND* wndPtr )
357 HWND hwnd = wndPtr->hwndSelf;
360 TRACE("%04x\n", wndPtr->hwndSelf );
362 /* free child windows */
363 WIN_LockWndPtr(wndPtr->child);
364 while ((pWnd = wndPtr->child))
366 wndPtr->child = WIN_DestroyWindow( pWnd );
367 WIN_ReleaseWndPtr(pWnd);
371 * Clear the update region to make sure no WM_PAINT messages will be
372 * generated for this window while processing the WM_NCDESTROY.
374 RedrawWindow( wndPtr->hwndSelf, NULL, 0,
375 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
378 * Send the WM_NCDESTROY to the window being destroyed.
380 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
382 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
384 WINPOS_CheckInternalPos( hwnd );
385 if( hwnd == GetCapture()) ReleaseCapture();
387 /* free resources associated with the window */
389 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
390 PROPERTY_RemoveWindowProps( wndPtr );
392 /* toss stale messages from the queue */
394 QUEUE_CleanupWindow( hwnd );
395 wndPtr->hmemTaskQ = 0;
397 if (!(wndPtr->dwStyle & WS_CHILD))
400 DestroyMenu( wndPtr->wIDmenu );
403 if (wndPtr->hSysMenu)
405 DestroyMenu( wndPtr->hSysMenu );
406 wndPtr->hSysMenu = 0;
408 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
409 DCE_FreeWindowDCE( wndPtr->hwndSelf ); /* Always do this to catch orphaned DCs */
410 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
411 CLASS_RemoveWindow( wndPtr->class );
412 wndPtr->class = NULL;
413 wndPtr->dwMagic = 0; /* Mark it as invalid */
415 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
420 /***********************************************************************
421 * WIN_DestroyThreadWindows
423 * Destroy all children of 'wnd' owned by the current thread.
424 * Return TRUE if something was done.
426 void WIN_DestroyThreadWindows( HWND hwnd )
431 if (!(list = WIN_BuildWinArray( hwnd ))) return;
432 for (i = 0; list[i]; i++)
434 if (!IsWindow( list[i] )) continue;
435 if (GetWindowThreadProcessId( list[i], NULL ) == GetCurrentThreadId())
436 DestroyWindow( list[i] );
438 WIN_DestroyThreadWindows( list[i] );
440 WIN_ReleaseWinArray( list );
443 /***********************************************************************
444 * WIN_CreateDesktopWindow
446 * Create the desktop window.
448 BOOL WIN_CreateDesktopWindow(void)
450 struct tagCLASS *class;
458 TRACE("Creating desktop window\n");
461 if (!WINPOS_CreateInternalPosAtom() ||
462 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
463 &wndExtra, &winproc, &clsStyle, &dce )))
466 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
467 if (!hwndDesktop) return FALSE;
468 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
470 pWndDesktop->next = NULL;
471 pWndDesktop->child = NULL;
472 pWndDesktop->parent = NULL;
473 pWndDesktop->owner = NULL;
474 pWndDesktop->class = class;
475 pWndDesktop->dwMagic = WND_MAGIC;
476 pWndDesktop->hwndSelf = hwndDesktop;
477 pWndDesktop->hInstance = 0;
478 pWndDesktop->rectWindow.left = 0;
479 pWndDesktop->rectWindow.top = 0;
480 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
481 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
482 pWndDesktop->rectClient = pWndDesktop->rectWindow;
483 pWndDesktop->text = NULL;
484 pWndDesktop->hmemTaskQ = 0;
485 pWndDesktop->hrgnUpdate = 0;
486 pWndDesktop->hwndLastActive = hwndDesktop;
487 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
489 pWndDesktop->dwExStyle = 0;
490 pWndDesktop->clsStyle = clsStyle;
491 pWndDesktop->dce = NULL;
492 pWndDesktop->pVScroll = NULL;
493 pWndDesktop->pHScroll = NULL;
494 pWndDesktop->pProp = NULL;
495 pWndDesktop->wIDmenu = 0;
496 pWndDesktop->helpContext = 0;
497 pWndDesktop->flags = 0;
498 pWndDesktop->hSysMenu = 0;
499 pWndDesktop->userdata = 0;
500 pWndDesktop->winproc = winproc;
501 pWndDesktop->cbWndExtra = wndExtra;
502 pWndDesktop->irefCount = 0;
504 cs.lpCreateParams = NULL;
510 cs.cx = pWndDesktop->rectWindow.right;
511 cs.cy = pWndDesktop->rectWindow.bottom;
512 cs.style = pWndDesktop->dwStyle;
513 cs.dwExStyle = pWndDesktop->dwExStyle;
515 cs.lpszClass = DESKTOP_CLASS_ATOM;
517 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
519 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
524 /***********************************************************************
527 * Fix the coordinates - Helper for WIN_CreateWindowEx.
528 * returns default show mode in sw.
529 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
531 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
533 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
534 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
536 if (cs->style & (WS_CHILD | WS_POPUP))
538 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
539 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
541 else /* overlapped window */
545 GetStartupInfoA( &info );
547 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
549 /* Never believe Microsoft's documentation... CreateWindowEx doc says
550 * that if an overlapped window is created with WS_VISIBLE style bit
551 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
552 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
555 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
556 * 2) it does not ignore the y parameter as the docs claim; instead, it
557 * uses it as second parameter to ShowWindow() unless y is either
558 * CW_USEDEFAULT or CW_USEDEFAULT16.
560 * The fact that we didn't do 2) caused bogus windows pop up when wine
561 * was running apps that were using this obscure feature. Example -
562 * calc.exe that comes with Win98 (only Win98, it's different from
563 * the one that comes with Win95 and NT)
565 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
566 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
567 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
570 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
572 if (info.dwFlags & STARTF_USESIZE)
574 cs->cx = info.dwXSize;
575 cs->cy = info.dwYSize;
577 else /* if no other hint from the app, pick 3/4 of the screen real estate */
580 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
581 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
582 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
589 /***********************************************************************
592 * Implementation of CreateWindowEx().
594 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
595 WINDOWPROCTYPE type )
598 struct tagCLASS *classPtr;
600 HWND hwnd, hwndLinkAfter;
601 POINT maxSize, maxPos, minTrack, maxTrack;
606 BOOL unicode = (type == WIN_PROC_32W);
608 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
609 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
610 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
611 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
612 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
614 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
615 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
617 /* Find the parent window */
621 /* Make sure parent is valid */
622 if (!IsWindow( cs->hwndParent ))
624 WARN("Bad parent %04x\n", cs->hwndParent );
627 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
628 WARN("No parent for child window\n" );
629 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
632 /* Find the window class */
633 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
634 &wndExtra, &winproc, &clsStyle, &dce )))
636 WARN("Bad class '%s'\n", cs->lpszClass );
640 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
642 /* Correct the window style - stage 1
644 * These are patches that appear to affect both the style loaded into the
645 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
647 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
648 * why does the user get to set it?
651 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
652 * tested for WS_POPUP
654 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
655 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
656 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
657 cs->dwExStyle |= WS_EX_WINDOWEDGE;
659 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
661 /* Create the window structure */
663 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
665 TRACE("out of memory\n" );
669 /* Fill the window structure */
671 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
673 wndPtr->child = NULL;
675 if ((cs->style & WS_CHILD) && cs->hwndParent)
677 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
678 wndPtr->owner = NULL;
679 WIN_ReleaseWndPtr(wndPtr->parent);
683 wndPtr->parent = pWndDesktop;
684 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
685 wndPtr->owner = NULL;
688 wndPtr->owner = WIN_FindWndPtr( GetAncestor( cs->hwndParent, GA_ROOT ));
689 WIN_ReleaseWndPtr(wndPtr->owner);
694 wndPtr->class = classPtr;
695 wndPtr->winproc = winproc;
696 wndPtr->dwMagic = WND_MAGIC;
697 wndPtr->hwndSelf = hwnd;
698 wndPtr->hInstance = cs->hInstance;
700 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
701 wndPtr->hrgnUpdate = 0;
703 wndPtr->hwndLastActive = hwnd;
704 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
705 wndPtr->dwExStyle = cs->dwExStyle;
706 wndPtr->clsStyle = clsStyle;
708 wndPtr->helpContext = 0;
709 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
710 wndPtr->pVScroll = NULL;
711 wndPtr->pHScroll = NULL;
712 wndPtr->pProp = NULL;
713 wndPtr->userdata = 0;
714 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
715 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
716 wndPtr->cbWndExtra = wndExtra;
717 wndPtr->irefCount = 1;
719 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
721 /* Call the WH_CBT hook */
723 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
724 ? HWND_BOTTOM : HWND_TOP;
726 if (HOOK_IsHooked( WH_CBT ))
732 cbtc.hwndInsertAfter = hwndLinkAfter;
733 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
734 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
737 TRACE("CBT-hook returned 0\n");
738 USER_HEAP_FREE( hwnd );
739 CLASS_RemoveWindow( classPtr );
745 /* Correct the window style - stage 2 */
747 if (!(cs->style & WS_CHILD))
749 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
750 if (!(cs->style & WS_POPUP))
752 wndPtr->dwStyle |= WS_CAPTION;
753 wndPtr->flags |= WIN_NEED_SIZE;
757 /* Get class or window DC if needed */
759 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
760 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
761 else wndPtr->dce = NULL;
763 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
765 wndPtr->rectWindow.left = cs->x;
766 wndPtr->rectWindow.top = cs->y;
767 wndPtr->rectWindow.right = cs->x + cs->cx;
768 wndPtr->rectWindow.bottom = cs->y + cs->cy;
769 wndPtr->rectClient = wndPtr->rectWindow;
771 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
773 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
775 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
776 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
777 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
778 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
779 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
782 if (cs->cx < 0) cs->cx = 0;
783 if (cs->cy < 0) cs->cy = 0;
785 wndPtr->rectWindow.left = cs->x;
786 wndPtr->rectWindow.top = cs->y;
787 wndPtr->rectWindow.right = cs->x + cs->cx;
788 wndPtr->rectWindow.bottom = cs->y + cs->cy;
789 wndPtr->rectClient = wndPtr->rectWindow;
791 /* Set the window menu */
793 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
795 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
798 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
801 if (HIWORD(cs->hInstance))
802 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
804 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
806 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
810 else wndPtr->wIDmenu = (UINT)cs->hMenu;
812 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
814 WARN("aborted by WM_xxCREATE!\n");
815 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
816 CLASS_RemoveWindow( classPtr );
817 WIN_ReleaseWndPtr(wndPtr);
821 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
823 /* Notify the parent window only */
825 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
826 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
827 if( !IsWindow(hwnd) )
834 if (cs->style & WS_VISIBLE)
836 /* in case WS_VISIBLE got set in the meantime */
837 wndPtr->dwStyle &= ~WS_VISIBLE;
838 ShowWindow( hwnd, sw );
841 /* Call WH_SHELL hook */
843 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
844 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
846 TRACE("created window %04x\n", hwnd);
848 WIN_ReleaseWndPtr(wndPtr);
853 /***********************************************************************
854 * CreateWindow (USER.41)
856 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
857 DWORD style, INT16 x, INT16 y, INT16 width,
858 INT16 height, HWND16 parent, HMENU16 menu,
859 HINSTANCE16 instance, LPVOID data )
861 return CreateWindowEx16( 0, className, windowName, style,
862 x, y, width, height, parent, menu, instance, data );
866 /***********************************************************************
867 * CreateWindowEx (USER.452)
869 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
870 LPCSTR windowName, DWORD style, INT16 x,
871 INT16 y, INT16 width, INT16 height,
872 HWND16 parent, HMENU16 menu,
873 HINSTANCE16 instance, LPVOID data )
879 /* Find the class atom */
881 if (HIWORD(className))
883 if (!(classAtom = GlobalFindAtomA( className )))
885 ERR( "bad class name %s\n", debugres_a(className) );
891 classAtom = LOWORD(className);
892 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
894 ERR( "bad atom %x\n", classAtom);
900 /* Fix the coordinates */
902 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
903 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
904 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
905 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
907 /* Create the window */
909 cs.lpCreateParams = data;
910 cs.hInstance = (HINSTANCE)instance;
911 cs.hMenu = (HMENU)menu;
912 cs.hwndParent = (HWND)parent;
914 cs.lpszName = windowName;
915 cs.lpszClass = className;
916 cs.dwExStyle = exStyle;
918 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
922 /***********************************************************************
923 * CreateWindowExA (USER32.@)
925 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
926 LPCSTR windowName, DWORD style, INT x,
927 INT y, INT width, INT height,
928 HWND parent, HMENU menu,
929 HINSTANCE instance, LPVOID data )
936 instance=GetModuleHandleA(NULL);
938 if(exStyle & WS_EX_MDICHILD)
939 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
941 /* Find the class atom */
943 if (HIWORD(className))
945 if (!(classAtom = GlobalFindAtomA( className )))
947 ERR( "bad class name %s\n", debugres_a(className) );
953 classAtom = LOWORD(className);
954 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
956 ERR( "bad atom %x\n", classAtom);
962 /* Create the window */
964 cs.lpCreateParams = data;
965 cs.hInstance = instance;
967 cs.hwndParent = parent;
973 cs.lpszName = windowName;
974 cs.lpszClass = className;
975 cs.dwExStyle = exStyle;
977 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
981 /***********************************************************************
982 * CreateWindowExW (USER32.@)
984 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
985 LPCWSTR windowName, DWORD style, INT x,
986 INT y, INT width, INT height,
987 HWND parent, HMENU menu,
988 HINSTANCE instance, LPVOID data )
995 instance=GetModuleHandleA(NULL);
997 if(exStyle & WS_EX_MDICHILD)
998 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1000 /* Find the class atom */
1002 if (HIWORD(className))
1004 if (!(classAtom = GlobalFindAtomW( className )))
1006 ERR( "bad class name %s\n", debugres_w(className) );
1012 classAtom = LOWORD(className);
1013 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1015 ERR( "bad atom %x\n", classAtom);
1021 /* Create the window */
1023 cs.lpCreateParams = data;
1024 cs.hInstance = instance;
1026 cs.hwndParent = parent;
1032 cs.lpszName = windowName;
1033 cs.lpszClass = className;
1034 cs.dwExStyle = exStyle;
1036 /* Note: we rely on the fact that CREATESTRUCTA and */
1037 /* CREATESTRUCTW have the same layout. */
1038 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1042 /***********************************************************************
1043 * WIN_SendDestroyMsg
1045 static void WIN_SendDestroyMsg( HWND hwnd )
1047 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1048 if (USER_Driver.pResetSelectionOwner)
1049 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1052 * Send the WM_DESTROY to the window.
1054 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1057 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1058 * make sure that the window still exists when we come back.
1065 if (!(pWndArray = WIN_BuildWinArray( hwnd ))) return;
1067 /* start from the end (FIXME: is this needed?) */
1068 for (i = 0; pWndArray[i]; i++) ;
1072 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1074 WIN_ReleaseWinArray( pWndArray );
1077 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1081 /***********************************************************************
1082 * DestroyWindow (USER.53)
1084 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1086 return DestroyWindow(hwnd);
1090 /***********************************************************************
1091 * DestroyWindow (USER32.@)
1093 BOOL WINAPI DestroyWindow( HWND hwnd )
1099 TRACE("(%04x)\n", hwnd);
1101 /* Initialization */
1103 if (hwnd == GetDesktopWindow()) return FALSE; /* Can't destroy desktop */
1105 /* Look whether the focus is within the tree of windows we will
1109 if (h == hwnd || IsChild( hwnd, h ))
1111 HWND parent = GetAncestor( hwnd, GA_PARENT );
1112 if (parent == GetDesktopWindow()) parent = 0;
1118 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) ) return FALSE;
1120 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1121 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1123 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1124 /* FIXME: clean up palette - see "Internals" p.352 */
1127 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1128 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1130 /* Notify the parent window only */
1131 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1132 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1133 if( !IsWindow(hwnd) )
1140 if (USER_Driver.pResetSelectionOwner)
1141 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1143 /* Hide the window */
1145 if (wndPtr->dwStyle & WS_VISIBLE)
1147 ShowWindow( hwnd, SW_HIDE );
1148 if (!IsWindow(hwnd))
1155 /* Recursively destroy owned windows */
1157 if( !(wndPtr->dwStyle & WS_CHILD) )
1161 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1164 if (siblingPtr->owner == wndPtr)
1166 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1169 siblingPtr->owner = NULL;
1171 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1175 DestroyWindow( siblingPtr->hwndSelf );
1176 WIN_ReleaseWndPtr(siblingPtr);
1181 WINPOS_ActivateOtherWindow(wndPtr->hwndSelf);
1183 if( wndPtr->owner &&
1184 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1185 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1188 /* Send destroy messages */
1190 WIN_SendDestroyMsg( hwnd );
1191 if (!IsWindow(hwnd))
1197 /* Unlink now so we won't bother with the children later on */
1199 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1201 /* Destroy the window storage */
1203 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1206 WIN_ReleaseWndPtr(wndPtr);
1211 /***********************************************************************
1212 * CloseWindow (USER.43)
1214 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1216 return CloseWindow( hwnd );
1220 /***********************************************************************
1221 * CloseWindow (USER32.@)
1223 BOOL WINAPI CloseWindow( HWND hwnd )
1225 WND * wndPtr = WIN_FindWndPtr( hwnd );
1228 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1233 ShowWindow( hwnd, SW_MINIMIZE );
1236 WIN_ReleaseWndPtr(wndPtr);
1242 /***********************************************************************
1243 * OpenIcon (USER.44)
1245 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1247 return OpenIcon( hwnd );
1251 /***********************************************************************
1252 * OpenIcon (USER32.@)
1254 BOOL WINAPI OpenIcon( HWND hwnd )
1256 if (!IsIconic( hwnd )) return FALSE;
1257 ShowWindow( hwnd, SW_SHOWNORMAL );
1262 /***********************************************************************
1265 * Implementation of FindWindow() and FindWindowEx().
1267 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1272 WCHAR *buffer = NULL;
1274 if (!parent) parent = GetDesktopWindow();
1277 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1278 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1281 if (!(list = WIN_BuildWinArray( parent )))
1283 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1289 while (list[i] && list[i] != child) i++;
1290 if (!list[i]) return 0;
1291 i++; /* start from next window */
1294 for ( ; list[i]; i++)
1296 if (className && (GetClassWord(list[i], GCW_ATOM) != className))
1297 continue; /* Not the right class */
1299 /* Now check the title */
1301 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1304 WIN_ReleaseWinArray( list );
1305 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1307 /* In this case we need to check whether other processes
1308 own a window with the given paramters on the Desktop,
1309 but we don't, so let's at least warn about it */
1310 if (!retvalue) FIXME("Returning 0 without checking other processes\n");
1316 /***********************************************************************
1317 * FindWindow (USER.50)
1319 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1321 return FindWindowA( className, title );
1325 /***********************************************************************
1326 * FindWindowEx (USER.427)
1328 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1330 return FindWindowExA( parent, child, className, title );
1334 /***********************************************************************
1335 * FindWindowA (USER32.@)
1337 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1339 HWND ret = FindWindowExA( 0, 0, className, title );
1340 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1345 /***********************************************************************
1346 * FindWindowExA (USER32.@)
1348 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1349 LPCSTR className, LPCSTR title )
1357 /* If the atom doesn't exist, then no class */
1358 /* with this name exists either. */
1359 if (!(atom = GlobalFindAtomA( className )))
1361 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1366 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1367 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1368 HeapFree( GetProcessHeap(), 0, buffer );
1373 /***********************************************************************
1374 * FindWindowExW (USER32.@)
1376 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1377 LPCWSTR className, LPCWSTR title )
1383 /* If the atom doesn't exist, then no class */
1384 /* with this name exists either. */
1385 if (!(atom = GlobalFindAtomW( className )))
1387 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1391 return WIN_FindWindow( parent, child, atom, title );
1395 /***********************************************************************
1396 * FindWindowW (USER32.@)
1398 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1400 return FindWindowExW( 0, 0, className, title );
1404 /**********************************************************************
1405 * GetDesktopWindow (USER.286)
1407 HWND16 WINAPI GetDesktopWindow16(void)
1409 return (HWND16)pWndDesktop->hwndSelf;
1413 /**********************************************************************
1414 * GetDesktopWindow (USER32.@)
1416 HWND WINAPI GetDesktopWindow(void)
1418 if (pWndDesktop) return pWndDesktop->hwndSelf;
1419 ERR( "You need the -desktop option when running with native USER\n" );
1425 /**********************************************************************
1426 * GetDesktopHwnd (USER.278)
1428 * Exactly the same thing as GetDesktopWindow(), but not documented.
1429 * Don't ask me why...
1431 HWND16 WINAPI GetDesktopHwnd16(void)
1433 return (HWND16)pWndDesktop->hwndSelf;
1437 /*******************************************************************
1438 * EnableWindow (USER.34)
1440 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1442 return EnableWindow( hwnd, enable );
1446 /*******************************************************************
1447 * EnableWindow (USER32.@)
1449 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1454 TRACE("( %x, %d )\n", hwnd, enable);
1456 if (USER_Driver.pEnableWindow)
1457 return USER_Driver.pEnableWindow( hwnd, enable );
1459 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1461 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1463 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1465 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1466 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1468 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1470 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1472 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1474 if (hwnd == GetFocus())
1475 SetFocus( 0 ); /* A disabled window can't have the focus */
1477 if (hwnd == GetCapture())
1478 ReleaseCapture(); /* A disabled window can't capture the mouse */
1480 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1482 WIN_ReleaseWndPtr(wndPtr);
1487 /***********************************************************************
1488 * IsWindowEnabled (USER.35)
1490 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1492 return IsWindowEnabled(hWnd);
1496 /***********************************************************************
1497 * IsWindowEnabled (USER32.@)
1499 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1504 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1505 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1506 WIN_ReleaseWndPtr(wndPtr);
1512 /***********************************************************************
1513 * IsWindowUnicode (USER32.@)
1515 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1520 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1521 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1522 WIN_ReleaseWndPtr(wndPtr);
1527 /**********************************************************************
1528 * GetWindowWord (USER.133)
1530 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1532 return GetWindowWord( hwnd, offset );
1536 /**********************************************************************
1537 * GetWindowWord (USER32.@)
1539 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1542 WND * wndPtr = WIN_FindWndPtr( hwnd );
1543 if (!wndPtr) return 0;
1546 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1548 WARN("Invalid offset %d\n", offset );
1552 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1558 if (HIWORD(wndPtr->wIDmenu))
1559 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1561 retvalue = (WORD)wndPtr->wIDmenu;
1563 case GWW_HWNDPARENT:
1564 retvalue = GetParent(hwnd);
1567 if (HIWORD(wndPtr->hInstance))
1568 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1570 retvalue = (WORD)wndPtr->hInstance;
1573 WARN("Invalid offset %d\n", offset );
1578 WIN_ReleaseWndPtr(wndPtr);
1582 /**********************************************************************
1583 * SetWindowWord (USER.134)
1585 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1587 return SetWindowWord( hwnd, offset, newval );
1591 /**********************************************************************
1592 * SetWindowWord (USER32.@)
1594 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1597 WND * wndPtr = WIN_FindWndPtr( hwnd );
1598 if (!wndPtr) return 0;
1601 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1603 WARN("Invalid offset %d\n", offset );
1607 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1611 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1612 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1613 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1616 WARN("Invalid offset %d\n", offset );
1623 WIN_ReleaseWndPtr(wndPtr);
1628 /**********************************************************************
1631 * Helper function for GetWindowLong().
1633 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1636 WND * wndPtr = WIN_FindWndPtr( hwnd );
1637 if (!wndPtr) return 0;
1640 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1642 WARN("Invalid offset %d\n", offset );
1646 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1647 /* Special case for dialog window procedure */
1648 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1650 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1657 case GWL_USERDATA: retvalue = wndPtr->userdata;
1659 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1661 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1663 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1665 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1668 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1670 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1673 WARN("Unknown offset %d\n", offset );
1677 WIN_ReleaseWndPtr(wndPtr);
1682 /**********************************************************************
1685 * Helper function for SetWindowLong().
1687 * 0 is the failure code. However, in the case of failure SetLastError
1688 * must be set to distinguish between a 0 return value and a failure.
1690 * FIXME: The error values for SetLastError may not be right. Can
1691 * someone check with the real thing?
1693 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1694 WINDOWPROCTYPE type )
1697 WND * wndPtr = WIN_FindWndPtr( hwnd );
1700 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1704 /* Is this the right error? */
1705 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1711 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1713 WARN("Invalid offset %d\n", offset );
1715 /* Is this the right error? */
1716 SetLastError( ERROR_OUTOFMEMORY );
1721 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1722 /* Special case for dialog window procedure */
1723 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1725 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1726 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1727 type, WIN_PROC_WINDOW );
1734 ptr = (DWORD*)&wndPtr->wIDmenu;
1737 retval = SetWindowWord( hwnd, offset, newval );
1740 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1741 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1742 type, WIN_PROC_WINDOW );
1745 style.styleOld = wndPtr->dwStyle;
1746 style.styleNew = newval;
1747 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1748 wndPtr->dwStyle = style.styleNew;
1749 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1750 retval = style.styleOld;
1754 ptr = &wndPtr->userdata;
1757 style.styleOld = wndPtr->dwExStyle;
1758 style.styleNew = newval;
1759 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1760 wndPtr->dwExStyle = newval;
1761 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1762 retval = style.styleOld;
1766 WARN("Invalid offset %d\n", offset );
1768 /* Don't think this is right error but it should do */
1769 SetLastError( ERROR_OUTOFMEMORY );
1777 WIN_ReleaseWndPtr(wndPtr);
1782 /**********************************************************************
1783 * GetWindowLong (USER.135)
1785 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1787 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1791 /**********************************************************************
1792 * GetWindowLongA (USER32.@)
1794 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1796 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1800 /**********************************************************************
1801 * GetWindowLongW (USER32.@)
1803 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1805 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1809 /**********************************************************************
1810 * SetWindowLong (USER.136)
1812 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1814 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1818 /**********************************************************************
1819 * SetWindowLongA (USER32.@)
1821 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1823 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1827 /**********************************************************************
1828 * SetWindowLongW (USER32.@) Set window attribute
1830 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1831 * value in a window's extra memory.
1833 * The _hwnd_ parameter specifies the window. is the handle to a
1834 * window that has extra memory. The _newval_ parameter contains the
1835 * new attribute or extra memory value. If positive, the _offset_
1836 * parameter is the byte-addressed location in the window's extra
1837 * memory to set. If negative, _offset_ specifies the window
1838 * attribute to set, and should be one of the following values:
1840 * GWL_EXSTYLE The window's extended window style
1842 * GWL_STYLE The window's window style.
1844 * GWL_WNDPROC Pointer to the window's window procedure.
1846 * GWL_HINSTANCE The window's pplication instance handle.
1848 * GWL_ID The window's identifier.
1850 * GWL_USERDATA The window's user-specified data.
1852 * If the window is a dialog box, the _offset_ parameter can be one of
1853 * the following values:
1855 * DWL_DLGPROC The address of the window's dialog box procedure.
1857 * DWL_MSGRESULT The return value of a message
1858 * that the dialog box procedure processed.
1860 * DWL_USER Application specific information.
1864 * If successful, returns the previous value located at _offset_. Otherwise,
1869 * Extra memory for a window class is specified by a nonzero cbWndExtra
1870 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1871 * time of class creation.
1873 * Using GWL_WNDPROC to set a new window procedure effectively creates
1874 * a window subclass. Use CallWindowProc() in the new windows procedure
1875 * to pass messages to the superclass's window procedure.
1877 * The user data is reserved for use by the application which created
1880 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1881 * instead, call the EnableWindow() function to change the window's
1884 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1885 * SetParent() instead.
1888 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1889 * it sends WM_STYLECHANGING before changing the settings
1890 * and WM_STYLECHANGED afterwards.
1891 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1895 * GWL_STYLE does not dispatch WM_STYLE... messages.
1902 LONG WINAPI SetWindowLongW(
1903 HWND hwnd, /* [in] window to alter */
1904 INT offset, /* [in] offset, in bytes, of location to alter */
1905 LONG newval /* [in] new value of location */
1907 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1911 /*******************************************************************
1912 * GetWindowText (USER.36)
1914 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1916 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1920 /*******************************************************************
1921 * GetWindowTextA (USER32.@)
1923 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
1925 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
1929 /*******************************************************************
1930 * InternalGetWindowText (USER32.@)
1932 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
1934 WND *win = WIN_FindWndPtr( hwnd );
1936 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
1937 else lpString[0] = 0;
1938 WIN_ReleaseWndPtr( win );
1939 return strlenW(lpString);
1943 /*******************************************************************
1944 * GetWindowTextW (USER32.@)
1946 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
1948 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
1953 /*******************************************************************
1954 * SetWindowText (USER.37)
1956 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1958 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1962 /*******************************************************************
1963 * SetWindowText (USER32.@)
1964 * SetWindowTextA (USER32.@)
1966 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
1968 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1972 /*******************************************************************
1973 * SetWindowTextW (USER32.@)
1975 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
1977 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1981 /*******************************************************************
1982 * GetWindowTextLength (USER.38)
1984 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1986 return (INT16)GetWindowTextLengthA( hwnd );
1990 /*******************************************************************
1991 * GetWindowTextLengthA (USER32.@)
1993 INT WINAPI GetWindowTextLengthA( HWND hwnd )
1995 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1998 /*******************************************************************
1999 * GetWindowTextLengthW (USER32.@)
2001 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2003 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2007 /*******************************************************************
2008 * IsWindow (USER.47)
2010 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2012 CURRENT_STACK16->es = USER_HeapSel;
2013 return IsWindow( hwnd );
2017 /*******************************************************************
2018 * IsWindow (USER32.@)
2020 BOOL WINAPI IsWindow( HWND hwnd )
2025 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2026 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2027 WIN_ReleaseWndPtr(wndPtr);
2033 /*****************************************************************
2034 * GetParent (USER.46)
2036 HWND16 WINAPI GetParent16( HWND16 hwnd )
2038 return (HWND16)GetParent( hwnd );
2042 /*****************************************************************
2043 * GetParent (USER32.@)
2045 HWND WINAPI GetParent( HWND hwnd )
2050 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2051 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2054 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2056 retvalue = wndPtr->hwndSelf;
2059 WIN_ReleaseWndPtr(wndPtr);
2065 /*****************************************************************
2066 * GetAncestor (USER32.@)
2068 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2071 WND *wndPtr, *parent;
2073 if (hwnd == GetDesktopWindow()) return 0;
2074 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2075 parent = wndPtr->parent;
2080 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2083 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2084 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2087 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2088 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2089 while (wndPtr->owner)
2090 WIN_UpdateWndPtr( &wndPtr, wndPtr->owner );
2093 ret = wndPtr->hwndSelf;
2094 WIN_ReleaseWndPtr( wndPtr );
2099 /*****************************************************************
2100 * SetParent (USER.233)
2102 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2104 return SetParent( hwndChild, hwndNewParent );
2108 /*****************************************************************
2109 * SetParent (USER32.@)
2111 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2118 if (hwnd == GetDesktopWindow()) /* sanity check */
2120 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2124 if (USER_Driver.pSetParent)
2125 return USER_Driver.pSetParent( hwnd, parent );
2127 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2129 dwStyle = wndPtr->dwStyle;
2131 if (!parent) parent = GetDesktopWindow();
2133 if (!(pWndParent = WIN_FindWndPtr(parent)))
2135 WIN_ReleaseWndPtr( wndPtr );
2139 /* Windows hides the window first, then shows it again
2140 * including the WM_SHOWWINDOW messages and all */
2141 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2143 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2144 if (pWndParent != wndPtr->parent)
2146 WIN_UnlinkWindow(wndPtr->hwndSelf);
2147 wndPtr->parent = pWndParent;
2149 if (parent != GetDesktopWindow()) /* a child window */
2151 if( !( wndPtr->dwStyle & WS_CHILD ) )
2153 if( wndPtr->wIDmenu != 0)
2155 DestroyMenu( (HMENU) wndPtr->wIDmenu );
2156 wndPtr->wIDmenu = 0;
2160 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
2162 WIN_ReleaseWndPtr( pWndParent );
2163 WIN_ReleaseWndPtr( wndPtr );
2165 /* SetParent additionally needs to make hwnd the topmost window
2166 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2167 WM_WINDOWPOSCHANGED notification messages.
2169 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2170 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2171 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2172 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2173 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2178 /*******************************************************************
2181 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2183 return IsChild(parent,child);
2187 /*******************************************************************
2188 * IsChild (USER32.@)
2190 BOOL WINAPI IsChild( HWND parent, HWND child )
2192 WND * wndPtr = WIN_FindWndPtr( child );
2193 while (wndPtr && wndPtr->parent)
2195 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2196 if (wndPtr->hwndSelf == GetDesktopWindow()) break;
2197 if (wndPtr->hwndSelf == parent)
2199 WIN_ReleaseWndPtr(wndPtr);
2203 WIN_ReleaseWndPtr(wndPtr);
2208 /***********************************************************************
2209 * IsWindowVisible (USER.49)
2211 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2213 return IsWindowVisible(hwnd);
2217 /***********************************************************************
2218 * IsWindowVisible (USER32.@)
2220 BOOL WINAPI IsWindowVisible( HWND hwnd )
2223 WND *wndPtr = WIN_FindWndPtr( hwnd );
2224 while (wndPtr && wndPtr->parent)
2226 if (!(wndPtr->dwStyle & WS_VISIBLE))
2228 WIN_ReleaseWndPtr(wndPtr);
2231 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2233 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2234 WIN_ReleaseWndPtr(wndPtr);
2239 /***********************************************************************
2240 * WIN_IsWindowDrawable
2242 * hwnd is drawable when it is visible, all parents are not
2243 * minimized, and it is itself not minimized unless we are
2244 * trying to draw its default class icon.
2246 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2248 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2249 if ((wnd->dwStyle & WS_MINIMIZE) &&
2250 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2251 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2252 if( wnd->dwStyle & WS_MINIMIZE ||
2253 !(wnd->dwStyle & WS_VISIBLE) ) break;
2254 return (wnd == NULL);
2258 /*******************************************************************
2259 * GetTopWindow (USER.229)
2261 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2263 return GetTopWindow(hwnd);
2267 /*******************************************************************
2268 * GetTopWindow (USER32.@)
2270 HWND WINAPI GetTopWindow( HWND hwnd )
2272 if (!hwnd) hwnd = GetDesktopWindow();
2273 return GetWindow( hwnd, GW_CHILD );
2277 /*******************************************************************
2278 * GetWindow (USER.262)
2280 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2282 return GetWindow( hwnd,rel );
2286 /*******************************************************************
2287 * GetWindow (USER32.@)
2289 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2293 WND * wndPtr = WIN_FindWndPtr( hwnd );
2294 if (!wndPtr) return 0;
2298 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2302 if (!wndPtr->parent)
2304 retval = 0; /* Desktop window */
2307 while (wndPtr->next)
2309 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2311 retval = wndPtr->hwndSelf;
2315 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2319 if (!wndPtr->parent)
2321 retval = 0; /* Desktop window */
2324 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2325 if (wndPtr->hwndSelf == hwnd)
2327 retval = 0; /* First in list */
2330 while (wndPtr->next)
2332 if (wndPtr->next->hwndSelf == hwnd)
2334 retval = wndPtr->hwndSelf;
2337 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2343 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2347 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2352 WIN_ReleaseWndPtr(wndPtr);
2357 /*******************************************************************
2358 * GetNextWindow (USER.230)
2360 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2362 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2363 return GetWindow16( hwnd, flag );
2366 /***********************************************************************
2367 * WIN_InternalShowOwnedPopups
2369 * Internal version of ShowOwnedPopups; Wine functions should use this
2370 * to avoid interfering with application calls to ShowOwnedPopups
2371 * and to make sure the application can't prevent showing/hiding.
2373 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2377 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2381 HWND *win_array = WIN_BuildWinArray( GetDesktopWindow() );
2383 if (!win_array) return TRUE;
2386 * Show windows Lowest first, Highest last to preserve Z-Order
2388 while (win_array[count]) count++;
2389 while (--count >= 0)
2391 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2392 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2394 if (pWnd->dwStyle & WS_POPUP)
2398 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2399 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2402 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2404 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2405 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2410 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2411 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2412 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2415 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2417 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2418 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2419 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2423 WIN_ReleaseWndPtr( pWnd );
2425 WIN_ReleaseWinArray( win_array );
2430 /*******************************************************************
2431 * ShowOwnedPopups (USER.265)
2433 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2435 ShowOwnedPopups( owner, fShow );
2439 /*******************************************************************
2440 * ShowOwnedPopups (USER32.@)
2442 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2446 HWND *win_array = WIN_BuildWinArray(GetDesktopWindow());
2448 if (!win_array) return TRUE;
2450 while (win_array[count]) count++;
2451 while (--count >= 0)
2453 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2454 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2456 if (pWnd->dwStyle & WS_POPUP)
2460 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2462 /* In Windows, ShowOwnedPopups(TRUE) generates
2463 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2464 * regardless of the state of the owner
2466 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2467 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2472 if (IsWindowVisible(pWnd->hwndSelf))
2474 /* In Windows, ShowOwnedPopups(FALSE) generates
2475 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2476 * regardless of the state of the owner
2478 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2479 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2483 WIN_ReleaseWndPtr( pWnd );
2485 WIN_ReleaseWinArray( win_array );
2490 /*******************************************************************
2491 * GetLastActivePopup (USER.287)
2493 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2495 return GetLastActivePopup( hwnd );
2498 /*******************************************************************
2499 * GetLastActivePopup (USER32.@)
2501 HWND WINAPI GetLastActivePopup( HWND hwnd )
2504 WND *wndPtr =WIN_FindWndPtr(hwnd);
2505 if (!wndPtr) return hwnd;
2506 retval = wndPtr->hwndLastActive;
2507 WIN_ReleaseWndPtr(wndPtr);
2508 if ((retval != hwnd) && (!IsWindow(retval)))
2514 /*******************************************************************
2517 * Build an array of pointers to the children of a given window.
2518 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2519 * when no windows are found.
2521 HWND *WIN_BuildWinArray( HWND hwnd )
2523 /* Future: this function will lock all windows associated with this array */
2524 WND *pWnd, *wndPtr = WIN_FindWndPtr( hwnd );
2528 /* First count the windows */
2530 if (!wndPtr) return NULL;
2532 pWnd = WIN_LockWndPtr(wndPtr->child);
2536 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2541 /* Now build the list of all windows */
2543 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1))))
2545 for (pWnd = WIN_LockWndPtr(wndPtr->child), phwnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2547 *phwnd++ = pWnd->hwndSelf;
2550 WIN_ReleaseWndPtr(pWnd);
2556 WIN_ReleaseWndPtr( wndPtr );
2560 /*******************************************************************
2561 * WIN_ReleaseWinArray
2563 void WIN_ReleaseWinArray(HWND *wndArray)
2565 if (wndArray) HeapFree( GetProcessHeap(), 0, wndArray );
2568 /*******************************************************************
2569 * EnumWindows (USER32.@)
2571 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2577 /* We have to build a list of all windows first, to avoid */
2578 /* unpleasant side-effects, for instance if the callback */
2579 /* function changes the Z-order of the windows. */
2581 if (!(list = WIN_BuildWinArray( GetDesktopWindow() ))) return FALSE;
2583 /* Now call the callback function for every window */
2585 iWndsLocks = WIN_SuspendWndsLock();
2586 for (i = 0; list[i]; i++)
2588 /* Make sure that the window still exists */
2589 if (!IsWindow( list[i] )) continue;
2590 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2592 WIN_RestoreWndsLock(iWndsLocks);
2593 WIN_ReleaseWinArray(list);
2598 /**********************************************************************
2599 * EnumTaskWindows16 (USER.225)
2601 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2604 TDB *tdb = TASK_GetPtr( hTask );
2605 if (!tdb) return FALSE;
2606 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2610 /**********************************************************************
2611 * EnumThreadWindows (USER32.@)
2613 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2618 if (!(list = WIN_BuildWinArray( GetDesktopWindow() ))) return FALSE;
2620 /* Now call the callback function for every window */
2622 iWndsLocks = WIN_SuspendWndsLock();
2623 for (i = 0; list[i]; i++)
2625 if (GetWindowThreadProcessId( list[i], NULL ) != id) continue;
2626 if (!func( list[i], lParam )) break;
2628 WIN_RestoreWndsLock(iWndsLocks);
2629 WIN_ReleaseWinArray(list);
2634 /**********************************************************************
2635 * WIN_EnumChildWindows
2637 * Helper function for EnumChildWindows().
2639 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2644 for ( ; *list; list++)
2646 /* Make sure that the window still exists */
2647 if (!IsWindow( *list )) continue;
2648 /* skip owned windows */
2649 if (GetWindow( *list, GW_OWNER )) continue;
2650 /* Build children list first */
2651 childList = WIN_BuildWinArray( *list );
2653 ret = func( *list, lParam );
2657 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2658 WIN_ReleaseWinArray(childList);
2660 if (!ret) return FALSE;
2666 /**********************************************************************
2667 * EnumChildWindows (USER32.@)
2669 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2674 if (!(list = WIN_BuildWinArray( parent ))) return FALSE;
2675 iWndsLocks = WIN_SuspendWndsLock();
2676 WIN_EnumChildWindows( list, func, lParam );
2677 WIN_RestoreWndsLock(iWndsLocks);
2678 WIN_ReleaseWinArray(list);
2683 /*******************************************************************
2684 * AnyPopup (USER.52)
2686 BOOL16 WINAPI AnyPopup16(void)
2692 /*******************************************************************
2693 * AnyPopup (USER32.@)
2695 BOOL WINAPI AnyPopup(void)
2699 HWND *list = WIN_BuildWinArray( GetDesktopWindow() );
2701 if (!list) return FALSE;
2702 for (i = 0; list[i]; i++)
2704 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2706 retvalue = (list[i] != 0);
2707 WIN_ReleaseWinArray( list );
2712 /*******************************************************************
2713 * FlashWindow (USER.105)
2715 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2717 return FlashWindow( hWnd, bInvert );
2721 /*******************************************************************
2722 * FlashWindow (USER32.@)
2724 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2726 WND *wndPtr = WIN_FindWndPtr(hWnd);
2728 TRACE("%04x\n", hWnd);
2730 if (!wndPtr) return FALSE;
2732 if (wndPtr->dwStyle & WS_MINIMIZE)
2734 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2736 HDC hDC = GetDC(hWnd);
2738 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2739 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2741 ReleaseDC( hWnd, hDC );
2742 wndPtr->flags |= WIN_NCACTIVATED;
2746 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2747 wndPtr->flags &= ~WIN_NCACTIVATED;
2749 WIN_ReleaseWndPtr(wndPtr);
2755 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2756 else wparam = (hWnd == GetActiveWindow());
2758 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2759 WIN_ReleaseWndPtr(wndPtr);
2765 /*******************************************************************
2766 * SetSysModalWindow (USER.188)
2768 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2770 HWND hWndOldModal = hwndSysModal;
2771 hwndSysModal = hWnd;
2772 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2773 return hWndOldModal;
2777 /*******************************************************************
2778 * GetSysModalWindow (USER.189)
2780 HWND16 WINAPI GetSysModalWindow16(void)
2782 return hwndSysModal;
2786 /*******************************************************************
2787 * GetWindowContextHelpId (USER32.@)
2789 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2792 WND *wnd = WIN_FindWndPtr( hwnd );
2794 retval = wnd->helpContext;
2795 WIN_ReleaseWndPtr(wnd);
2800 /*******************************************************************
2801 * SetWindowContextHelpId (USER32.@)
2803 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2805 WND *wnd = WIN_FindWndPtr( hwnd );
2806 if (!wnd) return FALSE;
2807 wnd->helpContext = id;
2808 WIN_ReleaseWndPtr(wnd);
2813 /*******************************************************************
2816 * recursively find a child that contains spDragInfo->pt point
2817 * and send WM_QUERYDROPOBJECT
2819 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2821 BOOL16 wParam, bResult = 0;
2823 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
2826 if (!ptrDragInfo) return FALSE;
2828 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2830 GetWindowRect(hQueryWnd,&tempRect);
2832 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
2834 if (!IsIconic( hQueryWnd ))
2836 WND *ptrWnd, *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd);
2838 tempRect = ptrQueryWnd->rectClient;
2839 if(ptrQueryWnd->parent)
2840 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
2841 (LPPOINT)&tempRect, 2 );
2843 if (PtInRect( &tempRect, pt))
2847 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
2849 if( ptrWnd->dwStyle & WS_VISIBLE )
2851 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
2852 if (PtInRect( &tempRect, pt )) break;
2858 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
2859 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2860 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2861 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2862 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2864 WIN_ReleaseWndPtr(ptrWnd);
2869 WIN_ReleaseWndPtr(ptrQueryWnd);
2874 WIN_ReleaseWndPtr(ptrQueryWnd);
2878 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2880 ptrDragInfo->hScope = hQueryWnd;
2882 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
2883 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
2885 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2891 /*******************************************************************
2892 * DragDetect (USER.465)
2894 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2897 CONV_POINT16TO32( &pt, &pt32 );
2898 return DragDetect( hWnd, pt32 );
2901 /*******************************************************************
2902 * DragDetect (USER32.@)
2904 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2909 rect.left = pt.x - wDragWidth;
2910 rect.right = pt.x + wDragWidth;
2912 rect.top = pt.y - wDragHeight;
2913 rect.bottom = pt.y + wDragHeight;
2919 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2921 if( msg.message == WM_LBUTTONUP )
2926 if( msg.message == WM_MOUSEMOVE )
2929 tmp.x = LOWORD(msg.lParam);
2930 tmp.y = HIWORD(msg.lParam);
2931 if( !PtInRect( &rect, tmp ))
2943 /******************************************************************************
2944 * DragObject (USER.464)
2946 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2947 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2950 LPDRAGINFO16 lpDragInfo;
2952 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2953 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
2954 HCURSOR16 hCurrentCursor = 0;
2955 HWND16 hCurrentWnd = 0;
2957 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
2958 spDragInfo = K32WOWGlobalLock16(hDragInfo);
2960 if( !lpDragInfo || !spDragInfo ) return 0L;
2962 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
2964 GlobalFree16(hDragInfo);
2970 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2972 GlobalFree16(hDragInfo);
2976 if( hDragCursor == hCursor ) hDragCursor = 0;
2977 else hCursor = hDragCursor;
2979 hOldCursor = SetCursor(hDragCursor);
2982 lpDragInfo->hWnd = hWnd;
2983 lpDragInfo->hScope = 0;
2984 lpDragInfo->wFlags = wObj;
2985 lpDragInfo->hList = szList; /* near pointer! */
2986 lpDragInfo->hOfStruct = hOfStruct;
2994 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
2996 *(lpDragInfo+1) = *lpDragInfo;
2998 lpDragInfo->pt.x = msg.pt.x;
2999 lpDragInfo->pt.y = msg.pt.y;
3001 /* update DRAGINFO struct */
3002 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3004 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3005 hCurrentCursor = hCursor;
3008 hCurrentCursor = hBummer;
3009 lpDragInfo->hScope = 0;
3011 if( hCurrentCursor )
3012 SetCursor(hCurrentCursor);
3014 /* send WM_DRAGLOOP */
3015 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3016 (LPARAM) spDragInfo );
3017 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3018 if( hCurrentWnd != lpDragInfo->hScope )
3021 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3022 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3023 HIWORD(spDragInfo)) );
3024 hCurrentWnd = lpDragInfo->hScope;
3026 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3030 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3032 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3035 ShowCursor( FALSE );
3039 SetCursor( hOldCursor );
3040 if (hDragCursor) DestroyCursor( hDragCursor );
3043 if( hCurrentCursor != hBummer )
3044 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3045 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3048 GlobalFree16(hDragInfo);
3050 return (DWORD)(msg.lParam);
3054 /******************************************************************************
3055 * GetWindowModuleFileNameA (USER32.@)
3057 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3059 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3060 hwnd, lpszFileName, cchFileNameMax);
3064 /******************************************************************************
3065 * GetWindowModuleFileNameW (USER32.@)
3067 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3069 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3070 hwnd, lpszFileName, cchFileNameMax);