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);
171 /***********************************************************************
174 * Remove a window from the siblings linked list.
176 BOOL WIN_UnlinkWindow( HWND hwnd )
178 WND *wndPtr, **ppWnd;
181 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
182 else if(!wndPtr->parent)
184 WIN_ReleaseWndPtr(wndPtr);
188 ppWnd = &wndPtr->parent->child;
189 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
192 *ppWnd = wndPtr->next;
195 WIN_ReleaseWndPtr(wndPtr);
200 /***********************************************************************
203 * Insert a window into the siblings linked list.
204 * The window is inserted after the specified window, which can also
205 * be specified as HWND_TOP or HWND_BOTTOM.
207 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
209 WND *wndPtr, **ppWnd;
211 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
212 else if(!wndPtr->parent)
214 WIN_ReleaseWndPtr(wndPtr);
217 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
219 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
220 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
221 while (*ppWnd) ppWnd = &(*ppWnd)->next;
223 else /* Normal case */
225 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
228 WIN_ReleaseWndPtr(wndPtr);
231 ppWnd = &afterPtr->next;
232 WIN_ReleaseWndPtr(afterPtr);
234 wndPtr->next = *ppWnd;
236 WIN_ReleaseWndPtr(wndPtr);
241 /***********************************************************************
242 * WIN_FindWinToRepaint
244 * Find a window that needs repaint.
246 HWND WIN_FindWinToRepaint( HWND hwnd )
251 /* Note: the desktop window never gets WM_PAINT messages
252 * The real reason why is because Windows DesktopWndProc
253 * does ValidateRgn inside WM_ERASEBKGND handler.
255 if (hwnd == GetDesktopWindow()) hwnd = 0;
257 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
259 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
261 if (!(pWnd->dwStyle & WS_VISIBLE))
263 TRACE("skipping window %04x\n",
266 else if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
267 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
270 else if (pWnd->child )
271 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
273 WIN_ReleaseWndPtr(pWnd);
284 hwndRet = pWnd->hwndSelf;
286 /* look among siblings if we got a transparent window */
287 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
288 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
290 WIN_UpdateWndPtr(&pWnd,pWnd->next);
294 hwndRet = pWnd->hwndSelf;
295 WIN_ReleaseWndPtr(pWnd);
297 TRACE("found %04x\n",hwndRet);
302 /***********************************************************************
305 * Destroy storage associated to a window. "Internals" p.358
306 * returns a locked wndPtr->next
308 static WND* WIN_DestroyWindow( WND* wndPtr )
310 HWND hwnd = wndPtr->hwndSelf;
313 TRACE("%04x\n", wndPtr->hwndSelf );
315 /* free child windows */
316 WIN_LockWndPtr(wndPtr->child);
317 while ((pWnd = wndPtr->child))
319 wndPtr->child = WIN_DestroyWindow( pWnd );
320 WIN_ReleaseWndPtr(pWnd);
324 * Clear the update region to make sure no WM_PAINT messages will be
325 * generated for this window while processing the WM_NCDESTROY.
327 RedrawWindow( wndPtr->hwndSelf, NULL, 0,
328 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
331 * Send the WM_NCDESTROY to the window being destroyed.
333 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
335 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
337 WINPOS_CheckInternalPos( hwnd );
338 if( hwnd == GetCapture()) ReleaseCapture();
340 /* free resources associated with the window */
342 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
343 PROPERTY_RemoveWindowProps( wndPtr );
345 /* toss stale messages from the queue */
347 QUEUE_CleanupWindow( hwnd );
348 wndPtr->hmemTaskQ = 0;
350 if (!(wndPtr->dwStyle & WS_CHILD))
353 DestroyMenu( wndPtr->wIDmenu );
356 if (wndPtr->hSysMenu)
358 DestroyMenu( wndPtr->hSysMenu );
359 wndPtr->hSysMenu = 0;
361 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
362 DCE_FreeWindowDCE( wndPtr->hwndSelf ); /* Always do this to catch orphaned DCs */
363 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
364 CLASS_RemoveWindow( wndPtr->class );
365 wndPtr->class = NULL;
366 wndPtr->dwMagic = 0; /* Mark it as invalid */
368 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
373 /***********************************************************************
374 * WIN_DestroyThreadWindows
376 * Destroy all children of 'wnd' owned by the current thread.
377 * Return TRUE if something was done.
379 void WIN_DestroyThreadWindows( HWND hwnd )
384 if (!(list = WIN_ListChildren( hwnd ))) return;
385 for (i = 0; list[i]; i++)
387 if (!IsWindow( list[i] )) continue;
388 if (GetWindowThreadProcessId( list[i], NULL ) == GetCurrentThreadId())
389 DestroyWindow( list[i] );
391 WIN_DestroyThreadWindows( list[i] );
393 HeapFree( GetProcessHeap(), 0, list );
396 /***********************************************************************
397 * WIN_CreateDesktopWindow
399 * Create the desktop window.
401 BOOL WIN_CreateDesktopWindow(void)
403 struct tagCLASS *class;
411 TRACE("Creating desktop window\n");
414 if (!WINPOS_CreateInternalPosAtom() ||
415 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
416 &wndExtra, &winproc, &clsStyle, &dce )))
419 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
420 if (!hwndDesktop) return FALSE;
421 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
423 pWndDesktop->next = NULL;
424 pWndDesktop->child = NULL;
425 pWndDesktop->parent = NULL;
426 pWndDesktop->owner = 0;
427 pWndDesktop->class = class;
428 pWndDesktop->dwMagic = WND_MAGIC;
429 pWndDesktop->hwndSelf = hwndDesktop;
430 pWndDesktop->hInstance = 0;
431 pWndDesktop->rectWindow.left = 0;
432 pWndDesktop->rectWindow.top = 0;
433 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
434 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
435 pWndDesktop->rectClient = pWndDesktop->rectWindow;
436 pWndDesktop->text = NULL;
437 pWndDesktop->hmemTaskQ = 0;
438 pWndDesktop->hrgnUpdate = 0;
439 pWndDesktop->hwndLastActive = hwndDesktop;
440 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
442 pWndDesktop->dwExStyle = 0;
443 pWndDesktop->clsStyle = clsStyle;
444 pWndDesktop->dce = NULL;
445 pWndDesktop->pVScroll = NULL;
446 pWndDesktop->pHScroll = NULL;
447 pWndDesktop->pProp = NULL;
448 pWndDesktop->wIDmenu = 0;
449 pWndDesktop->helpContext = 0;
450 pWndDesktop->flags = 0;
451 pWndDesktop->hSysMenu = 0;
452 pWndDesktop->userdata = 0;
453 pWndDesktop->winproc = winproc;
454 pWndDesktop->cbWndExtra = wndExtra;
455 pWndDesktop->irefCount = 0;
457 cs.lpCreateParams = NULL;
463 cs.cx = pWndDesktop->rectWindow.right;
464 cs.cy = pWndDesktop->rectWindow.bottom;
465 cs.style = pWndDesktop->dwStyle;
466 cs.dwExStyle = pWndDesktop->dwExStyle;
468 cs.lpszClass = DESKTOP_CLASS_ATOM;
470 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
472 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
477 /***********************************************************************
480 * Fix the coordinates - Helper for WIN_CreateWindowEx.
481 * returns default show mode in sw.
482 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
484 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
486 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
487 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
489 if (cs->style & (WS_CHILD | WS_POPUP))
491 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
492 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
494 else /* overlapped window */
498 GetStartupInfoA( &info );
500 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
502 /* Never believe Microsoft's documentation... CreateWindowEx doc says
503 * that if an overlapped window is created with WS_VISIBLE style bit
504 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
505 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
508 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
509 * 2) it does not ignore the y parameter as the docs claim; instead, it
510 * uses it as second parameter to ShowWindow() unless y is either
511 * CW_USEDEFAULT or CW_USEDEFAULT16.
513 * The fact that we didn't do 2) caused bogus windows pop up when wine
514 * was running apps that were using this obscure feature. Example -
515 * calc.exe that comes with Win98 (only Win98, it's different from
516 * the one that comes with Win95 and NT)
518 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
519 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
520 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
523 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
525 if (info.dwFlags & STARTF_USESIZE)
527 cs->cx = info.dwXSize;
528 cs->cy = info.dwYSize;
530 else /* if no other hint from the app, pick 3/4 of the screen real estate */
533 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
534 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
535 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
542 /***********************************************************************
545 * Implementation of CreateWindowEx().
547 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
548 WINDOWPROCTYPE type )
551 struct tagCLASS *classPtr;
553 HWND hwnd, hwndLinkAfter;
554 POINT maxSize, maxPos, minTrack, maxTrack;
559 BOOL unicode = (type == WIN_PROC_32W);
561 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
562 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
563 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
564 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
565 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
567 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
568 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
570 /* Find the parent window */
574 /* Make sure parent is valid */
575 if (!IsWindow( cs->hwndParent ))
577 WARN("Bad parent %04x\n", cs->hwndParent );
580 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
581 WARN("No parent for child window\n" );
582 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
585 /* Find the window class */
586 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
587 &wndExtra, &winproc, &clsStyle, &dce )))
589 WARN("Bad class '%s'\n", cs->lpszClass );
593 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
595 /* Correct the window style - stage 1
597 * These are patches that appear to affect both the style loaded into the
598 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
600 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
601 * why does the user get to set it?
604 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
605 * tested for WS_POPUP
607 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
608 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
609 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
610 cs->dwExStyle |= WS_EX_WINDOWEDGE;
612 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
614 /* Create the window structure */
616 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
618 TRACE("out of memory\n" );
622 /* Fill the window structure */
624 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
626 wndPtr->child = NULL;
628 if ((cs->style & WS_CHILD) && cs->hwndParent)
630 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
632 WIN_ReleaseWndPtr(wndPtr->parent);
636 wndPtr->parent = pWndDesktop;
637 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
640 wndPtr->owner = GetAncestor( cs->hwndParent, GA_ROOT );
644 wndPtr->class = classPtr;
645 wndPtr->winproc = winproc;
646 wndPtr->dwMagic = WND_MAGIC;
647 wndPtr->hwndSelf = hwnd;
648 wndPtr->hInstance = cs->hInstance;
650 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
651 wndPtr->hrgnUpdate = 0;
653 wndPtr->hwndLastActive = hwnd;
654 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
655 wndPtr->dwExStyle = cs->dwExStyle;
656 wndPtr->clsStyle = clsStyle;
658 wndPtr->helpContext = 0;
659 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
660 wndPtr->pVScroll = NULL;
661 wndPtr->pHScroll = NULL;
662 wndPtr->pProp = NULL;
663 wndPtr->userdata = 0;
664 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
665 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
666 wndPtr->cbWndExtra = wndExtra;
667 wndPtr->irefCount = 1;
669 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
671 /* Call the WH_CBT hook */
673 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
674 ? HWND_BOTTOM : HWND_TOP;
676 if (HOOK_IsHooked( WH_CBT ))
682 cbtc.hwndInsertAfter = hwndLinkAfter;
683 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
684 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
687 TRACE("CBT-hook returned 0\n");
688 USER_HEAP_FREE( hwnd );
689 CLASS_RemoveWindow( classPtr );
695 /* Correct the window style - stage 2 */
697 if (!(cs->style & WS_CHILD))
699 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
700 if (!(cs->style & WS_POPUP))
702 wndPtr->dwStyle |= WS_CAPTION;
703 wndPtr->flags |= WIN_NEED_SIZE;
707 /* Get class or window DC if needed */
709 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
710 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
711 else wndPtr->dce = NULL;
713 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
715 wndPtr->rectWindow.left = cs->x;
716 wndPtr->rectWindow.top = cs->y;
717 wndPtr->rectWindow.right = cs->x + cs->cx;
718 wndPtr->rectWindow.bottom = cs->y + cs->cy;
719 wndPtr->rectClient = wndPtr->rectWindow;
721 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
723 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
725 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
726 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
727 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
728 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
729 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
732 if (cs->cx < 0) cs->cx = 0;
733 if (cs->cy < 0) cs->cy = 0;
735 wndPtr->rectWindow.left = cs->x;
736 wndPtr->rectWindow.top = cs->y;
737 wndPtr->rectWindow.right = cs->x + cs->cx;
738 wndPtr->rectWindow.bottom = cs->y + cs->cy;
739 wndPtr->rectClient = wndPtr->rectWindow;
741 /* Set the window menu */
743 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
745 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
748 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
751 if (HIWORD(cs->hInstance))
752 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
754 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
756 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
760 else wndPtr->wIDmenu = (UINT)cs->hMenu;
762 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
764 WARN("aborted by WM_xxCREATE!\n");
765 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
766 CLASS_RemoveWindow( classPtr );
767 WIN_ReleaseWndPtr(wndPtr);
771 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
773 /* Notify the parent window only */
775 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
776 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
777 if( !IsWindow(hwnd) )
784 if (cs->style & WS_VISIBLE)
786 /* in case WS_VISIBLE got set in the meantime */
787 wndPtr->dwStyle &= ~WS_VISIBLE;
788 ShowWindow( hwnd, sw );
791 /* Call WH_SHELL hook */
793 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
794 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
796 TRACE("created window %04x\n", hwnd);
798 WIN_ReleaseWndPtr(wndPtr);
803 /***********************************************************************
804 * CreateWindow (USER.41)
806 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
807 DWORD style, INT16 x, INT16 y, INT16 width,
808 INT16 height, HWND16 parent, HMENU16 menu,
809 HINSTANCE16 instance, LPVOID data )
811 return CreateWindowEx16( 0, className, windowName, style,
812 x, y, width, height, parent, menu, instance, data );
816 /***********************************************************************
817 * CreateWindowEx (USER.452)
819 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
820 LPCSTR windowName, DWORD style, INT16 x,
821 INT16 y, INT16 width, INT16 height,
822 HWND16 parent, HMENU16 menu,
823 HINSTANCE16 instance, LPVOID data )
829 /* Find the class atom */
831 if (HIWORD(className))
833 if (!(classAtom = GlobalFindAtomA( className )))
835 ERR( "bad class name %s\n", debugres_a(className) );
841 classAtom = LOWORD(className);
842 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
844 ERR( "bad atom %x\n", classAtom);
850 /* Fix the coordinates */
852 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
853 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
854 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
855 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
857 /* Create the window */
859 cs.lpCreateParams = data;
860 cs.hInstance = (HINSTANCE)instance;
861 cs.hMenu = (HMENU)menu;
862 cs.hwndParent = (HWND)parent;
864 cs.lpszName = windowName;
865 cs.lpszClass = className;
866 cs.dwExStyle = exStyle;
868 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
872 /***********************************************************************
873 * CreateWindowExA (USER32.@)
875 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
876 LPCSTR windowName, DWORD style, INT x,
877 INT y, INT width, INT height,
878 HWND parent, HMENU menu,
879 HINSTANCE instance, LPVOID data )
886 instance=GetModuleHandleA(NULL);
888 if(exStyle & WS_EX_MDICHILD)
889 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
891 /* Find the class atom */
893 if (HIWORD(className))
895 if (!(classAtom = GlobalFindAtomA( className )))
897 ERR( "bad class name %s\n", debugres_a(className) );
903 classAtom = LOWORD(className);
904 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
906 ERR( "bad atom %x\n", classAtom);
912 /* Create the window */
914 cs.lpCreateParams = data;
915 cs.hInstance = instance;
917 cs.hwndParent = parent;
923 cs.lpszName = windowName;
924 cs.lpszClass = className;
925 cs.dwExStyle = exStyle;
927 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
931 /***********************************************************************
932 * CreateWindowExW (USER32.@)
934 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
935 LPCWSTR windowName, DWORD style, INT x,
936 INT y, INT width, INT height,
937 HWND parent, HMENU menu,
938 HINSTANCE instance, LPVOID data )
945 instance=GetModuleHandleA(NULL);
947 if(exStyle & WS_EX_MDICHILD)
948 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
950 /* Find the class atom */
952 if (HIWORD(className))
954 if (!(classAtom = GlobalFindAtomW( className )))
956 ERR( "bad class name %s\n", debugres_w(className) );
962 classAtom = LOWORD(className);
963 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
965 ERR( "bad atom %x\n", classAtom);
971 /* Create the window */
973 cs.lpCreateParams = data;
974 cs.hInstance = instance;
976 cs.hwndParent = parent;
982 cs.lpszName = windowName;
983 cs.lpszClass = className;
984 cs.dwExStyle = exStyle;
986 /* Note: we rely on the fact that CREATESTRUCTA and */
987 /* CREATESTRUCTW have the same layout. */
988 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
992 /***********************************************************************
995 static void WIN_SendDestroyMsg( HWND hwnd )
997 if( CARET_GetHwnd() == hwnd) DestroyCaret();
998 if (USER_Driver.pResetSelectionOwner)
999 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1002 * Send the WM_DESTROY to the window.
1004 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1007 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1008 * make sure that the window still exists when we come back.
1015 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1017 /* start from the end (FIXME: is this needed?) */
1018 for (i = 0; pWndArray[i]; i++) ;
1022 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1024 HeapFree( GetProcessHeap(), 0, pWndArray );
1027 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1031 /***********************************************************************
1032 * DestroyWindow (USER.53)
1034 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1036 return DestroyWindow(hwnd);
1040 /***********************************************************************
1041 * DestroyWindow (USER32.@)
1043 BOOL WINAPI DestroyWindow( HWND hwnd )
1049 TRACE("(%04x)\n", hwnd);
1051 /* Initialization */
1053 if (hwnd == GetDesktopWindow()) return FALSE; /* Can't destroy desktop */
1055 /* Look whether the focus is within the tree of windows we will
1059 if (h == hwnd || IsChild( hwnd, h ))
1061 HWND parent = GetAncestor( hwnd, GA_PARENT );
1062 if (parent == GetDesktopWindow()) parent = 0;
1068 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) ) return FALSE;
1070 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1071 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1073 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1074 /* FIXME: clean up palette - see "Internals" p.352 */
1077 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1078 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1080 /* Notify the parent window only */
1081 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1082 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1083 if( !IsWindow(hwnd) )
1090 if (USER_Driver.pResetSelectionOwner)
1091 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1093 /* Hide the window */
1095 if (wndPtr->dwStyle & WS_VISIBLE)
1097 ShowWindow( hwnd, SW_HIDE );
1098 if (!IsWindow(hwnd))
1105 /* Recursively destroy owned windows */
1107 if( !(wndPtr->dwStyle & WS_CHILD) )
1112 HWND *list = WIN_ListChildren( wndPtr->parent->hwndSelf );
1115 for (i = 0; list[i]; i++)
1117 WND *siblingPtr = WIN_FindWndPtr( list[i] );
1118 if (!siblingPtr) continue;
1119 if (siblingPtr->owner == hwnd)
1121 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1123 WIN_ReleaseWndPtr( siblingPtr );
1124 DestroyWindow( list[i] );
1128 else siblingPtr->owner = 0;
1130 WIN_ReleaseWndPtr( siblingPtr );
1132 HeapFree( GetProcessHeap(), 0, list );
1134 if (!got_one) break;
1137 WINPOS_ActivateOtherWindow(wndPtr->hwndSelf);
1141 WND *owner = WIN_FindWndPtr( wndPtr->owner );
1142 if (owner->hwndLastActive == hwnd) owner->hwndLastActive = wndPtr->owner;
1143 WIN_ReleaseWndPtr( owner );
1147 /* Send destroy messages */
1149 WIN_SendDestroyMsg( hwnd );
1150 if (!IsWindow(hwnd))
1156 /* Unlink now so we won't bother with the children later on */
1158 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1160 /* Destroy the window storage */
1162 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1165 WIN_ReleaseWndPtr(wndPtr);
1170 /***********************************************************************
1171 * CloseWindow (USER.43)
1173 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1175 return CloseWindow( hwnd );
1179 /***********************************************************************
1180 * CloseWindow (USER32.@)
1182 BOOL WINAPI CloseWindow( HWND hwnd )
1184 WND * wndPtr = WIN_FindWndPtr( hwnd );
1187 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1192 ShowWindow( hwnd, SW_MINIMIZE );
1195 WIN_ReleaseWndPtr(wndPtr);
1201 /***********************************************************************
1202 * OpenIcon (USER.44)
1204 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1206 return OpenIcon( hwnd );
1210 /***********************************************************************
1211 * OpenIcon (USER32.@)
1213 BOOL WINAPI OpenIcon( HWND hwnd )
1215 if (!IsIconic( hwnd )) return FALSE;
1216 ShowWindow( hwnd, SW_SHOWNORMAL );
1221 /***********************************************************************
1224 * Implementation of FindWindow() and FindWindowEx().
1226 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1231 WCHAR *buffer = NULL;
1233 if (!parent) parent = GetDesktopWindow();
1236 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1237 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1240 if (!(list = WIN_ListChildren( parent )))
1242 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1248 while (list[i] && list[i] != child) i++;
1249 if (!list[i]) return 0;
1250 i++; /* start from next window */
1253 for ( ; list[i]; i++)
1255 if (className && (GetClassWord(list[i], GCW_ATOM) != className))
1256 continue; /* Not the right class */
1258 /* Now check the title */
1260 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1263 HeapFree( GetProcessHeap(), 0, list );
1264 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1266 /* In this case we need to check whether other processes
1267 own a window with the given paramters on the Desktop,
1268 but we don't, so let's at least warn about it */
1269 if (!retvalue) FIXME("Returning 0 without checking other processes\n");
1275 /***********************************************************************
1276 * FindWindow (USER.50)
1278 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1280 return FindWindowA( className, title );
1284 /***********************************************************************
1285 * FindWindowEx (USER.427)
1287 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1289 return FindWindowExA( parent, child, className, title );
1293 /***********************************************************************
1294 * FindWindowA (USER32.@)
1296 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1298 HWND ret = FindWindowExA( 0, 0, className, title );
1299 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1304 /***********************************************************************
1305 * FindWindowExA (USER32.@)
1307 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1308 LPCSTR className, LPCSTR title )
1316 /* If the atom doesn't exist, then no class */
1317 /* with this name exists either. */
1318 if (!(atom = GlobalFindAtomA( className )))
1320 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1325 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1326 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1327 HeapFree( GetProcessHeap(), 0, buffer );
1332 /***********************************************************************
1333 * FindWindowExW (USER32.@)
1335 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1336 LPCWSTR className, LPCWSTR title )
1342 /* If the atom doesn't exist, then no class */
1343 /* with this name exists either. */
1344 if (!(atom = GlobalFindAtomW( className )))
1346 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1350 return WIN_FindWindow( parent, child, atom, title );
1354 /***********************************************************************
1355 * FindWindowW (USER32.@)
1357 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1359 return FindWindowExW( 0, 0, className, title );
1363 /**********************************************************************
1364 * GetDesktopWindow (USER.286)
1366 HWND16 WINAPI GetDesktopWindow16(void)
1368 return (HWND16)pWndDesktop->hwndSelf;
1372 /**********************************************************************
1373 * GetDesktopWindow (USER32.@)
1375 HWND WINAPI GetDesktopWindow(void)
1377 if (pWndDesktop) return pWndDesktop->hwndSelf;
1378 ERR( "You need the -desktop option when running with native USER\n" );
1384 /**********************************************************************
1385 * GetDesktopHwnd (USER.278)
1387 * Exactly the same thing as GetDesktopWindow(), but not documented.
1388 * Don't ask me why...
1390 HWND16 WINAPI GetDesktopHwnd16(void)
1392 return (HWND16)pWndDesktop->hwndSelf;
1396 /*******************************************************************
1397 * EnableWindow (USER.34)
1399 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1401 return EnableWindow( hwnd, enable );
1405 /*******************************************************************
1406 * EnableWindow (USER32.@)
1408 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1413 TRACE("( %x, %d )\n", hwnd, enable);
1415 if (USER_Driver.pEnableWindow)
1416 return USER_Driver.pEnableWindow( hwnd, enable );
1418 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1420 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1422 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1424 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1425 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1427 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1429 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1431 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1433 if (hwnd == GetFocus())
1434 SetFocus( 0 ); /* A disabled window can't have the focus */
1436 if (hwnd == GetCapture())
1437 ReleaseCapture(); /* A disabled window can't capture the mouse */
1439 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1441 WIN_ReleaseWndPtr(wndPtr);
1446 /***********************************************************************
1447 * IsWindowEnabled (USER.35)
1449 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1451 return IsWindowEnabled(hWnd);
1455 /***********************************************************************
1456 * IsWindowEnabled (USER32.@)
1458 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1463 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1464 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1465 WIN_ReleaseWndPtr(wndPtr);
1471 /***********************************************************************
1472 * IsWindowUnicode (USER32.@)
1474 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1479 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1480 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1481 WIN_ReleaseWndPtr(wndPtr);
1486 /**********************************************************************
1487 * GetWindowWord (USER.133)
1489 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1491 return GetWindowWord( hwnd, offset );
1495 /**********************************************************************
1496 * GetWindowWord (USER32.@)
1498 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1501 WND * wndPtr = WIN_FindWndPtr( hwnd );
1502 if (!wndPtr) return 0;
1505 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1507 WARN("Invalid offset %d\n", offset );
1511 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1517 if (HIWORD(wndPtr->wIDmenu))
1518 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1520 retvalue = (WORD)wndPtr->wIDmenu;
1522 case GWW_HWNDPARENT:
1523 retvalue = GetParent(hwnd);
1526 if (HIWORD(wndPtr->hInstance))
1527 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1529 retvalue = (WORD)wndPtr->hInstance;
1532 WARN("Invalid offset %d\n", offset );
1537 WIN_ReleaseWndPtr(wndPtr);
1541 /**********************************************************************
1542 * SetWindowWord (USER.134)
1544 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1546 return SetWindowWord( hwnd, offset, newval );
1550 /**********************************************************************
1551 * SetWindowWord (USER32.@)
1553 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1556 WND * wndPtr = WIN_FindWndPtr( hwnd );
1557 if (!wndPtr) return 0;
1560 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1562 WARN("Invalid offset %d\n", offset );
1566 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1570 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1571 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1572 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1575 WARN("Invalid offset %d\n", offset );
1582 WIN_ReleaseWndPtr(wndPtr);
1587 /**********************************************************************
1590 * Helper function for GetWindowLong().
1592 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1595 WND * wndPtr = WIN_FindWndPtr( hwnd );
1596 if (!wndPtr) return 0;
1599 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1601 WARN("Invalid offset %d\n", offset );
1605 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1606 /* Special case for dialog window procedure */
1607 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1609 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1616 case GWL_USERDATA: retvalue = wndPtr->userdata;
1618 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1620 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1622 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1624 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1627 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1629 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1632 WARN("Unknown offset %d\n", offset );
1636 WIN_ReleaseWndPtr(wndPtr);
1641 /**********************************************************************
1644 * Helper function for SetWindowLong().
1646 * 0 is the failure code. However, in the case of failure SetLastError
1647 * must be set to distinguish between a 0 return value and a failure.
1649 * FIXME: The error values for SetLastError may not be right. Can
1650 * someone check with the real thing?
1652 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1653 WINDOWPROCTYPE type )
1656 WND * wndPtr = WIN_FindWndPtr( hwnd );
1659 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1663 /* Is this the right error? */
1664 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1670 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1672 WARN("Invalid offset %d\n", offset );
1674 /* Is this the right error? */
1675 SetLastError( ERROR_OUTOFMEMORY );
1680 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1681 /* Special case for dialog window procedure */
1682 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1684 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1685 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1686 type, WIN_PROC_WINDOW );
1693 ptr = (DWORD*)&wndPtr->wIDmenu;
1696 retval = SetWindowWord( hwnd, offset, newval );
1699 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1700 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1701 type, WIN_PROC_WINDOW );
1704 style.styleOld = wndPtr->dwStyle;
1705 style.styleNew = newval;
1706 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1707 wndPtr->dwStyle = style.styleNew;
1708 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1709 retval = style.styleOld;
1713 ptr = &wndPtr->userdata;
1716 style.styleOld = wndPtr->dwExStyle;
1717 style.styleNew = newval;
1718 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1719 wndPtr->dwExStyle = newval;
1720 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1721 retval = style.styleOld;
1725 WARN("Invalid offset %d\n", offset );
1727 /* Don't think this is right error but it should do */
1728 SetLastError( ERROR_OUTOFMEMORY );
1736 WIN_ReleaseWndPtr(wndPtr);
1741 /**********************************************************************
1742 * GetWindowLong (USER.135)
1744 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1746 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1750 /**********************************************************************
1751 * GetWindowLongA (USER32.@)
1753 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1755 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1759 /**********************************************************************
1760 * GetWindowLongW (USER32.@)
1762 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1764 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1768 /**********************************************************************
1769 * SetWindowLong (USER.136)
1771 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1773 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1777 /**********************************************************************
1778 * SetWindowLongA (USER32.@)
1780 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1782 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1786 /**********************************************************************
1787 * SetWindowLongW (USER32.@) Set window attribute
1789 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1790 * value in a window's extra memory.
1792 * The _hwnd_ parameter specifies the window. is the handle to a
1793 * window that has extra memory. The _newval_ parameter contains the
1794 * new attribute or extra memory value. If positive, the _offset_
1795 * parameter is the byte-addressed location in the window's extra
1796 * memory to set. If negative, _offset_ specifies the window
1797 * attribute to set, and should be one of the following values:
1799 * GWL_EXSTYLE The window's extended window style
1801 * GWL_STYLE The window's window style.
1803 * GWL_WNDPROC Pointer to the window's window procedure.
1805 * GWL_HINSTANCE The window's pplication instance handle.
1807 * GWL_ID The window's identifier.
1809 * GWL_USERDATA The window's user-specified data.
1811 * If the window is a dialog box, the _offset_ parameter can be one of
1812 * the following values:
1814 * DWL_DLGPROC The address of the window's dialog box procedure.
1816 * DWL_MSGRESULT The return value of a message
1817 * that the dialog box procedure processed.
1819 * DWL_USER Application specific information.
1823 * If successful, returns the previous value located at _offset_. Otherwise,
1828 * Extra memory for a window class is specified by a nonzero cbWndExtra
1829 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1830 * time of class creation.
1832 * Using GWL_WNDPROC to set a new window procedure effectively creates
1833 * a window subclass. Use CallWindowProc() in the new windows procedure
1834 * to pass messages to the superclass's window procedure.
1836 * The user data is reserved for use by the application which created
1839 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1840 * instead, call the EnableWindow() function to change the window's
1843 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1844 * SetParent() instead.
1847 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1848 * it sends WM_STYLECHANGING before changing the settings
1849 * and WM_STYLECHANGED afterwards.
1850 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1854 * GWL_STYLE does not dispatch WM_STYLE... messages.
1861 LONG WINAPI SetWindowLongW(
1862 HWND hwnd, /* [in] window to alter */
1863 INT offset, /* [in] offset, in bytes, of location to alter */
1864 LONG newval /* [in] new value of location */
1866 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1870 /*******************************************************************
1871 * GetWindowText (USER.36)
1873 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1875 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1879 /*******************************************************************
1880 * GetWindowTextA (USER32.@)
1882 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
1884 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
1888 /*******************************************************************
1889 * InternalGetWindowText (USER32.@)
1891 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
1893 WND *win = WIN_FindWndPtr( hwnd );
1895 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
1896 else lpString[0] = 0;
1897 WIN_ReleaseWndPtr( win );
1898 return strlenW(lpString);
1902 /*******************************************************************
1903 * GetWindowTextW (USER32.@)
1905 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
1907 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
1912 /*******************************************************************
1913 * SetWindowText (USER.37)
1915 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1917 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1921 /*******************************************************************
1922 * SetWindowText (USER32.@)
1923 * SetWindowTextA (USER32.@)
1925 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
1927 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1931 /*******************************************************************
1932 * SetWindowTextW (USER32.@)
1934 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
1936 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1940 /*******************************************************************
1941 * GetWindowTextLength (USER.38)
1943 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1945 return (INT16)GetWindowTextLengthA( hwnd );
1949 /*******************************************************************
1950 * GetWindowTextLengthA (USER32.@)
1952 INT WINAPI GetWindowTextLengthA( HWND hwnd )
1954 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1957 /*******************************************************************
1958 * GetWindowTextLengthW (USER32.@)
1960 INT WINAPI GetWindowTextLengthW( HWND hwnd )
1962 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1966 /*******************************************************************
1967 * IsWindow (USER.47)
1969 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1971 CURRENT_STACK16->es = USER_HeapSel;
1972 return IsWindow( hwnd );
1976 /*******************************************************************
1977 * IsWindow (USER32.@)
1979 BOOL WINAPI IsWindow( HWND hwnd )
1984 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1985 retvalue = (wndPtr->dwMagic == WND_MAGIC);
1986 WIN_ReleaseWndPtr(wndPtr);
1992 /*****************************************************************
1993 * GetParent (USER.46)
1995 HWND16 WINAPI GetParent16( HWND16 hwnd )
1997 return (HWND16)GetParent( hwnd );
2001 /*****************************************************************
2002 * GetParent (USER32.@)
2004 HWND WINAPI GetParent( HWND hwnd )
2009 if ((wndPtr = WIN_FindWndPtr(hwnd)))
2011 if (wndPtr->dwStyle & WS_CHILD)
2012 retvalue = wndPtr->parent->hwndSelf;
2013 else if (wndPtr->dwStyle & WS_POPUP)
2014 retvalue = wndPtr->owner;
2015 WIN_ReleaseWndPtr(wndPtr);
2021 /*****************************************************************
2022 * GetAncestor (USER32.@)
2024 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2027 WND *wndPtr, *parent;
2029 if (hwnd == GetDesktopWindow()) return 0;
2030 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2031 parent = wndPtr->parent;
2036 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2039 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2040 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2043 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2044 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2045 while (wndPtr->owner)
2047 WND *ptr = WIN_FindWndPtr( wndPtr->owner );
2048 WIN_ReleaseWndPtr( wndPtr );
2053 ret = wndPtr->hwndSelf;
2054 WIN_ReleaseWndPtr( wndPtr );
2059 /*****************************************************************
2060 * SetParent (USER.233)
2062 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2064 return SetParent( hwndChild, hwndNewParent );
2068 /*****************************************************************
2069 * SetParent (USER32.@)
2071 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2078 if (hwnd == GetDesktopWindow()) /* sanity check */
2080 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2084 if (USER_Driver.pSetParent)
2085 return USER_Driver.pSetParent( hwnd, parent );
2087 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2089 dwStyle = wndPtr->dwStyle;
2091 if (!parent) parent = GetDesktopWindow();
2093 if (!(pWndParent = WIN_FindWndPtr(parent)))
2095 WIN_ReleaseWndPtr( wndPtr );
2099 /* Windows hides the window first, then shows it again
2100 * including the WM_SHOWWINDOW messages and all */
2101 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2103 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2104 if (pWndParent != wndPtr->parent)
2106 WIN_UnlinkWindow(wndPtr->hwndSelf);
2107 wndPtr->parent = pWndParent;
2109 if (parent != GetDesktopWindow()) /* a child window */
2111 if( !( wndPtr->dwStyle & WS_CHILD ) )
2113 if( wndPtr->wIDmenu != 0)
2115 DestroyMenu( (HMENU) wndPtr->wIDmenu );
2116 wndPtr->wIDmenu = 0;
2120 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
2122 WIN_ReleaseWndPtr( pWndParent );
2123 WIN_ReleaseWndPtr( wndPtr );
2125 /* SetParent additionally needs to make hwnd the topmost window
2126 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2127 WM_WINDOWPOSCHANGED notification messages.
2129 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2130 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2131 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2132 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2133 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2138 /*******************************************************************
2141 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2143 return IsChild(parent,child);
2147 /*******************************************************************
2148 * IsChild (USER32.@)
2150 BOOL WINAPI IsChild( HWND parent, HWND child )
2152 HWND *list = WIN_ListParents( child );
2156 if (!list) return FALSE;
2157 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2158 ret = (list[i] != 0);
2159 HeapFree( GetProcessHeap(), 0, list );
2164 /***********************************************************************
2165 * IsWindowVisible (USER.49)
2167 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2169 return IsWindowVisible(hwnd);
2173 /***********************************************************************
2174 * IsWindowVisible (USER32.@)
2176 BOOL WINAPI IsWindowVisible( HWND hwnd )
2182 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2183 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2184 for (i = 0; list[i]; i++)
2185 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2187 HeapFree( GetProcessHeap(), 0, list );
2192 /***********************************************************************
2193 * WIN_IsWindowDrawable
2195 * hwnd is drawable when it is visible, all parents are not
2196 * minimized, and it is itself not minimized unless we are
2197 * trying to draw its default class icon.
2199 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2205 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2206 if ((wnd->dwStyle & WS_MINIMIZE) &&
2207 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2209 if (!(list = WIN_ListParents( wnd->hwndSelf ))) return TRUE;
2210 for (i = 0; list[i]; i++)
2211 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2214 HeapFree( GetProcessHeap(), 0, list );
2219 /*******************************************************************
2220 * GetTopWindow (USER.229)
2222 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2224 return GetTopWindow(hwnd);
2228 /*******************************************************************
2229 * GetTopWindow (USER32.@)
2231 HWND WINAPI GetTopWindow( HWND hwnd )
2233 if (!hwnd) hwnd = GetDesktopWindow();
2234 return GetWindow( hwnd, GW_CHILD );
2238 /*******************************************************************
2239 * GetWindow (USER.262)
2241 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2243 return GetWindow( hwnd,rel );
2247 /*******************************************************************
2248 * GetWindow (USER32.@)
2250 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2254 WND * wndPtr = WIN_FindWndPtr( hwnd );
2255 if (!wndPtr) return 0;
2259 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2263 if (!wndPtr->parent)
2265 retval = 0; /* Desktop window */
2268 while (wndPtr->next)
2270 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2272 retval = wndPtr->hwndSelf;
2276 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2280 if (!wndPtr->parent)
2282 retval = 0; /* Desktop window */
2285 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2286 if (wndPtr->hwndSelf == hwnd)
2288 retval = 0; /* First in list */
2291 while (wndPtr->next)
2293 if (wndPtr->next->hwndSelf == hwnd)
2295 retval = wndPtr->hwndSelf;
2298 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2304 retval = wndPtr->owner;
2308 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2313 WIN_ReleaseWndPtr(wndPtr);
2318 /*******************************************************************
2319 * GetNextWindow (USER.230)
2321 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2323 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2324 return GetWindow16( hwnd, flag );
2327 /***********************************************************************
2328 * WIN_InternalShowOwnedPopups
2330 * Internal version of ShowOwnedPopups; Wine functions should use this
2331 * to avoid interfering with application calls to ShowOwnedPopups
2332 * and to make sure the application can't prevent showing/hiding.
2334 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2338 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2342 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2344 if (!win_array) return TRUE;
2347 * Show windows Lowest first, Highest last to preserve Z-Order
2349 while (win_array[count]) count++;
2350 while (--count >= 0)
2352 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2353 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2355 if (pWnd->dwStyle & WS_POPUP)
2359 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2360 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2363 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2365 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2366 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2371 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2372 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2373 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2376 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2378 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2379 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2380 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2384 WIN_ReleaseWndPtr( pWnd );
2386 HeapFree( GetProcessHeap(), 0, win_array );
2391 /*******************************************************************
2392 * ShowOwnedPopups (USER.265)
2394 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2396 ShowOwnedPopups( owner, fShow );
2400 /*******************************************************************
2401 * ShowOwnedPopups (USER32.@)
2403 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2407 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2409 if (!win_array) return TRUE;
2411 while (win_array[count]) count++;
2412 while (--count >= 0)
2414 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2415 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2417 if (pWnd->dwStyle & WS_POPUP)
2421 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2423 /* In Windows, ShowOwnedPopups(TRUE) generates
2424 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2425 * regardless of the state of the owner
2427 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2428 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2433 if (IsWindowVisible(pWnd->hwndSelf))
2435 /* In Windows, ShowOwnedPopups(FALSE) generates
2436 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2437 * regardless of the state of the owner
2439 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2440 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2444 WIN_ReleaseWndPtr( pWnd );
2446 HeapFree( GetProcessHeap(), 0, win_array );
2451 /*******************************************************************
2452 * GetLastActivePopup (USER.287)
2454 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2456 return GetLastActivePopup( hwnd );
2459 /*******************************************************************
2460 * GetLastActivePopup (USER32.@)
2462 HWND WINAPI GetLastActivePopup( HWND hwnd )
2465 WND *wndPtr =WIN_FindWndPtr(hwnd);
2466 if (!wndPtr) return hwnd;
2467 retval = wndPtr->hwndLastActive;
2468 WIN_ReleaseWndPtr(wndPtr);
2469 if ((retval != hwnd) && (!IsWindow(retval)))
2475 /*******************************************************************
2478 * Build an array of all parents of a given window, starting with
2479 * the immediate parent. The array must be freed with HeapFree.
2480 * Returns NULL if window is a top-level window.
2482 HWND *WIN_ListParents( HWND hwnd )
2484 WND *parent, *wndPtr = WIN_FindWndPtr( hwnd );
2488 /* First count the windows */
2490 if (!wndPtr) return NULL;
2492 parent = wndPtr->parent;
2493 while (parent && parent->hwndSelf != GetDesktopWindow())
2496 parent = parent->parent;
2501 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1) )))
2503 parent = wndPtr->parent;
2504 for (i = 0; i < count; i++)
2506 list[i] = parent->hwndSelf;
2507 parent = parent->parent;
2513 WIN_ReleaseWndPtr( wndPtr );
2518 /*******************************************************************
2521 * Build an array of the children of a given window. The array must be
2522 * freed with HeapFree. Returns NULL when no windows are found.
2524 HWND *WIN_ListChildren( HWND hwnd )
2526 WND *pWnd, *wndPtr = WIN_FindWndPtr( hwnd );
2530 /* First count the windows */
2532 if (!wndPtr) return NULL;
2534 pWnd = WIN_LockWndPtr(wndPtr->child);
2538 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2543 /* Now build the list of all windows */
2545 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1))))
2547 for (pWnd = WIN_LockWndPtr(wndPtr->child), phwnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2549 *phwnd++ = pWnd->hwndSelf;
2552 WIN_ReleaseWndPtr(pWnd);
2558 WIN_ReleaseWndPtr( wndPtr );
2563 /*******************************************************************
2564 * EnumWindows (USER32.@)
2566 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2572 /* We have to build a list of all windows first, to avoid */
2573 /* unpleasant side-effects, for instance if the callback */
2574 /* function changes the Z-order of the windows. */
2576 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2578 /* Now call the callback function for every window */
2580 iWndsLocks = WIN_SuspendWndsLock();
2581 for (i = 0; list[i]; i++)
2583 /* Make sure that the window still exists */
2584 if (!IsWindow( list[i] )) continue;
2585 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2587 WIN_RestoreWndsLock(iWndsLocks);
2588 HeapFree( GetProcessHeap(), 0, list );
2593 /**********************************************************************
2594 * EnumTaskWindows16 (USER.225)
2596 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2599 TDB *tdb = TASK_GetPtr( hTask );
2600 if (!tdb) return FALSE;
2601 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2605 /**********************************************************************
2606 * EnumThreadWindows (USER32.@)
2608 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2613 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2615 /* Now call the callback function for every window */
2617 iWndsLocks = WIN_SuspendWndsLock();
2618 for (i = 0; list[i]; i++)
2620 if (GetWindowThreadProcessId( list[i], NULL ) != id) continue;
2621 if (!func( list[i], lParam )) break;
2623 WIN_RestoreWndsLock(iWndsLocks);
2624 HeapFree( GetProcessHeap(), 0, list );
2629 /**********************************************************************
2630 * WIN_EnumChildWindows
2632 * Helper function for EnumChildWindows().
2634 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2639 for ( ; *list; list++)
2641 /* Make sure that the window still exists */
2642 if (!IsWindow( *list )) continue;
2643 /* skip owned windows */
2644 if (GetWindow( *list, GW_OWNER )) continue;
2645 /* Build children list first */
2646 childList = WIN_ListChildren( *list );
2648 ret = func( *list, lParam );
2652 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2653 HeapFree( GetProcessHeap(), 0, childList );
2655 if (!ret) return FALSE;
2661 /**********************************************************************
2662 * EnumChildWindows (USER32.@)
2664 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2669 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2670 iWndsLocks = WIN_SuspendWndsLock();
2671 WIN_EnumChildWindows( list, func, lParam );
2672 WIN_RestoreWndsLock(iWndsLocks);
2673 HeapFree( GetProcessHeap(), 0, list );
2678 /*******************************************************************
2679 * AnyPopup (USER.52)
2681 BOOL16 WINAPI AnyPopup16(void)
2687 /*******************************************************************
2688 * AnyPopup (USER32.@)
2690 BOOL WINAPI AnyPopup(void)
2694 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2696 if (!list) return FALSE;
2697 for (i = 0; list[i]; i++)
2699 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2701 retvalue = (list[i] != 0);
2702 HeapFree( GetProcessHeap(), 0, list );
2707 /*******************************************************************
2708 * FlashWindow (USER.105)
2710 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2712 return FlashWindow( hWnd, bInvert );
2716 /*******************************************************************
2717 * FlashWindow (USER32.@)
2719 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2721 WND *wndPtr = WIN_FindWndPtr(hWnd);
2723 TRACE("%04x\n", hWnd);
2725 if (!wndPtr) return FALSE;
2727 if (wndPtr->dwStyle & WS_MINIMIZE)
2729 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2731 HDC hDC = GetDC(hWnd);
2733 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2734 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2736 ReleaseDC( hWnd, hDC );
2737 wndPtr->flags |= WIN_NCACTIVATED;
2741 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2742 wndPtr->flags &= ~WIN_NCACTIVATED;
2744 WIN_ReleaseWndPtr(wndPtr);
2750 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2751 else wparam = (hWnd == GetActiveWindow());
2753 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2754 WIN_ReleaseWndPtr(wndPtr);
2760 /*******************************************************************
2761 * SetSysModalWindow (USER.188)
2763 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2765 HWND hWndOldModal = hwndSysModal;
2766 hwndSysModal = hWnd;
2767 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2768 return hWndOldModal;
2772 /*******************************************************************
2773 * GetSysModalWindow (USER.189)
2775 HWND16 WINAPI GetSysModalWindow16(void)
2777 return hwndSysModal;
2781 /*******************************************************************
2782 * GetWindowContextHelpId (USER32.@)
2784 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2787 WND *wnd = WIN_FindWndPtr( hwnd );
2789 retval = wnd->helpContext;
2790 WIN_ReleaseWndPtr(wnd);
2795 /*******************************************************************
2796 * SetWindowContextHelpId (USER32.@)
2798 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2800 WND *wnd = WIN_FindWndPtr( hwnd );
2801 if (!wnd) return FALSE;
2802 wnd->helpContext = id;
2803 WIN_ReleaseWndPtr(wnd);
2808 /*******************************************************************
2811 * recursively find a child that contains spDragInfo->pt point
2812 * and send WM_QUERYDROPOBJECT
2814 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2816 BOOL16 wParam, bResult = 0;
2818 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
2821 if (!ptrDragInfo) return FALSE;
2823 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2825 GetWindowRect(hQueryWnd,&tempRect);
2827 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
2829 if (!IsIconic( hQueryWnd ))
2831 WND *ptrWnd, *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd);
2833 tempRect = ptrQueryWnd->rectClient;
2834 if(ptrQueryWnd->parent)
2835 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
2836 (LPPOINT)&tempRect, 2 );
2838 if (PtInRect( &tempRect, pt))
2842 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
2844 if( ptrWnd->dwStyle & WS_VISIBLE )
2846 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
2847 if (PtInRect( &tempRect, pt )) break;
2853 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
2854 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2855 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2856 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2857 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2859 WIN_ReleaseWndPtr(ptrWnd);
2864 WIN_ReleaseWndPtr(ptrQueryWnd);
2869 WIN_ReleaseWndPtr(ptrQueryWnd);
2873 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2875 ptrDragInfo->hScope = hQueryWnd;
2877 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
2878 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
2880 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2886 /*******************************************************************
2887 * DragDetect (USER.465)
2889 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2892 CONV_POINT16TO32( &pt, &pt32 );
2893 return DragDetect( hWnd, pt32 );
2896 /*******************************************************************
2897 * DragDetect (USER32.@)
2899 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2904 rect.left = pt.x - wDragWidth;
2905 rect.right = pt.x + wDragWidth;
2907 rect.top = pt.y - wDragHeight;
2908 rect.bottom = pt.y + wDragHeight;
2914 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2916 if( msg.message == WM_LBUTTONUP )
2921 if( msg.message == WM_MOUSEMOVE )
2924 tmp.x = LOWORD(msg.lParam);
2925 tmp.y = HIWORD(msg.lParam);
2926 if( !PtInRect( &rect, tmp ))
2938 /******************************************************************************
2939 * DragObject (USER.464)
2941 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2942 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2945 LPDRAGINFO16 lpDragInfo;
2947 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2948 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
2949 HCURSOR16 hCurrentCursor = 0;
2950 HWND16 hCurrentWnd = 0;
2952 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
2953 spDragInfo = K32WOWGlobalLock16(hDragInfo);
2955 if( !lpDragInfo || !spDragInfo ) return 0L;
2957 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
2959 GlobalFree16(hDragInfo);
2965 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2967 GlobalFree16(hDragInfo);
2971 if( hDragCursor == hCursor ) hDragCursor = 0;
2972 else hCursor = hDragCursor;
2974 hOldCursor = SetCursor(hDragCursor);
2977 lpDragInfo->hWnd = hWnd;
2978 lpDragInfo->hScope = 0;
2979 lpDragInfo->wFlags = wObj;
2980 lpDragInfo->hList = szList; /* near pointer! */
2981 lpDragInfo->hOfStruct = hOfStruct;
2989 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
2991 *(lpDragInfo+1) = *lpDragInfo;
2993 lpDragInfo->pt.x = msg.pt.x;
2994 lpDragInfo->pt.y = msg.pt.y;
2996 /* update DRAGINFO struct */
2997 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
2999 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3000 hCurrentCursor = hCursor;
3003 hCurrentCursor = hBummer;
3004 lpDragInfo->hScope = 0;
3006 if( hCurrentCursor )
3007 SetCursor(hCurrentCursor);
3009 /* send WM_DRAGLOOP */
3010 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3011 (LPARAM) spDragInfo );
3012 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3013 if( hCurrentWnd != lpDragInfo->hScope )
3016 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3017 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3018 HIWORD(spDragInfo)) );
3019 hCurrentWnd = lpDragInfo->hScope;
3021 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3025 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3027 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3030 ShowCursor( FALSE );
3034 SetCursor( hOldCursor );
3035 if (hDragCursor) DestroyCursor( hDragCursor );
3038 if( hCurrentCursor != hBummer )
3039 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3040 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3043 GlobalFree16(hDragInfo);
3045 return (DWORD)(msg.lParam);
3049 /******************************************************************************
3050 * GetWindowModuleFileNameA (USER32.@)
3052 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3054 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3055 hwnd, lpszFileName, cchFileNameMax);
3059 /******************************************************************************
3060 * GetWindowModuleFileNameW (USER32.@)
3062 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3064 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3065 hwnd, lpszFileName, cchFileNameMax);