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 * Get the full 32-bit window handle from a possibly truncated handle.
154 HWND WIN_GetFullHandle( HWND hwnd )
158 SERVER_START_REQ( get_window_info )
161 if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
169 /***********************************************************************
172 * Return a pointer to the WND structure corresponding to a HWND.
174 WND * WIN_FindWndPtr( HWND hwnd )
178 if (!hwnd) return NULL;
181 if (!(ptr = user_handles[LOWORD(hwnd)]))
183 /* check other processes */
184 if (IsWindow( hwnd ))
186 ERR( "window %04x belongs to other process\n", hwnd );
187 /* DbgBreakPoint(); */
191 if (ptr->dwMagic != WND_MAGIC) goto error;
192 /* verify that handle highword (if any) matches the window */
193 if (HIWORD(hwnd) && hwnd != ptr->hwndSelf) goto error;
194 /*and increment destruction monitoring*/
199 /* Unlock all WND structures for thread safeness*/
201 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
206 /***********************************************************************
209 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
211 * Returns the locked initialisation pointer
213 WND *WIN_LockWndPtr(WND *initWndPtr)
215 if(!initWndPtr) return 0;
217 /* Lock all WND structures for thread safeness*/
219 /*and increment destruction monitoring*/
220 initWndPtr->irefCount++;
226 /***********************************************************************
229 * Release the pointer to the WND structure.
231 void WIN_ReleaseWndPtr(WND *wndPtr)
235 /*Decrement destruction monitoring value*/
237 /* Check if it's time to release the memory*/
238 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
241 free_window_handle( wndPtr->hwndSelf );
243 else if(wndPtr->irefCount < 0)
245 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
246 ERR("forgot a Lock on %p somewhere\n",wndPtr);
248 /*unlock all WND structures for thread safeness*/
252 /***********************************************************************
255 * Updates the value of oldPtr to newPtr.
257 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
261 tmpWnd = WIN_LockWndPtr(newPtr);
262 WIN_ReleaseWndPtr(*oldPtr);
268 /***********************************************************************
271 * Remove a window from the siblings linked list.
273 void WIN_UnlinkWindow( HWND hwnd )
275 WIN_LinkWindow( hwnd, 0, 0 );
279 /***********************************************************************
282 * Insert a window into the siblings linked list.
283 * The window is inserted after the specified window, which can also
284 * be specified as HWND_TOP or HWND_BOTTOM.
285 * If parent is 0, window is unlinked from the tree.
287 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
289 WND *wndPtr, **ppWnd, *parentPtr = NULL;
292 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
293 if (parent && !(parentPtr = WIN_FindWndPtr( parent )))
295 WIN_ReleaseWndPtr(wndPtr);
299 SERVER_START_REQ( link_window )
302 req->parent = parent;
303 req->previous = hwndInsertAfter;
304 ret = !SERVER_CALL_ERR();
309 /* first unlink it if it is linked */
312 ppWnd = &wndPtr->parent->child;
313 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
314 if (*ppWnd) *ppWnd = wndPtr->next;
319 wndPtr->parent = parentPtr;
320 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
322 ppWnd = &parentPtr->child; /* Point to first sibling hwnd */
323 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
324 while (*ppWnd) ppWnd = &(*ppWnd)->next;
326 else /* Normal case */
328 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
329 if (!afterPtr) goto done;
330 ppWnd = &afterPtr->next;
331 WIN_ReleaseWndPtr(afterPtr);
333 wndPtr->next = *ppWnd;
336 else wndPtr->next = NULL; /* unlinked */
339 WIN_ReleaseWndPtr( parentPtr );
340 WIN_ReleaseWndPtr( wndPtr );
344 /***********************************************************************
345 * WIN_FindWinToRepaint
347 * Find a window that needs repaint.
349 HWND WIN_FindWinToRepaint( HWND hwnd )
354 /* Note: the desktop window never gets WM_PAINT messages
355 * The real reason why is because Windows DesktopWndProc
356 * does ValidateRgn inside WM_ERASEBKGND handler.
358 if (hwnd == GetDesktopWindow()) hwnd = 0;
360 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
362 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
364 if (!(pWnd->dwStyle & WS_VISIBLE)) continue;
365 if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
366 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
370 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
372 WIN_ReleaseWndPtr(pWnd);
380 TRACE("nothing found\n");
383 hwndRet = pWnd->hwndSelf;
385 /* look among siblings if we got a transparent window */
388 if (!(pWnd->dwExStyle & WS_EX_TRANSPARENT) &&
389 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
390 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
392 hwndRet = pWnd->hwndSelf;
393 WIN_ReleaseWndPtr(pWnd);
396 WIN_UpdateWndPtr(&pWnd,pWnd->next);
398 TRACE("found %04x\n",hwndRet);
403 /***********************************************************************
406 * Destroy storage associated to a window. "Internals" p.358
407 * returns a locked wndPtr->next
409 static WND* WIN_DestroyWindow( WND* wndPtr )
411 HWND hwnd = wndPtr->hwndSelf;
414 TRACE("%04x\n", wndPtr->hwndSelf );
416 /* free child windows */
417 WIN_LockWndPtr(wndPtr->child);
418 while ((pWnd = wndPtr->child))
420 wndPtr->child = WIN_DestroyWindow( pWnd );
421 WIN_ReleaseWndPtr(pWnd);
425 * Clear the update region to make sure no WM_PAINT messages will be
426 * generated for this window while processing the WM_NCDESTROY.
428 RedrawWindow( wndPtr->hwndSelf, NULL, 0,
429 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
432 * Send the WM_NCDESTROY to the window being destroyed.
434 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
436 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
438 WINPOS_CheckInternalPos( hwnd );
439 if( hwnd == GetCapture()) ReleaseCapture();
441 /* free resources associated with the window */
443 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
444 PROPERTY_RemoveWindowProps( wndPtr );
446 /* toss stale messages from the queue */
448 QUEUE_CleanupWindow( hwnd );
449 wndPtr->hmemTaskQ = 0;
451 if (!(wndPtr->dwStyle & WS_CHILD))
454 DestroyMenu( wndPtr->wIDmenu );
457 if (wndPtr->hSysMenu)
459 DestroyMenu( wndPtr->hSysMenu );
460 wndPtr->hSysMenu = 0;
462 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
463 DCE_FreeWindowDCE( wndPtr->hwndSelf ); /* Always do this to catch orphaned DCs */
464 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
465 CLASS_RemoveWindow( wndPtr->class );
466 wndPtr->class = NULL;
467 wndPtr->dwMagic = 0; /* Mark it as invalid */
469 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
474 /***********************************************************************
475 * WIN_DestroyThreadWindows
477 * Destroy all children of 'wnd' owned by the current thread.
478 * Return TRUE if something was done.
480 void WIN_DestroyThreadWindows( HWND hwnd )
485 if (!(list = WIN_ListChildren( hwnd ))) return;
486 for (i = 0; list[i]; i++)
488 if (!IsWindow( list[i] )) continue;
489 if (GetWindowThreadProcessId( list[i], NULL ) == GetCurrentThreadId())
490 DestroyWindow( list[i] );
492 WIN_DestroyThreadWindows( list[i] );
494 HeapFree( GetProcessHeap(), 0, list );
497 /***********************************************************************
498 * WIN_CreateDesktopWindow
500 * Create the desktop window.
502 BOOL WIN_CreateDesktopWindow(void)
504 struct tagCLASS *class;
512 TRACE("Creating desktop window\n");
515 if (!WINPOS_CreateInternalPosAtom() ||
516 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
517 &wndExtra, &winproc, &clsStyle, &dce )))
520 pWndDesktop = create_window_handle( TRUE, sizeof(WND) + wndExtra );
521 if (!pWndDesktop) return FALSE;
522 hwndDesktop = pWndDesktop->hwndSelf;
524 pWndDesktop->tid = 0; /* nobody owns the desktop */
525 pWndDesktop->next = NULL;
526 pWndDesktop->child = NULL;
527 pWndDesktop->parent = NULL;
528 pWndDesktop->owner = 0;
529 pWndDesktop->class = class;
530 pWndDesktop->hInstance = 0;
531 pWndDesktop->rectWindow.left = 0;
532 pWndDesktop->rectWindow.top = 0;
533 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
534 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
535 pWndDesktop->rectClient = pWndDesktop->rectWindow;
536 pWndDesktop->text = NULL;
537 pWndDesktop->hmemTaskQ = 0;
538 pWndDesktop->hrgnUpdate = 0;
539 pWndDesktop->hwndLastActive = hwndDesktop;
540 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
542 pWndDesktop->dwExStyle = 0;
543 pWndDesktop->clsStyle = clsStyle;
544 pWndDesktop->dce = NULL;
545 pWndDesktop->pVScroll = NULL;
546 pWndDesktop->pHScroll = NULL;
547 pWndDesktop->pProp = NULL;
548 pWndDesktop->wIDmenu = 0;
549 pWndDesktop->helpContext = 0;
550 pWndDesktop->flags = 0;
551 pWndDesktop->hSysMenu = 0;
552 pWndDesktop->userdata = 0;
553 pWndDesktop->winproc = winproc;
554 pWndDesktop->cbWndExtra = wndExtra;
556 cs.lpCreateParams = NULL;
562 cs.cx = pWndDesktop->rectWindow.right;
563 cs.cy = pWndDesktop->rectWindow.bottom;
564 cs.style = pWndDesktop->dwStyle;
565 cs.dwExStyle = pWndDesktop->dwExStyle;
567 cs.lpszClass = DESKTOP_CLASS_ATOM;
569 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
571 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
572 WIN_ReleaseWndPtr( pWndDesktop );
577 /***********************************************************************
580 * Fix the coordinates - Helper for WIN_CreateWindowEx.
581 * returns default show mode in sw.
582 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
584 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
586 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
587 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
589 if (cs->style & (WS_CHILD | WS_POPUP))
591 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
592 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
594 else /* overlapped window */
598 GetStartupInfoA( &info );
600 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
602 /* Never believe Microsoft's documentation... CreateWindowEx doc says
603 * that if an overlapped window is created with WS_VISIBLE style bit
604 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
605 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
608 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
609 * 2) it does not ignore the y parameter as the docs claim; instead, it
610 * uses it as second parameter to ShowWindow() unless y is either
611 * CW_USEDEFAULT or CW_USEDEFAULT16.
613 * The fact that we didn't do 2) caused bogus windows pop up when wine
614 * was running apps that were using this obscure feature. Example -
615 * calc.exe that comes with Win98 (only Win98, it's different from
616 * the one that comes with Win95 and NT)
618 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
619 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
620 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
623 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
625 if (info.dwFlags & STARTF_USESIZE)
627 cs->cx = info.dwXSize;
628 cs->cy = info.dwYSize;
630 else /* if no other hint from the app, pick 3/4 of the screen real estate */
633 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
634 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
635 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
642 /***********************************************************************
645 * Implementation of CreateWindowEx().
647 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
648 WINDOWPROCTYPE type )
651 struct tagCLASS *classPtr;
653 HWND hwnd, hwndLinkAfter;
654 POINT maxSize, maxPos, minTrack, maxTrack;
659 BOOL unicode = (type == WIN_PROC_32W);
661 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
662 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
663 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
664 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
665 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
667 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
668 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
670 /* Find the parent window */
674 /* Make sure parent is valid */
675 if (!IsWindow( cs->hwndParent ))
677 WARN("Bad parent %04x\n", cs->hwndParent );
680 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
681 WARN("No parent for child window\n" );
682 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
685 /* Find the window class */
686 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
687 &wndExtra, &winproc, &clsStyle, &dce )))
689 WARN("Bad class '%s'\n", cs->lpszClass );
693 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
695 /* Correct the window style - stage 1
697 * These are patches that appear to affect both the style loaded into the
698 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
700 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
701 * why does the user get to set it?
704 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
705 * tested for WS_POPUP
707 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
708 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
709 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
710 cs->dwExStyle |= WS_EX_WINDOWEDGE;
712 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
714 /* Create the window structure */
716 if (!(wndPtr = create_window_handle( FALSE,
717 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
719 TRACE("out of memory\n" );
722 hwnd = wndPtr->hwndSelf;
724 /* Fill the window structure */
726 wndPtr->tid = GetCurrentThreadId();
728 wndPtr->child = NULL;
730 if ((cs->style & WS_CHILD) && cs->hwndParent)
732 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
734 WIN_ReleaseWndPtr(wndPtr->parent);
738 wndPtr->parent = pWndDesktop;
739 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
742 wndPtr->owner = GetAncestor( cs->hwndParent, GA_ROOT );
746 wndPtr->class = classPtr;
747 wndPtr->winproc = winproc;
748 wndPtr->hInstance = cs->hInstance;
750 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
751 wndPtr->hrgnUpdate = 0;
753 wndPtr->hwndLastActive = hwnd;
754 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
755 wndPtr->dwExStyle = cs->dwExStyle;
756 wndPtr->clsStyle = clsStyle;
758 wndPtr->helpContext = 0;
759 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
760 wndPtr->pVScroll = NULL;
761 wndPtr->pHScroll = NULL;
762 wndPtr->pProp = NULL;
763 wndPtr->userdata = 0;
764 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
765 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
766 wndPtr->cbWndExtra = wndExtra;
768 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
770 /* Call the WH_CBT hook */
772 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
773 ? HWND_BOTTOM : HWND_TOP;
775 if (HOOK_IsHooked( WH_CBT ))
781 cbtc.hwndInsertAfter = hwndLinkAfter;
782 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
783 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
786 TRACE("CBT-hook returned 0\n");
787 free_window_handle( hwnd );
788 CLASS_RemoveWindow( classPtr );
794 /* Correct the window style - stage 2 */
796 if (!(cs->style & WS_CHILD))
798 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
799 if (!(cs->style & WS_POPUP))
801 wndPtr->dwStyle |= WS_CAPTION;
802 wndPtr->flags |= WIN_NEED_SIZE;
806 /* Get class or window DC if needed */
808 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
809 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
810 else wndPtr->dce = NULL;
812 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
814 wndPtr->rectWindow.left = cs->x;
815 wndPtr->rectWindow.top = cs->y;
816 wndPtr->rectWindow.right = cs->x + cs->cx;
817 wndPtr->rectWindow.bottom = cs->y + cs->cy;
818 wndPtr->rectClient = wndPtr->rectWindow;
820 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
822 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
824 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
825 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
826 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
827 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
828 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
831 if (cs->cx < 0) cs->cx = 0;
832 if (cs->cy < 0) cs->cy = 0;
834 wndPtr->rectWindow.left = cs->x;
835 wndPtr->rectWindow.top = cs->y;
836 wndPtr->rectWindow.right = cs->x + cs->cx;
837 wndPtr->rectWindow.bottom = cs->y + cs->cy;
838 wndPtr->rectClient = wndPtr->rectWindow;
840 /* Set the window menu */
842 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
844 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
847 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
850 if (HIWORD(cs->hInstance))
851 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
853 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
855 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
859 else wndPtr->wIDmenu = (UINT)cs->hMenu;
861 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
863 WARN("aborted by WM_xxCREATE!\n");
864 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
865 CLASS_RemoveWindow( classPtr );
866 WIN_ReleaseWndPtr(wndPtr);
870 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
872 /* Notify the parent window only */
874 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
875 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
876 if( !IsWindow(hwnd) )
883 if (cs->style & WS_VISIBLE)
885 /* in case WS_VISIBLE got set in the meantime */
886 wndPtr->dwStyle &= ~WS_VISIBLE;
887 ShowWindow( hwnd, sw );
890 /* Call WH_SHELL hook */
892 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
893 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
895 TRACE("created window %04x\n", hwnd);
897 WIN_ReleaseWndPtr(wndPtr);
902 /***********************************************************************
903 * CreateWindow (USER.41)
905 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
906 DWORD style, INT16 x, INT16 y, INT16 width,
907 INT16 height, HWND16 parent, HMENU16 menu,
908 HINSTANCE16 instance, LPVOID data )
910 return CreateWindowEx16( 0, className, windowName, style,
911 x, y, width, height, parent, menu, instance, data );
915 /***********************************************************************
916 * CreateWindowEx (USER.452)
918 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
919 LPCSTR windowName, DWORD style, INT16 x,
920 INT16 y, INT16 width, INT16 height,
921 HWND16 parent, HMENU16 menu,
922 HINSTANCE16 instance, LPVOID data )
928 /* Find the class atom */
930 if (HIWORD(className))
932 if (!(classAtom = GlobalFindAtomA( className )))
934 ERR( "bad class name %s\n", debugres_a(className) );
940 classAtom = LOWORD(className);
941 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
943 ERR( "bad atom %x\n", classAtom);
949 /* Fix the coordinates */
951 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
952 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
953 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
954 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
956 /* Create the window */
958 cs.lpCreateParams = data;
959 cs.hInstance = (HINSTANCE)instance;
960 cs.hMenu = (HMENU)menu;
961 cs.hwndParent = (HWND)parent;
963 cs.lpszName = windowName;
964 cs.lpszClass = className;
965 cs.dwExStyle = exStyle;
967 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
971 /***********************************************************************
972 * CreateWindowExA (USER32.@)
974 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
975 LPCSTR windowName, DWORD style, INT x,
976 INT y, INT width, INT height,
977 HWND parent, HMENU menu,
978 HINSTANCE instance, LPVOID data )
985 instance=GetModuleHandleA(NULL);
987 if(exStyle & WS_EX_MDICHILD)
988 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
990 /* Find the class atom */
992 if (HIWORD(className))
994 if (!(classAtom = GlobalFindAtomA( className )))
996 ERR( "bad class name %s\n", debugres_a(className) );
1002 classAtom = LOWORD(className);
1003 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1005 ERR( "bad atom %x\n", classAtom);
1011 /* Create the window */
1013 cs.lpCreateParams = data;
1014 cs.hInstance = instance;
1016 cs.hwndParent = parent;
1022 cs.lpszName = windowName;
1023 cs.lpszClass = className;
1024 cs.dwExStyle = exStyle;
1026 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1030 /***********************************************************************
1031 * CreateWindowExW (USER32.@)
1033 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1034 LPCWSTR windowName, DWORD style, INT x,
1035 INT y, INT width, INT height,
1036 HWND parent, HMENU menu,
1037 HINSTANCE instance, LPVOID data )
1044 instance=GetModuleHandleA(NULL);
1046 if(exStyle & WS_EX_MDICHILD)
1047 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1049 /* Find the class atom */
1051 if (HIWORD(className))
1053 if (!(classAtom = GlobalFindAtomW( className )))
1055 ERR( "bad class name %s\n", debugres_w(className) );
1061 classAtom = LOWORD(className);
1062 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1064 ERR( "bad atom %x\n", classAtom);
1070 /* Create the window */
1072 cs.lpCreateParams = data;
1073 cs.hInstance = instance;
1075 cs.hwndParent = parent;
1081 cs.lpszName = windowName;
1082 cs.lpszClass = className;
1083 cs.dwExStyle = exStyle;
1085 /* Note: we rely on the fact that CREATESTRUCTA and */
1086 /* CREATESTRUCTW have the same layout. */
1087 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1091 /***********************************************************************
1092 * WIN_SendDestroyMsg
1094 static void WIN_SendDestroyMsg( HWND hwnd )
1096 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1097 if (USER_Driver.pResetSelectionOwner)
1098 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1101 * Send the WM_DESTROY to the window.
1103 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1106 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1107 * make sure that the window still exists when we come back.
1114 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1116 /* start from the end (FIXME: is this needed?) */
1117 for (i = 0; pWndArray[i]; i++) ;
1121 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1123 HeapFree( GetProcessHeap(), 0, pWndArray );
1126 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1130 /***********************************************************************
1131 * DestroyWindow (USER.53)
1133 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1135 return DestroyWindow(hwnd);
1139 /***********************************************************************
1140 * DestroyWindow (USER32.@)
1142 BOOL WINAPI DestroyWindow( HWND hwnd )
1148 TRACE("(%04x)\n", hwnd);
1150 /* Initialization */
1152 if (hwnd == GetDesktopWindow()) return FALSE; /* Can't destroy desktop */
1154 /* Look whether the focus is within the tree of windows we will
1158 if (h == hwnd || IsChild( hwnd, h ))
1160 HWND parent = GetAncestor( hwnd, GA_PARENT );
1161 if (parent == GetDesktopWindow()) parent = 0;
1167 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) ) return FALSE;
1169 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1170 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1172 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1173 /* FIXME: clean up palette - see "Internals" p.352 */
1176 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1177 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1179 /* Notify the parent window only */
1180 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1181 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1182 if( !IsWindow(hwnd) )
1189 if (USER_Driver.pResetSelectionOwner)
1190 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1192 /* Hide the window */
1194 if (wndPtr->dwStyle & WS_VISIBLE)
1196 ShowWindow( hwnd, SW_HIDE );
1197 if (!IsWindow(hwnd))
1204 /* Recursively destroy owned windows */
1206 if( !(wndPtr->dwStyle & WS_CHILD) )
1211 HWND *list = WIN_ListChildren( wndPtr->parent->hwndSelf );
1214 for (i = 0; list[i]; i++)
1216 WND *siblingPtr = WIN_FindWndPtr( list[i] );
1217 if (!siblingPtr) continue;
1218 if (siblingPtr->owner == hwnd)
1220 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1222 WIN_ReleaseWndPtr( siblingPtr );
1223 DestroyWindow( list[i] );
1227 else siblingPtr->owner = 0;
1229 WIN_ReleaseWndPtr( siblingPtr );
1231 HeapFree( GetProcessHeap(), 0, list );
1233 if (!got_one) break;
1236 WINPOS_ActivateOtherWindow(wndPtr->hwndSelf);
1240 WND *owner = WIN_FindWndPtr( wndPtr->owner );
1241 if (owner->hwndLastActive == hwnd) owner->hwndLastActive = wndPtr->owner;
1242 WIN_ReleaseWndPtr( owner );
1246 /* Send destroy messages */
1248 WIN_SendDestroyMsg( hwnd );
1249 if (!IsWindow(hwnd))
1255 /* Unlink now so we won't bother with the children later on */
1257 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1259 /* Destroy the window storage */
1261 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1264 WIN_ReleaseWndPtr(wndPtr);
1269 /***********************************************************************
1270 * CloseWindow (USER.43)
1272 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1274 return CloseWindow( hwnd );
1278 /***********************************************************************
1279 * CloseWindow (USER32.@)
1281 BOOL WINAPI CloseWindow( HWND hwnd )
1283 WND * wndPtr = WIN_FindWndPtr( hwnd );
1286 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1291 ShowWindow( hwnd, SW_MINIMIZE );
1294 WIN_ReleaseWndPtr(wndPtr);
1300 /***********************************************************************
1301 * OpenIcon (USER.44)
1303 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1305 return OpenIcon( hwnd );
1309 /***********************************************************************
1310 * OpenIcon (USER32.@)
1312 BOOL WINAPI OpenIcon( HWND hwnd )
1314 if (!IsIconic( hwnd )) return FALSE;
1315 ShowWindow( hwnd, SW_SHOWNORMAL );
1320 /***********************************************************************
1323 * Implementation of FindWindow() and FindWindowEx().
1325 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1330 WCHAR *buffer = NULL;
1332 if (!parent) parent = GetDesktopWindow();
1335 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1336 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1339 if (!(list = WIN_ListChildren( parent )))
1341 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1347 while (list[i] && list[i] != child) i++;
1348 if (!list[i]) return 0;
1349 i++; /* start from next window */
1352 for ( ; list[i]; i++)
1354 if (className && (GetClassWord(list[i], GCW_ATOM) != className))
1355 continue; /* Not the right class */
1357 /* Now check the title */
1359 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1362 HeapFree( GetProcessHeap(), 0, list );
1363 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1365 /* In this case we need to check whether other processes
1366 own a window with the given paramters on the Desktop,
1367 but we don't, so let's at least warn about it */
1368 if (!retvalue) FIXME("Returning 0 without checking other processes\n");
1374 /***********************************************************************
1375 * FindWindow (USER.50)
1377 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1379 return FindWindowA( className, title );
1383 /***********************************************************************
1384 * FindWindowEx (USER.427)
1386 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1388 return FindWindowExA( parent, child, className, title );
1392 /***********************************************************************
1393 * FindWindowA (USER32.@)
1395 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1397 HWND ret = FindWindowExA( 0, 0, className, title );
1398 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1403 /***********************************************************************
1404 * FindWindowExA (USER32.@)
1406 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1407 LPCSTR className, LPCSTR title )
1415 /* If the atom doesn't exist, then no class */
1416 /* with this name exists either. */
1417 if (!(atom = GlobalFindAtomA( className )))
1419 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1424 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1425 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1426 HeapFree( GetProcessHeap(), 0, buffer );
1431 /***********************************************************************
1432 * FindWindowExW (USER32.@)
1434 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1435 LPCWSTR className, LPCWSTR title )
1441 /* If the atom doesn't exist, then no class */
1442 /* with this name exists either. */
1443 if (!(atom = GlobalFindAtomW( className )))
1445 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1449 return WIN_FindWindow( parent, child, atom, title );
1453 /***********************************************************************
1454 * FindWindowW (USER32.@)
1456 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1458 return FindWindowExW( 0, 0, className, title );
1462 /**********************************************************************
1463 * GetDesktopWindow (USER.286)
1465 HWND16 WINAPI GetDesktopWindow16(void)
1467 return (HWND16)pWndDesktop->hwndSelf;
1471 /**********************************************************************
1472 * GetDesktopWindow (USER32.@)
1474 HWND WINAPI GetDesktopWindow(void)
1476 if (pWndDesktop) return pWndDesktop->hwndSelf;
1477 ERR( "You need the -desktop option when running with native USER\n" );
1483 /**********************************************************************
1484 * GetDesktopHwnd (USER.278)
1486 * Exactly the same thing as GetDesktopWindow(), but not documented.
1487 * Don't ask me why...
1489 HWND16 WINAPI GetDesktopHwnd16(void)
1491 return (HWND16)pWndDesktop->hwndSelf;
1495 /*******************************************************************
1496 * EnableWindow (USER.34)
1498 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1500 return EnableWindow( hwnd, enable );
1504 /*******************************************************************
1505 * EnableWindow (USER32.@)
1507 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1512 TRACE("( %x, %d )\n", hwnd, enable);
1514 if (USER_Driver.pEnableWindow)
1515 return USER_Driver.pEnableWindow( hwnd, enable );
1517 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1519 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1521 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1523 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1524 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1526 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1528 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1530 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1532 if (hwnd == GetFocus())
1533 SetFocus( 0 ); /* A disabled window can't have the focus */
1535 if (hwnd == GetCapture())
1536 ReleaseCapture(); /* A disabled window can't capture the mouse */
1538 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1540 WIN_ReleaseWndPtr(wndPtr);
1545 /***********************************************************************
1546 * IsWindowEnabled (USER.35)
1548 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1550 return IsWindowEnabled(hWnd);
1554 /***********************************************************************
1555 * IsWindowEnabled (USER32.@)
1557 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1562 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1563 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1564 WIN_ReleaseWndPtr(wndPtr);
1570 /***********************************************************************
1571 * IsWindowUnicode (USER32.@)
1573 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1578 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1579 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1580 WIN_ReleaseWndPtr(wndPtr);
1585 /**********************************************************************
1586 * GetWindowWord (USER.133)
1588 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1590 return GetWindowWord( hwnd, offset );
1594 /**********************************************************************
1595 * GetWindowWord (USER32.@)
1597 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1600 WND * wndPtr = WIN_FindWndPtr( hwnd );
1601 if (!wndPtr) return 0;
1604 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1606 WARN("Invalid offset %d\n", offset );
1610 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1616 if (HIWORD(wndPtr->wIDmenu))
1617 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1619 retvalue = (WORD)wndPtr->wIDmenu;
1621 case GWW_HWNDPARENT:
1622 retvalue = GetParent(hwnd);
1625 if (HIWORD(wndPtr->hInstance))
1626 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1628 retvalue = (WORD)wndPtr->hInstance;
1631 WARN("Invalid offset %d\n", offset );
1636 WIN_ReleaseWndPtr(wndPtr);
1640 /**********************************************************************
1641 * SetWindowWord (USER.134)
1643 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1645 return SetWindowWord( hwnd, offset, newval );
1649 /**********************************************************************
1650 * SetWindowWord (USER32.@)
1652 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1655 WND * wndPtr = WIN_FindWndPtr( hwnd );
1656 if (!wndPtr) return 0;
1659 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1661 WARN("Invalid offset %d\n", offset );
1665 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1669 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1670 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1671 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1674 WARN("Invalid offset %d\n", offset );
1681 WIN_ReleaseWndPtr(wndPtr);
1686 /**********************************************************************
1689 * Helper function for GetWindowLong().
1691 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1694 WND * wndPtr = WIN_FindWndPtr( hwnd );
1695 if (!wndPtr) return 0;
1698 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1700 WARN("Invalid offset %d\n", offset );
1704 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1705 /* Special case for dialog window procedure */
1706 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1708 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1715 case GWL_USERDATA: retvalue = wndPtr->userdata;
1717 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1719 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1721 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1723 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1726 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1728 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1731 WARN("Unknown offset %d\n", offset );
1735 WIN_ReleaseWndPtr(wndPtr);
1740 /**********************************************************************
1743 * Helper function for SetWindowLong().
1745 * 0 is the failure code. However, in the case of failure SetLastError
1746 * must be set to distinguish between a 0 return value and a failure.
1748 * FIXME: The error values for SetLastError may not be right. Can
1749 * someone check with the real thing?
1751 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1752 WINDOWPROCTYPE type )
1755 WND * wndPtr = WIN_FindWndPtr( hwnd );
1758 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1762 /* Is this the right error? */
1763 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1769 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1771 WARN("Invalid offset %d\n", offset );
1773 /* Is this the right error? */
1774 SetLastError( ERROR_OUTOFMEMORY );
1779 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1780 /* Special case for dialog window procedure */
1781 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1783 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1784 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1785 type, WIN_PROC_WINDOW );
1792 ptr = (DWORD*)&wndPtr->wIDmenu;
1795 retval = SetWindowWord( hwnd, offset, newval );
1798 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1799 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1800 type, WIN_PROC_WINDOW );
1803 style.styleOld = wndPtr->dwStyle;
1804 style.styleNew = newval;
1805 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1806 wndPtr->dwStyle = style.styleNew;
1807 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1808 retval = style.styleOld;
1812 ptr = &wndPtr->userdata;
1815 style.styleOld = wndPtr->dwExStyle;
1816 style.styleNew = newval;
1817 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1818 wndPtr->dwExStyle = style.styleNew;
1819 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1820 retval = style.styleOld;
1824 WARN("Invalid offset %d\n", offset );
1826 /* Don't think this is right error but it should do */
1827 SetLastError( ERROR_OUTOFMEMORY );
1835 WIN_ReleaseWndPtr(wndPtr);
1840 /**********************************************************************
1841 * GetWindowLong (USER.135)
1843 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1845 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1849 /**********************************************************************
1850 * GetWindowLongA (USER32.@)
1852 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1854 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1858 /**********************************************************************
1859 * GetWindowLongW (USER32.@)
1861 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1863 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1867 /**********************************************************************
1868 * SetWindowLong (USER.136)
1870 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1872 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1876 /**********************************************************************
1877 * SetWindowLongA (USER32.@)
1879 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1881 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1885 /**********************************************************************
1886 * SetWindowLongW (USER32.@) Set window attribute
1888 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1889 * value in a window's extra memory.
1891 * The _hwnd_ parameter specifies the window. is the handle to a
1892 * window that has extra memory. The _newval_ parameter contains the
1893 * new attribute or extra memory value. If positive, the _offset_
1894 * parameter is the byte-addressed location in the window's extra
1895 * memory to set. If negative, _offset_ specifies the window
1896 * attribute to set, and should be one of the following values:
1898 * GWL_EXSTYLE The window's extended window style
1900 * GWL_STYLE The window's window style.
1902 * GWL_WNDPROC Pointer to the window's window procedure.
1904 * GWL_HINSTANCE The window's pplication instance handle.
1906 * GWL_ID The window's identifier.
1908 * GWL_USERDATA The window's user-specified data.
1910 * If the window is a dialog box, the _offset_ parameter can be one of
1911 * the following values:
1913 * DWL_DLGPROC The address of the window's dialog box procedure.
1915 * DWL_MSGRESULT The return value of a message
1916 * that the dialog box procedure processed.
1918 * DWL_USER Application specific information.
1922 * If successful, returns the previous value located at _offset_. Otherwise,
1927 * Extra memory for a window class is specified by a nonzero cbWndExtra
1928 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1929 * time of class creation.
1931 * Using GWL_WNDPROC to set a new window procedure effectively creates
1932 * a window subclass. Use CallWindowProc() in the new windows procedure
1933 * to pass messages to the superclass's window procedure.
1935 * The user data is reserved for use by the application which created
1938 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1939 * instead, call the EnableWindow() function to change the window's
1942 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1943 * SetParent() instead.
1946 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1947 * it sends WM_STYLECHANGING before changing the settings
1948 * and WM_STYLECHANGED afterwards.
1949 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1953 * GWL_STYLE does not dispatch WM_STYLE... messages.
1960 LONG WINAPI SetWindowLongW(
1961 HWND hwnd, /* [in] window to alter */
1962 INT offset, /* [in] offset, in bytes, of location to alter */
1963 LONG newval /* [in] new value of location */
1965 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1969 /*******************************************************************
1970 * GetWindowText (USER.36)
1972 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1974 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1978 /*******************************************************************
1979 * GetWindowTextA (USER32.@)
1981 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
1983 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
1987 /*******************************************************************
1988 * InternalGetWindowText (USER32.@)
1990 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
1992 WND *win = WIN_FindWndPtr( hwnd );
1994 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
1995 else lpString[0] = 0;
1996 WIN_ReleaseWndPtr( win );
1997 return strlenW(lpString);
2001 /*******************************************************************
2002 * GetWindowTextW (USER32.@)
2004 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2006 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2011 /*******************************************************************
2012 * SetWindowText (USER.37)
2014 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2016 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2020 /*******************************************************************
2021 * SetWindowText (USER32.@)
2022 * SetWindowTextA (USER32.@)
2024 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2026 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2030 /*******************************************************************
2031 * SetWindowTextW (USER32.@)
2033 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2035 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2039 /*******************************************************************
2040 * GetWindowTextLength (USER.38)
2042 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2044 return (INT16)GetWindowTextLengthA( hwnd );
2048 /*******************************************************************
2049 * GetWindowTextLengthA (USER32.@)
2051 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2053 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2056 /*******************************************************************
2057 * GetWindowTextLengthW (USER32.@)
2059 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2061 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2065 /*******************************************************************
2066 * IsWindow (USER.47)
2068 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2070 CURRENT_STACK16->es = USER_HeapSel;
2071 return IsWindow( hwnd );
2075 /*******************************************************************
2076 * IsWindow (USER32.@)
2078 BOOL WINAPI IsWindow( HWND hwnd )
2084 if ((ptr = user_handles[LOWORD(hwnd)]))
2086 ret = ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf));
2090 if (!ret) /* check other processes */
2092 SERVER_START_REQ( get_window_info )
2095 ret = !SERVER_CALL_ERR();
2103 /***********************************************************************
2104 * GetWindowThreadProcessId (USER32.@)
2106 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2112 if ((ptr = user_handles[LOWORD(hwnd)]))
2114 if ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
2116 /* got a valid window */
2118 if (process) *process = GetCurrentProcessId();
2120 else SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2126 /* check other processes */
2127 SERVER_START_REQ( get_window_info )
2130 if (!SERVER_CALL_ERR())
2132 tid = (DWORD)req->tid;
2133 if (process) *process = (DWORD)req->pid;
2141 /*****************************************************************
2142 * GetParent (USER.46)
2144 HWND16 WINAPI GetParent16( HWND16 hwnd )
2146 return (HWND16)GetParent( hwnd );
2150 /*****************************************************************
2151 * GetParent (USER32.@)
2153 HWND WINAPI GetParent( HWND hwnd )
2158 if ((wndPtr = WIN_FindWndPtr(hwnd)))
2160 if (wndPtr->dwStyle & WS_CHILD)
2161 retvalue = wndPtr->parent->hwndSelf;
2162 else if (wndPtr->dwStyle & WS_POPUP)
2163 retvalue = wndPtr->owner;
2164 WIN_ReleaseWndPtr(wndPtr);
2170 /*****************************************************************
2171 * GetAncestor (USER32.@)
2173 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2178 if (hwnd == GetDesktopWindow()) return 0;
2179 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2184 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2187 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2188 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2191 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2192 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2193 while (wndPtr && wndPtr->owner)
2195 WND *ptr = WIN_FindWndPtr( wndPtr->owner );
2196 WIN_ReleaseWndPtr( wndPtr );
2201 ret = wndPtr ? wndPtr->hwndSelf : 0;
2202 WIN_ReleaseWndPtr( wndPtr );
2207 /*****************************************************************
2208 * SetParent (USER.233)
2210 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2212 return SetParent( hwndChild, hwndNewParent );
2216 /*****************************************************************
2217 * SetParent (USER32.@)
2219 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2225 if (!parent) parent = GetDesktopWindow();
2228 if (hwnd == GetDesktopWindow() || !IsWindow( parent ))
2230 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2234 if (USER_Driver.pSetParent)
2235 return USER_Driver.pSetParent( hwnd, parent );
2237 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2239 dwStyle = wndPtr->dwStyle;
2241 /* Windows hides the window first, then shows it again
2242 * including the WM_SHOWWINDOW messages and all */
2243 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2245 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2246 if (parent != retvalue)
2248 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2250 if (parent != GetDesktopWindow()) /* a child window */
2252 if (!(dwStyle & WS_CHILD))
2254 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2255 if (menu) DestroyMenu( menu );
2259 WIN_ReleaseWndPtr( wndPtr );
2261 /* SetParent additionally needs to make hwnd the topmost window
2262 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2263 WM_WINDOWPOSCHANGED notification messages.
2265 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2266 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2267 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2268 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2269 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2274 /*******************************************************************
2277 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2279 return IsChild(parent,child);
2283 /*******************************************************************
2284 * IsChild (USER32.@)
2286 BOOL WINAPI IsChild( HWND parent, HWND child )
2288 HWND *list = WIN_ListParents( child );
2292 if (!list) return FALSE;
2293 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2294 ret = (list[i] != 0);
2295 HeapFree( GetProcessHeap(), 0, list );
2300 /***********************************************************************
2301 * IsWindowVisible (USER.49)
2303 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2305 return IsWindowVisible(hwnd);
2309 /***********************************************************************
2310 * IsWindowVisible (USER32.@)
2312 BOOL WINAPI IsWindowVisible( HWND hwnd )
2318 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2319 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2320 for (i = 0; list[i]; i++)
2321 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2323 HeapFree( GetProcessHeap(), 0, list );
2328 /***********************************************************************
2329 * WIN_IsWindowDrawable
2331 * hwnd is drawable when it is visible, all parents are not
2332 * minimized, and it is itself not minimized unless we are
2333 * trying to draw its default class icon.
2335 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2341 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2342 if ((wnd->dwStyle & WS_MINIMIZE) &&
2343 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2345 if (!(list = WIN_ListParents( wnd->hwndSelf ))) return TRUE;
2346 for (i = 0; list[i]; i++)
2347 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2350 HeapFree( GetProcessHeap(), 0, list );
2355 /*******************************************************************
2356 * GetTopWindow (USER.229)
2358 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2360 return GetTopWindow(hwnd);
2364 /*******************************************************************
2365 * GetTopWindow (USER32.@)
2367 HWND WINAPI GetTopWindow( HWND hwnd )
2369 if (!hwnd) hwnd = GetDesktopWindow();
2370 return GetWindow( hwnd, GW_CHILD );
2374 /*******************************************************************
2375 * GetWindow (USER.262)
2377 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2379 return GetWindow( hwnd,rel );
2383 /*******************************************************************
2384 * GetWindow (USER32.@)
2386 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2390 WND * wndPtr = WIN_FindWndPtr( hwnd );
2391 if (!wndPtr) return 0;
2395 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2399 if (!wndPtr->parent)
2401 retval = 0; /* Desktop window */
2404 while (wndPtr->next)
2406 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2408 retval = wndPtr->hwndSelf;
2412 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2416 if (!wndPtr->parent)
2418 retval = 0; /* Desktop window */
2421 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2422 if (wndPtr->hwndSelf == hwnd)
2424 retval = 0; /* First in list */
2427 while (wndPtr->next)
2429 if (wndPtr->next->hwndSelf == hwnd)
2431 retval = wndPtr->hwndSelf;
2434 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2440 retval = wndPtr->owner;
2444 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2449 WIN_ReleaseWndPtr(wndPtr);
2454 /*******************************************************************
2455 * GetNextWindow (USER.230)
2457 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2459 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2460 return GetWindow16( hwnd, flag );
2463 /***********************************************************************
2464 * WIN_InternalShowOwnedPopups
2466 * Internal version of ShowOwnedPopups; Wine functions should use this
2467 * to avoid interfering with application calls to ShowOwnedPopups
2468 * and to make sure the application can't prevent showing/hiding.
2470 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2474 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2478 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2480 if (!win_array) return TRUE;
2483 * Show windows Lowest first, Highest last to preserve Z-Order
2485 while (win_array[count]) count++;
2486 while (--count >= 0)
2488 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2489 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2491 if (pWnd->dwStyle & WS_POPUP)
2495 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2496 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2499 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2501 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2502 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2507 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2508 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2509 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2512 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2514 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2515 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2516 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2520 WIN_ReleaseWndPtr( pWnd );
2522 HeapFree( GetProcessHeap(), 0, win_array );
2527 /*******************************************************************
2528 * ShowOwnedPopups (USER.265)
2530 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2532 ShowOwnedPopups( owner, fShow );
2536 /*******************************************************************
2537 * ShowOwnedPopups (USER32.@)
2539 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2543 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2545 if (!win_array) return TRUE;
2547 while (win_array[count]) count++;
2548 while (--count >= 0)
2550 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2551 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2553 if (pWnd->dwStyle & WS_POPUP)
2557 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2559 /* In Windows, ShowOwnedPopups(TRUE) generates
2560 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2561 * regardless of the state of the owner
2563 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2564 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2569 if (IsWindowVisible(pWnd->hwndSelf))
2571 /* In Windows, ShowOwnedPopups(FALSE) generates
2572 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2573 * regardless of the state of the owner
2575 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2576 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2580 WIN_ReleaseWndPtr( pWnd );
2582 HeapFree( GetProcessHeap(), 0, win_array );
2587 /*******************************************************************
2588 * GetLastActivePopup (USER.287)
2590 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2592 return GetLastActivePopup( hwnd );
2595 /*******************************************************************
2596 * GetLastActivePopup (USER32.@)
2598 HWND WINAPI GetLastActivePopup( HWND hwnd )
2601 WND *wndPtr =WIN_FindWndPtr(hwnd);
2602 if (!wndPtr) return hwnd;
2603 retval = wndPtr->hwndLastActive;
2604 WIN_ReleaseWndPtr(wndPtr);
2605 if ((retval != hwnd) && (!IsWindow(retval)))
2611 /*******************************************************************
2614 * Build an array of all parents of a given window, starting with
2615 * the immediate parent. The array must be freed with HeapFree.
2616 * Returns NULL if window is a top-level window.
2618 HWND *WIN_ListParents( HWND hwnd )
2620 WND *parent, *wndPtr = WIN_FindWndPtr( hwnd );
2624 /* First count the windows */
2626 if (!wndPtr) return NULL;
2628 parent = wndPtr->parent;
2629 while (parent && parent->hwndSelf != GetDesktopWindow())
2632 parent = parent->parent;
2637 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1) )))
2639 parent = wndPtr->parent;
2640 for (i = 0; i < count; i++)
2642 list[i] = parent->hwndSelf;
2643 parent = parent->parent;
2649 WIN_ReleaseWndPtr( wndPtr );
2654 /*******************************************************************
2657 * Build an array of the children of a given window. The array must be
2658 * freed with HeapFree. Returns NULL when no windows are found.
2660 HWND *WIN_ListChildren( HWND hwnd )
2662 WND *pWnd, *wndPtr = WIN_FindWndPtr( hwnd );
2666 /* First count the windows */
2668 if (!wndPtr) return NULL;
2670 pWnd = WIN_LockWndPtr(wndPtr->child);
2674 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2679 /* Now build the list of all windows */
2681 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1))))
2683 for (pWnd = WIN_LockWndPtr(wndPtr->child), phwnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2685 *phwnd++ = pWnd->hwndSelf;
2688 WIN_ReleaseWndPtr(pWnd);
2694 WIN_ReleaseWndPtr( wndPtr );
2699 /*******************************************************************
2700 * EnumWindows (USER32.@)
2702 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2708 /* We have to build a list of all windows first, to avoid */
2709 /* unpleasant side-effects, for instance if the callback */
2710 /* function changes the Z-order of the windows. */
2712 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2714 /* Now call the callback function for every window */
2716 iWndsLocks = WIN_SuspendWndsLock();
2717 for (i = 0; list[i]; i++)
2719 /* Make sure that the window still exists */
2720 if (!IsWindow( list[i] )) continue;
2721 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2723 WIN_RestoreWndsLock(iWndsLocks);
2724 HeapFree( GetProcessHeap(), 0, list );
2729 /**********************************************************************
2730 * EnumTaskWindows16 (USER.225)
2732 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2735 TDB *tdb = TASK_GetPtr( hTask );
2736 if (!tdb) return FALSE;
2737 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2741 /**********************************************************************
2742 * EnumThreadWindows (USER32.@)
2744 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2749 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2751 /* Now call the callback function for every window */
2753 iWndsLocks = WIN_SuspendWndsLock();
2754 for (i = 0; list[i]; i++)
2756 if (GetWindowThreadProcessId( list[i], NULL ) != id) continue;
2757 if (!func( list[i], lParam )) break;
2759 WIN_RestoreWndsLock(iWndsLocks);
2760 HeapFree( GetProcessHeap(), 0, list );
2765 /**********************************************************************
2766 * WIN_EnumChildWindows
2768 * Helper function for EnumChildWindows().
2770 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2775 for ( ; *list; list++)
2777 /* Make sure that the window still exists */
2778 if (!IsWindow( *list )) continue;
2779 /* skip owned windows */
2780 if (GetWindow( *list, GW_OWNER )) continue;
2781 /* Build children list first */
2782 childList = WIN_ListChildren( *list );
2784 ret = func( *list, lParam );
2788 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2789 HeapFree( GetProcessHeap(), 0, childList );
2791 if (!ret) return FALSE;
2797 /**********************************************************************
2798 * EnumChildWindows (USER32.@)
2800 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2805 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2806 iWndsLocks = WIN_SuspendWndsLock();
2807 WIN_EnumChildWindows( list, func, lParam );
2808 WIN_RestoreWndsLock(iWndsLocks);
2809 HeapFree( GetProcessHeap(), 0, list );
2814 /*******************************************************************
2815 * AnyPopup (USER.52)
2817 BOOL16 WINAPI AnyPopup16(void)
2823 /*******************************************************************
2824 * AnyPopup (USER32.@)
2826 BOOL WINAPI AnyPopup(void)
2830 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2832 if (!list) return FALSE;
2833 for (i = 0; list[i]; i++)
2835 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2837 retvalue = (list[i] != 0);
2838 HeapFree( GetProcessHeap(), 0, list );
2843 /*******************************************************************
2844 * FlashWindow (USER.105)
2846 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2848 return FlashWindow( hWnd, bInvert );
2852 /*******************************************************************
2853 * FlashWindow (USER32.@)
2855 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2857 WND *wndPtr = WIN_FindWndPtr(hWnd);
2859 TRACE("%04x\n", hWnd);
2861 if (!wndPtr) return FALSE;
2863 if (wndPtr->dwStyle & WS_MINIMIZE)
2865 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2867 HDC hDC = GetDC(hWnd);
2869 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2870 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2872 ReleaseDC( hWnd, hDC );
2873 wndPtr->flags |= WIN_NCACTIVATED;
2877 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2878 wndPtr->flags &= ~WIN_NCACTIVATED;
2880 WIN_ReleaseWndPtr(wndPtr);
2886 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2887 else wparam = (hWnd == GetActiveWindow());
2889 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2890 WIN_ReleaseWndPtr(wndPtr);
2896 /*******************************************************************
2897 * SetSysModalWindow (USER.188)
2899 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2901 HWND hWndOldModal = hwndSysModal;
2902 hwndSysModal = hWnd;
2903 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2904 return hWndOldModal;
2908 /*******************************************************************
2909 * GetSysModalWindow (USER.189)
2911 HWND16 WINAPI GetSysModalWindow16(void)
2913 return hwndSysModal;
2917 /*******************************************************************
2918 * GetWindowContextHelpId (USER32.@)
2920 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2923 WND *wnd = WIN_FindWndPtr( hwnd );
2925 retval = wnd->helpContext;
2926 WIN_ReleaseWndPtr(wnd);
2931 /*******************************************************************
2932 * SetWindowContextHelpId (USER32.@)
2934 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2936 WND *wnd = WIN_FindWndPtr( hwnd );
2937 if (!wnd) return FALSE;
2938 wnd->helpContext = id;
2939 WIN_ReleaseWndPtr(wnd);
2944 /*******************************************************************
2947 * recursively find a child that contains spDragInfo->pt point
2948 * and send WM_QUERYDROPOBJECT
2950 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2952 BOOL16 wParam, bResult = 0;
2954 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
2957 if (!ptrDragInfo) return FALSE;
2959 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2961 GetWindowRect(hQueryWnd,&tempRect);
2963 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
2965 if (!IsIconic( hQueryWnd ))
2967 GetClientRect( hQueryWnd, &tempRect );
2968 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
2970 if (PtInRect( &tempRect, pt))
2973 HWND *list = WIN_ListChildren( hQueryWnd );
2979 for (i = 0; list[i]; i++)
2981 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
2983 GetWindowRect( list[i], &tempRect );
2984 if (PtInRect( &tempRect, pt )) break;
2989 if (IsWindowEnabled( list[i] ))
2990 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
2992 HeapFree( GetProcessHeap(), 0, list );
2994 if(bResult) return bResult;
3000 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3002 ptrDragInfo->hScope = hQueryWnd;
3004 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3005 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3007 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3013 /*******************************************************************
3014 * DragDetect (USER.465)
3016 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3019 CONV_POINT16TO32( &pt, &pt32 );
3020 return DragDetect( hWnd, pt32 );
3023 /*******************************************************************
3024 * DragDetect (USER32.@)
3026 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3031 rect.left = pt.x - wDragWidth;
3032 rect.right = pt.x + wDragWidth;
3034 rect.top = pt.y - wDragHeight;
3035 rect.bottom = pt.y + wDragHeight;
3041 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3043 if( msg.message == WM_LBUTTONUP )
3048 if( msg.message == WM_MOUSEMOVE )
3051 tmp.x = LOWORD(msg.lParam);
3052 tmp.y = HIWORD(msg.lParam);
3053 if( !PtInRect( &rect, tmp ))
3065 /******************************************************************************
3066 * DragObject (USER.464)
3068 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3069 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3072 LPDRAGINFO16 lpDragInfo;
3074 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3075 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3076 HCURSOR16 hCurrentCursor = 0;
3077 HWND16 hCurrentWnd = 0;
3079 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3080 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3082 if( !lpDragInfo || !spDragInfo ) return 0L;
3084 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3086 GlobalFree16(hDragInfo);
3092 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3094 GlobalFree16(hDragInfo);
3098 if( hDragCursor == hCursor ) hDragCursor = 0;
3099 else hCursor = hDragCursor;
3101 hOldCursor = SetCursor(hDragCursor);
3104 lpDragInfo->hWnd = hWnd;
3105 lpDragInfo->hScope = 0;
3106 lpDragInfo->wFlags = wObj;
3107 lpDragInfo->hList = szList; /* near pointer! */
3108 lpDragInfo->hOfStruct = hOfStruct;
3116 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3118 *(lpDragInfo+1) = *lpDragInfo;
3120 lpDragInfo->pt.x = msg.pt.x;
3121 lpDragInfo->pt.y = msg.pt.y;
3123 /* update DRAGINFO struct */
3124 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3126 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3127 hCurrentCursor = hCursor;
3130 hCurrentCursor = hBummer;
3131 lpDragInfo->hScope = 0;
3133 if( hCurrentCursor )
3134 SetCursor(hCurrentCursor);
3136 /* send WM_DRAGLOOP */
3137 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3138 (LPARAM) spDragInfo );
3139 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3140 if( hCurrentWnd != lpDragInfo->hScope )
3143 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3144 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3145 HIWORD(spDragInfo)) );
3146 hCurrentWnd = lpDragInfo->hScope;
3148 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3152 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3154 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3157 ShowCursor( FALSE );
3161 SetCursor( hOldCursor );
3162 if (hDragCursor) DestroyCursor( hDragCursor );
3165 if( hCurrentCursor != hBummer )
3166 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3167 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3170 GlobalFree16(hDragInfo);
3172 return (DWORD)(msg.lParam);
3176 /******************************************************************************
3177 * GetWindowModuleFileNameA (USER32.@)
3179 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3181 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3182 hwnd, lpszFileName, cchFileNameMax);
3186 /******************************************************************************
3187 * GetWindowModuleFileNameW (USER32.@)
3189 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3191 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3192 hwnd, lpszFileName, cchFileNameMax);