2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
23 * FILE: subsys/win32k/ntuser/window.c
24 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * 06-06-2001 CSH Created
29 /* INCLUDES ******************************************************************/
36 static WndProcHandle
*WndProcHandlesArray
= 0;
37 static WORD WndProcHandlesArraySize
= 0;
38 #define WPH_SIZE 0x40 /* the size to add to the WndProcHandle array each time */
40 /* dialog resources appear to pass this in 16 bits, handle them properly */
41 #define CW_USEDEFAULT16 (0x8000)
43 #define POINT_IN_RECT(p, r) (((r.bottom >= p.y) && (r.top <= p.y))&&((r.left <= p.x )&&( r.right >= p.x )))
45 /* PRIVATE FUNCTIONS **********************************************************/
50 * Initialize windowing implementation.
56 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,WPH_SIZE
* sizeof(WndProcHandle
), TAG_WINPROCLST
);
57 WndProcHandlesArraySize
= WPH_SIZE
;
58 return STATUS_SUCCESS
;
64 * Cleanup windowing implementation.
68 CleanupWindowImpl(VOID
)
70 ExFreePool(WndProcHandlesArray
);
71 WndProcHandlesArray
= 0;
72 WndProcHandlesArraySize
= 0;
73 return STATUS_SUCCESS
;
76 /* HELPER FUNCTIONS ***********************************************************/
81 * The function determines whether the specified window handle identifies
86 * Handle to the window to test.
89 * If the window handle identifies an existing window, the return value
90 * is TRUE. If the window handle does not identify an existing window,
91 * the return value is FALSE.
95 IntIsWindow(HWND hWnd
)
97 PWINDOW_OBJECT Window
;
99 if (!(Window
= IntGetWindowObject(hWnd
)))
102 IntReleaseWindowObject(Window
);
107 * IntGetProcessWindowObject
109 * Get window object from handle of specified process.
112 PWINDOW_OBJECT FASTCALL
113 IntGetProcessWindowObject(PW32THREAD Thread
, HWND hWnd
)
115 PWINDOW_OBJECT WindowObject
;
118 if(Thread
->Desktop
!= NULL
)
120 Status
= ObmReferenceObjectByHandle(Thread
->Desktop
->WindowStation
->HandleTable
,
121 hWnd
, otWindow
, (PVOID
*)&WindowObject
);
122 if (NT_SUCCESS(Status
))
131 PWINDOW_OBJECT FASTCALL
132 IntGetParent(PWINDOW_OBJECT Wnd
)
136 if (Wnd
->Style
& WS_POPUP
)
139 return IntGetWindowObject(hWnd
);
141 else if (Wnd
->Style
& WS_CHILD
)
144 return IntGetWindowObject(hWnd
);
150 PWINDOW_OBJECT FASTCALL
151 IntGetOwner(PWINDOW_OBJECT Wnd
)
157 return IntGetWindowObject(hWnd
);
160 PWINDOW_OBJECT FASTCALL
161 IntGetParentObject(PWINDOW_OBJECT Wnd
)
165 hParent
= Wnd
->Parent
;
166 return IntGetWindowObject(hParent
);
172 * Compile a list of all child window handles from given window.
175 * This function is similar to Wine WIN_ListChildren. The caller
176 * must free the returned list with ExFreePool.
180 IntWinListChildren(PWINDOW_OBJECT Window
)
182 PWINDOW_OBJECT Child
;
184 UINT Index
, NumChildren
= 0;
186 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
189 List
= ExAllocatePoolWithTag(PagedPool
, (NumChildren
+ 1) * sizeof(HWND
), TAG_WINLIST
);
192 DPRINT1("Failed to allocate memory for children array\n");
193 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
196 for (Child
= Window
->FirstChild
, Index
= 0;
198 Child
= Child
->NextSibling
, ++Index
)
199 List
[Index
] = Child
->Self
;
205 /***********************************************************************
208 static void IntSendDestroyMsg(HWND Wnd
)
211 PWINDOW_OBJECT Window
, Owner
, Parent
;
215 if (GetGUIThreadInfo(GetCurrentThreadId(), &info
))
217 if (Wnd
== info
.hwndCaret
)
224 Window
= IntGetWindowObject(Wnd
);
226 Owner
= IntGetOwner(Window
);
228 Parent
= IntGetParent(Window
);
230 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
) Wnd
);
232 IntReleaseWindowObject(Parent
);
234 IntReleaseWindowObject(Owner
);
237 IntReleaseWindowObject(Window
);
240 /* The window could already be destroyed here */
243 * Send the WM_DESTROY to the window.
246 co_IntSendMessage(Wnd
, WM_DESTROY
, 0, 0);
249 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
250 * make sure that the window still exists when we come back.
258 if (!(pWndArray
= WIN_ListChildren( hwnd
))) return;
260 /* start from the end (FIXME: is this needed?) */
261 for (i
= 0; pWndArray
[i
]; i
++) ;
265 if (IsWindow( pWndArray
[i
] )) WIN_SendDestroyMsg( pWndArray
[i
] );
267 HeapFree(GetProcessHeap(), 0, pWndArray
);
271 DPRINT("destroyed itself while in WM_DESTROY!\n");
276 /***********************************************************************
279 * Destroy storage associated to a window. "Internals" p.358
281 static LRESULT
co_IntDestroyWindow(PWINDOW_OBJECT Window
,
282 PW32PROCESS ProcessData
,
283 PW32THREAD ThreadData
,
284 BOOLEAN SendMessages
)
288 PWINDOW_OBJECT Child
;
290 BOOLEAN BelongsToThreadData
;
294 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
296 DPRINT("Tried to call IntDestroyWindow() twice\n");
299 Window
->Status
|= WINDOWSTATUS_DESTROYING
;
300 Window
->Flags
&= ~WS_VISIBLE
;
301 /* remove the window already at this point from the thread window list so we
302 don't get into trouble when destroying the thread windows while we're still
303 in IntDestroyWindow() */
304 RemoveEntryList(&Window
->ThreadListEntry
);
306 BelongsToThreadData
= IntWndBelongsToThread(Window
, ThreadData
);
308 IntDeRegisterShellHookWindow(Window
->Self
);
312 /* Send destroy messages */
313 IntSendDestroyMsg(Window
->Self
);
316 /* free child windows */
317 Children
= IntWinListChildren(Window
);
320 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
322 if ((Child
= IntGetWindowObject(*ChildHandle
)))
324 if(!IntWndBelongsToThread(Child
, ThreadData
))
326 /* send WM_DESTROY messages to windows not belonging to the same thread */
327 IntSendDestroyMsg(Child
->Self
);
330 co_IntDestroyWindow(Child
, ProcessData
, ThreadData
, SendMessages
);
331 IntReleaseWindowObject(Child
);
334 ExFreePool(Children
);
340 * Clear the update region to make sure no WM_PAINT messages will be
341 * generated for this window while processing the WM_NCDESTROY.
343 co_UserRedrawWindow(Window
, NULL
, 0,
344 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
|
345 RDW_NOINTERNALPAINT
| RDW_NOCHILDREN
);
346 if(BelongsToThreadData
)
347 co_IntSendMessage(Window
->Self
, WM_NCDESTROY
, 0, 0);
349 MsqRemoveTimersWindow(ThreadData
->MessageQueue
, Window
->Self
);
351 /* flush the message queue */
352 MsqRemoveWindowMessagesFromQueue(Window
);
354 /* from now on no messages can be sent to this window anymore */
355 Window
->Status
|= WINDOWSTATUS_DESTROYED
;
356 /* don't remove the WINDOWSTATUS_DESTROYING bit */
358 /* reset shell window handles */
359 if(ThreadData
->Desktop
)
361 if (Window
->Self
== ThreadData
->Desktop
->WindowStation
->ShellWindow
)
362 ThreadData
->Desktop
->WindowStation
->ShellWindow
= NULL
;
364 if (Window
->Self
== ThreadData
->Desktop
->WindowStation
->ShellListView
)
365 ThreadData
->Desktop
->WindowStation
->ShellListView
= NULL
;
368 /* Unregister hot keys */
369 UnregisterWindowHotKeys (Window
);
371 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
374 WinPosCheckInternalPos(Window
->Self
);
375 if (Window
->Self
== GetCapture())
380 /* free resources associated with the window */
381 TIMER_RemoveWindowTimers(Window
->Self
);
384 if (!(Window
->Style
& WS_CHILD
) && Window
->IDMenu
385 && (Menu
= IntGetMenuObject((HMENU
)Window
->IDMenu
)))
387 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
389 IntReleaseMenuObject(Menu
);
392 if(Window
->SystemMenu
393 && (Menu
= IntGetMenuObject(Window
->SystemMenu
)))
395 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
396 Window
->SystemMenu
= (HMENU
)0;
397 IntReleaseMenuObject(Menu
);
400 DceFreeWindowDCE(Window
); /* Always do this to catch orphaned DCs */
402 WINPROC_FreeProc(Window
->winproc
, WIN_PROC_WINDOW
);
403 CLASS_RemoveWindow(Window
->Class
);
406 IntUnlinkWindow(Window
);
408 IntReferenceWindowObject(Window
);
409 ObmCloseHandle(ThreadData
->Desktop
->WindowStation
->HandleTable
, Window
->Self
);
411 IntDestroyScrollBars(Window
);
413 /* remove the window from the class object */
414 RemoveEntryList(&Window
->ClassListEntry
);
416 /* dereference the class */
417 ClassDereferenceObject(Window
->Class
);
418 Window
->Class
= NULL
;
420 if(Window
->WindowRegion
)
422 NtGdiDeleteObject(Window
->WindowRegion
);
425 RtlFreeUnicodeString(&Window
->WindowName
);
427 IntReleaseWindowObject(Window
);
433 IntGetWindowBorderMeasures(PWINDOW_OBJECT WindowObject
, UINT
*cx
, UINT
*cy
)
435 if(HAS_DLGFRAME(WindowObject
->Style
, WindowObject
->ExStyle
) && !(WindowObject
->Style
& WS_MINIMIZE
))
437 *cx
= UserGetSystemMetrics(SM_CXDLGFRAME
);
438 *cy
= UserGetSystemMetrics(SM_CYDLGFRAME
);
442 if(HAS_THICKFRAME(WindowObject
->Style
, WindowObject
->ExStyle
)&& !(WindowObject
->Style
& WS_MINIMIZE
))
444 *cx
= UserGetSystemMetrics(SM_CXFRAME
);
445 *cy
= UserGetSystemMetrics(SM_CYFRAME
);
447 else if(HAS_THINFRAME(WindowObject
->Style
, WindowObject
->ExStyle
))
449 *cx
= UserGetSystemMetrics(SM_CXBORDER
);
450 *cy
= UserGetSystemMetrics(SM_CYBORDER
);
460 IntGetWindowInfo(PWINDOW_OBJECT WindowObject
, PWINDOWINFO pwi
)
462 pwi
->cbSize
= sizeof(WINDOWINFO
);
463 pwi
->rcWindow
= WindowObject
->WindowRect
;
464 pwi
->rcClient
= WindowObject
->ClientRect
;
465 pwi
->dwStyle
= WindowObject
->Style
;
466 pwi
->dwExStyle
= WindowObject
->ExStyle
;
467 pwi
->dwWindowStatus
= (UserGetForegroundWindow() == WindowObject
->Self
); /* WS_ACTIVECAPTION */
468 IntGetWindowBorderMeasures(WindowObject
, &pwi
->cxWindowBorders
, &pwi
->cyWindowBorders
);
469 pwi
->atomWindowType
= (WindowObject
->Class
? WindowObject
->Class
->Atom
: 0);
470 pwi
->wCreatorVersion
= 0x400; /* FIXME - return a real version number */
476 PWINDOW_OBJECT WindowObject
,
480 PMENU_OBJECT OldMenuObject
, NewMenuObject
= NULL
;
482 if ((WindowObject
->Style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
484 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
488 *Changed
= (WindowObject
->IDMenu
!= (UINT
) Menu
);
494 if (WindowObject
->IDMenu
)
496 OldMenuObject
= IntGetMenuObject((HMENU
) WindowObject
->IDMenu
);
497 ASSERT(NULL
== OldMenuObject
|| OldMenuObject
->MenuInfo
.Wnd
== WindowObject
->Self
);
501 OldMenuObject
= NULL
;
506 NewMenuObject
= IntGetMenuObject(Menu
);
507 if (NULL
== NewMenuObject
)
509 if (NULL
!= OldMenuObject
)
511 IntReleaseMenuObject(OldMenuObject
);
513 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
516 if (NULL
!= NewMenuObject
->MenuInfo
.Wnd
)
518 /* Can't use the same menu for two windows */
519 if (NULL
!= OldMenuObject
)
521 IntReleaseMenuObject(OldMenuObject
);
523 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
529 WindowObject
->IDMenu
= (UINT
) Menu
;
530 if (NULL
!= NewMenuObject
)
532 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
533 IntReleaseMenuObject(NewMenuObject
);
535 if (NULL
!= OldMenuObject
)
537 OldMenuObject
->MenuInfo
.Wnd
= NULL
;
538 IntReleaseMenuObject(OldMenuObject
);
545 /* INTERNAL ******************************************************************/
549 co_DestroyThreadWindows(struct _ETHREAD
*Thread
)
552 PW32PROCESS Win32Process
;
553 PW32THREAD Win32Thread
;
554 PWINDOW_OBJECT
*List
, *pWnd
;
557 Win32Thread
= Thread
->Tcb
.Win32Thread
;
558 Win32Process
= (PW32PROCESS
)Thread
->ThreadsProcess
->Win32Process
;
560 Current
= Win32Thread
->WindowListHead
.Flink
;
561 while (Current
!= &(Win32Thread
->WindowListHead
))
564 Current
= Current
->Flink
;
569 List
= ExAllocatePool(PagedPool
, (Cnt
+ 1) * sizeof(PWINDOW_OBJECT
));
572 DPRINT("Not enough memory to allocate window handle list\n");
576 Current
= Win32Thread
->WindowListHead
.Flink
;
577 while (Current
!= &(Win32Thread
->WindowListHead
))
579 *pWnd
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
580 IntReferenceWindowObject(*pWnd
);
582 Current
= Current
->Flink
;
586 for(pWnd
= List
; *pWnd
; pWnd
++)
588 co_UserDestroyWindow(*pWnd
);
589 IntReleaseWindowObject(*pWnd
);
600 * Returns client window rectangle relative to the upper-left corner of client area.
602 * \note Does not check the validity of the parameters
605 IntGetClientRect(PWINDOW_OBJECT WindowObject
, PRECT Rect
)
607 ASSERT( WindowObject
);
610 Rect
->left
= Rect
->top
= 0;
611 Rect
->right
= WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
;
612 Rect
->bottom
= WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
;
618 IntGetFocusWindow(VOID
)
620 PUSER_MESSAGE_QUEUE Queue
;
621 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
626 Queue
= (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
631 return(Queue
->FocusWindow
);
635 PMENU_OBJECT FASTCALL
636 IntGetSystemMenu(PWINDOW_OBJECT WindowObject
, BOOL bRevert
, BOOL RetMenu
)
638 PMENU_OBJECT MenuObject
, NewMenuObject
, SysMenuObject
, ret
= NULL
;
639 PW32THREAD W32Thread
;
640 HMENU NewMenu
, SysMenu
;
641 ROSMENUITEMINFO ItemInfo
;
645 W32Thread
= PsGetWin32Thread();
647 if(!W32Thread
->Desktop
)
650 if(WindowObject
->SystemMenu
)
652 MenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
655 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
656 WindowObject
->SystemMenu
= (HMENU
)0;
657 IntReleaseMenuObject(MenuObject
);
661 if(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
)
663 /* clone system menu */
664 MenuObject
= IntGetMenuObject(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
);
668 NewMenuObject
= IntCloneMenu(MenuObject
);
671 WindowObject
->SystemMenu
= NewMenuObject
->MenuInfo
.Self
;
672 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
673 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
675 //IntReleaseMenuObject(NewMenuObject);
677 IntReleaseMenuObject(MenuObject
);
681 SysMenu
= UserCreateMenu(FALSE
);
686 SysMenuObject
= IntGetMenuObject(SysMenu
);
687 if (NULL
== SysMenuObject
)
689 UserDestroyMenu(SysMenu
);
692 SysMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
693 SysMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
694 NewMenu
= co_IntLoadSysMenuTemplate();
697 IntReleaseMenuObject(SysMenuObject
);
698 UserDestroyMenu(SysMenu
);
701 MenuObject
= IntGetMenuObject(NewMenu
);
704 IntReleaseMenuObject(SysMenuObject
);
705 UserDestroyMenu(SysMenu
);
709 NewMenuObject
= IntCloneMenu(MenuObject
);
712 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
| MF_POPUP
;
713 IntReleaseMenuObject(NewMenuObject
);
714 UserSetMenuDefaultItem(NewMenuObject
->MenuInfo
.Self
, SC_CLOSE
, FALSE
);
716 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
717 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
718 ItemInfo
.fType
= MF_POPUP
;
719 ItemInfo
.fState
= MFS_ENABLED
;
720 ItemInfo
.dwTypeData
= NULL
;
722 ItemInfo
.hSubMenu
= NewMenuObject
->MenuInfo
.Self
;
723 IntInsertMenuItem(SysMenuObject
, (UINT
) -1, TRUE
, &ItemInfo
);
725 WindowObject
->SystemMenu
= SysMenuObject
->MenuInfo
.Self
;
729 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
730 IntReleaseMenuObject(MenuObject
);
739 if(WindowObject
->SystemMenu
)
740 return IntGetMenuObject((HMENU
)WindowObject
->SystemMenu
);
748 IntIsChildWindow(HWND Parent
, HWND Child
)
750 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
752 if(!(BaseWindow
= IntGetWindowObject(Child
)))
760 if (Window
->Self
== Parent
)
762 if(Window
!= BaseWindow
)
763 IntReleaseWindowObject(Window
);
764 IntReleaseWindowObject(BaseWindow
);
767 if(!(Window
->Style
& WS_CHILD
))
769 if(Window
!= BaseWindow
)
770 IntReleaseWindowObject(Window
);
774 Window
= IntGetParentObject(Window
);
775 if(Old
!= BaseWindow
)
776 IntReleaseWindowObject(Old
);
779 IntReleaseWindowObject(BaseWindow
);
784 IntIsWindowVisible(HWND hWnd
)
786 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
788 if(!(BaseWindow
= IntGetWindowObject(hWnd
)))
796 if(!(Window
->Style
& WS_CHILD
))
800 if(!(Window
->Style
& WS_VISIBLE
))
802 if(Window
!= BaseWindow
)
803 IntReleaseWindowObject(Window
);
804 IntReleaseWindowObject(BaseWindow
);
808 Window
= IntGetParentObject(Window
);
809 if(Old
!= BaseWindow
)
810 IntReleaseWindowObject(Old
);
815 if(Window
->Style
& WS_VISIBLE
)
817 if(Window
!= BaseWindow
)
818 IntReleaseWindowObject(Window
);
819 IntReleaseWindowObject(BaseWindow
);
822 if(Window
!= BaseWindow
)
823 IntReleaseWindowObject(Window
);
825 IntReleaseWindowObject(BaseWindow
);
830 /* link the window into siblings and parent. children are kept in place. */
834 PWINDOW_OBJECT WndParent
,
835 PWINDOW_OBJECT WndPrevSibling
/* set to NULL if top sibling */
838 PWINDOW_OBJECT Parent
;
840 Wnd
->Parent
= WndParent
->Self
;
841 if ((Wnd
->PrevSibling
= WndPrevSibling
))
843 /* link after WndPrevSibling */
844 if ((Wnd
->NextSibling
= WndPrevSibling
->NextSibling
))
845 Wnd
->NextSibling
->PrevSibling
= Wnd
;
846 else if ((Parent
= IntGetWindowObject(Wnd
->Parent
)))
848 if(Parent
->LastChild
== WndPrevSibling
)
849 Parent
->LastChild
= Wnd
;
850 IntReleaseWindowObject(Parent
);
852 Wnd
->PrevSibling
->NextSibling
= Wnd
;
857 Parent
= IntGetWindowObject(Wnd
->Parent
);
858 if ((Wnd
->NextSibling
= WndParent
->FirstChild
))
859 Wnd
->NextSibling
->PrevSibling
= Wnd
;
862 Parent
->LastChild
= Wnd
;
863 Parent
->FirstChild
= Wnd
;
864 IntReleaseWindowObject(Parent
);
869 Parent
->FirstChild
= Wnd
;
870 IntReleaseWindowObject(Parent
);
877 IntSetOwner(HWND hWnd
, HWND hWndNewOwner
)
879 PWINDOW_OBJECT Wnd
, WndOldOwner
, WndNewOwner
;
882 Wnd
= IntGetWindowObject(hWnd
);
886 WndOldOwner
= IntGetWindowObject(Wnd
->Owner
);
889 ret
= WndOldOwner
->Self
;
890 IntReleaseWindowObject(WndOldOwner
);
897 if((WndNewOwner
= IntGetWindowObject(hWndNewOwner
)))
899 Wnd
->Owner
= hWndNewOwner
;
900 IntReleaseWindowObject(WndNewOwner
);
905 IntReleaseWindowObject(Wnd
);
909 PWINDOW_OBJECT FASTCALL
910 IntSetParent(PWINDOW_OBJECT Wnd
, PWINDOW_OBJECT WndNewParent
)
912 PWINDOW_OBJECT WndOldParent
, Sibling
, InsertAfter
;
913 HWND hWnd
, hWndNewParent
, hWndOldParent
;
918 ASSERT(WndNewParent
);
921 hWndNewParent
= WndNewParent
->Self
;
924 * Windows hides the window first, then shows it again
925 * including the WM_SHOWWINDOW messages and all
927 WasVisible
= co_WinPosShowWindow(hWnd
, SW_HIDE
);
929 /* Validate that window and parent still exist */
930 if (!IntIsWindow(hWnd
) || !IntIsWindow(hWndNewParent
))
933 /* Window must belong to current process */
934 if (Wnd
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
937 WndOldParent
= IntGetParentObject(Wnd
);
938 hWndOldParent
= (WndOldParent
? WndOldParent
->Self
: NULL
);
940 if (WndNewParent
!= WndOldParent
)
942 IntUnlinkWindow(Wnd
);
944 if (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
))
946 /* Not a TOPMOST window, put after TOPMOSTs of new parent */
947 Sibling
= WndNewParent
->FirstChild
;
948 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
950 InsertAfter
= Sibling
;
951 Sibling
= Sibling
->NextSibling
;
954 if (NULL
== InsertAfter
)
956 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
960 IntReferenceWindowObject(InsertAfter
);
961 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
962 IntReleaseWindowObject(InsertAfter
);
965 if (WndNewParent
->Self
!= IntGetDesktopWindow()) /* a child window */
967 if (!(Wnd
->Style
& WS_CHILD
))
969 //if ( Wnd->Menu ) DestroyMenu ( Wnd->menu );
970 IntSetMenu(Wnd
, NULL
, &MenuChanged
);
976 * SetParent additionally needs to make hwnd the top window
977 * in the z-order and send the expected WM_WINDOWPOSCHANGING and
978 * WM_WINDOWPOSCHANGED notification messages.
980 co_WinPosSetWindowPos(hWnd
, (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOP
: HWND_TOPMOST
),
981 0, 0, 0, 0, SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
982 | (WasVisible
? SWP_SHOWWINDOW
: 0));
985 * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
986 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
990 * Validate that the old parent still exist, since it migth have been
991 * destroyed during the last callbacks to user-mode
995 if(!IntIsWindow(WndOldParent
->Self
))
997 IntReleaseWindowObject(WndOldParent
);
1001 /* don't dereference the window object here, it must be done by the caller
1002 of IntSetParent() */
1003 return WndOldParent
;
1009 IntSetSystemMenu(PWINDOW_OBJECT WindowObject
, PMENU_OBJECT MenuObject
)
1011 PMENU_OBJECT OldMenuObject
;
1012 if(WindowObject
->SystemMenu
)
1014 OldMenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
1017 OldMenuObject
->MenuInfo
.Flags
&= ~ MF_SYSMENU
;
1018 IntReleaseMenuObject(OldMenuObject
);
1024 /* FIXME check window style, propably return FALSE ? */
1025 WindowObject
->SystemMenu
= MenuObject
->MenuInfo
.Self
;
1026 MenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
1029 WindowObject
->SystemMenu
= (HMENU
)0;
1035 /* unlink the window from siblings and parent. children are kept in place. */
1037 IntUnlinkWindow(PWINDOW_OBJECT Wnd
)
1039 PWINDOW_OBJECT WndParent
;
1041 if((WndParent
= IntGetWindowObject(Wnd
->Parent
)))
1046 if (Wnd
->NextSibling
) Wnd
->NextSibling
->PrevSibling
= Wnd
->PrevSibling
;
1047 else if (WndParent
&& WndParent
->LastChild
== Wnd
) WndParent
->LastChild
= Wnd
->PrevSibling
;
1049 if (Wnd
->PrevSibling
) Wnd
->PrevSibling
->NextSibling
= Wnd
->NextSibling
;
1050 else if (WndParent
&& WndParent
->FirstChild
== Wnd
) WndParent
->FirstChild
= Wnd
->NextSibling
;
1054 IntReleaseWindowObject(WndParent
);
1056 Wnd
->PrevSibling
= Wnd
->NextSibling
= Wnd
->Parent
= NULL
;
1062 PWINDOW_OBJECT Window
, Child
;
1064 if(!(Window
= IntGetWindowObject(IntGetDesktopWindow())))
1066 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1070 for(Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
1072 if(Child
->Owner
&& Child
->Style
& WS_VISIBLE
)
1075 * The desktop has a popup window if one of them has
1076 * an owner window and is visible
1078 IntReleaseWindowObject(Window
);
1083 IntReleaseWindowObject(Window
);
1088 IntIsWindowInDestroy(PWINDOW_OBJECT Window
)
1090 return ((Window
->Status
& WINDOWSTATUS_DESTROYING
) == WINDOWSTATUS_DESTROYING
);
1093 /* FUNCTIONS *****************************************************************/
1099 NtUserAlterWindowStyle(DWORD Unknown0
,
1110 * As best as I can figure, this function is used by EnumWindows,
1111 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
1113 * It's supposed to build a list of HWNDs to return to the caller.
1114 * We can figure out what kind of list by what parameters are
1122 NtUserBuildHwndList(
1134 /* FIXME handle bChildren */
1138 PWINDOW_OBJECT Window
, Child
;
1139 if(!(Window
= IntGetWindowObject(hwndParent
)))
1141 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1145 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1147 if(dwCount
++ < nBufSize
&& pWnd
)
1149 Status
= MmCopyToCaller(pWnd
++, &Child
->Self
, sizeof(HWND
));
1150 if(!NT_SUCCESS(Status
))
1152 SetLastNtError(Status
);
1158 IntReleaseWindowObject(Window
);
1163 PW32THREAD W32Thread
;
1164 PLIST_ENTRY Current
;
1165 PWINDOW_OBJECT Window
;
1167 Status
= PsLookupThreadByThreadId((HANDLE
)dwThreadId
, &Thread
);
1168 if(!NT_SUCCESS(Status
))
1170 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1173 if(!(W32Thread
= Thread
->Tcb
.Win32Thread
))
1175 ObDereferenceObject(Thread
);
1176 DPRINT("Thread is not a GUI Thread!\n");
1177 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1181 Current
= W32Thread
->WindowListHead
.Flink
;
1182 while(Current
!= &(W32Thread
->WindowListHead
))
1184 Window
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
1187 if(dwCount
< nBufSize
&& pWnd
)
1189 Status
= MmCopyToCaller(pWnd
++, &Window
->Self
, sizeof(HWND
));
1190 if(!NT_SUCCESS(Status
))
1192 SetLastNtError(Status
);
1197 Current
= Current
->Flink
;
1200 ObDereferenceObject(Thread
);
1204 PDESKTOP_OBJECT Desktop
;
1205 PWINDOW_OBJECT Window
, Child
;
1207 if(hDesktop
== NULL
&& !(Desktop
= IntGetActiveDesktop()))
1209 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1215 Status
= IntValidateDesktopHandle(hDesktop
,
1219 if(!NT_SUCCESS(Status
))
1221 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1225 if(!(Window
= IntGetWindowObject(Desktop
->DesktopWindow
)))
1228 ObDereferenceObject(Desktop
);
1229 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1233 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1235 if(dwCount
++ < nBufSize
&& pWnd
)
1237 Status
= MmCopyToCaller(pWnd
++, &Child
->Self
, sizeof(HWND
));
1238 if(!NT_SUCCESS(Status
))
1240 SetLastNtError(Status
);
1246 IntReleaseWindowObject(Window
);
1248 ObDereferenceObject(Desktop
);
1259 NtUserChildWindowFromPointEx(HWND hwndParent
,
1264 PWINDOW_OBJECT Parent
;
1269 if(!(Parent
= IntGetWindowObject(hwndParent
)))
1271 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1278 if(Parent
->Self
!= IntGetDesktopWindow())
1280 Pt
.x
+= Parent
->ClientRect
.left
;
1281 Pt
.y
+= Parent
->ClientRect
.top
;
1284 if(!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
))
1286 IntReleaseWindowObject(Parent
);
1291 if((List
= IntWinListChildren(Parent
)))
1293 for(phWnd
= List
; *phWnd
; phWnd
++)
1295 PWINDOW_OBJECT Child
;
1296 if((Child
= IntGetWindowObject(*phWnd
)))
1298 if(!(Child
->Style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
))
1300 IntReleaseWindowObject(Child
);
1303 if((Child
->Style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
))
1305 IntReleaseWindowObject(Child
);
1308 if((Child
->ExStyle
& WS_EX_TRANSPARENT
) && (uiFlags
& CWP_SKIPTRANSPARENT
))
1310 IntReleaseWindowObject(Child
);
1313 if(IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
1316 IntReleaseWindowObject(Child
);
1319 IntReleaseWindowObject(Child
);
1325 IntReleaseWindowObject(Parent
);
1331 * calculates the default position of a window
1334 IntCalcDefPosSize(PWINDOW_OBJECT Parent
, PWINDOW_OBJECT WindowObject
, RECT
*rc
, BOOL IncPos
)
1341 IntGdiIntersectRect(rc
, rc
, &Parent
->ClientRect
);
1345 Pos
.x
= Parent
->TiledCounter
* (UserGetSystemMetrics(SM_CXSIZE
) + UserGetSystemMetrics(SM_CXFRAME
));
1346 Pos
.y
= Parent
->TiledCounter
* (UserGetSystemMetrics(SM_CYSIZE
) + UserGetSystemMetrics(SM_CYFRAME
));
1347 if(Pos
.x
> ((rc
->right
- rc
->left
) / 4) ||
1348 Pos
.y
> ((rc
->bottom
- rc
->top
) / 4))
1350 /* reset counter and position */
1353 Parent
->TiledCounter
= 0;
1355 Parent
->TiledCounter
++;
1366 Sz
.cx
= EngMulDiv(rc
->right
- rc
->left
, 3, 4);
1367 Sz
.cy
= EngMulDiv(rc
->bottom
- rc
->top
, 3, 4);
1371 rc
->right
= rc
->left
+ Sz
.cx
;
1372 rc
->bottom
= rc
->top
+ Sz
.cy
;
1381 co_IntCreateWindowEx(DWORD dwExStyle
,
1382 PUNICODE_STRING ClassName
,
1383 PUNICODE_STRING WindowName
,
1391 HINSTANCE hInstance
,
1394 BOOL bUnicodeWindow
)
1396 PWINSTATION_OBJECT WinStaObject
;
1397 PWNDCLASS_OBJECT ClassObject
;
1398 PWINDOW_OBJECT WindowObject
;
1399 PWINDOW_OBJECT ParentWindow
, OwnerWindow
;
1400 HWND ParentWindowHandle
;
1401 HWND OwnerWindowHandle
;
1402 PMENU_OBJECT SystemMenu
;
1407 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1412 CBT_CREATEWNDW CbtCreate
;
1419 ParentWindowHandle
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
1420 OwnerWindowHandle
= NULL
;
1422 if (hWndParent
== HWND_MESSAGE
)
1425 * native ole32.OleInitialize uses HWND_MESSAGE to create the
1426 * message window (style: WS_POPUP|WS_DISABLED)
1428 DPRINT1("FIXME - Parent is HWND_MESSAGE\n");
1430 else if (hWndParent
)
1432 if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1433 ParentWindowHandle
= hWndParent
;
1435 OwnerWindowHandle
= UserGetAncestor(hWndParent
, GA_ROOT
);
1437 else if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1439 return (HWND
)0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1442 if (NULL
!= ParentWindowHandle
)
1444 ParentWindow
= IntGetWindowObject(ParentWindowHandle
);
1448 ParentWindow
= NULL
;
1451 /* FIXME: parent must belong to the current process */
1453 /* Check the class. */
1454 ClassFound
= ClassReferenceClassByNameOrAtom(&ClassObject
, ClassName
->Buffer
, hInstance
);
1457 if (IS_ATOM(ClassName
->Buffer
))
1459 DPRINT1("Class 0x%x not found\n", (DWORD_PTR
) ClassName
->Buffer
);
1463 DPRINT1("Class %wZ not found\n", ClassName
);
1465 if (NULL
!= ParentWindow
)
1467 IntReleaseWindowObject(ParentWindow
);
1469 SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS
);
1473 /* Check the window station. */
1474 if (PsGetWin32Thread()->Desktop
== NULL
)
1476 ClassDereferenceObject(ClassObject
);
1477 if (NULL
!= ParentWindow
)
1479 IntReleaseWindowObject(ParentWindow
);
1481 DPRINT("Thread is not attached to a desktop! Cannot create window!\n");
1484 WinStaObject
= PsGetWin32Thread()->Desktop
->WindowStation
;
1485 ObReferenceObjectByPointer(WinStaObject
, KernelMode
, ExWindowStationObjectType
, 0);
1487 /* Create the window object. */
1488 WindowObject
= (PWINDOW_OBJECT
)
1489 ObmCreateObject(PsGetWin32Thread()->Desktop
->WindowStation
->HandleTable
, &Handle
,
1490 otWindow
, sizeof(WINDOW_OBJECT
) + ClassObject
->cbWndExtra
1493 DPRINT("Created object with handle %X\n", Handle
);
1496 ObDereferenceObject(WinStaObject
);
1497 ClassDereferenceObject(ClassObject
);
1498 if (NULL
!= ParentWindow
)
1500 IntReleaseWindowObject(ParentWindow
);
1502 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1505 ObDereferenceObject(WinStaObject
);
1507 if (NULL
== PsGetWin32Thread()->Desktop
->DesktopWindow
)
1509 /* If there is no desktop window yet, we must be creating it */
1510 PsGetWin32Thread()->Desktop
->DesktopWindow
= Handle
;
1514 * Fill out the structure describing it.
1516 WindowObject
->Class
= ClassObject
;
1518 InsertTailList(&ClassObject
->ClassWindowsListHead
, &WindowObject
->ClassListEntry
);
1520 WindowObject
->ExStyle
= dwExStyle
;
1521 WindowObject
->Style
= dwStyle
& ~WS_VISIBLE
;
1522 DPRINT("1: Style is now %lx\n", WindowObject
->Style
);
1524 WindowObject
->SystemMenu
= (HMENU
)0;
1525 WindowObject
->ContextHelpId
= 0;
1526 WindowObject
->IDMenu
= 0;
1527 WindowObject
->Instance
= hInstance
;
1528 WindowObject
->Self
= Handle
;
1529 if (0 != (dwStyle
& WS_CHILD
))
1531 WindowObject
->IDMenu
= (UINT
) hMenu
;
1535 IntSetMenu(WindowObject
, hMenu
, &MenuChanged
);
1537 WindowObject
->MessageQueue
= PsGetWin32Thread()->MessageQueue
;
1538 IntReferenceMessageQueue(WindowObject
->MessageQueue
);
1539 WindowObject
->Parent
= (ParentWindow
? ParentWindow
->Self
: NULL
);
1540 if((OwnerWindow
= IntGetWindowObject(OwnerWindowHandle
)))
1542 WindowObject
->Owner
= OwnerWindowHandle
;
1543 IntReleaseWindowObject(OwnerWindow
);
1546 WindowObject
->Owner
= NULL
;
1549 WindowObject
->UserData
= 0;
1550 if ((((DWORD
)ClassObject
->lpfnWndProcA
& 0xFFFF0000) != 0xFFFF0000)
1551 && (((DWORD
)ClassObject
->lpfnWndProcW
& 0xFFFF0000) != 0xFFFF0000))
1553 WindowObject
->Unicode
= bUnicodeWindow
;
1557 WindowObject
->Unicode
= ClassObject
->Unicode
;
1559 WindowObject
->WndProcA
= ClassObject
->lpfnWndProcA
;
1560 WindowObject
->WndProcW
= ClassObject
->lpfnWndProcW
;
1561 WindowObject
->OwnerThread
= PsGetCurrentThread();
1562 WindowObject
->FirstChild
= NULL
;
1563 WindowObject
->LastChild
= NULL
;
1564 WindowObject
->PrevSibling
= NULL
;
1565 WindowObject
->NextSibling
= NULL
;
1567 /* extra window data */
1568 if (ClassObject
->cbWndExtra
!= 0)
1570 WindowObject
->ExtraData
= (PCHAR
)(WindowObject
+ 1);
1571 WindowObject
->ExtraDataSize
= ClassObject
->cbWndExtra
;
1572 RtlZeroMemory(WindowObject
->ExtraData
, WindowObject
->ExtraDataSize
);
1576 WindowObject
->ExtraData
= NULL
;
1577 WindowObject
->ExtraDataSize
= 0;
1580 InitializeListHead(&WindowObject
->PropListHead
);
1581 ExInitializeFastMutex(&WindowObject
->UpdateLock
);
1582 InitializeListHead(&WindowObject
->WndObjListHead
);
1583 ExInitializeFastMutex(&WindowObject
->WndObjListLock
);
1585 if (NULL
!= WindowName
->Buffer
)
1587 WindowObject
->WindowName
.MaximumLength
= WindowName
->MaximumLength
;
1588 WindowObject
->WindowName
.Length
= WindowName
->Length
;
1589 WindowObject
->WindowName
.Buffer
= ExAllocatePoolWithTag(PagedPool
, WindowName
->MaximumLength
,
1591 if (NULL
== WindowObject
->WindowName
.Buffer
)
1593 ClassDereferenceObject(ClassObject
);
1594 DPRINT1("Failed to allocate mem for window name\n");
1595 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1598 RtlCopyMemory(WindowObject
->WindowName
.Buffer
, WindowName
->Buffer
, WindowName
->MaximumLength
);
1602 RtlInitUnicodeString(&WindowObject
->WindowName
, NULL
);
1607 * This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1608 * tested for WS_POPUP
1610 if ((dwExStyle
& WS_EX_DLGMODALFRAME
) ||
1611 ((!(dwExStyle
& WS_EX_STATICEDGE
)) &&
1612 (dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
))))
1613 dwExStyle
|= WS_EX_WINDOWEDGE
;
1615 dwExStyle
&= ~WS_EX_WINDOWEDGE
;
1617 /* Correct the window style. */
1618 if (!(dwStyle
& WS_CHILD
))
1620 WindowObject
->Style
|= WS_CLIPSIBLINGS
;
1621 DPRINT("3: Style is now %lx\n", WindowObject
->Style
);
1622 if (!(dwStyle
& WS_POPUP
))
1624 WindowObject
->Style
|= WS_CAPTION
;
1625 WindowObject
->Flags
|= WINDOWOBJECT_NEED_SIZE
;
1626 DPRINT("4: Style is now %lx\n", WindowObject
->Style
);
1630 /* create system menu */
1631 if((WindowObject
->Style
& WS_SYSMENU
) &&
1632 (WindowObject
->Style
& WS_CAPTION
) == WS_CAPTION
)
1634 SystemMenu
= IntGetSystemMenu(WindowObject
, TRUE
, TRUE
);
1637 WindowObject
->SystemMenu
= SystemMenu
->MenuInfo
.Self
;
1638 IntReleaseMenuObject(SystemMenu
);
1642 /* Insert the window into the thread's window list. */
1643 InsertTailList (&PsGetWin32Thread()->WindowListHead
,
1644 &WindowObject
->ThreadListEntry
);
1646 /* Allocate a DCE for this window. */
1647 if (dwStyle
& CS_OWNDC
)
1649 WindowObject
->Dce
= DceAllocDCE(WindowObject
->Self
, DCE_WINDOW_DC
);
1651 /* FIXME: Handle "CS_CLASSDC" */
1659 Cs
.lpCreateParams
= lpParam
;
1660 Cs
.hInstance
= hInstance
;
1662 Cs
.hwndParent
= ParentWindowHandle
;
1668 Cs
.lpszName
= (LPCWSTR
) WindowName
;
1669 Cs
.lpszClass
= (LPCWSTR
) ClassName
;
1670 Cs
.dwExStyle
= dwExStyle
;
1671 CbtCreate
.lpcs
= &Cs
;
1672 CbtCreate
.hwndInsertAfter
= HWND_TOP
;
1673 if (co_HOOK_CallHooks(WH_CBT
, HCBT_CREATEWND
, (WPARAM
) Handle
, (LPARAM
) &CbtCreate
))
1675 if (NULL
!= ParentWindow
)
1677 IntReleaseWindowObject(ParentWindow
);
1680 /* FIXME - Delete window object and remove it from the thread windows list */
1681 /* FIXME - delete allocated DCE */
1683 ClassDereferenceObject(ClassObject
);
1684 DPRINT1("CBT-hook returned !0\n");
1693 /* default positioning for overlapped windows */
1694 if(!(WindowObject
->Style
& (WS_POPUP
| WS_CHILD
)))
1697 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
1698 BOOL CalculatedDefPosSize
= FALSE
;
1700 IntGetDesktopWorkArea(WindowObject
->OwnerThread
->Tcb
.Win32Thread
->Desktop
, &WorkArea
);
1703 ProcessParams
= PsGetCurrentProcess()->Peb
->ProcessParameters
;
1705 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1707 CalculatedDefPosSize
= IntCalcDefPosSize(ParentWindow
, WindowObject
, &rc
, TRUE
);
1709 if(ProcessParams
->WindowFlags
& STARTF_USEPOSITION
)
1711 ProcessParams
->WindowFlags
&= ~STARTF_USEPOSITION
;
1712 Pos
.x
= WorkArea
.left
+ ProcessParams
->StartingX
;
1713 Pos
.y
= WorkArea
.top
+ ProcessParams
->StartingY
;
1721 /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
1722 y is something else */
1723 if(y
!= CW_USEDEFAULT
&& y
!= CW_USEDEFAULT16
)
1728 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1730 if(!CalculatedDefPosSize
)
1732 IntCalcDefPosSize(ParentWindow
, WindowObject
, &rc
, FALSE
);
1734 if(ProcessParams
->WindowFlags
& STARTF_USESIZE
)
1736 ProcessParams
->WindowFlags
&= ~STARTF_USESIZE
;
1737 Size
.cx
= ProcessParams
->CountX
;
1738 Size
.cy
= ProcessParams
->CountY
;
1742 Size
.cx
= rc
.right
- rc
.left
;
1743 Size
.cy
= rc
.bottom
- rc
.top
;
1746 /* move the window if necessary */
1748 Pos
.x
= max(rc
.left
, 0);
1750 Pos
.y
= max(rc
.top
, 0);
1755 /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
1756 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1761 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1768 /* Initialize the window dimensions. */
1769 WindowObject
->WindowRect
.left
= Pos
.x
;
1770 WindowObject
->WindowRect
.top
= Pos
.y
;
1771 WindowObject
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1772 WindowObject
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1773 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1775 IntGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1776 ParentWindow
->ClientRect
.top
);
1778 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1781 * Get the size and position of the window.
1783 if ((dwStyle
& WS_THICKFRAME
) || !(dwStyle
& (WS_POPUP
| WS_CHILD
)))
1785 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1787 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1788 co_WinPosGetMinMaxInfo(WindowObject
, &MaxSize
, &MaxPos
, &MinTrack
,
1790 if (MaxSize
.x
< nWidth
) nWidth
= MaxSize
.x
;
1791 if (MaxSize
.y
< nHeight
) nHeight
= MaxSize
.y
;
1792 if (nWidth
< MinTrack
.x
) nWidth
= MinTrack
.x
;
1793 if (nHeight
< MinTrack
.y
) nHeight
= MinTrack
.y
;
1794 if (nWidth
< 0) nWidth
= 0;
1795 if (nHeight
< 0) nHeight
= 0;
1798 WindowObject
->WindowRect
.left
= Pos
.x
;
1799 WindowObject
->WindowRect
.top
= Pos
.y
;
1800 WindowObject
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1801 WindowObject
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1802 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1804 IntGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1805 ParentWindow
->ClientRect
.top
);
1807 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1809 /* FIXME: Initialize the window menu. */
1811 /* Send a NCCREATE message. */
1817 DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d\n", Cs
.style
, Cs
.dwExStyle
, Cs
.hwndParent
);
1818 DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1819 DPRINT("IntCreateWindowEx(): About to send NCCREATE message.\n");
1820 Result
= co_IntSendMessage(WindowObject
->Self
, WM_NCCREATE
, 0, (LPARAM
) &Cs
);
1823 /* FIXME: Cleanup. */
1824 if (NULL
!= ParentWindow
)
1826 IntReleaseWindowObject(ParentWindow
);
1828 DPRINT("IntCreateWindowEx(): NCCREATE message failed.\n");
1832 /* Calculate the non-client size. */
1833 MaxPos
.x
= WindowObject
->WindowRect
.left
;
1834 MaxPos
.y
= WindowObject
->WindowRect
.top
;
1835 DPRINT("IntCreateWindowEx(): About to get non-client size.\n");
1836 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1837 Result
= co_WinPosGetNonClientSize(WindowObject
->Self
,
1838 &WindowObject
->WindowRect
,
1839 &WindowObject
->ClientRect
);
1840 IntGdiOffsetRect(&WindowObject
->WindowRect
,
1841 MaxPos
.x
- WindowObject
->WindowRect
.left
,
1842 MaxPos
.y
- WindowObject
->WindowRect
.top
);
1844 if (NULL
!= ParentWindow
)
1846 /* link the window into the parent's child list */
1847 if ((dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
1849 PWINDOW_OBJECT PrevSibling
;
1850 if((PrevSibling
= ParentWindow
->LastChild
))
1851 IntReferenceWindowObject(PrevSibling
);
1852 /* link window as bottom sibling */
1853 IntLinkWindow(WindowObject
, ParentWindow
, PrevSibling
/*prev sibling*/);
1855 IntReleaseWindowObject(PrevSibling
);
1859 /* link window as top sibling (but after topmost siblings) */
1860 PWINDOW_OBJECT InsertAfter
, Sibling
;
1861 if (0 == (dwExStyle
& WS_EX_TOPMOST
))
1864 Sibling
= ParentWindow
->FirstChild
;
1865 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
1867 InsertAfter
= Sibling
;
1868 Sibling
= Sibling
->NextSibling
;
1875 if (NULL
!= InsertAfter
)
1877 IntReferenceWindowObject(InsertAfter
);
1879 IntLinkWindow(WindowObject
, ParentWindow
, InsertAfter
/* prev sibling */);
1880 if (NULL
!= InsertAfter
)
1882 IntReleaseWindowObject(InsertAfter
);
1887 /* Send the WM_CREATE message. */
1888 DPRINT("IntCreateWindowEx(): about to send CREATE message.\n");
1889 Result
= co_IntSendMessage(WindowObject
->Self
, WM_CREATE
, 0, (LPARAM
) &Cs
);
1890 if (Result
== (LRESULT
)-1)
1892 /* FIXME: Cleanup. */
1893 if (NULL
!= ParentWindow
)
1895 IntReleaseWindowObject(ParentWindow
);
1897 ClassDereferenceObject(ClassObject
);
1898 DPRINT("IntCreateWindowEx(): send CREATE message failed.\n");
1902 /* Send move and size messages. */
1903 if (!(WindowObject
->Flags
& WINDOWOBJECT_NEED_SIZE
))
1907 DPRINT("IntCreateWindow(): About to send WM_SIZE\n");
1909 if ((WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
) < 0 ||
1910 (WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
) < 0)
1912 DPRINT("Sending bogus WM_SIZE\n");
1915 lParam
= MAKE_LONG(WindowObject
->ClientRect
.right
-
1916 WindowObject
->ClientRect
.left
,
1917 WindowObject
->ClientRect
.bottom
-
1918 WindowObject
->ClientRect
.top
);
1919 co_IntSendMessage(WindowObject
->Self
, WM_SIZE
, SIZE_RESTORED
,
1922 DPRINT("IntCreateWindow(): About to send WM_MOVE\n");
1924 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1926 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
- ParentWindow
->ClientRect
.left
,
1927 WindowObject
->ClientRect
.top
- ParentWindow
->ClientRect
.top
);
1931 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
,
1932 WindowObject
->ClientRect
.top
);
1934 co_IntSendMessage(WindowObject
->Self
, WM_MOVE
, 0, lParam
);
1936 /* Call WNDOBJ change procs */
1937 IntEngWindowChanged(WindowObject
, WOC_RGN_CLIENT
);
1940 /* Show or maybe minimize or maximize the window. */
1941 if (WindowObject
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1946 SwFlag
= (WindowObject
->Style
& WS_MINIMIZE
) ? SW_MINIMIZE
:
1948 co_WinPosMinMaximize(WindowObject
, SwFlag
, &NewPos
);
1950 ((WindowObject
->Style
& WS_CHILD
) || UserGetActiveWindow()) ?
1951 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
:
1952 SWP_NOZORDER
| SWP_FRAMECHANGED
;
1953 DPRINT("IntCreateWindow(): About to minimize/maximize\n");
1954 DPRINT("%d,%d %dx%d\n", NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
);
1955 co_WinPosSetWindowPos(WindowObject
->Self
, 0, NewPos
.left
, NewPos
.top
,
1956 NewPos
.right
, NewPos
.bottom
, SwFlag
);
1959 /* Notify the parent window of a new child. */
1960 if ((WindowObject
->Style
& WS_CHILD
) &&
1961 (!(WindowObject
->ExStyle
& WS_EX_NOPARENTNOTIFY
)) && ParentWindow
)
1963 DPRINT("IntCreateWindow(): About to notify parent\n");
1964 co_IntSendMessage(ParentWindow
->Self
,
1966 MAKEWPARAM(WM_CREATE
, WindowObject
->IDMenu
),
1967 (LPARAM
)WindowObject
->Self
);
1970 if ((!hWndParent
) && (!HasOwner
)) {
1971 DPRINT("Sending CREATED notify\n");
1972 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Handle
);
1974 DPRINT("Not sending CREATED notify, %x %d\n", ParentWindow
, HasOwner
);
1977 if (NULL
!= ParentWindow
)
1979 IntReleaseWindowObject(ParentWindow
);
1982 /* Initialize and show the window's scrollbars */
1983 if (WindowObject
->Style
& WS_VSCROLL
)
1985 co_UserShowScrollBar(WindowObject
->Self
, SB_VERT
, TRUE
);
1987 if (WindowObject
->Style
& WS_HSCROLL
)
1989 co_UserShowScrollBar(WindowObject
->Self
, SB_HORZ
, TRUE
);
1992 if (dwStyle
& WS_VISIBLE
)
1994 DPRINT("IntCreateWindow(): About to show window\n");
1995 co_WinPosShowWindow(WindowObject
->Self
, dwShowMode
);
1998 DPRINT("IntCreateWindow(): = %X\n", Handle
);
1999 DPRINT("WindowObject->SystemMenu = 0x%x\n", WindowObject
->SystemMenu
);
2000 return((HWND
)Handle
);
2004 NtUserCreateWindowEx(DWORD dwExStyle
,
2005 PUNICODE_STRING UnsafeClassName
,
2006 PUNICODE_STRING UnsafeWindowName
,
2014 HINSTANCE hInstance
,
2017 BOOL bUnicodeWindow
)
2020 UNICODE_STRING WindowName
;
2021 UNICODE_STRING ClassName
;
2023 DECLARE_RETURN(HWND
);
2025 DPRINT("Enter NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
2026 UserEnterExclusive();
2028 /* Get the class name (string or atom) */
2029 Status
= MmCopyFromCaller(&ClassName
, UnsafeClassName
, sizeof(UNICODE_STRING
));
2030 if (! NT_SUCCESS(Status
))
2032 SetLastNtError(Status
);
2035 if (! IS_ATOM(ClassName
.Buffer
))
2037 Status
= IntSafeCopyUnicodeStringTerminateNULL(&ClassName
, UnsafeClassName
);
2038 if (! NT_SUCCESS(Status
))
2040 SetLastNtError(Status
);
2045 /* safely copy the window name */
2046 if (NULL
!= UnsafeWindowName
)
2048 Status
= IntSafeCopyUnicodeString(&WindowName
, UnsafeWindowName
);
2049 if (! NT_SUCCESS(Status
))
2051 if (! IS_ATOM(ClassName
.Buffer
))
2053 RtlFreeUnicodeString(&ClassName
);
2055 SetLastNtError(Status
);
2061 RtlInitUnicodeString(&WindowName
, NULL
);
2064 NewWindow
= co_IntCreateWindowEx(dwExStyle
, &ClassName
, &WindowName
, dwStyle
, x
, y
, nWidth
, nHeight
,
2065 hWndParent
, hMenu
, hInstance
, lpParam
, dwShowMode
, bUnicodeWindow
);
2067 RtlFreeUnicodeString(&WindowName
);
2068 if (! IS_ATOM(ClassName
.Buffer
))
2070 RtlFreeUnicodeString(&ClassName
);
2076 DPRINT("Leave NtUserCreateWindowEx, ret=%i\n",_ret_
);
2085 NtUserDeferWindowPos(HDWP WinPosInfo
,
2087 HWND WndInsertAfter
,
2100 BOOLEAN FASTCALL
co_UserDestroyWindow(PWINDOW_OBJECT Window
)
2109 /* Check for owner thread and desktop window */
2110 if ((Window
->OwnerThread
!= PsGetCurrentThread()) || IntIsDesktopWindow(Window
))
2112 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2116 /* Look whether the focus is within the tree of windows we will
2119 if (!co_WinPosShowWindow(Window
->Self
, SW_HIDE
))
2121 if (UserGetActiveWindow() == Window
->Self
)
2123 co_WinPosActivateOtherWindow(Window
);
2126 IntLockMessageQueue(Window
->MessageQueue
);
2127 if (Window
->MessageQueue
->ActiveWindow
== Window
->Self
)
2128 Window
->MessageQueue
->ActiveWindow
= NULL
;
2129 if (Window
->MessageQueue
->FocusWindow
== Window
->Self
)
2130 Window
->MessageQueue
->FocusWindow
= NULL
;
2131 if (Window
->MessageQueue
->CaptureWindow
== Window
->Self
)
2132 Window
->MessageQueue
->CaptureWindow
= NULL
;
2133 IntUnLockMessageQueue(Window
->MessageQueue
);
2134 IntDereferenceMessageQueue(Window
->MessageQueue
);
2137 if (co_HOOK_CallHooks(WH_CBT
, HCBT_DESTROYWND
, (WPARAM
) hwnd
, 0, TRUE
))
2143 IntEngWindowChanged(Window
, WOC_DELETE
);
2144 isChild
= (0 != (Window
->Style
& WS_CHILD
));
2149 if (! USER_IsExitingThread(GetCurrentThreadId()))
2151 send_parent_notify(hwnd
, WM_DESTROY
);
2154 else if (NULL
!= GetWindow(Wnd
, GW_OWNER
))
2156 co_HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
2157 /* FIXME: clean up palette - see "Internals" p.352 */
2161 if (!IntIsWindow(Window
->Self
))
2166 /* Recursively destroy owned windows */
2171 BOOL GotOne
= FALSE
;
2174 PWINDOW_OBJECT Child
, Desktop
;
2176 Desktop
= IntGetWindowObject(IntGetDesktopWindow());
2177 Children
= IntWinListChildren(Desktop
);
2178 IntReleaseWindowObject(Desktop
);
2181 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
2183 Child
= IntGetWindowObject(*ChildHandle
);
2186 if (Child
->Owner
!= Window
->Self
)
2188 IntReleaseWindowObject(Child
);
2192 if (IntWndBelongsToThread(Child
, PsGetWin32Thread()))
2194 co_UserDestroyWindow(Child
);
2195 IntReleaseWindowObject(Child
);
2200 if (Child
->Owner
!= NULL
)
2202 Child
->Owner
= NULL
;
2205 IntReleaseWindowObject(Child
);
2207 ExFreePool(Children
);
2216 if (!IntIsWindow(Window
->Self
))
2221 /* Destroy the window storage */
2222 co_IntDestroyWindow(Window
, PsGetWin32Process(), PsGetWin32Thread(), TRUE
);
2234 NtUserDestroyWindow(HWND Wnd
)
2236 PWINDOW_OBJECT Window
;
2237 DECLARE_RETURN(BOOLEAN
);
2239 DPRINT("Enter NtUserDestroyWindow\n");
2240 UserEnterExclusive();
2242 Window
= IntGetWindowObject(Wnd
);
2248 RETURN(co_UserDestroyWindow(Window
));
2251 DPRINT("Leave NtUserDestroyWindow, ret=%i\n",_ret_
);
2263 NtUserDrawMenuBarTemp(
2270 /* we'll use this function just for caching the menu bar */
2280 NtUserEndDeferWindowPosEx(DWORD Unknown0
,
2293 NtUserFillWindow(DWORD Unknown0
,
2305 IntFindWindow(PWINDOW_OBJECT Parent
,
2306 PWINDOW_OBJECT ChildAfter
,
2308 PUNICODE_STRING WindowName
)
2310 BOOL CheckWindowName
;
2316 CheckWindowName
= (WindowName
&& (WindowName
->Length
> 0));
2318 if((List
= IntWinListChildren(Parent
)))
2323 /* skip handles before and including ChildAfter */
2324 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->Self
));
2327 /* search children */
2330 PWINDOW_OBJECT Child
;
2331 if(!(Child
= IntGetWindowObject(*(phWnd
++))))
2336 /* Do not send WM_GETTEXT messages in the kernel mode version!
2337 The user mode version however calls GetWindowText() which will
2338 send WM_GETTEXT messages to windows belonging to its processes */
2339 if((!CheckWindowName
|| !RtlCompareUnicodeString(WindowName
, &(Child
->WindowName
), FALSE
)) &&
2340 (!ClassAtom
|| Child
->Class
->Atom
== ClassAtom
))
2343 IntReleaseWindowObject(Child
);
2347 IntReleaseWindowObject(Child
);
2357 * Searches a window's children for a window with the specified
2360 * hwndParent = The window whose childs are to be searched.
2362 * HWND_MESSAGE = message-only windows
2364 * hwndChildAfter = Search starts after this child window.
2365 * NULL = start from beginning
2367 * ucClassName = Class name to search for
2368 * Reguired parameter.
2370 * ucWindowName = Window name
2371 * ->Buffer == NULL = don't care
2374 * The HWND of the window if it was found, otherwise NULL
2380 NtUserFindWindowEx(HWND hwndParent
,
2381 HWND hwndChildAfter
,
2382 PUNICODE_STRING ucClassName
,
2383 PUNICODE_STRING ucWindowName
)
2385 PWINDOW_OBJECT Parent
, ChildAfter
;
2386 UNICODE_STRING ClassName
, WindowName
;
2388 HWND Desktop
, Ret
= NULL
;
2390 DECLARE_RETURN(HWND
);
2392 DPRINT("Enter NtUserFindWindowEx\n");
2395 Desktop
= IntGetCurrentThreadDesktopWindow();
2397 if(hwndParent
== NULL
)
2398 hwndParent
= Desktop
;
2400 else if(hwndParent == HWND_MESSAGE)
2402 hwndParent = IntGetMessageWindow();
2406 if(!(Parent
= IntGetWindowObject(hwndParent
)))
2408 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2413 if(hwndChildAfter
&& !(ChildAfter
= IntGetWindowObject(hwndChildAfter
)))
2415 IntReleaseWindowObject(Parent
);
2416 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2420 /* copy the window name */
2421 Status
= IntSafeCopyUnicodeString(&WindowName
, ucWindowName
);
2422 if(!NT_SUCCESS(Status
))
2424 SetLastNtError(Status
);
2428 /* safely copy the class name */
2429 Status
= MmCopyFromCaller(&ClassName
, ucClassName
, sizeof(UNICODE_STRING
));
2430 if(!NT_SUCCESS(Status
))
2432 SetLastNtError(Status
);
2435 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2438 /* safely copy the class name string (NULL terminated because class-lookup
2440 buf
= ExAllocatePoolWithTag(PagedPool
, ClassName
.Length
+ sizeof(WCHAR
), TAG_STRING
);
2443 SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES
);
2446 Status
= MmCopyFromCaller(buf
, ClassName
.Buffer
, ClassName
.Length
);
2447 if(!NT_SUCCESS(Status
))
2450 SetLastNtError(Status
);
2453 ClassName
.Buffer
= buf
;
2454 /* make sure the string is null-terminated */
2455 buf
+= ClassName
.Length
/ sizeof(WCHAR
);
2459 /* find the class object */
2460 if(ClassName
.Buffer
)
2462 PWINSTATION_OBJECT WinStaObject
;
2464 if (PsGetWin32Thread()->Desktop
== NULL
)
2466 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2470 WinStaObject
= PsGetWin32Thread()->Desktop
->WindowStation
;
2472 Status
= RtlLookupAtomInAtomTable(
2473 WinStaObject
->AtomTable
,
2477 if (!NT_SUCCESS(Status
))
2479 DPRINT1("Failed to lookup class atom!\n");
2480 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST
);
2485 if(Parent
->Self
== Desktop
)
2488 PWINDOW_OBJECT TopLevelWindow
;
2489 BOOLEAN CheckWindowName
;
2490 BOOLEAN CheckClassName
;
2491 BOOLEAN WindowMatches
;
2492 BOOLEAN ClassMatches
;
2494 /* windows searches through all top-level windows if the parent is the desktop
2497 if((List
= IntWinListChildren(Parent
)))
2503 /* skip handles before and including ChildAfter */
2504 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->Self
));
2507 CheckWindowName
= WindowName
.Length
> 0;
2508 CheckClassName
= ClassName
.Buffer
!= NULL
;
2510 /* search children */
2513 if(!(TopLevelWindow
= IntGetWindowObject(*(phWnd
++))))
2518 /* Do not send WM_GETTEXT messages in the kernel mode version!
2519 The user mode version however calls GetWindowText() which will
2520 send WM_GETTEXT messages to windows belonging to its processes */
2521 WindowMatches
= !CheckWindowName
|| !RtlCompareUnicodeString(
2522 &WindowName
, &TopLevelWindow
->WindowName
, FALSE
);
2523 ClassMatches
= !CheckClassName
||
2524 ClassAtom
== TopLevelWindow
->Class
->Atom
;
2526 if (WindowMatches
&& ClassMatches
)
2528 Ret
= TopLevelWindow
->Self
;
2529 IntReleaseWindowObject(TopLevelWindow
);
2533 if (IntFindWindow(TopLevelWindow
, NULL
, ClassAtom
, &WindowName
))
2535 /* window returns the handle of the top-level window, in case it found
2537 Ret
= TopLevelWindow
->Self
;
2538 IntReleaseWindowObject(TopLevelWindow
);
2542 IntReleaseWindowObject(TopLevelWindow
);
2548 Ret
= IntFindWindow(Parent
, ChildAfter
, ClassAtom
, &WindowName
);
2551 if(Ret
== NULL
&& hwndParent
== NULL
&& hwndChildAfter
== NULL
)
2553 /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
2554 search the message-only windows. Should this also be done if
2555 Parent is the desktop window??? */
2556 PWINDOW_OBJECT MsgWindows
;
2558 if((MsgWindows
= IntGetWindowObject(IntGetMessageWindow())))
2560 Ret
= IntFindWindow(MsgWindows
, ChildAfter
, ClassAtom
, &WindowName
);
2561 IntReleaseWindowObject(MsgWindows
);
2567 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2568 ExFreePool(ClassName
.Buffer
);
2571 RtlFreeUnicodeString(&WindowName
);
2575 IntReleaseWindowObject(ChildAfter
);
2576 IntReleaseWindowObject(Parent
);
2581 DPRINT("Leave NtUserFindWindowEx, ret %i\n",_ret_
);
2591 NtUserFlashWindowEx(DWORD Unknown0
)
2602 HWND FASTCALL
UserGetAncestor(HWND hWnd
, UINT Type
)
2604 PWINDOW_OBJECT Wnd
, WndAncestor
, Parent
;
2607 if (hWnd
== IntGetDesktopWindow())
2612 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2614 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2622 WndAncestor
= IntGetParentObject(Wnd
);
2635 if(!(Parent
= IntGetParentObject(WndAncestor
)))
2639 if(IntIsDesktopWindow(Parent
))
2641 IntReleaseWindowObject(Parent
);
2645 IntReleaseWindowObject(tmp
);
2646 WndAncestor
= Parent
;
2654 IntReferenceWindowObject(WndAncestor
);
2659 Parent
= IntGetParent(WndAncestor
);
2660 IntReleaseWindowObject(Old
);
2665 WndAncestor
= Parent
;
2672 IntReleaseWindowObject(Wnd
);
2677 hWndAncestor
= (WndAncestor
? WndAncestor
->Self
: NULL
);
2678 IntReleaseWindowObject(Wnd
);
2680 if(WndAncestor
&& (WndAncestor
!= Wnd
))
2681 IntReleaseWindowObject(WndAncestor
);
2683 return hWndAncestor
;
2692 NtUserGetAncestor(HWND hWnd
, UINT Type
)
2694 DECLARE_RETURN(HWND
);
2696 DPRINT("Enter NtUserGetAncestor\n");
2697 UserEnterExclusive();
2699 RETURN(UserGetAncestor(hWnd
, Type
));
2702 DPRINT("Leave NtUserGetAncestor, ret=%i\n",_ret_
);
2708 * Returns client window rectangle relative to the upper-left corner of client area.
2710 * \param hWnd window handle.
2711 * \param Rect pointer to the buffer where the coordinates are returned.
2718 NtUserGetClientRect(HWND hWnd
, LPRECT Rect
)
2720 PWINDOW_OBJECT WindowObject
;
2722 DECLARE_RETURN(BOOL
);
2724 DPRINT("Enter NtUserGetClientRect\n");
2727 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
2729 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2733 IntGetClientRect(WindowObject
, &SafeRect
);
2734 IntReleaseWindowObject(WindowObject
);
2736 if(!NT_SUCCESS(MmCopyToCaller(Rect
, &SafeRect
, sizeof(RECT
))))
2743 DPRINT("Leave NtUserGetClientRect, ret=%i\n",_ret_
);
2753 NtUserGetDesktopWindow()
2755 DECLARE_RETURN(HWND
);
2757 DPRINT("Enter NtUserGetDesktopWindow\n");
2760 RETURN( IntGetDesktopWindow());
2763 DPRINT("Leave NtUserGetDesktopWindow, ret=%i\n",_ret_
);
2773 NtUserGetInternalWindowPos(DWORD Unknown0
,
2787 NtUserGetLastActivePopup(HWND hWnd
)
2790 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2791 * not changed anywhere.
2792 * -- Filip, 01/nov/2003
2798 IntAcquireWinLockShared();
2800 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2802 IntReleaseWinLock();
2803 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2807 hWndLastPopup
= Wnd
->hWndLastPopup
;
2809 IntReleaseWinLock();
2811 return hWndLastPopup
;
2820 * The NtUserGetParent function retrieves a handle to the specified window's
2824 * Note that, despite its name, this function can return an owner window
2825 * instead of a parent window.
2832 NtUserGetParent(HWND hWnd
)
2834 PWINDOW_OBJECT Wnd
, WndParent
;
2835 HWND hWndParent
= NULL
;
2836 DECLARE_RETURN(HWND
);
2838 DPRINT("Enter NtUserGetParent\n");
2839 UserEnterExclusive();
2841 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2843 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2847 WndParent
= IntGetParent(Wnd
);
2850 hWndParent
= WndParent
->Self
;
2851 IntReleaseWindowObject(WndParent
);
2854 IntReleaseWindowObject(Wnd
);
2856 RETURN( hWndParent
);
2859 DPRINT("Leave NtUserGetParent, ret=%i\n",_ret_
);
2868 UserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2870 PWINDOW_OBJECT Wnd
= NULL
, WndParent
= NULL
, WndOldParent
;
2871 HWND hWndOldParent
= NULL
;
2873 if (IntIsBroadcastHwnd(hWndChild
) || IntIsBroadcastHwnd(hWndNewParent
))
2875 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2879 if (hWndChild
== IntGetDesktopWindow())
2881 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2887 if (!(WndParent
= IntGetWindowObject(hWndNewParent
)))
2889 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2895 if (!(WndParent
= IntGetWindowObject(IntGetDesktopWindow())))
2897 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2902 if (!(Wnd
= IntGetWindowObject(hWndChild
)))
2904 IntReleaseWindowObject(WndParent
);
2905 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2909 WndOldParent
= IntSetParent(Wnd
, WndParent
);
2913 hWndOldParent
= WndOldParent
->Self
;
2914 IntReleaseWindowObject(WndOldParent
);
2917 IntReleaseWindowObject(Wnd
);
2918 IntReleaseWindowObject(WndParent
);
2920 return( hWndOldParent
);
2928 * The NtUserSetParent function changes the parent window of the specified
2932 * The new parent window and the child window must belong to the same
2933 * application. If the window identified by the hWndChild parameter is
2934 * visible, the system performs the appropriate redrawing and repainting.
2935 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2936 * or WS_POPUP window styles of the window whose parent is being changed.
2943 NtUserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2945 DECLARE_RETURN(HWND
);
2947 DPRINT("Enter NtUserSetParent\n");
2948 UserEnterExclusive();
2950 RETURN( UserSetParent(hWndChild
, hWndNewParent
));
2953 DPRINT("Leave NtUserSetParent, ret=%i\n",_ret_
);
2961 HWND FASTCALL
UserGetShellWindow()
2963 PWINSTATION_OBJECT WinStaObject
;
2966 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
2971 if (!NT_SUCCESS(Status
))
2973 SetLastNtError(Status
);
2977 Ret
= (HWND
)WinStaObject
->ShellWindow
;
2979 ObDereferenceObject(WinStaObject
);
2985 * NtUserGetShellWindow
2987 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
2994 NtUserGetShellWindow()
2996 DECLARE_RETURN(HWND
);
2998 DPRINT("Enter NtUserGetShellWindow\n");
3001 RETURN( UserGetShellWindow() );
3004 DPRINT("Leave NtUserGetShellWindow, ret=%i\n",_ret_
);
3010 * NtUserSetShellWindowEx
3012 * This is undocumented function to set global shell window. The global
3013 * shell window has special handling of window position.
3020 NtUserSetShellWindowEx(HWND hwndShell
, HWND hwndListView
)
3022 PWINSTATION_OBJECT WinStaObject
;
3023 DECLARE_RETURN(BOOL
);
3025 DPRINT("Enter NtUserSetShellWindowEx\n");
3026 UserEnterExclusive();
3028 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
3033 if (!NT_SUCCESS(Status
))
3035 SetLastNtError(Status
);
3040 * Test if we are permitted to change the shell window.
3042 if (WinStaObject
->ShellWindow
)
3044 ObDereferenceObject(WinStaObject
);
3049 * Move shell window into background.
3051 if (hwndListView
&& hwndListView
!= hwndShell
)
3054 * Disabled for now to get Explorer working.
3055 * -- Filip, 01/nov/2003
3058 co_WinPosSetWindowPos(hwndListView
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
3061 if (UserGetWindowLong(hwndListView
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
3063 ObDereferenceObject(WinStaObject
);
3068 if (UserGetWindowLong(hwndShell
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
3070 ObDereferenceObject(WinStaObject
);
3074 co_WinPosSetWindowPos(hwndShell
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
3076 WinStaObject
->ShellWindow
= hwndShell
;
3077 WinStaObject
->ShellListView
= hwndListView
;
3079 ObDereferenceObject(WinStaObject
);
3083 DPRINT("Leave NtUserSetShellWindowEx, ret=%i\n",_ret_
);
3089 * NtUserGetSystemMenu
3091 * The NtUserGetSystemMenu function allows the application to access the
3092 * window menu (also known as the system menu or the control menu) for
3093 * copying and modifying.
3097 * Handle to the window that will own a copy of the window menu.
3099 * Specifies the action to be taken. If this parameter is FALSE,
3100 * NtUserGetSystemMenu returns a handle to the copy of the window menu
3101 * currently in use. The copy is initially identical to the window menu
3102 * but it can be modified.
3103 * If this parameter is TRUE, GetSystemMenu resets the window menu back
3104 * to the default state. The previous window menu, if any, is destroyed.
3107 * If the bRevert parameter is FALSE, the return value is a handle to a
3108 * copy of the window menu. If the bRevert parameter is TRUE, the return
3116 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
3119 PWINDOW_OBJECT WindowObject
;
3120 PMENU_OBJECT MenuObject
;
3121 DECLARE_RETURN(HMENU
);
3123 DPRINT("Enter NtUserGetSystemMenu\n");
3126 WindowObject
= IntGetWindowObject((HWND
)hWnd
);
3127 if (WindowObject
== NULL
)
3129 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3133 MenuObject
= IntGetSystemMenu(WindowObject
, bRevert
, FALSE
);
3136 Result
= MenuObject
->MenuInfo
.Self
;
3137 IntReleaseMenuObject(MenuObject
);
3140 IntReleaseWindowObject(WindowObject
);
3144 DPRINT("Leave NtUserGetSystemMenu, ret=%i\n",_ret_
);
3150 * NtUserSetSystemMenu
3157 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
3159 BOOL Result
= FALSE
;
3160 PWINDOW_OBJECT WindowObject
;
3161 PMENU_OBJECT MenuObject
;
3162 DECLARE_RETURN(BOOL
);
3164 DPRINT("Enter NtUserSetSystemMenu\n");
3165 UserEnterExclusive();
3167 WindowObject
= IntGetWindowObject(hWnd
);
3170 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3177 * Assign new menu handle.
3179 MenuObject
= IntGetMenuObject(hMenu
);
3182 IntReleaseWindowObject(WindowObject
);
3183 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
3187 Result
= IntSetSystemMenu(WindowObject
, MenuObject
);
3189 IntReleaseMenuObject(MenuObject
);
3192 IntReleaseWindowObject(WindowObject
);
3197 DPRINT("Leave NtUserSetSystemMenu, ret=%i\n",_ret_
);
3206 UserGetWindow(HWND hWnd
, UINT Relationship
)
3208 PWINDOW_OBJECT Parent
, WindowObject
;
3209 HWND hWndResult
= NULL
;
3211 if (!(WindowObject
= IntGetWindowObject(hWnd
))) return NULL
;
3213 switch (Relationship
)
3216 if((Parent
= IntGetParentObject(WindowObject
)))
3218 if (Parent
->FirstChild
)
3219 hWndResult
= Parent
->FirstChild
->Self
;
3221 IntReleaseWindowObject(Parent
);
3226 if((Parent
= IntGetParentObject(WindowObject
)))
3228 if (Parent
->LastChild
)
3229 hWndResult
= Parent
->LastChild
->Self
;
3231 IntReleaseWindowObject(Parent
);
3236 if (WindowObject
->NextSibling
)
3237 hWndResult
= WindowObject
->NextSibling
->Self
;
3241 if (WindowObject
->PrevSibling
)
3242 hWndResult
= WindowObject
->PrevSibling
->Self
;
3246 if((Parent
= IntGetWindowObject(WindowObject
->Owner
)))
3248 hWndResult
= Parent
->Self
;
3249 IntReleaseWindowObject(Parent
);
3253 if (WindowObject
->FirstChild
)
3254 hWndResult
= WindowObject
->FirstChild
->Self
;
3258 IntReleaseWindowObject(WindowObject
);
3268 * The NtUserGetWindow function retrieves a handle to a window that has the
3269 * specified relationship (Z order or owner) to the specified window.
3276 NtUserGetWindow(HWND hWnd
, UINT Relationship
)
3278 DECLARE_RETURN(HWND
);
3280 DPRINT("Enter NtUserGetWindow\n");
3283 RETURN(UserGetWindow(hWnd
, Relationship
));
3286 DPRINT("Leave NtUserGetWindow, ret=%i\n",_ret_
);
3295 * NtUserGetWindowLong
3297 * The NtUserGetWindowLong function retrieves information about the specified
3298 * window. The function also retrieves the 32-bit (long) value at the
3299 * specified offset into the extra window memory.
3306 UserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3308 PWINDOW_OBJECT WindowObject
, Parent
;
3311 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3313 WindowObject
= IntGetWindowObject(hWnd
);
3314 if (WindowObject
== NULL
)
3316 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3321 * WndProc is only available to the owner process
3323 if (GWL_WNDPROC
== Index
3324 && WindowObject
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
3326 SetLastWin32Error(ERROR_ACCESS_DENIED
);
3330 if ((INT
)Index
>= 0)
3332 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
3334 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3337 Result
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
3344 Result
= WindowObject
->ExStyle
;
3348 Result
= WindowObject
->Style
;
3353 Result
= (LONG
) WindowObject
->WndProcA
;
3355 Result
= (LONG
) WindowObject
->WndProcW
;
3359 Result
= (LONG
) WindowObject
->Instance
;
3362 case GWL_HWNDPARENT
:
3363 Parent
= IntGetWindowObject(WindowObject
->Parent
);
3366 if (Parent
&& Parent
->Self
== IntGetDesktopWindow())
3367 Result
= (LONG
) UserGetWindow(WindowObject
->Self
, GW_OWNER
);
3369 Result
= (LONG
) Parent
->Self
;
3370 IntReleaseWindowObject(Parent
);
3375 Result
= (LONG
) WindowObject
->IDMenu
;
3379 Result
= WindowObject
->UserData
;
3383 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index
);
3384 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3390 IntReleaseWindowObject(WindowObject
);
3399 * NtUserGetWindowLong
3401 * The NtUserGetWindowLong function retrieves information about the specified
3402 * window. The function also retrieves the 32-bit (long) value at the
3403 * specified offset into the extra window memory.
3410 NtUserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3412 DECLARE_RETURN(LONG
);
3414 DPRINT("Enter NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3415 UserEnterExclusive();
3417 RETURN(UserGetWindowLong(hWnd
, Index
, Ansi
));
3420 DPRINT("Leave NtUserGetWindowLong, ret=%i\n",_ret_
);
3429 UserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3431 PWINDOW_OBJECT WindowObject
, Parent
;
3432 PWINSTATION_OBJECT WindowStation
;
3436 if (hWnd
== IntGetDesktopWindow())
3438 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3442 WindowObject
= IntGetWindowObject(hWnd
);
3443 if (WindowObject
== NULL
)
3445 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3449 if ((INT
)Index
>= 0)
3451 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
3453 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3454 IntReleaseWindowObject(WindowObject
);
3457 OldValue
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
3458 *((LONG
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
3465 OldValue
= (LONG
) WindowObject
->ExStyle
;
3466 Style
.styleOld
= OldValue
;
3467 Style
.styleNew
= NewValue
;
3470 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3472 WindowStation
= WindowObject
->OwnerThread
->Tcb
.Win32Thread
->Desktop
->WindowStation
;
3475 if (hWnd
== WindowStation
->ShellWindow
|| hWnd
== WindowStation
->ShellListView
)
3476 Style
.styleNew
&= ~WS_EX_TOPMOST
;
3479 co_IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3480 WindowObject
->ExStyle
= (DWORD
)Style
.styleNew
;
3481 co_IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3485 OldValue
= (LONG
) WindowObject
->Style
;
3486 Style
.styleOld
= OldValue
;
3487 Style
.styleNew
= NewValue
;
3488 co_IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_STYLE
, (LPARAM
) &Style
);
3489 WindowObject
->Style
= (DWORD
)Style
.styleNew
;
3490 co_IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_STYLE
, (LPARAM
) &Style
);
3494 /* FIXME: should check if window belongs to current process */
3497 OldValue
= (LONG
) WindowObject
->WndProcA
;
3498 WindowObject
->WndProcA
= (WNDPROC
) NewValue
;
3499 WindowObject
->WndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,FALSE
);
3500 WindowObject
->Unicode
= FALSE
;
3504 OldValue
= (LONG
) WindowObject
->WndProcW
;
3505 WindowObject
->WndProcW
= (WNDPROC
) NewValue
;
3506 WindowObject
->WndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,TRUE
);
3507 WindowObject
->Unicode
= TRUE
;
3512 OldValue
= (LONG
) WindowObject
->Instance
;
3513 WindowObject
->Instance
= (HINSTANCE
) NewValue
;
3516 case GWL_HWNDPARENT
:
3517 Parent
= IntGetParentObject(WindowObject
);
3518 if (Parent
&& (Parent
->Self
== IntGetDesktopWindow()))
3519 OldValue
= (LONG
) IntSetOwner(WindowObject
->Self
, (HWND
) NewValue
);
3521 OldValue
= (LONG
) UserSetParent(WindowObject
->Self
, (HWND
) NewValue
);
3523 IntReleaseWindowObject(Parent
);
3527 OldValue
= (LONG
) WindowObject
->IDMenu
;
3528 WindowObject
->IDMenu
= (UINT
) NewValue
;
3532 OldValue
= WindowObject
->UserData
;
3533 WindowObject
->UserData
= NewValue
;
3537 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index
);
3538 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3544 IntReleaseWindowObject(WindowObject
);
3552 * NtUserSetWindowLong
3554 * The NtUserSetWindowLong function changes an attribute of the specified
3555 * window. The function also sets the 32-bit (long) value at the specified
3556 * offset into the extra window memory.
3563 NtUserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3565 DECLARE_RETURN(LONG
);
3567 DPRINT("Enter NtUserSetWindowLong\n");
3568 UserEnterExclusive();
3570 RETURN( UserSetWindowLong(hWnd
, Index
, NewValue
, Ansi
));
3573 DPRINT("Leave NtUserSetWindowLong, ret=%i\n",_ret_
);
3579 * NtUserSetWindowWord
3581 * Legacy function similar to NtUserSetWindowLong.
3588 NtUserSetWindowWord(HWND hWnd
, INT Index
, WORD NewValue
)
3590 PWINDOW_OBJECT WindowObject
;
3592 DECLARE_RETURN(WORD
);
3594 DPRINT("Enter NtUserSetWindowWord\n");
3595 UserEnterExclusive();
3601 case GWL_HWNDPARENT
:
3602 RETURN( UserSetWindowLong(hWnd
, Index
, (UINT
)NewValue
, TRUE
));
3606 SetLastWin32Error(ERROR_INVALID_INDEX
);
3611 WindowObject
= IntGetWindowObject(hWnd
);
3612 if (WindowObject
== NULL
)
3614 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3618 if (Index
> WindowObject
->ExtraDataSize
- sizeof(WORD
))
3620 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3621 IntReleaseWindowObject(WindowObject
);
3625 OldValue
= *((WORD
*)(WindowObject
->ExtraData
+ Index
));
3626 *((WORD
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
3628 IntReleaseWindowObject(WindowObject
);
3633 DPRINT("Leave NtUserSetWindowWord, ret=%i\n",_ret_
);
3642 NtUserGetWindowPlacement(HWND hWnd
,
3643 WINDOWPLACEMENT
*lpwndpl
)
3645 PWINDOW_OBJECT WindowObject
;
3646 PINTERNALPOS InternalPos
;
3648 WINDOWPLACEMENT Safepl
;
3650 DECLARE_RETURN(BOOL
);
3652 DPRINT("Enter NtUserGetWindowPlacement\n");
3655 WindowObject
= IntGetWindowObject(hWnd
);
3656 if (WindowObject
== NULL
)
3658 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3662 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3663 if(!NT_SUCCESS(Status
))
3665 SetLastNtError(Status
);
3666 IntReleaseWindowObject(WindowObject
);
3669 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3671 IntReleaseWindowObject(WindowObject
);
3676 Safepl
.showCmd
= ((WindowObject
->Flags
& WINDOWOBJECT_RESTOREMAX
) ? SW_MAXIMIZE
: SW_SHOWNORMAL
);
3678 Size
.x
= WindowObject
->WindowRect
.left
;
3679 Size
.y
= WindowObject
->WindowRect
.top
;
3680 InternalPos
= WinPosInitInternalPos(WindowObject
, &Size
,
3681 &WindowObject
->WindowRect
);
3684 Safepl
.rcNormalPosition
= InternalPos
->NormalRect
;
3685 Safepl
.ptMinPosition
= InternalPos
->IconPos
;
3686 Safepl
.ptMaxPosition
= InternalPos
->MaxPos
;
3690 IntReleaseWindowObject(WindowObject
);
3694 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3695 if(!NT_SUCCESS(Status
))
3697 SetLastNtError(Status
);
3698 IntReleaseWindowObject(WindowObject
);
3702 IntReleaseWindowObject(WindowObject
);
3706 DPRINT("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
3713 * Return the dimension of the window in the screen coordinates.
3714 * \param hWnd window handle.
3715 * \param Rect pointer to the buffer where the coordinates are returned.
3721 NtUserGetWindowRect(HWND hWnd
, LPRECT Rect
)
3725 DECLARE_RETURN(BOOL
);
3727 DPRINT("Enter NtUserGetWindowRect\n");
3730 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3732 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3735 Status
= MmCopyToCaller(Rect
, &Wnd
->WindowRect
, sizeof(RECT
));
3736 if (!NT_SUCCESS(Status
))
3738 IntReleaseWindowObject(Wnd
);
3739 SetLastNtError(Status
);
3743 IntReleaseWindowObject(Wnd
);
3747 DPRINT("Leave NtUserGetWindowRect, ret=%i\n",_ret_
);
3757 NtUserGetWindowThreadProcessId(HWND hWnd
, LPDWORD UnsafePid
)
3761 DECLARE_RETURN(DWORD
);
3763 DPRINT("Enter NtUserGetWindowThreadProcessId\n");
3766 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3768 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3772 tid
= (DWORD
)IntGetWndThreadId(Wnd
);
3773 pid
= (DWORD
)IntGetWndProcessId(Wnd
);
3775 if (UnsafePid
) MmCopyToCaller(UnsafePid
, &pid
, sizeof(DWORD
));
3780 DPRINT("Leave NtUserGetWindowThreadProcessId, ret=%i\n",_ret_
);
3790 NtUserLockWindowUpdate(DWORD Unknown0
)
3810 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3811 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3812 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3816 QueryWindow based on KJK::Hyperion and James Tabor.
3818 0 = QWUniqueProcessId
3819 1 = QWUniqueThreadId
3820 4 = QWIsHung Implements IsHungAppWindow found
3823 9 = QWKillWindow When I called this with hWnd ==
3824 DesktopWindow, it shutdown the system
3831 NtUserQueryWindow(HWND hWnd
, DWORD Index
)
3833 PWINDOW_OBJECT Window
= IntGetWindowObject(hWnd
);
3835 DECLARE_RETURN(UINT
);
3837 DPRINT("Enter NtUserQueryWindow\n");
3842 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3848 case QUERY_WINDOW_UNIQUE_PROCESS_ID
:
3849 Result
= (DWORD
)IntGetWndProcessId(Window
);
3852 case QUERY_WINDOW_UNIQUE_THREAD_ID
:
3853 Result
= (DWORD
)IntGetWndThreadId(Window
);
3856 case QUERY_WINDOW_ISHUNG
:
3857 Result
= (DWORD
)MsqIsHung(Window
->MessageQueue
);
3861 Result
= (DWORD
)NULL
;
3865 IntReleaseWindowObject(Window
);
3871 DPRINT("Leave NtUserQueryWindow, ret=%i\n",_ret_
);
3881 NtUserRealChildWindowFromPoint(DWORD Unknown0
,
3895 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe
)
3897 UNICODE_STRING SafeMessageName
;
3900 DECLARE_RETURN(UINT
);
3902 DPRINT("Enter NtUserRegisterWindowMessage\n");
3903 UserEnterExclusive();
3905 if(MessageNameUnsafe
== NULL
)
3907 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3911 Status
= IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName
, MessageNameUnsafe
);
3912 if(!NT_SUCCESS(Status
))
3914 SetLastNtError(Status
);
3918 Ret
= (UINT
)IntAddAtom(SafeMessageName
.Buffer
);
3920 RtlFreeUnicodeString(&SafeMessageName
);
3924 DPRINT("Leave NtUserRegisterWindowMessage, ret=%i\n",_ret_
);
3934 NtUserSetImeOwnerWindow(DWORD Unknown0
,
3947 NtUserSetInternalWindowPos(DWORD Unknown0
,
3963 NtUserSetLayeredWindowAttributes(DWORD Unknown0
,
3978 NtUserSetLogonNotifyWindow(DWORD Unknown0
)
3995 PWINDOW_OBJECT WindowObject
;
3997 DECLARE_RETURN(BOOL
);
3999 DPRINT("Enter NtUserSetMenu\n");
4000 UserEnterExclusive();
4002 WindowObject
= IntGetWindowObject((HWND
) Wnd
);
4003 if (NULL
== WindowObject
)
4005 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4009 if (! IntSetMenu(WindowObject
, Menu
, &Changed
))
4011 IntReleaseWindowObject(WindowObject
);
4015 IntReleaseWindowObject(WindowObject
);
4017 if (Changed
&& Repaint
)
4019 co_WinPosSetWindowPos(Wnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
4020 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
4026 DPRINT("Leave NtUserSetMenu, ret=%i\n",_ret_
);
4036 NtUserSetWindowFNID(DWORD Unknown0
,
4050 NtUserSetWindowPlacement(HWND hWnd
,
4051 WINDOWPLACEMENT
*lpwndpl
)
4053 PWINDOW_OBJECT WindowObject
;
4054 WINDOWPLACEMENT Safepl
;
4056 DECLARE_RETURN(BOOL
);
4058 DPRINT("Enter NtUserSetWindowPlacement\n");
4059 UserEnterExclusive();
4061 WindowObject
= IntGetWindowObject(hWnd
);
4062 if (WindowObject
== NULL
)
4064 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4067 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
4068 if(!NT_SUCCESS(Status
))
4070 SetLastNtError(Status
);
4071 IntReleaseWindowObject(WindowObject
);
4074 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
4076 IntReleaseWindowObject(WindowObject
);
4080 if ((WindowObject
->Style
& (WS_MAXIMIZE
| WS_MINIMIZE
)) == 0)
4082 co_WinPosSetWindowPos(WindowObject
->Self
, NULL
,
4083 Safepl
.rcNormalPosition
.left
, Safepl
.rcNormalPosition
.top
,
4084 Safepl
.rcNormalPosition
.right
- Safepl
.rcNormalPosition
.left
,
4085 Safepl
.rcNormalPosition
.bottom
- Safepl
.rcNormalPosition
.top
,
4086 SWP_NOZORDER
| SWP_NOACTIVATE
);
4089 /* FIXME - change window status */
4090 co_WinPosShowWindow(WindowObject
->Self
, Safepl
.showCmd
);
4092 if (WindowObject
->InternalPos
== NULL
)
4093 WindowObject
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
4094 WindowObject
->InternalPos
->NormalRect
= Safepl
.rcNormalPosition
;
4095 WindowObject
->InternalPos
->IconPos
= Safepl
.ptMinPosition
;
4096 WindowObject
->InternalPos
->MaxPos
= Safepl
.ptMaxPosition
;
4098 IntReleaseWindowObject(WindowObject
);
4102 DPRINT("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
4114 HWND hWndInsertAfter
,
4121 DECLARE_RETURN(BOOL
);
4123 DPRINT("Enter NtUserSetWindowPos\n");
4124 UserEnterExclusive();
4126 RETURN( co_WinPosSetWindowPos(hWnd
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
));
4129 DPRINT("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
4136 IntGetWindowRgn(HWND hWnd
, HRGN hRgn
)
4139 PWINDOW_OBJECT WindowObject
;
4143 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
4145 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4150 IntReleaseWindowObject(WindowObject
);
4154 /* Create a new window region using the window rectangle */
4155 VisRgn
= UnsafeIntCreateRectRgnIndirect(&WindowObject
->WindowRect
);
4156 NtGdiOffsetRgn(VisRgn
, -WindowObject
->WindowRect
.left
, -WindowObject
->WindowRect
.top
);
4157 /* if there's a region assigned to the window, combine them both */
4158 if(WindowObject
->WindowRegion
&& !(WindowObject
->Style
& WS_MINIMIZE
))
4159 NtGdiCombineRgn(VisRgn
, VisRgn
, WindowObject
->WindowRegion
, RGN_AND
);
4160 /* Copy the region into hRgn */
4161 NtGdiCombineRgn(hRgn
, VisRgn
, NULL
, RGN_COPY
);
4163 if((pRgn
= RGNDATA_LockRgn(hRgn
)))
4165 Ret
= pRgn
->rdh
.iType
;
4166 RGNDATA_UnlockRgn(pRgn
);
4171 NtGdiDeleteObject(VisRgn
);
4173 IntReleaseWindowObject(WindowObject
);
4178 IntGetWindowRgnBox(HWND hWnd
, RECT
*Rect
)
4181 PWINDOW_OBJECT WindowObject
;
4185 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
4187 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4192 IntReleaseWindowObject(WindowObject
);
4196 /* Create a new window region using the window rectangle */
4197 VisRgn
= UnsafeIntCreateRectRgnIndirect(&WindowObject
->WindowRect
);
4198 NtGdiOffsetRgn(VisRgn
, -WindowObject
->WindowRect
.left
, -WindowObject
->WindowRect
.top
);
4199 /* if there's a region assigned to the window, combine them both */
4200 if(WindowObject
->WindowRegion
&& !(WindowObject
->Style
& WS_MINIMIZE
))
4201 NtGdiCombineRgn(VisRgn
, VisRgn
, WindowObject
->WindowRegion
, RGN_AND
);
4203 if((pRgn
= RGNDATA_LockRgn(VisRgn
)))
4205 Ret
= pRgn
->rdh
.iType
;
4206 *Rect
= pRgn
->rdh
.rcBound
;
4207 RGNDATA_UnlockRgn(pRgn
);
4212 NtGdiDeleteObject(VisRgn
);
4214 IntReleaseWindowObject(WindowObject
);
4228 PWINDOW_OBJECT WindowObject
;
4229 DECLARE_RETURN(INT
);
4231 DPRINT("Enter NtUserSetWindowRgn\n");
4232 UserEnterExclusive();
4234 WindowObject
= IntGetWindowObject(hWnd
);
4235 if (WindowObject
== NULL
)
4237 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4241 /* FIXME - Verify if hRgn is a valid handle!!!!
4242 Propably make this operation thread-safe, but maybe it's not necessary */
4244 if(WindowObject
->WindowRegion
)
4246 /* Delete no longer needed region handle */
4247 NtGdiDeleteObject(WindowObject
->WindowRegion
);
4249 WindowObject
->WindowRegion
= hRgn
;
4251 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
4255 co_UserRedrawWindow(WindowObject
, NULL
, NULL
, RDW_INVALIDATE
);
4258 IntReleaseWindowObject(WindowObject
);
4262 DPRINT("Leave NtUserSystemParametersInfo, ret=%i\n",_ret_
);
4272 NtUserShowWindow(HWND hWnd
,
4275 DECLARE_RETURN(BOOL
);
4277 DPRINT("Enter NtUserShowWindow\n");
4278 UserEnterExclusive();
4280 RETURN( co_WinPosShowWindow(hWnd
, nCmdShow
));
4283 DPRINT("Leave NtUserShowWindow, ret=%i\n",_ret_
);
4293 NtUserShowWindowAsync(DWORD Unknown0
,
4306 NtUserUpdateLayeredWindow(DWORD Unknown0
,
4326 NtUserValidateRect(HWND hWnd
, const RECT
* Rect
)
4328 return (VOID
)NtUserRedrawWindow(hWnd
, Rect
, 0, RDW_VALIDATE
| RDW_NOCHILDREN
);
4336 NtUserWindowFromPoint(LONG X
, LONG Y
)
4340 PWINDOW_OBJECT DesktopWindow
, Window
= NULL
;
4341 DECLARE_RETURN(HWND
);
4343 DPRINT("Enter NtUserWindowFromPoint\n");
4344 UserEnterExclusive();
4346 if ((DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow())))
4353 Hit
= co_WinPosWindowFromPoint(DesktopWindow
, PsGetWin32Thread()->MessageQueue
, &pt
, &Window
);
4358 IntReleaseWindowObject(Window
);
4359 IntReleaseWindowObject(DesktopWindow
);
4363 IntReleaseWindowObject(DesktopWindow
);
4369 DPRINT("Leave NtUserWindowFromPoint, ret=%i\n",_ret_
);
4379 * Undocumented function that is called from DefWindowProc to set
4387 NtUserDefSetText(HWND WindowHandle
, PUNICODE_STRING WindowText
)
4389 PWINDOW_OBJECT WindowObject
, Parent
, Owner
;
4390 UNICODE_STRING SafeText
;
4392 DECLARE_RETURN(INT
);
4394 DPRINT("Enter NtUserDefSetText\n");
4395 UserEnterExclusive();
4397 WindowObject
= IntGetWindowObject(WindowHandle
);
4400 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4406 Status
= IntSafeCopyUnicodeString(&SafeText
, WindowText
);
4407 if(!NT_SUCCESS(Status
))
4409 SetLastNtError(Status
);
4410 IntReleaseWindowObject(WindowObject
);
4416 RtlInitUnicodeString(&SafeText
, NULL
);
4419 /* FIXME - do this thread-safe! otherwise one could crash here! */
4420 RtlFreeUnicodeString(&WindowObject
->WindowName
);
4422 WindowObject
->WindowName
= SafeText
;
4424 /* Send shell notifications */
4426 Owner
= IntGetOwner(WindowObject
);
4427 Parent
= IntGetParent(WindowObject
);
4429 if ((!Owner
) && (!Parent
))
4431 co_IntShellHookNotify(HSHELL_REDRAW
, (LPARAM
) WindowHandle
);
4436 IntReleaseWindowObject(Owner
);
4441 IntReleaseWindowObject(Parent
);
4444 IntReleaseWindowObject(WindowObject
);
4448 DPRINT("Leave NtUserDefSetText, ret=%i\n",_ret_
);
4454 * NtUserInternalGetWindowText
4461 NtUserInternalGetWindowText(HWND hWnd
, LPWSTR lpString
, INT nMaxCount
)
4463 PWINDOW_OBJECT WindowObject
;
4466 DECLARE_RETURN(INT
);
4468 DPRINT("Enter NtUserInternalGetWindowText\n");
4471 if(lpString
&& (nMaxCount
<= 1))
4473 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
4477 WindowObject
= IntGetWindowObject(hWnd
);
4480 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4484 /* FIXME - do this thread-safe! otherwise one could crash here! */
4485 Result
= WindowObject
->WindowName
.Length
/ sizeof(WCHAR
);
4488 const WCHAR Terminator
= L
'\0';
4490 WCHAR
*Buffer
= (WCHAR
*)lpString
;
4492 Copy
= min(nMaxCount
- 1, Result
);
4495 Status
= MmCopyToCaller(Buffer
, WindowObject
->WindowName
.Buffer
, Copy
* sizeof(WCHAR
));
4496 if(!NT_SUCCESS(Status
))
4498 SetLastNtError(Status
);
4499 IntReleaseWindowObject(WindowObject
);
4505 Status
= MmCopyToCaller(Buffer
, &Terminator
, sizeof(WCHAR
));
4506 if(!NT_SUCCESS(Status
))
4508 SetLastNtError(Status
);
4509 IntReleaseWindowObject(WindowObject
);
4516 IntReleaseWindowObject(WindowObject
);
4520 DPRINT("Leave NtUserInternalGetWindowText, ret=%i\n",_ret_
);
4526 NtUserDereferenceWndProcHandle(WNDPROC wpHandle
, WndProcHandle
*Data
)
4528 DECLARE_RETURN(DWORD
);
4530 DPRINT("Enter NtUserDereferenceWndProcHandle\n");
4533 WndProcHandle Entry
;
4534 if (((DWORD
)wpHandle
& 0xFFFF0000) == 0xFFFF0000)
4536 Entry
= WndProcHandlesArray
[(DWORD
)wpHandle
& 0x0000FFFF];
4537 Data
->WindowProc
= Entry
.WindowProc
;
4538 Data
->IsUnicode
= Entry
.IsUnicode
;
4539 Data
->ProcessID
= Entry
.ProcessID
;
4547 DPRINT("Leave NtUserDereferenceWndProcHandle, ret=%i\n",_ret_
);
4553 IntAddWndProcHandle(WNDPROC WindowProc
, BOOL IsUnicode
)
4558 WndProcHandle
*OldArray
;
4561 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4563 if (WndProcHandlesArray
[i
].WindowProc
== NULL
)
4571 OldArray
= WndProcHandlesArray
;
4572 OldArraySize
= WndProcHandlesArraySize
;
4573 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,(OldArraySize
+ WPH_SIZE
) * sizeof(WndProcHandle
), TAG_WINPROCLST
);
4574 WndProcHandlesArraySize
= OldArraySize
+ WPH_SIZE
;
4575 RtlCopyMemory(WndProcHandlesArray
,OldArray
,OldArraySize
* sizeof(WndProcHandle
));
4576 ExFreePool(OldArray
);
4577 FreeSpot
= OldArraySize
+ 1;
4579 WndProcHandlesArray
[FreeSpot
].WindowProc
= WindowProc
;
4580 WndProcHandlesArray
[FreeSpot
].IsUnicode
= IsUnicode
;
4581 WndProcHandlesArray
[FreeSpot
].ProcessID
= PsGetCurrentProcessId();
4582 return FreeSpot
+ 0xFFFF0000;
4586 IntRemoveWndProcHandle(WNDPROC Handle
)
4589 position
= (DWORD
)Handle
& 0x0000FFFF;
4590 if (position
> WndProcHandlesArraySize
)
4594 WndProcHandlesArray
[position
].WindowProc
= NULL
;
4595 WndProcHandlesArray
[position
].IsUnicode
= FALSE
;
4596 WndProcHandlesArray
[position
].ProcessID
= NULL
;
4601 IntRemoveProcessWndProcHandles(HANDLE ProcessID
)
4604 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4606 if (WndProcHandlesArray
[i
].ProcessID
== ProcessID
)
4608 WndProcHandlesArray
[i
].WindowProc
= NULL
;
4609 WndProcHandlesArray
[i
].IsUnicode
= FALSE
;
4610 WndProcHandlesArray
[i
].ProcessID
= NULL
;
4616 #define WIN_NEEDS_SHOW_OWNEDPOPUP (0x00000040)
4620 IntShowOwnedPopups( HWND owner
, BOOL fShow
)
4623 PWINDOW_OBJECT Window
, pWnd
;
4626 if(!(Window
= IntGetWindowObject(owner
)))
4628 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4632 win_array
= IntWinListChildren( Window
);
4633 IntReleaseWindowObject(Window
);
4635 if (!win_array
) return TRUE
;
4637 while (win_array
[count
]) count
++;
4638 while (--count
>= 0)
4640 if (UserGetWindow( win_array
[count
], GW_OWNER
) != owner
) continue;
4641 if (!(pWnd
= IntGetWindowObject( win_array
[count
] ))) continue;
4642 // if (pWnd == WND_OTHER_PROCESS) continue;
4646 if (pWnd
->Flags
& WIN_NEEDS_SHOW_OWNEDPOPUP
)
4648 IntReleaseWindowObject( pWnd
);
4649 /* In Windows, ShowOwnedPopups(TRUE) generates
4650 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
4651 * regardless of the state of the owner
4653 co_IntSendMessage(win_array
[count
], WM_SHOWWINDOW
, SW_SHOWNORMAL
, SW_PARENTOPENING
);
4659 if (pWnd
->Style
& WS_VISIBLE
)
4661 IntReleaseWindowObject( pWnd
);
4662 /* In Windows, ShowOwnedPopups(FALSE) generates
4663 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
4664 * regardless of the state of the owner
4666 co_IntSendMessage(win_array
[count
], WM_SHOWWINDOW
, SW_HIDE
, SW_PARENTCLOSING
);
4670 IntReleaseWindowObject( pWnd
);
4672 ExFreePool( win_array
);