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 /**********************************************************************/
33 static WND *pWndDesktop = NULL;
35 static HWND hwndSysModal = 0;
37 static WORD wDragWidth = 4;
38 static WORD wDragHeight= 3;
41 extern SYSLEVEL USER_SysLevel; /* FIXME */
43 /***********************************************************************
46 * Suspend the lock on WND structures.
47 * Returns the number of locks suspended
49 int WIN_SuspendWndsLock( void )
51 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
52 int count = isuspendedLocks;
55 _LeaveSysLevel( &USER_SysLevel );
57 return isuspendedLocks;
60 /***********************************************************************
63 * Restore the suspended locks on WND structures
65 void WIN_RestoreWndsLock( int ipreviousLocks )
67 while ( ipreviousLocks-- > 0 )
68 _EnterSysLevel( &USER_SysLevel );
71 /***********************************************************************
74 * Return a pointer to the WND structure corresponding to a HWND.
76 WND * WIN_FindWndPtr( HWND hwnd )
80 if (!hwnd || HIWORD(hwnd)) goto error2;
81 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
82 /* Lock all WND structures for thread safeness*/
84 /*and increment destruction monitoring*/
87 if (ptr->dwMagic != WND_MAGIC) goto error;
88 if (ptr->hwndSelf != hwnd)
90 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
93 /* returns a locked pointer */
96 /* Unlock all WND structures for thread safeness*/
98 /* and decrement destruction monitoring value */
103 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
107 /***********************************************************************
110 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
112 * Returns the locked initialisation pointer
114 WND *WIN_LockWndPtr(WND *initWndPtr)
116 if(!initWndPtr) return 0;
118 /* Lock all WND structures for thread safeness*/
120 /*and increment destruction monitoring*/
121 initWndPtr->irefCount++;
127 /***********************************************************************
130 * Release the pointer to the WND structure.
132 void WIN_ReleaseWndPtr(WND *wndPtr)
136 /*Decrement destruction monitoring value*/
138 /* Check if it's time to release the memory*/
139 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
142 USER_HEAP_FREE( wndPtr->hwndSelf);
143 wndPtr->hwndSelf = 0;
145 else if(wndPtr->irefCount < 0)
147 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
148 ERR("forgot a Lock on %p somewhere\n",wndPtr);
150 /*unlock all WND structures for thread safeness*/
154 /***********************************************************************
157 * Updates the value of oldPtr to newPtr.
159 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
163 tmpWnd = WIN_LockWndPtr(newPtr);
164 WIN_ReleaseWndPtr(*oldPtr);
169 /***********************************************************************
172 * Dump the content of a window structure to stderr.
174 void WIN_DumpWindow( HWND hwnd )
180 if (!(ptr = WIN_FindWndPtr( hwnd )))
182 WARN("%04x is not a window handle\n", hwnd );
186 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
187 strcpy( className, "#NULL#" );
189 TRACE("Window %04x (%p):\n", hwnd, ptr );
190 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
191 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
192 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
193 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
194 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
195 ptr->next, ptr->child, ptr->parent, ptr->owner,
196 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
197 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
198 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
199 ptr->text ? debugstr_w(ptr->text) : "",
200 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
201 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
202 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
203 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
207 DPRINTF( "extra bytes:" );
208 for (i = 0; i < ptr->cbWndExtra; i++)
209 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
213 WIN_ReleaseWndPtr(ptr);
217 /***********************************************************************
220 * Walk the windows tree and print each window on stderr.
222 void WIN_WalkWindows( HWND hwnd, int indent )
227 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
231 WARN("Invalid window handle %04x\n", hwnd );
235 if (!indent) /* first time around */
236 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
237 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
242 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
244 GetClassNameA( ptr->hwndSelf, className, sizeof(className) );
245 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
246 (DWORD)ptr, ptr->hmemTaskQ, className,
247 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
248 ptr->text ? debugstr_w(ptr->text) : "<null>");
250 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
251 WIN_UpdateWndPtr(&ptr,ptr->next);
255 /***********************************************************************
258 * Remove a window from the siblings linked list.
260 BOOL WIN_UnlinkWindow( HWND hwnd )
262 WND *wndPtr, **ppWnd;
265 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
266 else if(!wndPtr->parent)
268 WIN_ReleaseWndPtr(wndPtr);
272 ppWnd = &wndPtr->parent->child;
273 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
276 *ppWnd = wndPtr->next;
279 WIN_ReleaseWndPtr(wndPtr);
284 /***********************************************************************
287 * Insert a window into the siblings linked list.
288 * The window is inserted after the specified window, which can also
289 * be specified as HWND_TOP or HWND_BOTTOM.
291 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
293 WND *wndPtr, **ppWnd;
295 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
296 else if(!wndPtr->parent)
298 WIN_ReleaseWndPtr(wndPtr);
301 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
303 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
304 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
305 while (*ppWnd) ppWnd = &(*ppWnd)->next;
307 else /* Normal case */
309 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
312 WIN_ReleaseWndPtr(wndPtr);
315 ppWnd = &afterPtr->next;
316 WIN_ReleaseWndPtr(afterPtr);
318 wndPtr->next = *ppWnd;
320 WIN_ReleaseWndPtr(wndPtr);
325 /***********************************************************************
326 * WIN_FindWinToRepaint
328 * Find a window that needs repaint.
330 HWND WIN_FindWinToRepaint( HWND hwnd )
335 /* Note: the desktop window never gets WM_PAINT messages
336 * The real reason why is because Windows DesktopWndProc
337 * does ValidateRgn inside WM_ERASEBKGND handler.
339 if (hwnd == GetDesktopWindow()) hwnd = 0;
341 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
343 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
345 if (!(pWnd->dwStyle & WS_VISIBLE))
347 TRACE("skipping window %04x\n",
350 else if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
351 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
354 else if (pWnd->child )
355 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
357 WIN_ReleaseWndPtr(pWnd);
368 hwndRet = pWnd->hwndSelf;
370 /* look among siblings if we got a transparent window */
371 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
372 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
374 WIN_UpdateWndPtr(&pWnd,pWnd->next);
378 hwndRet = pWnd->hwndSelf;
379 WIN_ReleaseWndPtr(pWnd);
381 TRACE("found %04x\n",hwndRet);
386 /***********************************************************************
389 * Destroy storage associated to a window. "Internals" p.358
390 * returns a locked wndPtr->next
392 static WND* WIN_DestroyWindow( WND* wndPtr )
394 HWND hwnd = wndPtr->hwndSelf;
397 TRACE("%04x\n", wndPtr->hwndSelf );
399 /* free child windows */
400 WIN_LockWndPtr(wndPtr->child);
401 while ((pWnd = wndPtr->child))
403 wndPtr->child = WIN_DestroyWindow( pWnd );
404 WIN_ReleaseWndPtr(pWnd);
408 * Clear the update region to make sure no WM_PAINT messages will be
409 * generated for this window while processing the WM_NCDESTROY.
411 RedrawWindow( wndPtr->hwndSelf, NULL, 0,
412 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
415 * Send the WM_NCDESTROY to the window being destroyed.
417 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
419 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
421 WINPOS_CheckInternalPos( hwnd );
422 if( hwnd == GetCapture()) ReleaseCapture();
424 /* free resources associated with the window */
426 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
427 PROPERTY_RemoveWindowProps( wndPtr );
429 /* toss stale messages from the queue */
431 QUEUE_CleanupWindow( hwnd );
432 wndPtr->hmemTaskQ = 0;
434 if (!(wndPtr->dwStyle & WS_CHILD))
437 DestroyMenu( wndPtr->wIDmenu );
440 if (wndPtr->hSysMenu)
442 DestroyMenu( wndPtr->hSysMenu );
443 wndPtr->hSysMenu = 0;
445 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
446 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
447 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
448 CLASS_RemoveWindow( wndPtr->class );
449 wndPtr->class = NULL;
450 wndPtr->dwMagic = 0; /* Mark it as invalid */
452 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
457 /***********************************************************************
458 * WIN_DestroyThreadWindows
460 * Destroy all children of 'wnd' owned by the current thread.
461 * Return TRUE if something was done.
463 BOOL WIN_DestroyThreadWindows( HWND hwnd )
466 WND *wnd = WIN_FindWndPtr( hwnd );
468 if (!wnd) return FALSE;
471 WND *tmp = WIN_LockWndPtr(wnd->child);
475 if (GetWindowThreadProcessId( tmp->hwndSelf, NULL ) == GetCurrentThreadId())
477 DestroyWindow( tmp->hwndSelf );
481 if (tmp->child && WIN_DestroyThreadWindows( tmp->hwndSelf ))
484 WIN_UpdateWndPtr(&tmp,tmp->next);
486 WIN_ReleaseWndPtr(tmp);
489 WIN_ReleaseWndPtr( wnd );
493 /***********************************************************************
494 * WIN_CreateDesktopWindow
496 * Create the desktop window.
498 BOOL WIN_CreateDesktopWindow(void)
500 struct tagCLASS *class;
508 TRACE("Creating desktop window\n");
511 if (!WINPOS_CreateInternalPosAtom() ||
512 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
513 &wndExtra, &winproc, &clsStyle, &dce )))
516 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
517 if (!hwndDesktop) return FALSE;
518 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
520 pWndDesktop->next = NULL;
521 pWndDesktop->child = NULL;
522 pWndDesktop->parent = NULL;
523 pWndDesktop->owner = NULL;
524 pWndDesktop->class = class;
525 pWndDesktop->dwMagic = WND_MAGIC;
526 pWndDesktop->hwndSelf = hwndDesktop;
527 pWndDesktop->hInstance = 0;
528 pWndDesktop->rectWindow.left = 0;
529 pWndDesktop->rectWindow.top = 0;
530 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
531 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
532 pWndDesktop->rectClient = pWndDesktop->rectWindow;
533 pWndDesktop->text = NULL;
534 pWndDesktop->hmemTaskQ = 0;
535 pWndDesktop->hrgnUpdate = 0;
536 pWndDesktop->hwndLastActive = hwndDesktop;
537 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
539 pWndDesktop->dwExStyle = 0;
540 pWndDesktop->clsStyle = clsStyle;
541 pWndDesktop->dce = NULL;
542 pWndDesktop->pVScroll = NULL;
543 pWndDesktop->pHScroll = NULL;
544 pWndDesktop->pProp = NULL;
545 pWndDesktop->wIDmenu = 0;
546 pWndDesktop->helpContext = 0;
547 pWndDesktop->flags = 0;
548 pWndDesktop->hSysMenu = 0;
549 pWndDesktop->userdata = 0;
550 pWndDesktop->winproc = winproc;
551 pWndDesktop->cbWndExtra = wndExtra;
552 pWndDesktop->irefCount = 0;
554 cs.lpCreateParams = NULL;
560 cs.cx = pWndDesktop->rectWindow.right;
561 cs.cy = pWndDesktop->rectWindow.bottom;
562 cs.style = pWndDesktop->dwStyle;
563 cs.dwExStyle = pWndDesktop->dwExStyle;
565 cs.lpszClass = DESKTOP_CLASS_ATOM;
567 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
569 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
574 /***********************************************************************
577 * Fix the coordinates - Helper for WIN_CreateWindowEx.
578 * returns default show mode in sw.
579 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
581 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
583 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
584 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
586 if (cs->style & (WS_CHILD | WS_POPUP))
588 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
589 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
591 else /* overlapped window */
595 GetStartupInfoA( &info );
597 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
599 /* Never believe Microsoft's documentation... CreateWindowEx doc says
600 * that if an overlapped window is created with WS_VISIBLE style bit
601 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
602 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
605 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
606 * 2) it does not ignore the y parameter as the docs claim; instead, it
607 * uses it as second parameter to ShowWindow() unless y is either
608 * CW_USEDEFAULT or CW_USEDEFAULT16.
610 * The fact that we didn't do 2) caused bogus windows pop up when wine
611 * was running apps that were using this obscure feature. Example -
612 * calc.exe that comes with Win98 (only Win98, it's different from
613 * the one that comes with Win95 and NT)
615 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
616 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
617 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
620 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
622 if (info.dwFlags & STARTF_USESIZE)
624 cs->cx = info.dwXSize;
625 cs->cy = info.dwYSize;
627 else /* if no other hint from the app, pick 3/4 of the screen real estate */
630 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
631 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
632 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
639 /***********************************************************************
642 * Implementation of CreateWindowEx().
644 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
645 WINDOWPROCTYPE type )
648 struct tagCLASS *classPtr;
650 HWND hwnd, hwndLinkAfter;
651 POINT maxSize, maxPos, minTrack, maxTrack;
656 BOOL unicode = (type == WIN_PROC_32W);
658 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
659 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
660 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
661 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
662 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
664 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
665 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
667 /* Find the parent window */
671 /* Make sure parent is valid */
672 if (!IsWindow( cs->hwndParent ))
674 WARN("Bad parent %04x\n", cs->hwndParent );
677 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
678 WARN("No parent for child window\n" );
679 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
682 /* Find the window class */
683 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
684 &wndExtra, &winproc, &clsStyle, &dce )))
686 WARN("Bad class '%s'\n", cs->lpszClass );
690 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
692 /* Correct the window style - stage 1
694 * These are patches that appear to affect both the style loaded into the
695 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
697 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
698 * why does the user get to set it?
701 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
702 * tested for WS_POPUP
704 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
705 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
706 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
707 cs->dwExStyle |= WS_EX_WINDOWEDGE;
709 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
711 /* Create the window structure */
713 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
715 TRACE("out of memory\n" );
719 /* Fill the window structure */
721 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
723 wndPtr->child = NULL;
725 if ((cs->style & WS_CHILD) && cs->hwndParent)
727 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
728 wndPtr->owner = NULL;
729 WIN_ReleaseWndPtr(wndPtr->parent);
733 wndPtr->parent = pWndDesktop;
734 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
735 wndPtr->owner = NULL;
738 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
739 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
740 WIN_ReleaseWndPtr(wndPtr->owner);
741 WIN_ReleaseWndPtr(tmpWnd);
746 wndPtr->class = classPtr;
747 wndPtr->winproc = winproc;
748 wndPtr->dwMagic = WND_MAGIC;
749 wndPtr->hwndSelf = hwnd;
750 wndPtr->hInstance = cs->hInstance;
752 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
753 wndPtr->hrgnUpdate = 0;
755 wndPtr->hwndLastActive = hwnd;
756 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
757 wndPtr->dwExStyle = cs->dwExStyle;
758 wndPtr->clsStyle = clsStyle;
760 wndPtr->helpContext = 0;
761 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
762 wndPtr->pVScroll = NULL;
763 wndPtr->pHScroll = NULL;
764 wndPtr->pProp = NULL;
765 wndPtr->userdata = 0;
766 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
767 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
768 wndPtr->cbWndExtra = wndExtra;
769 wndPtr->irefCount = 1;
771 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
773 /* Call the WH_CBT hook */
775 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
776 ? HWND_BOTTOM : HWND_TOP;
778 if (HOOK_IsHooked( WH_CBT ))
784 cbtc.hwndInsertAfter = hwndLinkAfter;
785 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
786 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
789 TRACE("CBT-hook returned 0\n");
790 USER_HEAP_FREE( hwnd );
791 CLASS_RemoveWindow( classPtr );
797 /* Correct the window style - stage 2 */
799 if (!(cs->style & WS_CHILD))
801 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
802 if (!(cs->style & WS_POPUP))
804 wndPtr->dwStyle |= WS_CAPTION;
805 wndPtr->flags |= WIN_NEED_SIZE;
809 /* Get class or window DC if needed */
811 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
812 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
813 else wndPtr->dce = NULL;
815 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
817 wndPtr->rectWindow.left = cs->x;
818 wndPtr->rectWindow.top = cs->y;
819 wndPtr->rectWindow.right = cs->x + cs->cx;
820 wndPtr->rectWindow.bottom = cs->y + cs->cy;
821 wndPtr->rectClient = wndPtr->rectWindow;
823 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
825 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
827 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
828 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
829 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
830 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
831 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
834 if (cs->cx < 0) cs->cx = 0;
835 if (cs->cy < 0) cs->cy = 0;
837 wndPtr->rectWindow.left = cs->x;
838 wndPtr->rectWindow.top = cs->y;
839 wndPtr->rectWindow.right = cs->x + cs->cx;
840 wndPtr->rectWindow.bottom = cs->y + cs->cy;
841 wndPtr->rectClient = wndPtr->rectWindow;
843 /* Set the window menu */
845 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
847 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
850 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
853 if (HIWORD(cs->hInstance))
854 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
856 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
858 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
862 else wndPtr->wIDmenu = (UINT)cs->hMenu;
864 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
866 WARN("aborted by WM_xxCREATE!\n");
867 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
868 CLASS_RemoveWindow( classPtr );
869 WIN_ReleaseWndPtr(wndPtr);
873 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
875 /* Notify the parent window only */
877 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
878 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
879 if( !IsWindow(hwnd) )
886 if (cs->style & WS_VISIBLE)
888 /* in case WS_VISIBLE got set in the meantime */
889 wndPtr->dwStyle &= ~WS_VISIBLE;
890 ShowWindow( hwnd, sw );
893 /* Call WH_SHELL hook */
895 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
896 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
898 TRACE("created window %04x\n", hwnd);
900 WIN_ReleaseWndPtr(wndPtr);
905 /***********************************************************************
906 * CreateWindow (USER.41)
908 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
909 DWORD style, INT16 x, INT16 y, INT16 width,
910 INT16 height, HWND16 parent, HMENU16 menu,
911 HINSTANCE16 instance, LPVOID data )
913 return CreateWindowEx16( 0, className, windowName, style,
914 x, y, width, height, parent, menu, instance, data );
918 /***********************************************************************
919 * CreateWindowEx (USER.452)
921 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
922 LPCSTR windowName, DWORD style, INT16 x,
923 INT16 y, INT16 width, INT16 height,
924 HWND16 parent, HMENU16 menu,
925 HINSTANCE16 instance, LPVOID data )
931 /* Find the class atom */
933 if (HIWORD(className))
935 if (!(classAtom = GlobalFindAtomA( className )))
937 ERR( "bad class name %s\n", debugres_a(className) );
943 classAtom = LOWORD(className);
944 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
946 ERR( "bad atom %x\n", classAtom);
952 /* Fix the coordinates */
954 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
955 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
956 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
957 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
959 /* Create the window */
961 cs.lpCreateParams = data;
962 cs.hInstance = (HINSTANCE)instance;
963 cs.hMenu = (HMENU)menu;
964 cs.hwndParent = (HWND)parent;
966 cs.lpszName = windowName;
967 cs.lpszClass = className;
968 cs.dwExStyle = exStyle;
970 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
974 /***********************************************************************
975 * CreateWindowExA (USER32.@)
977 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
978 LPCSTR windowName, DWORD style, INT x,
979 INT y, INT width, INT height,
980 HWND parent, HMENU menu,
981 HINSTANCE instance, LPVOID data )
988 instance=GetModuleHandleA(NULL);
990 if(exStyle & WS_EX_MDICHILD)
991 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
993 /* Find the class atom */
995 if (HIWORD(className))
997 if (!(classAtom = GlobalFindAtomA( className )))
999 ERR( "bad class name %s\n", debugres_a(className) );
1005 classAtom = LOWORD(className);
1006 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1008 ERR( "bad atom %x\n", classAtom);
1014 /* Create the window */
1016 cs.lpCreateParams = data;
1017 cs.hInstance = instance;
1019 cs.hwndParent = parent;
1025 cs.lpszName = windowName;
1026 cs.lpszClass = className;
1027 cs.dwExStyle = exStyle;
1029 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1033 /***********************************************************************
1034 * CreateWindowExW (USER32.@)
1036 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1037 LPCWSTR windowName, DWORD style, INT x,
1038 INT y, INT width, INT height,
1039 HWND parent, HMENU menu,
1040 HINSTANCE instance, LPVOID data )
1047 instance=GetModuleHandleA(NULL);
1049 if(exStyle & WS_EX_MDICHILD)
1050 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1052 /* Find the class atom */
1054 if (HIWORD(className))
1056 if (!(classAtom = GlobalFindAtomW( className )))
1058 ERR( "bad class name %s\n", debugres_w(className) );
1064 classAtom = LOWORD(className);
1065 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1067 ERR( "bad atom %x\n", classAtom);
1073 /* Create the window */
1075 cs.lpCreateParams = data;
1076 cs.hInstance = instance;
1078 cs.hwndParent = parent;
1084 cs.lpszName = windowName;
1085 cs.lpszClass = className;
1086 cs.dwExStyle = exStyle;
1088 /* Note: we rely on the fact that CREATESTRUCTA and */
1089 /* CREATESTRUCTW have the same layout. */
1090 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1093 /***********************************************************************
1094 * WIN_SendDestroyMsg
1096 static void WIN_SendDestroyMsg( WND* pWnd )
1098 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1099 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1102 * Send the WM_DESTROY to the window.
1104 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1107 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1108 * make sure that the window still exists when we come back.
1110 if (IsWindow(pWnd->hwndSelf))
1112 HWND* pWndArray = NULL;
1117 * Now, if the window has kids, we have to send WM_DESTROY messages
1118 * recursively to it's kids. It seems that those calls can also
1119 * trigger re-entrant calls to DestroyWindow for the kids so we must
1120 * protect against corruption of the list of siblings. We first build
1121 * a list of HWNDs representing all the kids.
1123 pChild = WIN_LockWndPtr(pWnd->child);
1127 WIN_UpdateWndPtr(&pChild,pChild->next);
1131 * If there are no kids, we're done.
1136 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1141 if (pWndArray==NULL)
1145 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1146 * call, our linked list of siblings should be safe.
1149 pChild = WIN_LockWndPtr(pWnd->child);
1152 pWndArray[nKidCount] = pChild->hwndSelf;
1154 WIN_UpdateWndPtr(&pChild,pChild->next);
1158 * Now that we have a list, go through that list again and send the destroy
1159 * message to those windows. We are using the HWND to retrieve the
1160 * WND pointer so we are effectively checking that all the kid windows are
1161 * still valid before sending the message.
1165 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1169 WIN_SendDestroyMsg( pChild );
1170 WIN_ReleaseWndPtr(pChild);
1177 HeapFree(GetProcessHeap(), 0, pWndArray);
1180 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1184 /***********************************************************************
1185 * DestroyWindow (USER.53)
1187 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1189 return DestroyWindow(hwnd);
1193 /***********************************************************************
1194 * DestroyWindow (USER32.@)
1196 BOOL WINAPI DestroyWindow( HWND hwnd )
1201 BOOL bFocusSet = FALSE;
1203 TRACE("(%04x)\n", hwnd);
1205 /* Initialization */
1207 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1208 if (wndPtr == pWndDesktop)
1210 retvalue = FALSE; /* Can't destroy desktop */
1214 /* Look whether the focus is within the tree of windows we will
1218 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1222 SetFocus(GetParent(h));
1228 /* If the focus is on the window we will destroy and it has no parent,
1229 * set the focus to 0.
1231 if (! bFocusSet && (h == hwnd))
1233 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1239 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1245 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1247 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1248 /* FIXME: clean up palette - see "Internals" p.352 */
1251 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1252 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1254 /* Notify the parent window only */
1255 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1256 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1257 if( !IsWindow(hwnd) )
1264 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1266 /* Hide the window */
1268 if (wndPtr->dwStyle & WS_VISIBLE)
1270 ShowWindow( hwnd, SW_HIDE );
1271 if (!IsWindow(hwnd))
1278 /* Recursively destroy owned windows */
1280 if( !(wndPtr->dwStyle & WS_CHILD) )
1284 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1287 if (siblingPtr->owner == wndPtr)
1289 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1292 siblingPtr->owner = NULL;
1294 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1298 DestroyWindow( siblingPtr->hwndSelf );
1299 WIN_ReleaseWndPtr(siblingPtr);
1304 WINPOS_ActivateOtherWindow(wndPtr->hwndSelf);
1306 if( wndPtr->owner &&
1307 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1308 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1311 /* Send destroy messages */
1313 WIN_SendDestroyMsg( wndPtr );
1314 if (!IsWindow(hwnd))
1320 /* Unlink now so we won't bother with the children later on */
1322 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1324 /* Destroy the window storage */
1326 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1329 WIN_ReleaseWndPtr(wndPtr);
1334 /***********************************************************************
1335 * CloseWindow (USER.43)
1337 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1339 return CloseWindow( hwnd );
1343 /***********************************************************************
1344 * CloseWindow (USER32.@)
1346 BOOL WINAPI CloseWindow( HWND hwnd )
1348 WND * wndPtr = WIN_FindWndPtr( hwnd );
1351 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1356 ShowWindow( hwnd, SW_MINIMIZE );
1359 WIN_ReleaseWndPtr(wndPtr);
1365 /***********************************************************************
1366 * OpenIcon (USER.44)
1368 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1370 return OpenIcon( hwnd );
1374 /***********************************************************************
1375 * OpenIcon (USER32.@)
1377 BOOL WINAPI OpenIcon( HWND hwnd )
1379 if (!IsIconic( hwnd )) return FALSE;
1380 ShowWindow( hwnd, SW_SHOWNORMAL );
1385 /***********************************************************************
1388 * Implementation of FindWindow() and FindWindowEx().
1390 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1398 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1401 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1407 else if (pWnd->parent != pWndDesktop)
1412 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1416 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1421 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1429 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1431 if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
1432 continue; /* Not the right class */
1434 /* Now check the title */
1438 retvalue = pWnd->hwndSelf;
1441 if (pWnd->text && !strcmpW( pWnd->text, title ))
1443 retvalue = pWnd->hwndSelf;
1448 /* In this case we need to check whether other processes
1449 own a window with the given paramters on the Desktop,
1450 but we don't, so let's at least warn about it */
1451 FIXME("Returning 0 without checking other processes\n");
1453 WIN_ReleaseWndPtr(pWnd);
1459 /***********************************************************************
1460 * FindWindow (USER.50)
1462 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1464 return FindWindowA( className, title );
1468 /***********************************************************************
1469 * FindWindowEx (USER.427)
1471 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1473 return FindWindowExA( parent, child, className, title );
1477 /***********************************************************************
1478 * FindWindowA (USER32.@)
1480 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1482 HWND ret = FindWindowExA( 0, 0, className, title );
1483 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1488 /***********************************************************************
1489 * FindWindowExA (USER32.@)
1491 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1492 LPCSTR className, LPCSTR title )
1500 /* If the atom doesn't exist, then no class */
1501 /* with this name exists either. */
1502 if (!(atom = GlobalFindAtomA( className )))
1504 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1509 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1510 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1511 HeapFree( GetProcessHeap(), 0, buffer );
1516 /***********************************************************************
1517 * FindWindowExW (USER32.@)
1519 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1520 LPCWSTR className, LPCWSTR title )
1526 /* If the atom doesn't exist, then no class */
1527 /* with this name exists either. */
1528 if (!(atom = GlobalFindAtomW( className )))
1530 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1534 return WIN_FindWindow( parent, child, atom, title );
1538 /***********************************************************************
1539 * FindWindowW (USER32.@)
1541 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1543 return FindWindowExW( 0, 0, className, title );
1547 /**********************************************************************
1549 * returns a locked pointer
1551 WND *WIN_GetDesktop(void)
1553 return WIN_LockWndPtr(pWndDesktop);
1555 /**********************************************************************
1556 * WIN_ReleaseDesktop
1557 * unlock the desktop pointer
1559 void WIN_ReleaseDesktop(void)
1561 WIN_ReleaseWndPtr(pWndDesktop);
1565 /**********************************************************************
1566 * GetDesktopWindow (USER.286)
1568 HWND16 WINAPI GetDesktopWindow16(void)
1570 return (HWND16)pWndDesktop->hwndSelf;
1574 /**********************************************************************
1575 * GetDesktopWindow (USER32.@)
1577 HWND WINAPI GetDesktopWindow(void)
1579 if (pWndDesktop) return pWndDesktop->hwndSelf;
1580 ERR( "You need the -desktop option when running with native USER\n" );
1586 /**********************************************************************
1587 * GetDesktopHwnd (USER.278)
1589 * Exactly the same thing as GetDesktopWindow(), but not documented.
1590 * Don't ask me why...
1592 HWND16 WINAPI GetDesktopHwnd16(void)
1594 return (HWND16)pWndDesktop->hwndSelf;
1598 /*******************************************************************
1599 * EnableWindow (USER.34)
1601 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1603 return EnableWindow( hwnd, enable );
1607 /*******************************************************************
1608 * EnableWindow (USER32.@)
1610 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1615 TRACE("( %x, %d )\n", hwnd, enable);
1617 if (USER_Driver.pEnableWindow)
1618 return USER_Driver.pEnableWindow( hwnd, enable );
1620 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1622 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1624 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1626 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1627 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1629 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1631 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1633 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1635 if (hwnd == GetFocus())
1636 SetFocus( 0 ); /* A disabled window can't have the focus */
1638 if (hwnd == GetCapture())
1639 ReleaseCapture(); /* A disabled window can't capture the mouse */
1641 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1643 WIN_ReleaseWndPtr(wndPtr);
1648 /***********************************************************************
1649 * IsWindowEnabled (USER.35)
1651 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1653 return IsWindowEnabled(hWnd);
1657 /***********************************************************************
1658 * IsWindowEnabled (USER32.@)
1660 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1665 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1666 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1667 WIN_ReleaseWndPtr(wndPtr);
1673 /***********************************************************************
1674 * IsWindowUnicode (USER32.@)
1676 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1681 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1682 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1683 WIN_ReleaseWndPtr(wndPtr);
1688 /**********************************************************************
1689 * GetWindowWord (USER.133)
1691 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1693 return GetWindowWord( hwnd, offset );
1697 /**********************************************************************
1698 * GetWindowWord (USER32.@)
1700 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1703 WND * wndPtr = WIN_FindWndPtr( hwnd );
1704 if (!wndPtr) return 0;
1707 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1709 WARN("Invalid offset %d\n", offset );
1713 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1719 if (HIWORD(wndPtr->wIDmenu))
1720 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1722 retvalue = (WORD)wndPtr->wIDmenu;
1724 case GWW_HWNDPARENT:
1725 retvalue = GetParent(hwnd);
1728 if (HIWORD(wndPtr->hInstance))
1729 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1731 retvalue = (WORD)wndPtr->hInstance;
1734 WARN("Invalid offset %d\n", offset );
1739 WIN_ReleaseWndPtr(wndPtr);
1743 /**********************************************************************
1744 * SetWindowWord (USER.134)
1746 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1748 return SetWindowWord( hwnd, offset, newval );
1752 /**********************************************************************
1753 * SetWindowWord (USER32.@)
1755 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1758 WND * wndPtr = WIN_FindWndPtr( hwnd );
1759 if (!wndPtr) return 0;
1762 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1764 WARN("Invalid offset %d\n", offset );
1768 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1772 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1773 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1774 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1777 WARN("Invalid offset %d\n", offset );
1784 WIN_ReleaseWndPtr(wndPtr);
1789 /**********************************************************************
1792 * Helper function for GetWindowLong().
1794 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1797 WND * wndPtr = WIN_FindWndPtr( hwnd );
1798 if (!wndPtr) return 0;
1801 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1803 WARN("Invalid offset %d\n", offset );
1807 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1808 /* Special case for dialog window procedure */
1809 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1811 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1818 case GWL_USERDATA: retvalue = wndPtr->userdata;
1820 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1822 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1824 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1826 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1829 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1831 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1834 WARN("Unknown offset %d\n", offset );
1838 WIN_ReleaseWndPtr(wndPtr);
1843 /**********************************************************************
1846 * Helper function for SetWindowLong().
1848 * 0 is the failure code. However, in the case of failure SetLastError
1849 * must be set to distinguish between a 0 return value and a failure.
1851 * FIXME: The error values for SetLastError may not be right. Can
1852 * someone check with the real thing?
1854 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1855 WINDOWPROCTYPE type )
1858 WND * wndPtr = WIN_FindWndPtr( hwnd );
1861 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1865 /* Is this the right error? */
1866 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1872 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1874 WARN("Invalid offset %d\n", offset );
1876 /* Is this the right error? */
1877 SetLastError( ERROR_OUTOFMEMORY );
1882 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1883 /* Special case for dialog window procedure */
1884 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1886 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1887 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1888 type, WIN_PROC_WINDOW );
1895 ptr = (DWORD*)&wndPtr->wIDmenu;
1898 retval = SetWindowWord( hwnd, offset, newval );
1901 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1902 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1903 type, WIN_PROC_WINDOW );
1906 style.styleOld = wndPtr->dwStyle;
1907 style.styleNew = newval;
1908 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1909 wndPtr->dwStyle = style.styleNew;
1910 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1911 retval = style.styleOld;
1915 ptr = &wndPtr->userdata;
1918 style.styleOld = wndPtr->dwExStyle;
1919 style.styleNew = newval;
1920 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1921 wndPtr->dwExStyle = newval;
1922 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1923 retval = style.styleOld;
1927 WARN("Invalid offset %d\n", offset );
1929 /* Don't think this is right error but it should do */
1930 SetLastError( ERROR_OUTOFMEMORY );
1938 WIN_ReleaseWndPtr(wndPtr);
1943 /**********************************************************************
1944 * GetWindowLong (USER.135)
1946 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1948 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1952 /**********************************************************************
1953 * GetWindowLongA (USER32.@)
1955 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1957 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1961 /**********************************************************************
1962 * GetWindowLongW (USER32.@)
1964 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1966 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1970 /**********************************************************************
1971 * SetWindowLong (USER.136)
1973 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1975 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1979 /**********************************************************************
1980 * SetWindowLongA (USER32.@)
1982 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1984 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1988 /**********************************************************************
1989 * SetWindowLongW (USER32.@) Set window attribute
1991 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1992 * value in a window's extra memory.
1994 * The _hwnd_ parameter specifies the window. is the handle to a
1995 * window that has extra memory. The _newval_ parameter contains the
1996 * new attribute or extra memory value. If positive, the _offset_
1997 * parameter is the byte-addressed location in the window's extra
1998 * memory to set. If negative, _offset_ specifies the window
1999 * attribute to set, and should be one of the following values:
2001 * GWL_EXSTYLE The window's extended window style
2003 * GWL_STYLE The window's window style.
2005 * GWL_WNDPROC Pointer to the window's window procedure.
2007 * GWL_HINSTANCE The window's pplication instance handle.
2009 * GWL_ID The window's identifier.
2011 * GWL_USERDATA The window's user-specified data.
2013 * If the window is a dialog box, the _offset_ parameter can be one of
2014 * the following values:
2016 * DWL_DLGPROC The address of the window's dialog box procedure.
2018 * DWL_MSGRESULT The return value of a message
2019 * that the dialog box procedure processed.
2021 * DWL_USER Application specific information.
2025 * If successful, returns the previous value located at _offset_. Otherwise,
2030 * Extra memory for a window class is specified by a nonzero cbWndExtra
2031 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2032 * time of class creation.
2034 * Using GWL_WNDPROC to set a new window procedure effectively creates
2035 * a window subclass. Use CallWindowProc() in the new windows procedure
2036 * to pass messages to the superclass's window procedure.
2038 * The user data is reserved for use by the application which created
2041 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2042 * instead, call the EnableWindow() function to change the window's
2045 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2046 * SetParent() instead.
2049 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2050 * it sends WM_STYLECHANGING before changing the settings
2051 * and WM_STYLECHANGED afterwards.
2052 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2056 * GWL_STYLE does not dispatch WM_STYLE... messages.
2063 LONG WINAPI SetWindowLongW(
2064 HWND hwnd, /* [in] window to alter */
2065 INT offset, /* [in] offset, in bytes, of location to alter */
2066 LONG newval /* [in] new value of location */
2068 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2072 /*******************************************************************
2073 * GetWindowText (USER.36)
2075 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2077 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2081 /*******************************************************************
2082 * GetWindowTextA (USER32.@)
2084 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2086 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2090 /*******************************************************************
2091 * InternalGetWindowText (USER32.@)
2093 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2095 WND *win = WIN_FindWndPtr( hwnd );
2097 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2098 else lpString[0] = 0;
2099 WIN_ReleaseWndPtr( win );
2100 return strlenW(lpString);
2104 /*******************************************************************
2105 * GetWindowTextW (USER32.@)
2107 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2109 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2114 /*******************************************************************
2115 * SetWindowText (USER.37)
2117 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2119 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2123 /*******************************************************************
2124 * SetWindowText (USER32.@)
2125 * SetWindowTextA (USER32.@)
2127 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2129 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2133 /*******************************************************************
2134 * SetWindowTextW (USER32.@)
2136 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2138 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2142 /*******************************************************************
2143 * GetWindowTextLength (USER.38)
2145 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2147 return (INT16)GetWindowTextLengthA( hwnd );
2151 /*******************************************************************
2152 * GetWindowTextLengthA (USER32.@)
2154 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2156 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2159 /*******************************************************************
2160 * GetWindowTextLengthW (USER32.@)
2162 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2164 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2168 /*******************************************************************
2169 * IsWindow (USER.47)
2171 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2173 CURRENT_STACK16->es = USER_HeapSel;
2174 return IsWindow( hwnd );
2178 /*******************************************************************
2179 * IsWindow (USER32.@)
2181 BOOL WINAPI IsWindow( HWND hwnd )
2186 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2187 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2188 WIN_ReleaseWndPtr(wndPtr);
2194 /*****************************************************************
2195 * GetParent (USER.46)
2197 HWND16 WINAPI GetParent16( HWND16 hwnd )
2199 return (HWND16)GetParent( hwnd );
2203 /*****************************************************************
2204 * GetParent (USER32.@)
2206 HWND WINAPI GetParent( HWND hwnd )
2211 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2212 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2215 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2217 retvalue = wndPtr->hwndSelf;
2220 WIN_ReleaseWndPtr(wndPtr);
2225 /*****************************************************************
2228 * Get the top-level parent for a child window.
2229 * returns a locked pointer
2231 WND* WIN_GetTopParentPtr( WND* pWnd )
2233 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2235 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2237 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2242 /*****************************************************************
2245 * Get the top-level parent for a child window.
2247 HWND WIN_GetTopParent( HWND hwnd )
2250 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2251 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2253 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2254 WIN_ReleaseWndPtr(tmpPtr);
2255 WIN_ReleaseWndPtr(wndPtr);
2260 /*****************************************************************
2261 * SetParent (USER.233)
2263 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2265 return SetParent( hwndChild, hwndNewParent );
2269 /*****************************************************************
2270 * SetParent (USER32.@)
2272 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2279 if (hwnd == GetDesktopWindow()) /* sanity check */
2281 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2285 if (USER_Driver.pSetParent)
2286 return USER_Driver.pSetParent( hwnd, parent );
2288 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2290 dwStyle = wndPtr->dwStyle;
2292 if (!parent) parent = GetDesktopWindow();
2294 if (!(pWndParent = WIN_FindWndPtr(parent)))
2296 WIN_ReleaseWndPtr( wndPtr );
2300 /* Windows hides the window first, then shows it again
2301 * including the WM_SHOWWINDOW messages and all */
2302 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2304 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2305 if (pWndParent != wndPtr->parent)
2307 WIN_UnlinkWindow(wndPtr->hwndSelf);
2308 wndPtr->parent = pWndParent;
2310 if (parent != GetDesktopWindow()) /* a child window */
2312 if( !( wndPtr->dwStyle & WS_CHILD ) )
2314 if( wndPtr->wIDmenu != 0)
2316 DestroyMenu( (HMENU) wndPtr->wIDmenu );
2317 wndPtr->wIDmenu = 0;
2321 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
2323 WIN_ReleaseWndPtr( pWndParent );
2324 WIN_ReleaseWndPtr( wndPtr );
2326 /* SetParent additionally needs to make hwnd the topmost window
2327 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2328 WM_WINDOWPOSCHANGED notification messages.
2330 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2331 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2332 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2333 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2334 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2339 /*******************************************************************
2342 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2344 return IsChild(parent,child);
2348 /*******************************************************************
2349 * IsChild (USER32.@)
2351 BOOL WINAPI IsChild( HWND parent, HWND child )
2353 WND * wndPtr = WIN_FindWndPtr( child );
2354 while (wndPtr && wndPtr->parent)
2356 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2357 if (wndPtr->hwndSelf == GetDesktopWindow()) break;
2358 if (wndPtr->hwndSelf == parent)
2360 WIN_ReleaseWndPtr(wndPtr);
2364 WIN_ReleaseWndPtr(wndPtr);
2369 /***********************************************************************
2370 * IsWindowVisible (USER.49)
2372 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2374 return IsWindowVisible(hwnd);
2378 /***********************************************************************
2379 * IsWindowVisible (USER32.@)
2381 BOOL WINAPI IsWindowVisible( HWND hwnd )
2384 WND *wndPtr = WIN_FindWndPtr( hwnd );
2385 while (wndPtr && wndPtr->parent)
2387 if (!(wndPtr->dwStyle & WS_VISIBLE))
2389 WIN_ReleaseWndPtr(wndPtr);
2392 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2394 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2395 WIN_ReleaseWndPtr(wndPtr);
2400 /***********************************************************************
2401 * WIN_IsWindowDrawable
2403 * hwnd is drawable when it is visible, all parents are not
2404 * minimized, and it is itself not minimized unless we are
2405 * trying to draw its default class icon.
2407 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2409 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2410 if ((wnd->dwStyle & WS_MINIMIZE) &&
2411 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2412 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2413 if( wnd->dwStyle & WS_MINIMIZE ||
2414 !(wnd->dwStyle & WS_VISIBLE) ) break;
2415 return (wnd == NULL);
2419 /*******************************************************************
2420 * GetTopWindow (USER.229)
2422 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2424 return GetTopWindow(hwnd);
2428 /*******************************************************************
2429 * GetTopWindow (USER32.@)
2431 HWND WINAPI GetTopWindow( HWND hwnd )
2434 WND * wndPtr = (hwnd) ?
2435 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2437 if (wndPtr && wndPtr->child)
2438 retval = wndPtr->child->hwndSelf;
2440 WIN_ReleaseWndPtr(wndPtr);
2445 /*******************************************************************
2446 * GetWindow (USER.262)
2448 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2450 return GetWindow( hwnd,rel );
2454 /*******************************************************************
2455 * GetWindow (USER32.@)
2457 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2461 WND * wndPtr = WIN_FindWndPtr( hwnd );
2462 if (!wndPtr) return 0;
2466 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2470 if (!wndPtr->parent)
2472 retval = 0; /* Desktop window */
2475 while (wndPtr->next)
2477 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2479 retval = wndPtr->hwndSelf;
2483 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2487 if (!wndPtr->parent)
2489 retval = 0; /* Desktop window */
2492 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2493 if (wndPtr->hwndSelf == hwnd)
2495 retval = 0; /* First in list */
2498 while (wndPtr->next)
2500 if (wndPtr->next->hwndSelf == hwnd)
2502 retval = wndPtr->hwndSelf;
2505 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2511 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2515 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2520 WIN_ReleaseWndPtr(wndPtr);
2525 /*******************************************************************
2526 * GetNextWindow (USER.230)
2528 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2530 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2531 return GetWindow16( hwnd, flag );
2534 /***********************************************************************
2535 * WIN_InternalShowOwnedPopups
2537 * Internal version of ShowOwnedPopups; Wine functions should use this
2538 * to avoid interfering with application calls to ShowOwnedPopups
2539 * and to make sure the application can't prevent showing/hiding.
2541 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2545 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2547 INT totalChild=0, count=0;
2549 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2551 if (!pWnd) return TRUE;
2554 * Show windows Lowest first, Highest last to preserve Z-Order
2556 for (count = totalChild-1 ; count >=0; count--)
2558 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2562 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2563 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2566 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2568 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2569 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2574 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2575 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2576 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2579 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2581 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2582 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2583 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2588 WIN_ReleaseDesktop();
2589 WIN_ReleaseWinArray(pWnd);
2594 /*******************************************************************
2595 * ShowOwnedPopups (USER.265)
2597 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2599 ShowOwnedPopups( owner, fShow );
2603 /*******************************************************************
2604 * ShowOwnedPopups (USER32.@)
2606 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2608 UINT totalChild=0, count=0;
2610 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2612 if (!pWnd) return TRUE;
2614 for (; count < totalChild; count++)
2616 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2620 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2623 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2624 * regardless of the state of the owner
2626 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2627 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2632 if (IsWindowVisible(pWnd[count]->hwndSelf))
2635 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2636 * regardless of the state of the owner
2638 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2639 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2645 WIN_ReleaseDesktop();
2646 WIN_ReleaseWinArray(pWnd);
2651 /*******************************************************************
2652 * GetLastActivePopup (USER.287)
2654 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2656 return GetLastActivePopup( hwnd );
2659 /*******************************************************************
2660 * GetLastActivePopup (USER32.@)
2662 HWND WINAPI GetLastActivePopup( HWND hwnd )
2665 WND *wndPtr =WIN_FindWndPtr(hwnd);
2666 if (!wndPtr) return hwnd;
2667 retval = wndPtr->hwndLastActive;
2668 WIN_ReleaseWndPtr(wndPtr);
2669 if ((retval != hwnd) && (!IsWindow(retval)))
2675 /*******************************************************************
2678 * Build an array of pointers to the children of a given window.
2679 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2680 * when no windows are found.
2682 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2684 /* Future: this function will lock all windows associated with this array */
2686 WND **list, **ppWnd;
2688 UINT count = 0, skipOwned, skipHidden;
2691 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2692 skipOwned = bwaFlags & BWA_SKIPOWNED;
2693 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2694 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2696 /* First count the windows */
2699 wndPtr = WIN_GetDesktop();
2701 pWnd = WIN_LockWndPtr(wndPtr->child);
2704 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2705 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2707 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2712 /* Now build the list of all windows */
2714 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2716 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2718 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2719 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2725 WIN_ReleaseWndPtr(pWnd);
2731 if( pTotal ) *pTotal = count;
2734 /*******************************************************************
2735 * WIN_ReleaseWinArray
2737 void WIN_ReleaseWinArray(WND **wndArray)
2739 /* Future: this function will also unlock all windows associated with wndArray */
2740 HeapFree( GetProcessHeap(), 0, wndArray );
2744 /*******************************************************************
2745 * EnumWindows (USER32.@)
2747 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2749 WND **list, **ppWnd;
2751 /* We have to build a list of all windows first, to avoid */
2752 /* unpleasant side-effects, for instance if the callback */
2753 /* function changes the Z-order of the windows. */
2755 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2757 WIN_ReleaseDesktop();
2761 /* Now call the callback function for every window */
2763 for (ppWnd = list; *ppWnd; ppWnd++)
2765 LRESULT lpEnumFuncRetval;
2767 /* Make sure that the window still exists */
2768 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2770 /* To avoid any deadlocks, all the locks on the windows
2771 structures must be suspended before the control
2772 is passed to the application */
2773 iWndsLocks = WIN_SuspendWndsLock();
2774 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2775 WIN_RestoreWndsLock(iWndsLocks);
2777 if (!lpEnumFuncRetval) break;
2779 WIN_ReleaseWinArray(list);
2780 WIN_ReleaseDesktop();
2785 /**********************************************************************
2786 * WIN_EnumQueueWindows
2788 * Helper for EnumTaskWindows16 and EnumThreadWindows.
2790 static BOOL WIN_EnumQueueWindows( HQUEUE16 queue, WNDENUMPROC func, LPARAM lParam )
2792 WND **list, **ppWnd;
2794 /* This function is the same as EnumWindows(), */
2795 /* except for an added check on the window's task. */
2797 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2799 WIN_ReleaseDesktop();
2803 /* Now call the callback function for every window */
2805 for (ppWnd = list; *ppWnd; ppWnd++)
2809 /* Make sure that the window still exists */
2810 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2811 if ((*ppWnd)->hmemTaskQ != queue) continue;
2813 /* To avoid any deadlocks, all the locks on the windows
2814 structures must be suspended before the control
2815 is passed to the application */
2816 iWndsLocks = WIN_SuspendWndsLock();
2817 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2818 WIN_RestoreWndsLock(iWndsLocks);
2820 if (!funcRetval) break;
2822 WIN_ReleaseWinArray(list);
2823 WIN_ReleaseDesktop();
2828 /**********************************************************************
2829 * EnumTaskWindows16 (USER.225)
2831 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2834 HQUEUE16 queue = GetTaskQueue16( hTask );
2835 if (!queue) return FALSE;
2836 return WIN_EnumQueueWindows( queue, (WNDENUMPROC)func, lParam );
2840 /**********************************************************************
2841 * EnumThreadWindows (USER32.@)
2843 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2845 HQUEUE16 queue = GetThreadQueue16( id );
2846 if (!queue) return FALSE;
2847 return WIN_EnumQueueWindows( queue, func, lParam );
2851 /**********************************************************************
2852 * WIN_EnumChildWindows
2854 * Helper function for EnumChildWindows().
2856 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2861 for ( ; *ppWnd; ppWnd++)
2865 /* Make sure that the window still exists */
2866 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2867 /* Build children list first */
2868 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2870 /* To avoid any deadlocks, all the locks on the windows
2871 structures must be suspended before the control
2872 is passed to the application */
2873 iWndsLocks = WIN_SuspendWndsLock();
2874 ret = func( (*ppWnd)->hwndSelf, lParam );
2875 WIN_RestoreWndsLock(iWndsLocks);
2879 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2880 WIN_ReleaseWinArray(childList);
2882 if (!ret) return FALSE;
2888 /**********************************************************************
2889 * EnumChildWindows (USER32.@)
2891 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2894 WND **list, *pParent;
2896 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2897 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2899 WIN_ReleaseWndPtr(pParent);
2902 WIN_EnumChildWindows( list, func, lParam );
2903 WIN_ReleaseWinArray(list);
2904 WIN_ReleaseWndPtr(pParent);
2909 /*******************************************************************
2910 * AnyPopup (USER.52)
2912 BOOL16 WINAPI AnyPopup16(void)
2918 /*******************************************************************
2919 * AnyPopup (USER32.@)
2921 BOOL WINAPI AnyPopup(void)
2923 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2928 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2933 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2937 WIN_ReleaseWndPtr(wndPtr);
2942 /*******************************************************************
2943 * FlashWindow (USER.105)
2945 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2947 return FlashWindow( hWnd, bInvert );
2951 /*******************************************************************
2952 * FlashWindow (USER32.@)
2954 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2956 WND *wndPtr = WIN_FindWndPtr(hWnd);
2958 TRACE("%04x\n", hWnd);
2960 if (!wndPtr) return FALSE;
2962 if (wndPtr->dwStyle & WS_MINIMIZE)
2964 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2966 HDC hDC = GetDC(hWnd);
2968 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2969 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2971 ReleaseDC( hWnd, hDC );
2972 wndPtr->flags |= WIN_NCACTIVATED;
2976 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2977 wndPtr->flags &= ~WIN_NCACTIVATED;
2979 WIN_ReleaseWndPtr(wndPtr);
2985 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2986 else wparam = (hWnd == GetActiveWindow());
2988 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2989 WIN_ReleaseWndPtr(wndPtr);
2995 /*******************************************************************
2996 * SetSysModalWindow (USER.188)
2998 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3000 HWND hWndOldModal = hwndSysModal;
3001 hwndSysModal = hWnd;
3002 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3003 return hWndOldModal;
3007 /*******************************************************************
3008 * GetSysModalWindow (USER.189)
3010 HWND16 WINAPI GetSysModalWindow16(void)
3012 return hwndSysModal;
3016 /*******************************************************************
3017 * GetWindowContextHelpId (USER32.@)
3019 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3022 WND *wnd = WIN_FindWndPtr( hwnd );
3024 retval = wnd->helpContext;
3025 WIN_ReleaseWndPtr(wnd);
3030 /*******************************************************************
3031 * SetWindowContextHelpId (USER32.@)
3033 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3035 WND *wnd = WIN_FindWndPtr( hwnd );
3036 if (!wnd) return FALSE;
3037 wnd->helpContext = id;
3038 WIN_ReleaseWndPtr(wnd);
3043 /*******************************************************************
3046 * recursively find a child that contains spDragInfo->pt point
3047 * and send WM_QUERYDROPOBJECT
3049 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3051 BOOL16 wParam, bResult = 0;
3053 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3054 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3057 if( !ptrQueryWnd || !ptrDragInfo )
3060 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3062 GetWindowRect(hQueryWnd,&tempRect);
3064 if( !PtInRect(&tempRect,pt) ||
3065 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3068 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3070 tempRect = ptrQueryWnd->rectClient;
3071 if(ptrQueryWnd->parent)
3072 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3073 (LPPOINT)&tempRect, 2 );
3075 if (PtInRect( &tempRect, pt))
3079 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3081 if( ptrWnd->dwStyle & WS_VISIBLE )
3083 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3084 if (PtInRect( &tempRect, pt )) break;
3090 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3091 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3092 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3093 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3094 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3096 WIN_ReleaseWndPtr(ptrWnd);
3106 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3108 ptrDragInfo->hScope = hQueryWnd;
3110 bResult = ( bNoSend )
3111 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3112 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3113 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3115 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3118 WIN_ReleaseWndPtr(ptrQueryWnd);
3123 /*******************************************************************
3124 * DragDetect (USER.465)
3126 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3129 CONV_POINT16TO32( &pt, &pt32 );
3130 return DragDetect( hWnd, pt32 );
3133 /*******************************************************************
3134 * DragDetect (USER32.@)
3136 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3141 rect.left = pt.x - wDragWidth;
3142 rect.right = pt.x + wDragWidth;
3144 rect.top = pt.y - wDragHeight;
3145 rect.bottom = pt.y + wDragHeight;
3151 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3153 if( msg.message == WM_LBUTTONUP )
3158 if( msg.message == WM_MOUSEMOVE )
3161 tmp.x = LOWORD(msg.lParam);
3162 tmp.y = HIWORD(msg.lParam);
3163 if( !PtInRect( &rect, tmp ))
3175 /******************************************************************************
3176 * DragObject (USER.464)
3178 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3179 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3182 LPDRAGINFO16 lpDragInfo;
3184 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3185 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3186 WND *wndPtr = WIN_FindWndPtr(hWnd);
3187 HCURSOR16 hCurrentCursor = 0;
3188 HWND16 hCurrentWnd = 0;
3190 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3191 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3193 if( !lpDragInfo || !spDragInfo )
3195 WIN_ReleaseWndPtr(wndPtr);
3199 hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO));
3201 if( !hBummer || !wndPtr )
3203 GlobalFree16(hDragInfo);
3204 WIN_ReleaseWndPtr(wndPtr);
3210 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3212 GlobalFree16(hDragInfo);
3213 WIN_ReleaseWndPtr(wndPtr);
3217 if( hDragCursor == hCursor ) hDragCursor = 0;
3218 else hCursor = hDragCursor;
3220 hOldCursor = SetCursor(hDragCursor);
3223 lpDragInfo->hWnd = hWnd;
3224 lpDragInfo->hScope = 0;
3225 lpDragInfo->wFlags = wObj;
3226 lpDragInfo->hList = szList; /* near pointer! */
3227 lpDragInfo->hOfStruct = hOfStruct;
3235 do{ WaitMessage(); }
3236 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3238 *(lpDragInfo+1) = *lpDragInfo;
3240 lpDragInfo->pt.x = msg.pt.x;
3241 lpDragInfo->pt.y = msg.pt.y;
3243 /* update DRAGINFO struct */
3244 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3246 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3247 hCurrentCursor = hCursor;
3250 hCurrentCursor = hBummer;
3251 lpDragInfo->hScope = 0;
3253 if( hCurrentCursor )
3254 SetCursor(hCurrentCursor);
3256 /* send WM_DRAGLOOP */
3257 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3258 (LPARAM) spDragInfo );
3259 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3260 if( hCurrentWnd != lpDragInfo->hScope )
3263 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3264 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3265 HIWORD(spDragInfo)) );
3266 hCurrentWnd = lpDragInfo->hScope;
3268 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3272 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3274 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3277 ShowCursor( FALSE );
3281 SetCursor( hOldCursor );
3282 if (hDragCursor) DestroyCursor( hDragCursor );
3285 if( hCurrentCursor != hBummer )
3286 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3287 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3290 GlobalFree16(hDragInfo);
3291 WIN_ReleaseWndPtr(wndPtr);
3293 return (DWORD)(msg.lParam);
3297 /******************************************************************************
3298 * GetWindowModuleFileNameA (USER32.@)
3300 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3302 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3303 hwnd, lpszFileName, cchFileNameMax);
3307 /******************************************************************************
3308 * GetWindowModuleFileNameW (USER32.@)
3310 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3312 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3313 hwnd, lpszFileName, cchFileNameMax);