2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include "wine/winbase16.h"
11 #include "wine/winuser16.h"
12 #include "wine/server.h"
13 #include "wine/unicode.h"
19 #include "cursoricon.h"
26 #include "stackframe.h"
27 #include "debugtools.h"
29 DEFAULT_DEBUG_CHANNEL(win);
30 DECLARE_DEBUG_CHANNEL(msg);
32 /**********************************************************************/
35 static WND *pWndDesktop = NULL;
37 static HWND hwndSysModal = 0;
39 static WORD wDragWidth = 4;
40 static WORD wDragHeight= 3;
42 static void *user_handles[65536];
45 extern SYSLEVEL USER_SysLevel; /* FIXME */
47 /***********************************************************************
50 * Suspend the lock on WND structures.
51 * Returns the number of locks suspended
53 int WIN_SuspendWndsLock( void )
55 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
56 int count = isuspendedLocks;
59 _LeaveSysLevel( &USER_SysLevel );
61 return isuspendedLocks;
64 /***********************************************************************
67 * Restore the suspended locks on WND structures
69 void WIN_RestoreWndsLock( int ipreviousLocks )
71 while ( ipreviousLocks-- > 0 )
72 _EnterSysLevel( &USER_SysLevel );
75 /***********************************************************************
76 * create_window_handle
78 * Create a window handle with the server.
80 static WND *create_window_handle( BOOL desktop, INT size )
83 unsigned int handle = 0;
84 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
86 if (!win) return NULL;
92 SERVER_START_REQ( create_desktop_window )
94 if ((res = !SERVER_CALL_ERR())) handle = req->handle;
100 SERVER_START_REQ( create_window )
102 if ((res = !SERVER_CALL_ERR())) handle = req->handle;
110 HeapFree( GetProcessHeap(), 0, win );
113 user_handles[LOWORD(handle)] = win;
114 win->hwndSelf = (HWND)handle;
115 win->dwMagic = WND_MAGIC;
121 /***********************************************************************
124 * Free a window handle.
126 static WND *free_window_handle( HWND hwnd )
131 if ((ptr = user_handles[LOWORD(hwnd)]))
133 SERVER_START_REQ( destroy_window )
136 if (!SERVER_CALL_ERR())
137 user_handles[LOWORD(hwnd)] = NULL;
144 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
149 /***********************************************************************
152 * Return a pointer to the WND structure if local to the process.
153 * If ret value is non-NULL, the user lock is held.
155 static WND *get_wnd_ptr( HWND hwnd )
159 if (!hwnd) return NULL;
162 if ((ptr = user_handles[LOWORD(hwnd)]))
164 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
172 /***********************************************************************
175 * Convert a 16-bit window handle to a full 32-bit handle.
177 HWND WIN_Handle32( HWND16 hwnd16 )
180 HWND hwnd = (HWND)hwnd16;
182 if (!hwnd || hwnd == HWND_BROADCAST) return hwnd;
184 if ((ptr = get_wnd_ptr( hwnd )))
186 hwnd = ptr->hwndSelf;
189 else /* may belong to another process */
191 SERVER_START_REQ( get_window_info )
193 req->handle = (user_handle_t)hwnd16;
194 if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
202 /***********************************************************************
205 * Return a pointer to the WND structure corresponding to a HWND.
207 WND * WIN_FindWndPtr( HWND hwnd )
211 if (!hwnd) return NULL;
213 if ((ptr = get_wnd_ptr( hwnd )))
215 /* increment destruction monitoring */
220 /* check other processes */
221 if (IsWindow( hwnd ))
223 ERR( "window %04x belongs to other process\n", hwnd );
224 /* DbgBreakPoint(); */
226 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
231 /***********************************************************************
234 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
236 * Returns the locked initialisation pointer
238 WND *WIN_LockWndPtr(WND *initWndPtr)
240 if(!initWndPtr) return 0;
242 /* Lock all WND structures for thread safeness*/
244 /*and increment destruction monitoring*/
245 initWndPtr->irefCount++;
251 /***********************************************************************
254 * Release the pointer to the WND structure.
256 void WIN_ReleaseWndPtr(WND *wndPtr)
260 /*Decrement destruction monitoring value*/
262 /* Check if it's time to release the memory*/
263 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
266 free_window_handle( wndPtr->hwndSelf );
268 else if(wndPtr->irefCount < 0)
270 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
271 ERR("forgot a Lock on %p somewhere\n",wndPtr);
273 /*unlock all WND structures for thread safeness*/
277 /***********************************************************************
280 * Updates the value of oldPtr to newPtr.
282 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
286 tmpWnd = WIN_LockWndPtr(newPtr);
287 WIN_ReleaseWndPtr(*oldPtr);
293 /***********************************************************************
296 * Remove a window from the siblings linked list.
298 void WIN_UnlinkWindow( HWND hwnd )
300 WIN_LinkWindow( hwnd, 0, 0 );
304 /***********************************************************************
307 * Insert a window into the siblings linked list.
308 * The window is inserted after the specified window, which can also
309 * be specified as HWND_TOP or HWND_BOTTOM.
310 * If parent is 0, window is unlinked from the tree.
312 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
314 WND *wndPtr, **ppWnd, *parentPtr = NULL;
317 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
318 if (parent && !(parentPtr = WIN_FindWndPtr( parent )))
320 WIN_ReleaseWndPtr(wndPtr);
324 SERVER_START_REQ( link_window )
327 req->parent = parent;
328 req->previous = hwndInsertAfter;
329 ret = !SERVER_CALL_ERR();
334 /* first unlink it if it is linked */
337 ppWnd = &wndPtr->parent->child;
338 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
339 if (*ppWnd) *ppWnd = wndPtr->next;
344 wndPtr->parent = parentPtr;
345 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
347 ppWnd = &parentPtr->child; /* Point to first sibling hwnd */
348 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
349 while (*ppWnd) ppWnd = &(*ppWnd)->next;
351 else /* Normal case */
353 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
354 if (!afterPtr) goto done;
355 ppWnd = &afterPtr->next;
356 WIN_ReleaseWndPtr(afterPtr);
358 wndPtr->next = *ppWnd;
361 else wndPtr->next = NULL; /* unlinked */
364 WIN_ReleaseWndPtr( parentPtr );
365 WIN_ReleaseWndPtr( wndPtr );
369 /***********************************************************************
370 * WIN_FindWinToRepaint
372 * Find a window that needs repaint.
374 HWND WIN_FindWinToRepaint( HWND hwnd )
379 /* Note: the desktop window never gets WM_PAINT messages
380 * The real reason why is because Windows DesktopWndProc
381 * does ValidateRgn inside WM_ERASEBKGND handler.
383 if (hwnd == GetDesktopWindow()) hwnd = 0;
385 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
387 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
389 if (!(pWnd->dwStyle & WS_VISIBLE)) continue;
390 if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
391 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
395 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
397 WIN_ReleaseWndPtr(pWnd);
405 TRACE("nothing found\n");
408 hwndRet = pWnd->hwndSelf;
410 /* look among siblings if we got a transparent window */
413 if (!(pWnd->dwExStyle & WS_EX_TRANSPARENT) &&
414 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
415 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
417 hwndRet = pWnd->hwndSelf;
418 WIN_ReleaseWndPtr(pWnd);
421 WIN_UpdateWndPtr(&pWnd,pWnd->next);
423 TRACE("found %04x\n",hwndRet);
428 /***********************************************************************
431 * Destroy storage associated to a window. "Internals" p.358
432 * returns a locked wndPtr->next
434 static WND* WIN_DestroyWindow( WND* wndPtr )
436 HWND hwnd = wndPtr->hwndSelf;
439 TRACE("%04x\n", wndPtr->hwndSelf );
441 /* free child windows */
442 WIN_LockWndPtr(wndPtr->child);
443 while ((pWnd = wndPtr->child))
445 wndPtr->child = WIN_DestroyWindow( pWnd );
446 WIN_ReleaseWndPtr(pWnd);
450 * Clear the update region to make sure no WM_PAINT messages will be
451 * generated for this window while processing the WM_NCDESTROY.
453 RedrawWindow( wndPtr->hwndSelf, NULL, 0,
454 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
457 * Send the WM_NCDESTROY to the window being destroyed.
459 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
461 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
463 WINPOS_CheckInternalPos( hwnd );
464 if( hwnd == GetCapture()) ReleaseCapture();
466 /* free resources associated with the window */
468 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
469 PROPERTY_RemoveWindowProps( wndPtr );
471 /* toss stale messages from the queue */
473 QUEUE_CleanupWindow( hwnd );
474 wndPtr->hmemTaskQ = 0;
476 if (!(wndPtr->dwStyle & WS_CHILD))
479 DestroyMenu( wndPtr->wIDmenu );
482 if (wndPtr->hSysMenu)
484 DestroyMenu( wndPtr->hSysMenu );
485 wndPtr->hSysMenu = 0;
487 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
488 DCE_FreeWindowDCE( wndPtr->hwndSelf ); /* Always do this to catch orphaned DCs */
489 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
490 CLASS_RemoveWindow( wndPtr->class );
491 wndPtr->class = NULL;
492 wndPtr->dwMagic = 0; /* Mark it as invalid */
494 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
499 /***********************************************************************
500 * WIN_DestroyThreadWindows
502 * Destroy all children of 'wnd' owned by the current thread.
503 * Return TRUE if something was done.
505 void WIN_DestroyThreadWindows( HWND hwnd )
510 if (!(list = WIN_ListChildren( hwnd ))) return;
511 for (i = 0; list[i]; i++)
513 if (!IsWindow( list[i] )) continue;
514 if (GetWindowThreadProcessId( list[i], NULL ) == GetCurrentThreadId())
515 DestroyWindow( list[i] );
517 WIN_DestroyThreadWindows( list[i] );
519 HeapFree( GetProcessHeap(), 0, list );
522 /***********************************************************************
523 * WIN_CreateDesktopWindow
525 * Create the desktop window.
527 BOOL WIN_CreateDesktopWindow(void)
529 struct tagCLASS *class;
537 TRACE("Creating desktop window\n");
540 if (!WINPOS_CreateInternalPosAtom() ||
541 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
542 &wndExtra, &winproc, &clsStyle, &dce )))
545 pWndDesktop = create_window_handle( TRUE, sizeof(WND) + wndExtra );
546 if (!pWndDesktop) return FALSE;
547 hwndDesktop = pWndDesktop->hwndSelf;
549 pWndDesktop->tid = 0; /* nobody owns the desktop */
550 pWndDesktop->next = NULL;
551 pWndDesktop->child = NULL;
552 pWndDesktop->parent = NULL;
553 pWndDesktop->owner = 0;
554 pWndDesktop->class = class;
555 pWndDesktop->hInstance = 0;
556 pWndDesktop->rectWindow.left = 0;
557 pWndDesktop->rectWindow.top = 0;
558 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
559 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
560 pWndDesktop->rectClient = pWndDesktop->rectWindow;
561 pWndDesktop->text = NULL;
562 pWndDesktop->hmemTaskQ = 0;
563 pWndDesktop->hrgnUpdate = 0;
564 pWndDesktop->hwndLastActive = hwndDesktop;
565 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
567 pWndDesktop->dwExStyle = 0;
568 pWndDesktop->clsStyle = clsStyle;
569 pWndDesktop->dce = NULL;
570 pWndDesktop->pVScroll = NULL;
571 pWndDesktop->pHScroll = NULL;
572 pWndDesktop->pProp = NULL;
573 pWndDesktop->wIDmenu = 0;
574 pWndDesktop->helpContext = 0;
575 pWndDesktop->flags = 0;
576 pWndDesktop->hSysMenu = 0;
577 pWndDesktop->userdata = 0;
578 pWndDesktop->winproc = winproc;
579 pWndDesktop->cbWndExtra = wndExtra;
581 cs.lpCreateParams = NULL;
587 cs.cx = pWndDesktop->rectWindow.right;
588 cs.cy = pWndDesktop->rectWindow.bottom;
589 cs.style = pWndDesktop->dwStyle;
590 cs.dwExStyle = pWndDesktop->dwExStyle;
592 cs.lpszClass = DESKTOP_CLASS_ATOM;
594 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
596 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
597 WIN_ReleaseWndPtr( pWndDesktop );
602 /***********************************************************************
605 * Fix the coordinates - Helper for WIN_CreateWindowEx.
606 * returns default show mode in sw.
607 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
609 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
611 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
612 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
614 if (cs->style & (WS_CHILD | WS_POPUP))
616 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
617 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
619 else /* overlapped window */
623 GetStartupInfoA( &info );
625 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
627 /* Never believe Microsoft's documentation... CreateWindowEx doc says
628 * that if an overlapped window is created with WS_VISIBLE style bit
629 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
630 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
633 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
634 * 2) it does not ignore the y parameter as the docs claim; instead, it
635 * uses it as second parameter to ShowWindow() unless y is either
636 * CW_USEDEFAULT or CW_USEDEFAULT16.
638 * The fact that we didn't do 2) caused bogus windows pop up when wine
639 * was running apps that were using this obscure feature. Example -
640 * calc.exe that comes with Win98 (only Win98, it's different from
641 * the one that comes with Win95 and NT)
643 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
644 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
645 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
648 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
650 if (info.dwFlags & STARTF_USESIZE)
652 cs->cx = info.dwXSize;
653 cs->cy = info.dwYSize;
655 else /* if no other hint from the app, pick 3/4 of the screen real estate */
658 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
659 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
660 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
667 /***********************************************************************
670 * Implementation of CreateWindowEx().
672 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
673 WINDOWPROCTYPE type )
676 struct tagCLASS *classPtr;
678 HWND hwnd, hwndLinkAfter;
679 POINT maxSize, maxPos, minTrack, maxTrack;
684 BOOL unicode = (type == WIN_PROC_32W);
686 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
687 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
688 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
689 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
690 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
692 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
693 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
695 /* Find the parent window */
699 /* Make sure parent is valid */
700 if (!IsWindow( cs->hwndParent ))
702 WARN("Bad parent %04x\n", cs->hwndParent );
705 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
706 WARN("No parent for child window\n" );
707 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
710 /* Find the window class */
711 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
712 &wndExtra, &winproc, &clsStyle, &dce )))
714 WARN("Bad class '%s'\n", cs->lpszClass );
718 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
720 /* Correct the window style - stage 1
722 * These are patches that appear to affect both the style loaded into the
723 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
725 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
726 * why does the user get to set it?
729 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
730 * tested for WS_POPUP
732 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
733 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
734 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
735 cs->dwExStyle |= WS_EX_WINDOWEDGE;
737 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
739 /* Create the window structure */
741 if (!(wndPtr = create_window_handle( FALSE,
742 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
744 TRACE("out of memory\n" );
747 hwnd = wndPtr->hwndSelf;
749 /* Fill the window structure */
751 wndPtr->tid = GetCurrentThreadId();
753 wndPtr->child = NULL;
755 if ((cs->style & WS_CHILD) && cs->hwndParent)
757 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
759 WIN_ReleaseWndPtr(wndPtr->parent);
763 wndPtr->parent = pWndDesktop;
764 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
767 wndPtr->owner = GetAncestor( cs->hwndParent, GA_ROOT );
771 wndPtr->class = classPtr;
772 wndPtr->winproc = winproc;
773 wndPtr->hInstance = cs->hInstance;
775 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
776 wndPtr->hrgnUpdate = 0;
778 wndPtr->hwndLastActive = hwnd;
779 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
780 wndPtr->dwExStyle = cs->dwExStyle;
781 wndPtr->clsStyle = clsStyle;
783 wndPtr->helpContext = 0;
784 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
785 wndPtr->pVScroll = NULL;
786 wndPtr->pHScroll = NULL;
787 wndPtr->pProp = NULL;
788 wndPtr->userdata = 0;
789 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
790 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
791 wndPtr->cbWndExtra = wndExtra;
793 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
795 /* Call the WH_CBT hook */
797 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
798 ? HWND_BOTTOM : HWND_TOP;
800 if (HOOK_IsHooked( WH_CBT ))
806 cbtc.hwndInsertAfter = hwndLinkAfter;
807 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
808 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
811 TRACE("CBT-hook returned 0\n");
812 free_window_handle( hwnd );
813 CLASS_RemoveWindow( classPtr );
819 /* Correct the window style - stage 2 */
821 if (!(cs->style & WS_CHILD))
823 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
824 if (!(cs->style & WS_POPUP))
826 wndPtr->dwStyle |= WS_CAPTION;
827 wndPtr->flags |= WIN_NEED_SIZE;
831 /* Get class or window DC if needed */
833 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
834 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
835 else wndPtr->dce = NULL;
837 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
839 wndPtr->rectWindow.left = cs->x;
840 wndPtr->rectWindow.top = cs->y;
841 wndPtr->rectWindow.right = cs->x + cs->cx;
842 wndPtr->rectWindow.bottom = cs->y + cs->cy;
843 wndPtr->rectClient = wndPtr->rectWindow;
845 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
847 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
849 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
850 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
851 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
852 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
853 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
856 if (cs->cx < 0) cs->cx = 0;
857 if (cs->cy < 0) cs->cy = 0;
859 wndPtr->rectWindow.left = cs->x;
860 wndPtr->rectWindow.top = cs->y;
861 wndPtr->rectWindow.right = cs->x + cs->cx;
862 wndPtr->rectWindow.bottom = cs->y + cs->cy;
863 wndPtr->rectClient = wndPtr->rectWindow;
865 /* Set the window menu */
867 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
869 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
872 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
875 if (HIWORD(cs->hInstance))
876 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
878 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
880 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
884 else wndPtr->wIDmenu = (UINT)cs->hMenu;
886 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
888 WARN("aborted by WM_xxCREATE!\n");
889 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
890 CLASS_RemoveWindow( classPtr );
891 WIN_ReleaseWndPtr(wndPtr);
895 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
897 /* Notify the parent window only */
899 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
900 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
901 if( !IsWindow(hwnd) )
908 if (cs->style & WS_VISIBLE)
910 /* in case WS_VISIBLE got set in the meantime */
911 wndPtr->dwStyle &= ~WS_VISIBLE;
912 ShowWindow( hwnd, sw );
915 /* Call WH_SHELL hook */
917 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
918 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
920 TRACE("created window %04x\n", hwnd);
922 WIN_ReleaseWndPtr(wndPtr);
927 /***********************************************************************
928 * CreateWindow (USER.41)
930 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
931 DWORD style, INT16 x, INT16 y, INT16 width,
932 INT16 height, HWND16 parent, HMENU16 menu,
933 HINSTANCE16 instance, LPVOID data )
935 return CreateWindowEx16( 0, className, windowName, style,
936 x, y, width, height, parent, menu, instance, data );
940 /***********************************************************************
941 * CreateWindowEx (USER.452)
943 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
944 LPCSTR windowName, DWORD style, INT16 x,
945 INT16 y, INT16 width, INT16 height,
946 HWND16 parent, HMENU16 menu,
947 HINSTANCE16 instance, LPVOID data )
953 /* Find the class atom */
955 if (HIWORD(className))
957 if (!(classAtom = GlobalFindAtomA( className )))
959 ERR( "bad class name %s\n", debugres_a(className) );
965 classAtom = LOWORD(className);
966 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
968 ERR( "bad atom %x\n", classAtom);
974 /* Fix the coordinates */
976 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
977 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
978 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
979 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
981 /* Create the window */
983 cs.lpCreateParams = data;
984 cs.hInstance = (HINSTANCE)instance;
985 cs.hMenu = (HMENU)menu;
986 cs.hwndParent = (HWND)parent;
988 cs.lpszName = windowName;
989 cs.lpszClass = className;
990 cs.dwExStyle = exStyle;
992 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
996 /***********************************************************************
997 * CreateWindowExA (USER32.@)
999 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1000 LPCSTR windowName, DWORD style, INT x,
1001 INT y, INT width, INT height,
1002 HWND parent, HMENU menu,
1003 HINSTANCE instance, LPVOID data )
1010 instance=GetModuleHandleA(NULL);
1012 if(exStyle & WS_EX_MDICHILD)
1013 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1015 /* Find the class atom */
1017 if (HIWORD(className))
1019 if (!(classAtom = GlobalFindAtomA( className )))
1021 ERR( "bad class name %s\n", debugres_a(className) );
1027 classAtom = LOWORD(className);
1028 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1030 ERR( "bad atom %x\n", classAtom);
1036 /* Create the window */
1038 cs.lpCreateParams = data;
1039 cs.hInstance = instance;
1041 cs.hwndParent = parent;
1047 cs.lpszName = windowName;
1048 cs.lpszClass = className;
1049 cs.dwExStyle = exStyle;
1051 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1055 /***********************************************************************
1056 * CreateWindowExW (USER32.@)
1058 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1059 LPCWSTR windowName, DWORD style, INT x,
1060 INT y, INT width, INT height,
1061 HWND parent, HMENU menu,
1062 HINSTANCE instance, LPVOID data )
1069 instance=GetModuleHandleA(NULL);
1071 if(exStyle & WS_EX_MDICHILD)
1072 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1074 /* Find the class atom */
1076 if (HIWORD(className))
1078 if (!(classAtom = GlobalFindAtomW( className )))
1080 ERR( "bad class name %s\n", debugres_w(className) );
1086 classAtom = LOWORD(className);
1087 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1089 ERR( "bad atom %x\n", classAtom);
1095 /* Create the window */
1097 cs.lpCreateParams = data;
1098 cs.hInstance = instance;
1100 cs.hwndParent = parent;
1106 cs.lpszName = windowName;
1107 cs.lpszClass = className;
1108 cs.dwExStyle = exStyle;
1110 /* Note: we rely on the fact that CREATESTRUCTA and */
1111 /* CREATESTRUCTW have the same layout. */
1112 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1116 /***********************************************************************
1117 * WIN_SendDestroyMsg
1119 static void WIN_SendDestroyMsg( HWND hwnd )
1121 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1122 if (USER_Driver.pResetSelectionOwner)
1123 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1126 * Send the WM_DESTROY to the window.
1128 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1131 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1132 * make sure that the window still exists when we come back.
1139 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1141 /* start from the end (FIXME: is this needed?) */
1142 for (i = 0; pWndArray[i]; i++) ;
1146 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1148 HeapFree( GetProcessHeap(), 0, pWndArray );
1151 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1155 /***********************************************************************
1156 * DestroyWindow (USER.53)
1158 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1160 return DestroyWindow(hwnd);
1164 /***********************************************************************
1165 * DestroyWindow (USER32.@)
1167 BOOL WINAPI DestroyWindow( HWND hwnd )
1173 TRACE("(%04x)\n", hwnd);
1175 /* Initialization */
1177 if (hwnd == GetDesktopWindow()) return FALSE; /* Can't destroy desktop */
1179 /* Look whether the focus is within the tree of windows we will
1183 if (h == hwnd || IsChild( hwnd, h ))
1185 HWND parent = GetAncestor( hwnd, GA_PARENT );
1186 if (parent == GetDesktopWindow()) parent = 0;
1192 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) ) return FALSE;
1194 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1195 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1197 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1198 /* FIXME: clean up palette - see "Internals" p.352 */
1201 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1202 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1204 /* Notify the parent window only */
1205 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1206 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1207 if( !IsWindow(hwnd) )
1214 if (USER_Driver.pResetSelectionOwner)
1215 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1217 /* Hide the window */
1219 if (wndPtr->dwStyle & WS_VISIBLE)
1221 ShowWindow( hwnd, SW_HIDE );
1222 if (!IsWindow(hwnd))
1229 /* Recursively destroy owned windows */
1231 if( !(wndPtr->dwStyle & WS_CHILD) )
1236 HWND *list = WIN_ListChildren( wndPtr->parent->hwndSelf );
1239 for (i = 0; list[i]; i++)
1241 WND *siblingPtr = WIN_FindWndPtr( list[i] );
1242 if (!siblingPtr) continue;
1243 if (siblingPtr->owner == hwnd)
1245 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1247 WIN_ReleaseWndPtr( siblingPtr );
1248 DestroyWindow( list[i] );
1252 else siblingPtr->owner = 0;
1254 WIN_ReleaseWndPtr( siblingPtr );
1256 HeapFree( GetProcessHeap(), 0, list );
1258 if (!got_one) break;
1261 WINPOS_ActivateOtherWindow(wndPtr->hwndSelf);
1265 WND *owner = WIN_FindWndPtr( wndPtr->owner );
1266 if (owner->hwndLastActive == hwnd) owner->hwndLastActive = wndPtr->owner;
1267 WIN_ReleaseWndPtr( owner );
1271 /* Send destroy messages */
1273 WIN_SendDestroyMsg( hwnd );
1274 if (!IsWindow(hwnd))
1280 /* Unlink now so we won't bother with the children later on */
1282 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1284 /* Destroy the window storage */
1286 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1289 WIN_ReleaseWndPtr(wndPtr);
1294 /***********************************************************************
1295 * CloseWindow (USER.43)
1297 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1299 return CloseWindow( hwnd );
1303 /***********************************************************************
1304 * CloseWindow (USER32.@)
1306 BOOL WINAPI CloseWindow( HWND hwnd )
1308 WND * wndPtr = WIN_FindWndPtr( hwnd );
1311 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1316 ShowWindow( hwnd, SW_MINIMIZE );
1319 WIN_ReleaseWndPtr(wndPtr);
1325 /***********************************************************************
1326 * OpenIcon (USER.44)
1328 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1330 return OpenIcon( hwnd );
1334 /***********************************************************************
1335 * OpenIcon (USER32.@)
1337 BOOL WINAPI OpenIcon( HWND hwnd )
1339 if (!IsIconic( hwnd )) return FALSE;
1340 ShowWindow( hwnd, SW_SHOWNORMAL );
1345 /***********************************************************************
1348 * Implementation of FindWindow() and FindWindowEx().
1350 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1355 WCHAR *buffer = NULL;
1357 if (!parent) parent = GetDesktopWindow();
1360 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1361 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1364 if (!(list = WIN_ListChildren( parent )))
1366 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1372 while (list[i] && list[i] != child) i++;
1373 if (!list[i]) return 0;
1374 i++; /* start from next window */
1377 for ( ; list[i]; i++)
1379 if (className && (GetClassWord(list[i], GCW_ATOM) != className))
1380 continue; /* Not the right class */
1382 /* Now check the title */
1384 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1387 HeapFree( GetProcessHeap(), 0, list );
1388 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1390 /* In this case we need to check whether other processes
1391 own a window with the given paramters on the Desktop,
1392 but we don't, so let's at least warn about it */
1393 if (!retvalue) FIXME("Returning 0 without checking other processes\n");
1399 /***********************************************************************
1400 * FindWindow (USER.50)
1402 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1404 return FindWindowA( className, title );
1408 /***********************************************************************
1409 * FindWindowEx (USER.427)
1411 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1413 return FindWindowExA( parent, child, className, title );
1417 /***********************************************************************
1418 * FindWindowA (USER32.@)
1420 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1422 HWND ret = FindWindowExA( 0, 0, className, title );
1423 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1428 /***********************************************************************
1429 * FindWindowExA (USER32.@)
1431 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1432 LPCSTR className, LPCSTR title )
1440 /* If the atom doesn't exist, then no class */
1441 /* with this name exists either. */
1442 if (!(atom = GlobalFindAtomA( className )))
1444 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1449 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1450 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1451 HeapFree( GetProcessHeap(), 0, buffer );
1456 /***********************************************************************
1457 * FindWindowExW (USER32.@)
1459 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1460 LPCWSTR className, LPCWSTR title )
1466 /* If the atom doesn't exist, then no class */
1467 /* with this name exists either. */
1468 if (!(atom = GlobalFindAtomW( className )))
1470 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1474 return WIN_FindWindow( parent, child, atom, title );
1478 /***********************************************************************
1479 * FindWindowW (USER32.@)
1481 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1483 return FindWindowExW( 0, 0, className, title );
1487 /**********************************************************************
1488 * GetDesktopWindow (USER.286)
1490 HWND16 WINAPI GetDesktopWindow16(void)
1492 return (HWND16)pWndDesktop->hwndSelf;
1496 /**********************************************************************
1497 * GetDesktopWindow (USER32.@)
1499 HWND WINAPI GetDesktopWindow(void)
1501 if (pWndDesktop) return pWndDesktop->hwndSelf;
1502 ERR( "You need the -desktop option when running with native USER\n" );
1508 /**********************************************************************
1509 * GetDesktopHwnd (USER.278)
1511 * Exactly the same thing as GetDesktopWindow(), but not documented.
1512 * Don't ask me why...
1514 HWND16 WINAPI GetDesktopHwnd16(void)
1516 return (HWND16)pWndDesktop->hwndSelf;
1520 /*******************************************************************
1521 * EnableWindow (USER.34)
1523 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1525 return EnableWindow( hwnd, enable );
1529 /*******************************************************************
1530 * EnableWindow (USER32.@)
1532 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1537 TRACE("( %x, %d )\n", hwnd, enable);
1539 if (USER_Driver.pEnableWindow)
1540 return USER_Driver.pEnableWindow( hwnd, enable );
1542 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1544 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1546 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1548 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1549 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1551 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1553 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1555 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1557 if (hwnd == GetFocus())
1558 SetFocus( 0 ); /* A disabled window can't have the focus */
1560 if (hwnd == GetCapture())
1561 ReleaseCapture(); /* A disabled window can't capture the mouse */
1563 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1565 WIN_ReleaseWndPtr(wndPtr);
1570 /***********************************************************************
1571 * IsWindowEnabled (USER.35)
1573 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1575 return IsWindowEnabled(hWnd);
1579 /***********************************************************************
1580 * IsWindowEnabled (USER32.@)
1582 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1587 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1588 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1589 WIN_ReleaseWndPtr(wndPtr);
1595 /***********************************************************************
1596 * IsWindowUnicode (USER32.@)
1598 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1603 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1604 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1605 WIN_ReleaseWndPtr(wndPtr);
1610 /**********************************************************************
1611 * GetWindowWord (USER.133)
1613 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1615 return GetWindowWord( hwnd, offset );
1619 /**********************************************************************
1620 * GetWindowWord (USER32.@)
1622 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1625 WND * wndPtr = WIN_FindWndPtr( hwnd );
1626 if (!wndPtr) return 0;
1629 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1631 WARN("Invalid offset %d\n", offset );
1635 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1641 if (HIWORD(wndPtr->wIDmenu))
1642 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1644 retvalue = (WORD)wndPtr->wIDmenu;
1646 case GWW_HWNDPARENT:
1647 retvalue = GetParent(hwnd);
1650 if (HIWORD(wndPtr->hInstance))
1651 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1653 retvalue = (WORD)wndPtr->hInstance;
1656 WARN("Invalid offset %d\n", offset );
1661 WIN_ReleaseWndPtr(wndPtr);
1665 /**********************************************************************
1666 * SetWindowWord (USER.134)
1668 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1670 return SetWindowWord( hwnd, offset, newval );
1674 /**********************************************************************
1675 * SetWindowWord (USER32.@)
1677 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1680 WND * wndPtr = WIN_FindWndPtr( hwnd );
1681 if (!wndPtr) return 0;
1684 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1686 WARN("Invalid offset %d\n", offset );
1690 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1694 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1695 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1696 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1699 WARN("Invalid offset %d\n", offset );
1706 WIN_ReleaseWndPtr(wndPtr);
1711 /**********************************************************************
1714 * Helper function for GetWindowLong().
1716 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1719 WND * wndPtr = WIN_FindWndPtr( hwnd );
1720 if (!wndPtr) return 0;
1723 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1725 WARN("Invalid offset %d\n", offset );
1729 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1730 /* Special case for dialog window procedure */
1731 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1733 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1740 case GWL_USERDATA: retvalue = wndPtr->userdata;
1742 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1744 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1746 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1748 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1751 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1753 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1756 WARN("Unknown offset %d\n", offset );
1760 WIN_ReleaseWndPtr(wndPtr);
1765 /**********************************************************************
1768 * Helper function for SetWindowLong().
1770 * 0 is the failure code. However, in the case of failure SetLastError
1771 * must be set to distinguish between a 0 return value and a failure.
1773 * FIXME: The error values for SetLastError may not be right. Can
1774 * someone check with the real thing?
1776 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1777 WINDOWPROCTYPE type )
1780 WND * wndPtr = WIN_FindWndPtr( hwnd );
1783 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1787 /* Is this the right error? */
1788 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1794 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1796 WARN("Invalid offset %d\n", offset );
1798 /* Is this the right error? */
1799 SetLastError( ERROR_OUTOFMEMORY );
1804 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1805 /* Special case for dialog window procedure */
1806 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1808 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1809 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1810 type, WIN_PROC_WINDOW );
1817 ptr = (DWORD*)&wndPtr->wIDmenu;
1820 retval = SetWindowWord( hwnd, offset, newval );
1823 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1824 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1825 type, WIN_PROC_WINDOW );
1828 style.styleOld = wndPtr->dwStyle;
1829 style.styleNew = newval;
1830 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1831 wndPtr->dwStyle = style.styleNew;
1832 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1833 retval = style.styleOld;
1837 ptr = &wndPtr->userdata;
1840 style.styleOld = wndPtr->dwExStyle;
1841 style.styleNew = newval;
1842 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1843 wndPtr->dwExStyle = style.styleNew;
1844 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1845 retval = style.styleOld;
1849 WARN("Invalid offset %d\n", offset );
1851 /* Don't think this is right error but it should do */
1852 SetLastError( ERROR_OUTOFMEMORY );
1860 WIN_ReleaseWndPtr(wndPtr);
1865 /**********************************************************************
1866 * GetWindowLong (USER.135)
1868 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1870 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1874 /**********************************************************************
1875 * GetWindowLongA (USER32.@)
1877 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1879 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1883 /**********************************************************************
1884 * GetWindowLongW (USER32.@)
1886 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1888 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1892 /**********************************************************************
1893 * SetWindowLong (USER.136)
1895 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1897 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1901 /**********************************************************************
1902 * SetWindowLongA (USER32.@)
1904 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1906 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1910 /**********************************************************************
1911 * SetWindowLongW (USER32.@) Set window attribute
1913 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1914 * value in a window's extra memory.
1916 * The _hwnd_ parameter specifies the window. is the handle to a
1917 * window that has extra memory. The _newval_ parameter contains the
1918 * new attribute or extra memory value. If positive, the _offset_
1919 * parameter is the byte-addressed location in the window's extra
1920 * memory to set. If negative, _offset_ specifies the window
1921 * attribute to set, and should be one of the following values:
1923 * GWL_EXSTYLE The window's extended window style
1925 * GWL_STYLE The window's window style.
1927 * GWL_WNDPROC Pointer to the window's window procedure.
1929 * GWL_HINSTANCE The window's pplication instance handle.
1931 * GWL_ID The window's identifier.
1933 * GWL_USERDATA The window's user-specified data.
1935 * If the window is a dialog box, the _offset_ parameter can be one of
1936 * the following values:
1938 * DWL_DLGPROC The address of the window's dialog box procedure.
1940 * DWL_MSGRESULT The return value of a message
1941 * that the dialog box procedure processed.
1943 * DWL_USER Application specific information.
1947 * If successful, returns the previous value located at _offset_. Otherwise,
1952 * Extra memory for a window class is specified by a nonzero cbWndExtra
1953 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1954 * time of class creation.
1956 * Using GWL_WNDPROC to set a new window procedure effectively creates
1957 * a window subclass. Use CallWindowProc() in the new windows procedure
1958 * to pass messages to the superclass's window procedure.
1960 * The user data is reserved for use by the application which created
1963 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1964 * instead, call the EnableWindow() function to change the window's
1967 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1968 * SetParent() instead.
1971 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1972 * it sends WM_STYLECHANGING before changing the settings
1973 * and WM_STYLECHANGED afterwards.
1974 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1978 * GWL_STYLE does not dispatch WM_STYLE... messages.
1985 LONG WINAPI SetWindowLongW(
1986 HWND hwnd, /* [in] window to alter */
1987 INT offset, /* [in] offset, in bytes, of location to alter */
1988 LONG newval /* [in] new value of location */
1990 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1994 /*******************************************************************
1995 * GetWindowText (USER.36)
1997 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1999 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2003 /*******************************************************************
2004 * GetWindowTextA (USER32.@)
2006 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2008 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2012 /*******************************************************************
2013 * InternalGetWindowText (USER32.@)
2015 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2017 WND *win = WIN_FindWndPtr( hwnd );
2019 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2020 else lpString[0] = 0;
2021 WIN_ReleaseWndPtr( win );
2022 return strlenW(lpString);
2026 /*******************************************************************
2027 * GetWindowTextW (USER32.@)
2029 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2031 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2036 /*******************************************************************
2037 * SetWindowText (USER.37)
2039 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2041 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2045 /*******************************************************************
2046 * SetWindowText (USER32.@)
2047 * SetWindowTextA (USER32.@)
2049 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2051 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2055 /*******************************************************************
2056 * SetWindowTextW (USER32.@)
2058 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2060 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2064 /*******************************************************************
2065 * GetWindowTextLength (USER.38)
2067 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2069 return (INT16)GetWindowTextLengthA( hwnd );
2073 /*******************************************************************
2074 * GetWindowTextLengthA (USER32.@)
2076 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2078 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2081 /*******************************************************************
2082 * GetWindowTextLengthW (USER32.@)
2084 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2086 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2090 /*******************************************************************
2091 * IsWindow (USER.47)
2093 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2095 CURRENT_STACK16->es = USER_HeapSel;
2096 return IsWindow( hwnd );
2100 /*******************************************************************
2101 * IsWindow (USER32.@)
2103 BOOL WINAPI IsWindow( HWND hwnd )
2109 if ((ptr = user_handles[LOWORD(hwnd)]))
2111 ret = ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf));
2117 /* check other processes */
2118 SERVER_START_REQ( get_window_info )
2121 ret = !SERVER_CALL_ERR();
2128 /***********************************************************************
2129 * GetWindowThreadProcessId (USER32.@)
2131 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2137 if ((ptr = user_handles[LOWORD(hwnd)]))
2139 if ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
2141 /* got a valid window */
2143 if (process) *process = GetCurrentProcessId();
2145 else SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2151 /* check other processes */
2152 SERVER_START_REQ( get_window_info )
2155 if (!SERVER_CALL_ERR())
2157 tid = (DWORD)req->tid;
2158 if (process) *process = (DWORD)req->pid;
2166 /*****************************************************************
2167 * GetParent (USER.46)
2169 HWND16 WINAPI GetParent16( HWND16 hwnd )
2171 return (HWND16)GetParent( hwnd );
2175 /*****************************************************************
2176 * GetParent (USER32.@)
2178 HWND WINAPI GetParent( HWND hwnd )
2183 if ((wndPtr = WIN_FindWndPtr(hwnd)))
2185 if (wndPtr->dwStyle & WS_CHILD)
2186 retvalue = wndPtr->parent->hwndSelf;
2187 else if (wndPtr->dwStyle & WS_POPUP)
2188 retvalue = wndPtr->owner;
2189 WIN_ReleaseWndPtr(wndPtr);
2195 /*****************************************************************
2196 * GetAncestor (USER32.@)
2198 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2203 if (hwnd == GetDesktopWindow()) return 0;
2204 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2209 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2212 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2213 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2216 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2217 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2218 while (wndPtr && wndPtr->owner)
2220 WND *ptr = WIN_FindWndPtr( wndPtr->owner );
2221 WIN_ReleaseWndPtr( wndPtr );
2226 ret = wndPtr ? wndPtr->hwndSelf : 0;
2227 WIN_ReleaseWndPtr( wndPtr );
2232 /*****************************************************************
2233 * SetParent (USER.233)
2235 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2237 return SetParent( hwndChild, hwndNewParent );
2241 /*****************************************************************
2242 * SetParent (USER32.@)
2244 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2250 if (!parent) parent = GetDesktopWindow();
2253 if (hwnd == GetDesktopWindow() || !IsWindow( parent ))
2255 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2259 if (USER_Driver.pSetParent)
2260 return USER_Driver.pSetParent( hwnd, parent );
2262 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2264 dwStyle = wndPtr->dwStyle;
2266 /* Windows hides the window first, then shows it again
2267 * including the WM_SHOWWINDOW messages and all */
2268 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2270 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2271 if (parent != retvalue)
2273 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2275 if (parent != GetDesktopWindow()) /* a child window */
2277 if (!(dwStyle & WS_CHILD))
2279 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2280 if (menu) DestroyMenu( menu );
2284 WIN_ReleaseWndPtr( wndPtr );
2286 /* SetParent additionally needs to make hwnd the topmost window
2287 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2288 WM_WINDOWPOSCHANGED notification messages.
2290 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2291 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2292 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2293 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2294 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2299 /*******************************************************************
2302 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2304 return IsChild(parent,child);
2308 /*******************************************************************
2309 * IsChild (USER32.@)
2311 BOOL WINAPI IsChild( HWND parent, HWND child )
2313 HWND *list = WIN_ListParents( child );
2317 if (!list) return FALSE;
2318 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2319 ret = (list[i] != 0);
2320 HeapFree( GetProcessHeap(), 0, list );
2325 /***********************************************************************
2326 * IsWindowVisible (USER.49)
2328 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2330 return IsWindowVisible(hwnd);
2334 /***********************************************************************
2335 * IsWindowVisible (USER32.@)
2337 BOOL WINAPI IsWindowVisible( HWND hwnd )
2343 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2344 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2345 for (i = 0; list[i]; i++)
2346 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2348 HeapFree( GetProcessHeap(), 0, list );
2353 /***********************************************************************
2354 * WIN_IsWindowDrawable
2356 * hwnd is drawable when it is visible, all parents are not
2357 * minimized, and it is itself not minimized unless we are
2358 * trying to draw its default class icon.
2360 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2366 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2367 if ((wnd->dwStyle & WS_MINIMIZE) &&
2368 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2370 if (!(list = WIN_ListParents( wnd->hwndSelf ))) return TRUE;
2371 for (i = 0; list[i]; i++)
2372 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2375 HeapFree( GetProcessHeap(), 0, list );
2380 /*******************************************************************
2381 * GetTopWindow (USER.229)
2383 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2385 return GetTopWindow(hwnd);
2389 /*******************************************************************
2390 * GetTopWindow (USER32.@)
2392 HWND WINAPI GetTopWindow( HWND hwnd )
2394 if (!hwnd) hwnd = GetDesktopWindow();
2395 return GetWindow( hwnd, GW_CHILD );
2399 /*******************************************************************
2400 * GetWindow (USER.262)
2402 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2404 return GetWindow( hwnd,rel );
2408 /*******************************************************************
2409 * GetWindow (USER32.@)
2411 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2415 WND * wndPtr = WIN_FindWndPtr( hwnd );
2416 if (!wndPtr) return 0;
2420 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2424 if (!wndPtr->parent)
2426 retval = 0; /* Desktop window */
2429 while (wndPtr->next)
2431 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2433 retval = wndPtr->hwndSelf;
2437 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2441 if (!wndPtr->parent)
2443 retval = 0; /* Desktop window */
2446 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2447 if (wndPtr->hwndSelf == hwnd)
2449 retval = 0; /* First in list */
2452 while (wndPtr->next)
2454 if (wndPtr->next->hwndSelf == hwnd)
2456 retval = wndPtr->hwndSelf;
2459 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2465 retval = wndPtr->owner;
2469 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2474 WIN_ReleaseWndPtr(wndPtr);
2479 /*******************************************************************
2480 * GetNextWindow (USER.230)
2482 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2484 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2485 return GetWindow16( hwnd, flag );
2488 /***********************************************************************
2489 * WIN_InternalShowOwnedPopups
2491 * Internal version of ShowOwnedPopups; Wine functions should use this
2492 * to avoid interfering with application calls to ShowOwnedPopups
2493 * and to make sure the application can't prevent showing/hiding.
2495 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2499 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2503 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2505 if (!win_array) return TRUE;
2508 * Show windows Lowest first, Highest last to preserve Z-Order
2510 while (win_array[count]) count++;
2511 while (--count >= 0)
2513 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2514 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2516 if (pWnd->dwStyle & WS_POPUP)
2520 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2521 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2524 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2526 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2527 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2532 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2533 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2534 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2537 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2539 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2540 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2541 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2545 WIN_ReleaseWndPtr( pWnd );
2547 HeapFree( GetProcessHeap(), 0, win_array );
2552 /*******************************************************************
2553 * ShowOwnedPopups (USER.265)
2555 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2557 ShowOwnedPopups( owner, fShow );
2561 /*******************************************************************
2562 * ShowOwnedPopups (USER32.@)
2564 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2568 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2570 if (!win_array) return TRUE;
2572 while (win_array[count]) count++;
2573 while (--count >= 0)
2575 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2576 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2578 if (pWnd->dwStyle & WS_POPUP)
2582 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2584 /* In Windows, ShowOwnedPopups(TRUE) generates
2585 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2586 * regardless of the state of the owner
2588 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2589 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2594 if (IsWindowVisible(pWnd->hwndSelf))
2596 /* In Windows, ShowOwnedPopups(FALSE) generates
2597 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2598 * regardless of the state of the owner
2600 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2601 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2605 WIN_ReleaseWndPtr( pWnd );
2607 HeapFree( GetProcessHeap(), 0, win_array );
2612 /*******************************************************************
2613 * GetLastActivePopup (USER.287)
2615 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2617 return GetLastActivePopup( hwnd );
2620 /*******************************************************************
2621 * GetLastActivePopup (USER32.@)
2623 HWND WINAPI GetLastActivePopup( HWND hwnd )
2626 WND *wndPtr =WIN_FindWndPtr(hwnd);
2627 if (!wndPtr) return hwnd;
2628 retval = wndPtr->hwndLastActive;
2629 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2630 WIN_ReleaseWndPtr(wndPtr);
2635 /*******************************************************************
2638 * Build an array of all parents of a given window, starting with
2639 * the immediate parent. The array must be freed with HeapFree.
2640 * Returns NULL if window is a top-level window.
2642 HWND *WIN_ListParents( HWND hwnd )
2644 WND *parent, *wndPtr = WIN_FindWndPtr( hwnd );
2648 /* First count the windows */
2650 if (!wndPtr) return NULL;
2652 parent = wndPtr->parent;
2653 while (parent && parent->hwndSelf != GetDesktopWindow())
2656 parent = parent->parent;
2661 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1) )))
2663 parent = wndPtr->parent;
2664 for (i = 0; i < count; i++)
2666 list[i] = parent->hwndSelf;
2667 parent = parent->parent;
2673 WIN_ReleaseWndPtr( wndPtr );
2678 /*******************************************************************
2681 * Build an array of the children of a given window. The array must be
2682 * freed with HeapFree. Returns NULL when no windows are found.
2684 HWND *WIN_ListChildren( HWND hwnd )
2686 WND *pWnd, *wndPtr = WIN_FindWndPtr( hwnd );
2690 /* First count the windows */
2692 if (!wndPtr) return NULL;
2694 pWnd = WIN_LockWndPtr(wndPtr->child);
2698 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2703 /* Now build the list of all windows */
2705 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1))))
2707 for (pWnd = WIN_LockWndPtr(wndPtr->child), phwnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2709 *phwnd++ = pWnd->hwndSelf;
2712 WIN_ReleaseWndPtr(pWnd);
2718 WIN_ReleaseWndPtr( wndPtr );
2723 /*******************************************************************
2724 * EnumWindows (USER32.@)
2726 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2732 /* We have to build a list of all windows first, to avoid */
2733 /* unpleasant side-effects, for instance if the callback */
2734 /* function changes the Z-order of the windows. */
2736 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2738 /* Now call the callback function for every window */
2740 iWndsLocks = WIN_SuspendWndsLock();
2741 for (i = 0; list[i]; i++)
2743 /* Make sure that the window still exists */
2744 if (!IsWindow( list[i] )) continue;
2745 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2747 WIN_RestoreWndsLock(iWndsLocks);
2748 HeapFree( GetProcessHeap(), 0, list );
2753 /**********************************************************************
2754 * EnumTaskWindows16 (USER.225)
2756 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2759 TDB *tdb = TASK_GetPtr( hTask );
2760 if (!tdb) return FALSE;
2761 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2765 /**********************************************************************
2766 * EnumThreadWindows (USER32.@)
2768 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2773 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2775 /* Now call the callback function for every window */
2777 iWndsLocks = WIN_SuspendWndsLock();
2778 for (i = 0; list[i]; i++)
2780 if (GetWindowThreadProcessId( list[i], NULL ) != id) continue;
2781 if (!func( list[i], lParam )) break;
2783 WIN_RestoreWndsLock(iWndsLocks);
2784 HeapFree( GetProcessHeap(), 0, list );
2789 /**********************************************************************
2790 * WIN_EnumChildWindows
2792 * Helper function for EnumChildWindows().
2794 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2799 for ( ; *list; list++)
2801 /* Make sure that the window still exists */
2802 if (!IsWindow( *list )) continue;
2803 /* skip owned windows */
2804 if (GetWindow( *list, GW_OWNER )) continue;
2805 /* Build children list first */
2806 childList = WIN_ListChildren( *list );
2808 ret = func( *list, lParam );
2812 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2813 HeapFree( GetProcessHeap(), 0, childList );
2815 if (!ret) return FALSE;
2821 /**********************************************************************
2822 * EnumChildWindows (USER32.@)
2824 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2829 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2830 iWndsLocks = WIN_SuspendWndsLock();
2831 WIN_EnumChildWindows( list, func, lParam );
2832 WIN_RestoreWndsLock(iWndsLocks);
2833 HeapFree( GetProcessHeap(), 0, list );
2838 /*******************************************************************
2839 * AnyPopup (USER.52)
2841 BOOL16 WINAPI AnyPopup16(void)
2847 /*******************************************************************
2848 * AnyPopup (USER32.@)
2850 BOOL WINAPI AnyPopup(void)
2854 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2856 if (!list) return FALSE;
2857 for (i = 0; list[i]; i++)
2859 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2861 retvalue = (list[i] != 0);
2862 HeapFree( GetProcessHeap(), 0, list );
2867 /*******************************************************************
2868 * FlashWindow (USER.105)
2870 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2872 return FlashWindow( hWnd, bInvert );
2876 /*******************************************************************
2877 * FlashWindow (USER32.@)
2879 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2881 WND *wndPtr = WIN_FindWndPtr(hWnd);
2883 TRACE("%04x\n", hWnd);
2885 if (!wndPtr) return FALSE;
2887 if (wndPtr->dwStyle & WS_MINIMIZE)
2889 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2891 HDC hDC = GetDC(hWnd);
2893 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2894 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2896 ReleaseDC( hWnd, hDC );
2897 wndPtr->flags |= WIN_NCACTIVATED;
2901 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2902 wndPtr->flags &= ~WIN_NCACTIVATED;
2904 WIN_ReleaseWndPtr(wndPtr);
2910 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2911 else wparam = (hWnd == GetActiveWindow());
2913 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2914 WIN_ReleaseWndPtr(wndPtr);
2920 /*******************************************************************
2921 * SetSysModalWindow (USER.188)
2923 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2925 HWND hWndOldModal = hwndSysModal;
2926 hwndSysModal = hWnd;
2927 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2928 return hWndOldModal;
2932 /*******************************************************************
2933 * GetSysModalWindow (USER.189)
2935 HWND16 WINAPI GetSysModalWindow16(void)
2937 return hwndSysModal;
2941 /*******************************************************************
2942 * GetWindowContextHelpId (USER32.@)
2944 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2947 WND *wnd = WIN_FindWndPtr( hwnd );
2949 retval = wnd->helpContext;
2950 WIN_ReleaseWndPtr(wnd);
2955 /*******************************************************************
2956 * SetWindowContextHelpId (USER32.@)
2958 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2960 WND *wnd = WIN_FindWndPtr( hwnd );
2961 if (!wnd) return FALSE;
2962 wnd->helpContext = id;
2963 WIN_ReleaseWndPtr(wnd);
2968 /*******************************************************************
2971 * recursively find a child that contains spDragInfo->pt point
2972 * and send WM_QUERYDROPOBJECT
2974 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2976 BOOL16 wParam, bResult = 0;
2978 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
2981 if (!ptrDragInfo) return FALSE;
2983 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2985 GetWindowRect(hQueryWnd,&tempRect);
2987 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
2989 if (!IsIconic( hQueryWnd ))
2991 GetClientRect( hQueryWnd, &tempRect );
2992 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
2994 if (PtInRect( &tempRect, pt))
2997 HWND *list = WIN_ListChildren( hQueryWnd );
3003 for (i = 0; list[i]; i++)
3005 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3007 GetWindowRect( list[i], &tempRect );
3008 if (PtInRect( &tempRect, pt )) break;
3013 if (IsWindowEnabled( list[i] ))
3014 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
3016 HeapFree( GetProcessHeap(), 0, list );
3018 if(bResult) return bResult;
3024 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3026 ptrDragInfo->hScope = hQueryWnd;
3028 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3029 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3031 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3037 /*******************************************************************
3038 * DragDetect (USER.465)
3040 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3043 CONV_POINT16TO32( &pt, &pt32 );
3044 return DragDetect( hWnd, pt32 );
3047 /*******************************************************************
3048 * DragDetect (USER32.@)
3050 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3055 rect.left = pt.x - wDragWidth;
3056 rect.right = pt.x + wDragWidth;
3058 rect.top = pt.y - wDragHeight;
3059 rect.bottom = pt.y + wDragHeight;
3065 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3067 if( msg.message == WM_LBUTTONUP )
3072 if( msg.message == WM_MOUSEMOVE )
3075 tmp.x = LOWORD(msg.lParam);
3076 tmp.y = HIWORD(msg.lParam);
3077 if( !PtInRect( &rect, tmp ))
3089 /******************************************************************************
3090 * DragObject (USER.464)
3092 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3093 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3096 LPDRAGINFO16 lpDragInfo;
3098 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3099 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3100 HCURSOR16 hCurrentCursor = 0;
3101 HWND16 hCurrentWnd = 0;
3103 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3104 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3106 if( !lpDragInfo || !spDragInfo ) return 0L;
3108 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3110 GlobalFree16(hDragInfo);
3116 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3118 GlobalFree16(hDragInfo);
3122 if( hDragCursor == hCursor ) hDragCursor = 0;
3123 else hCursor = hDragCursor;
3125 hOldCursor = SetCursor(hDragCursor);
3128 lpDragInfo->hWnd = hWnd;
3129 lpDragInfo->hScope = 0;
3130 lpDragInfo->wFlags = wObj;
3131 lpDragInfo->hList = szList; /* near pointer! */
3132 lpDragInfo->hOfStruct = hOfStruct;
3140 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3142 *(lpDragInfo+1) = *lpDragInfo;
3144 lpDragInfo->pt.x = msg.pt.x;
3145 lpDragInfo->pt.y = msg.pt.y;
3147 /* update DRAGINFO struct */
3148 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3150 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3151 hCurrentCursor = hCursor;
3154 hCurrentCursor = hBummer;
3155 lpDragInfo->hScope = 0;
3157 if( hCurrentCursor )
3158 SetCursor(hCurrentCursor);
3160 /* send WM_DRAGLOOP */
3161 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3162 (LPARAM) spDragInfo );
3163 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3164 if( hCurrentWnd != lpDragInfo->hScope )
3167 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3168 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3169 HIWORD(spDragInfo)) );
3170 hCurrentWnd = lpDragInfo->hScope;
3172 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3176 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3178 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3181 ShowCursor( FALSE );
3185 SetCursor( hOldCursor );
3186 if (hDragCursor) DestroyCursor( hDragCursor );
3189 if( hCurrentCursor != hBummer )
3190 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3191 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3194 GlobalFree16(hDragInfo);
3196 return (DWORD)(msg.lParam);
3200 /******************************************************************************
3201 * GetWindowModuleFileNameA (USER32.@)
3203 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3205 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3206 hwnd, lpszFileName, cchFileNameMax);
3210 /******************************************************************************
3211 * GetWindowModuleFileNameW (USER32.@)
3213 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3215 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3216 hwnd, lpszFileName, cchFileNameMax);