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.
19 /* $Id: window.c,v 1.247 2004/09/28 15:02:30 weiden Exp $
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
24 * FILE: subsys/win32k/ntuser/window.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
27 * 06-06-2001 CSH Created
29 /* INCLUDES ******************************************************************/
32 static WndProcHandle
*WndProcHandlesArray
= 0;
33 static WORD WndProcHandlesArraySize
= 0;
34 #define WPH_SIZE 0x40 /* the size to add to the WndProcHandle array each time */
36 /* dialog resources appear to pass this in 16 bits, handle them properly */
37 #define CW_USEDEFAULT16 (0x8000)
39 #define POINT_IN_RECT(p, r) (((r.bottom >= p.y) && (r.top <= p.y))&&((r.left <= p.x )&&( r.right >= p.x )))
41 /* PRIVATE FUNCTIONS **********************************************************/
46 * Initialize windowing implementation.
52 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,WPH_SIZE
* sizeof(WndProcHandle
), TAG_WINPROCLST
);
53 WndProcHandlesArraySize
= WPH_SIZE
;
54 return STATUS_SUCCESS
;
60 * Cleanup windowing implementation.
64 CleanupWindowImpl(VOID
)
66 ExFreePool(WndProcHandlesArray
);
67 WndProcHandlesArray
= 0;
68 WndProcHandlesArraySize
= 0;
69 return STATUS_SUCCESS
;
72 /* HELPER FUNCTIONS ***********************************************************/
77 * The function determines whether the specified window handle identifies
82 * Handle to the window to test.
85 * If the window handle identifies an existing window, the return value
86 * is TRUE. If the window handle does not identify an existing window,
87 * the return value is FALSE.
91 IntIsWindow(HWND hWnd
)
93 PWINDOW_OBJECT Window
;
95 if (!(Window
= IntGetWindowObject(hWnd
)))
98 IntReleaseWindowObject(Window
);
103 * IntGetProcessWindowObject
105 * Get window object from handle of specified process.
108 PWINDOW_OBJECT FASTCALL
109 IntGetProcessWindowObject(PW32PROCESS ProcessData
, HWND hWnd
)
111 PWINDOW_OBJECT WindowObject
;
114 Status
= ObmReferenceObjectByHandle(ProcessData
->WindowStation
->HandleTable
,
115 hWnd
, otWindow
, (PVOID
*)&WindowObject
);
116 if (!NT_SUCCESS(Status
))
124 PWINDOW_OBJECT FASTCALL
125 IntGetParent(PWINDOW_OBJECT Wnd
)
129 if (Wnd
->Style
& WS_POPUP
)
131 IntLockRelatives(Wnd
);
133 IntUnLockRelatives(Wnd
);
134 return IntGetWindowObject(hWnd
);
136 else if (Wnd
->Style
& WS_CHILD
)
138 IntLockRelatives(Wnd
);
140 IntUnLockRelatives(Wnd
);
141 return IntGetWindowObject(hWnd
);
148 PWINDOW_OBJECT FASTCALL
149 IntGetParentObject(PWINDOW_OBJECT Wnd
)
153 IntLockRelatives(Wnd
);
154 hParent
= Wnd
->Parent
;
155 IntUnLockRelatives(Wnd
);
156 return IntGetWindowObject(hParent
);
162 * Compile a list of all child window handles from given window.
165 * This function is similar to Wine WIN_ListChildren. The caller
166 * must free the returned list with ExFreePool.
170 IntWinListChildren(PWINDOW_OBJECT Window
)
172 PWINDOW_OBJECT Child
;
174 UINT Index
, NumChildren
= 0;
176 IntLockRelatives(Window
);
178 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
181 List
= ExAllocatePoolWithTag(PagedPool
, (NumChildren
+ 1) * sizeof(HWND
), TAG_WINLIST
);
184 DPRINT1("Failed to allocate memory for children array\n");
185 IntUnLockRelatives(Window
);
186 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
189 for (Child
= Window
->FirstChild
, Index
= 0;
191 Child
= Child
->NextSibling
, ++Index
)
192 List
[Index
] = Child
->Self
;
195 IntUnLockRelatives(Window
);
200 /***********************************************************************
203 static void IntSendDestroyMsg(HWND Wnd
)
208 if (GetGUIThreadInfo(GetCurrentThreadId(), &info
))
210 if (Wnd
== info
.hwndCaret
)
218 * Send the WM_DESTROY to the window.
220 IntSendMessage(Wnd
, WM_DESTROY
, 0, 0);
223 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
224 * make sure that the window still exists when we come back.
232 if (!(pWndArray
= WIN_ListChildren( hwnd
))) return;
234 /* start from the end (FIXME: is this needed?) */
235 for (i
= 0; pWndArray
[i
]; i
++) ;
239 if (IsWindow( pWndArray
[i
] )) WIN_SendDestroyMsg( pWndArray
[i
] );
241 HeapFree(GetProcessHeap(), 0, pWndArray
);
245 DPRINT("destroyed itself while in WM_DESTROY!\n");
250 /***********************************************************************
253 * Destroy storage associated to a window. "Internals" p.358
255 static LRESULT
IntDestroyWindow(PWINDOW_OBJECT Window
,
256 PW32PROCESS ProcessData
,
257 PW32THREAD ThreadData
,
258 BOOLEAN SendMessages
)
262 PWINDOW_OBJECT Child
;
264 BOOL BelongsToThreadData
;
268 RemoveTimersWindow(Window
->Self
);
270 IntLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
271 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
273 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
274 DPRINT("Tried to call IntDestroyWindow() twice\n");
277 Window
->Status
|= WINDOWSTATUS_DESTROYING
;
278 /* remove the window already at this point from the thread window list so we
279 don't get into trouble when destroying the thread windows while we're still
280 in IntDestroyWindow() */
281 RemoveEntryList(&Window
->ThreadListEntry
);
282 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
284 BelongsToThreadData
= IntWndBelongsToThread(Window
, ThreadData
);
288 /* Send destroy messages */
289 IntSendDestroyMsg(Window
->Self
);
292 /* free child windows */
293 Children
= IntWinListChildren(Window
);
296 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
298 if ((Child
= IntGetWindowObject(*ChildHandle
)))
300 if(!IntWndBelongsToThread(Child
, ThreadData
))
302 /* send WM_DESTROY messages to windows not belonging to the same thread */
303 IntSendDestroyMsg(Child
->Self
);
306 IntDestroyWindow(Child
, ProcessData
, ThreadData
, SendMessages
);
307 IntReleaseWindowObject(Child
);
310 ExFreePool(Children
);
316 * Clear the update region to make sure no WM_PAINT messages will be
317 * generated for this window while processing the WM_NCDESTROY.
319 IntRedrawWindow(Window
, NULL
, 0,
320 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
|
321 RDW_NOINTERNALPAINT
| RDW_NOCHILDREN
);
324 * Send the WM_NCDESTROY to the window being destroyed.
326 if(BelongsToThreadData
)
327 IntSendMessage(Window
->Self
, WM_NCDESTROY
, 0, 0);
330 /* reset shell window handles */
331 if(ProcessData
->WindowStation
)
333 if (Window
->Self
== ProcessData
->WindowStation
->ShellWindow
)
334 ProcessData
->WindowStation
->ShellWindow
= NULL
;
336 if (Window
->Self
== ProcessData
->WindowStation
->ShellListView
)
337 ProcessData
->WindowStation
->ShellListView
= NULL
;
340 /* Unregister hot keys */
341 UnregisterWindowHotKeys (Window
);
343 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
346 WinPosCheckInternalPos(Window
->Self
);
347 if (Window
->Self
== GetCapture())
352 /* free resources associated with the window */
353 TIMER_RemoveWindowTimers(Window
->Self
);
356 if (!(Window
->Style
& WS_CHILD
) && Window
->IDMenu
357 && (Menu
= IntGetMenuObject((HMENU
)Window
->IDMenu
)))
359 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
361 IntReleaseMenuObject(Menu
);
364 if(Window
->SystemMenu
365 && (Menu
= IntGetMenuObject(Window
->SystemMenu
)))
367 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
368 Window
->SystemMenu
= (HMENU
)0;
369 IntReleaseMenuObject(Menu
);
372 DceFreeWindowDCE(Window
); /* Always do this to catch orphaned DCs */
374 WINPROC_FreeProc(Window
->winproc
, WIN_PROC_WINDOW
);
375 CLASS_RemoveWindow(Window
->Class
);
378 IntUnlinkWindow(Window
);
380 IntReferenceWindowObject(Window
);
381 ObmCloseHandle(ProcessData
->WindowStation
->HandleTable
, Window
->Self
);
383 IntDestroyScrollBars(Window
);
385 IntLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
386 Window
->Status
|= WINDOWSTATUS_DESTROYED
;
387 /* don't remove the WINDOWSTATUS_DESTROYING bit */
388 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
390 /* remove the window from the class object */
391 IntLockClassWindows(Window
->Class
);
392 RemoveEntryList(&Window
->ClassListEntry
);
393 IntUnLockClassWindows(Window
->Class
);
395 /* dereference the class */
396 ClassDereferenceObject(Window
->Class
);
397 Window
->Class
= NULL
;
399 if(Window
->WindowRegion
)
401 NtGdiDeleteObject(Window
->WindowRegion
);
404 RtlFreeUnicodeString(&Window
->WindowName
);
406 IntReleaseWindowObject(Window
);
412 IntGetWindowBorderMeasures(PWINDOW_OBJECT WindowObject
, INT
*cx
, INT
*cy
)
414 if(HAS_DLGFRAME(WindowObject
->Style
, WindowObject
->ExStyle
) && !(WindowObject
->Style
& WS_MINIMIZE
))
416 *cx
= NtUserGetSystemMetrics(SM_CXDLGFRAME
);
417 *cy
= NtUserGetSystemMetrics(SM_CYDLGFRAME
);
421 if(HAS_THICKFRAME(WindowObject
->Style
, WindowObject
->ExStyle
)&& !(WindowObject
->Style
& WS_MINIMIZE
))
423 *cx
= NtUserGetSystemMetrics(SM_CXFRAME
);
424 *cy
= NtUserGetSystemMetrics(SM_CYFRAME
);
426 else if(HAS_THINFRAME(WindowObject
->Style
, WindowObject
->ExStyle
))
428 *cx
= NtUserGetSystemMetrics(SM_CXBORDER
);
429 *cy
= NtUserGetSystemMetrics(SM_CYBORDER
);
439 IntGetWindowInfo(PWINDOW_OBJECT WindowObject
, PWINDOWINFO pwi
)
441 pwi
->cbSize
= sizeof(WINDOWINFO
);
442 pwi
->rcWindow
= WindowObject
->WindowRect
;
443 pwi
->rcClient
= WindowObject
->ClientRect
;
444 pwi
->dwStyle
= WindowObject
->Style
;
445 pwi
->dwExStyle
= WindowObject
->ExStyle
;
446 pwi
->dwWindowStatus
= (NtUserGetForegroundWindow() == WindowObject
->Self
); /* WS_ACTIVECAPTION */
447 IntGetWindowBorderMeasures(WindowObject
, &pwi
->cxWindowBorders
, &pwi
->cyWindowBorders
);
448 pwi
->atomWindowType
= (WindowObject
->Class
? WindowObject
->Class
->Atom
: 0);
449 pwi
->wCreatorVersion
= 0x400; /* FIXME - return a real version number */
455 PWINDOW_OBJECT WindowObject
,
459 PMENU_OBJECT OldMenuObject
, NewMenuObject
= NULL
;
461 *Changed
= (WindowObject
->IDMenu
!= (UINT
) Menu
);
467 if (0 != WindowObject
->IDMenu
)
469 OldMenuObject
= IntGetMenuObject((HMENU
) WindowObject
->IDMenu
);
470 ASSERT(NULL
== OldMenuObject
|| OldMenuObject
->MenuInfo
.Wnd
== WindowObject
->Self
);
474 OldMenuObject
= NULL
;
479 NewMenuObject
= IntGetMenuObject(Menu
);
480 if (NULL
== NewMenuObject
)
482 if (NULL
!= OldMenuObject
)
484 IntReleaseMenuObject(OldMenuObject
);
486 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
489 if (NULL
!= NewMenuObject
->MenuInfo
.Wnd
)
491 /* Can't use the same menu for two windows */
492 if (NULL
!= OldMenuObject
)
494 IntReleaseMenuObject(OldMenuObject
);
496 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
502 WindowObject
->IDMenu
= (UINT
) Menu
;
503 if (NULL
!= NewMenuObject
)
505 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
506 IntReleaseMenuObject(NewMenuObject
);
508 if (NULL
!= OldMenuObject
)
510 OldMenuObject
->MenuInfo
.Wnd
= NULL
;
511 IntReleaseMenuObject(OldMenuObject
);
518 /* INTERNAL ******************************************************************/
522 DestroyThreadWindows(struct _ETHREAD
*Thread
)
525 PW32PROCESS Win32Process
;
526 PW32THREAD Win32Thread
;
527 PWINDOW_OBJECT
*List
, *pWnd
;
530 Win32Thread
= Thread
->Tcb
.Win32Thread
;
531 Win32Process
= Thread
->ThreadsProcess
->Win32Process
;
533 IntLockThreadWindows(Win32Thread
);
534 Current
= Win32Thread
->WindowListHead
.Flink
;
535 while (Current
!= &(Win32Thread
->WindowListHead
))
538 Current
= Current
->Flink
;
543 List
= ExAllocatePool(PagedPool
, (Cnt
+ 1) * sizeof(PWINDOW_OBJECT
));
546 DPRINT("Not enough memory to allocate window handle list\n");
547 IntUnLockThreadWindows(Win32Thread
);
551 Current
= Win32Thread
->WindowListHead
.Flink
;
552 while (Current
!= &(Win32Thread
->WindowListHead
))
554 *pWnd
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
555 IntReferenceWindowObject(*pWnd
);
557 Current
= Current
->Flink
;
559 IntUnLockThreadWindows(Win32Thread
);
562 for(pWnd
= List
; *pWnd
; pWnd
++)
564 NtUserDestroyWindow((*pWnd
)->Self
);
565 IntReleaseWindowObject(*pWnd
);
571 IntUnLockThreadWindows(Win32Thread
);
577 * Returns client window rectangle relative to the upper-left corner of client area.
579 * \note Does not check the validity of the parameters
582 IntGetClientRect(PWINDOW_OBJECT WindowObject
, PRECT Rect
)
584 ASSERT( WindowObject
);
587 Rect
->left
= Rect
->top
= 0;
588 Rect
->right
= WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
;
589 Rect
->bottom
= WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
;
595 IntGetFocusWindow(VOID
)
597 PUSER_MESSAGE_QUEUE Queue
;
598 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
603 Queue
= (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
608 return(Queue
->FocusWindow
);
612 PMENU_OBJECT FASTCALL
613 IntGetSystemMenu(PWINDOW_OBJECT WindowObject
, BOOL bRevert
, BOOL RetMenu
)
615 PMENU_OBJECT MenuObject
, NewMenuObject
, SysMenuObject
, ret
= NULL
;
616 PW32PROCESS W32Process
;
617 HMENU NewMenu
, SysMenu
;
618 ROSMENUITEMINFO ItemInfo
;
622 W32Process
= PsGetWin32Process();
624 if(!W32Process
->WindowStation
)
627 if(WindowObject
->SystemMenu
)
629 MenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
632 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
633 WindowObject
->SystemMenu
= (HMENU
)0;
634 IntReleaseMenuObject(MenuObject
);
638 if(W32Process
->WindowStation
->SystemMenuTemplate
)
640 /* clone system menu */
641 MenuObject
= IntGetMenuObject(W32Process
->WindowStation
->SystemMenuTemplate
);
645 NewMenuObject
= IntCloneMenu(MenuObject
);
648 WindowObject
->SystemMenu
= NewMenuObject
->MenuInfo
.Self
;
649 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
650 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
652 //IntReleaseMenuObject(NewMenuObject);
654 IntReleaseMenuObject(MenuObject
);
658 SysMenu
= NtUserCreateMenu(FALSE
);
663 SysMenuObject
= IntGetMenuObject(SysMenu
);
664 if (NULL
== SysMenuObject
)
666 NtUserDestroyMenu(SysMenu
);
669 SysMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
670 SysMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
671 NewMenu
= IntLoadSysMenuTemplate();
674 IntReleaseMenuObject(SysMenuObject
);
675 NtUserDestroyMenu(SysMenu
);
678 MenuObject
= IntGetMenuObject(NewMenu
);
681 IntReleaseMenuObject(SysMenuObject
);
682 NtUserDestroyMenu(SysMenu
);
686 NewMenuObject
= IntCloneMenu(MenuObject
);
689 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
| MF_POPUP
;
690 IntReleaseMenuObject(NewMenuObject
);
691 NtUserSetMenuDefaultItem(NewMenuObject
->MenuInfo
.Self
, SC_CLOSE
, FALSE
);
693 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
694 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
695 ItemInfo
.fType
= MF_POPUP
;
696 ItemInfo
.fState
= MFS_ENABLED
;
697 ItemInfo
.dwTypeData
= NULL
;
699 ItemInfo
.hSubMenu
= NewMenuObject
->MenuInfo
.Self
;
700 IntInsertMenuItem(SysMenuObject
, (UINT
) -1, TRUE
, &ItemInfo
);
702 WindowObject
->SystemMenu
= SysMenuObject
->MenuInfo
.Self
;
706 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
707 IntReleaseMenuObject(MenuObject
);
716 if(WindowObject
->SystemMenu
)
717 return IntGetMenuObject((HMENU
)WindowObject
->SystemMenu
);
725 IntIsChildWindow(HWND Parent
, HWND Child
)
727 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
729 if(!(BaseWindow
= IntGetWindowObject(Child
)))
737 if (Window
->Self
== Parent
)
739 if(Window
!= BaseWindow
)
740 IntReleaseWindowObject(Window
);
741 IntReleaseWindowObject(BaseWindow
);
744 if(!(Window
->Style
& WS_CHILD
))
746 if(Window
!= BaseWindow
)
747 IntReleaseWindowObject(Window
);
751 Window
= IntGetParentObject(Window
);
752 if(Old
!= BaseWindow
)
753 IntReleaseWindowObject(Old
);
756 IntReleaseWindowObject(BaseWindow
);
761 IntIsWindowVisible(HWND hWnd
)
763 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
765 if(!(BaseWindow
= IntGetWindowObject(hWnd
)))
773 if(!(Window
->Style
& WS_CHILD
))
777 if(!(Window
->Style
& WS_VISIBLE
))
779 if(Window
!= BaseWindow
)
780 IntReleaseWindowObject(Window
);
781 IntReleaseWindowObject(BaseWindow
);
785 Window
= IntGetParentObject(Window
);
786 if(Old
!= BaseWindow
)
787 IntReleaseWindowObject(Old
);
792 if(Window
->Style
& WS_VISIBLE
)
794 if(Window
!= BaseWindow
)
795 IntReleaseWindowObject(Window
);
796 IntReleaseWindowObject(BaseWindow
);
799 if(Window
!= BaseWindow
)
800 IntReleaseWindowObject(Window
);
802 IntReleaseWindowObject(BaseWindow
);
807 /* link the window into siblings and parent. children are kept in place. */
811 PWINDOW_OBJECT WndParent
,
812 PWINDOW_OBJECT WndPrevSibling
/* set to NULL if top sibling */
815 PWINDOW_OBJECT Parent
;
817 IntLockRelatives(Wnd
);
818 Wnd
->Parent
= WndParent
->Self
;
819 if ((Wnd
->PrevSibling
= WndPrevSibling
))
821 /* link after WndPrevSibling */
822 if ((Wnd
->NextSibling
= WndPrevSibling
->NextSibling
))
823 Wnd
->NextSibling
->PrevSibling
= Wnd
;
824 else if ((Parent
= IntGetWindowObject(Wnd
->Parent
)))
826 IntLockRelatives(Parent
);
827 if(Parent
->LastChild
== WndPrevSibling
)
828 Parent
->LastChild
= Wnd
;
829 IntUnLockRelatives(Parent
);
830 IntReleaseWindowObject(Parent
);
832 Wnd
->PrevSibling
->NextSibling
= Wnd
;
837 Parent
= IntGetWindowObject(Wnd
->Parent
);
838 if ((Wnd
->NextSibling
= WndParent
->FirstChild
))
839 Wnd
->NextSibling
->PrevSibling
= Wnd
;
842 IntLockRelatives(Parent
);
843 Parent
->LastChild
= Wnd
;
844 Parent
->FirstChild
= Wnd
;
845 IntUnLockRelatives(Parent
);
846 IntReleaseWindowObject(Parent
);
847 IntUnLockRelatives(Wnd
);
852 IntLockRelatives(Parent
);
853 Parent
->FirstChild
= Wnd
;
854 IntUnLockRelatives(Parent
);
855 IntReleaseWindowObject(Parent
);
858 IntUnLockRelatives(Wnd
);
862 IntSetOwner(HWND hWnd
, HWND hWndNewOwner
)
864 PWINDOW_OBJECT Wnd
, WndOldOwner
, WndNewOwner
;
867 Wnd
= IntGetWindowObject(hWnd
);
871 IntLockRelatives(Wnd
);
872 WndOldOwner
= IntGetWindowObject(Wnd
->Owner
);
875 ret
= WndOldOwner
->Self
;
876 IntReleaseWindowObject(WndOldOwner
);
883 if((WndNewOwner
= IntGetWindowObject(hWndNewOwner
)))
885 Wnd
->Owner
= hWndNewOwner
;
886 IntReleaseWindowObject(WndNewOwner
);
891 IntUnLockRelatives(Wnd
);
892 IntReleaseWindowObject(Wnd
);
896 PWINDOW_OBJECT FASTCALL
897 IntSetParent(PWINDOW_OBJECT Wnd
, PWINDOW_OBJECT WndNewParent
)
899 PWINDOW_OBJECT WndOldParent
, Sibling
, InsertAfter
;
900 HWND hWnd
, hWndNewParent
, hWndOldParent
;
905 ASSERT(WndNewParent
);
908 hWndNewParent
= WndNewParent
->Self
;
911 * Windows hides the window first, then shows it again
912 * including the WM_SHOWWINDOW messages and all
914 WasVisible
= WinPosShowWindow(hWnd
, SW_HIDE
);
916 /* Validate that window and parent still exist */
917 if (!IntIsWindow(hWnd
) || !IntIsWindow(hWndNewParent
))
920 /* Window must belong to current process */
921 if (Wnd
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
924 WndOldParent
= IntGetParentObject(Wnd
);
925 hWndOldParent
= (WndOldParent
? WndOldParent
->Self
: NULL
);
927 if (WndNewParent
!= WndOldParent
)
929 IntUnlinkWindow(Wnd
);
931 if (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
))
933 /* Not a TOPMOST window, put after TOPMOSTs of new parent */
934 IntLockRelatives(WndNewParent
);
935 Sibling
= WndNewParent
->FirstChild
;
936 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
938 InsertAfter
= Sibling
;
939 Sibling
= Sibling
->NextSibling
;
941 IntUnLockRelatives(WndNewParent
);
943 if (NULL
== InsertAfter
)
945 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
949 IntReferenceWindowObject(InsertAfter
);
950 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
951 IntReleaseWindowObject(InsertAfter
);
954 if (WndNewParent
->Self
!= IntGetDesktopWindow()) /* a child window */
956 if (!(Wnd
->Style
& WS_CHILD
))
958 //if ( Wnd->Menu ) DestroyMenu ( Wnd->menu );
959 IntSetMenu(Wnd
, NULL
, &MenuChanged
);
965 * SetParent additionally needs to make hwnd the top window
966 * in the z-order and send the expected WM_WINDOWPOSCHANGING and
967 * WM_WINDOWPOSCHANGED notification messages.
969 WinPosSetWindowPos(hWnd
, (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOP
: HWND_TOPMOST
),
970 0, 0, 0, 0, SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
971 | (WasVisible
? SWP_SHOWWINDOW
: 0));
974 * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
975 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
979 * Validate that the old parent still exist, since it migth have been
980 * destroyed during the last callbacks to user-mode
984 if(!IntIsWindow(WndOldParent
->Self
))
986 IntReleaseWindowObject(WndOldParent
);
990 /* don't dereference the window object here, it must be done by the caller
998 IntSetSystemMenu(PWINDOW_OBJECT WindowObject
, PMENU_OBJECT MenuObject
)
1000 PMENU_OBJECT OldMenuObject
;
1001 if(WindowObject
->SystemMenu
)
1003 OldMenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
1006 OldMenuObject
->MenuInfo
.Flags
&= ~ MF_SYSMENU
;
1007 IntReleaseMenuObject(OldMenuObject
);
1013 /* FIXME check window style, propably return FALSE ? */
1014 WindowObject
->SystemMenu
= MenuObject
->MenuInfo
.Self
;
1015 MenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
1018 WindowObject
->SystemMenu
= (HMENU
)0;
1024 /* unlink the window from siblings and parent. children are kept in place. */
1026 IntUnlinkWindow(PWINDOW_OBJECT Wnd
)
1028 PWINDOW_OBJECT WndParent
;
1030 IntLockRelatives(Wnd
);
1031 if((WndParent
= IntGetWindowObject(Wnd
->Parent
)))
1033 IntLockRelatives(WndParent
);
1036 if (Wnd
->NextSibling
) Wnd
->NextSibling
->PrevSibling
= Wnd
->PrevSibling
;
1037 else if (WndParent
&& WndParent
->LastChild
== Wnd
) WndParent
->LastChild
= Wnd
->PrevSibling
;
1039 if (Wnd
->PrevSibling
) Wnd
->PrevSibling
->NextSibling
= Wnd
->NextSibling
;
1040 else if (WndParent
&& WndParent
->FirstChild
== Wnd
) WndParent
->FirstChild
= Wnd
->NextSibling
;
1044 IntUnLockRelatives(WndParent
);
1045 IntReleaseWindowObject(WndParent
);
1047 Wnd
->PrevSibling
= Wnd
->NextSibling
= Wnd
->Parent
= NULL
;
1048 IntUnLockRelatives(Wnd
);
1054 PWINDOW_OBJECT Window
, Child
;
1056 if(!(Window
= IntGetWindowObject(IntGetDesktopWindow())))
1058 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1062 IntLockRelatives(Window
);
1063 for(Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
1065 if(Child
->Owner
&& Child
->Style
& WS_VISIBLE
)
1068 * The desktop has a popup window if one of them has
1069 * an owner window and is visible
1071 IntUnLockRelatives(Window
);
1072 IntReleaseWindowObject(Window
);
1076 IntUnLockRelatives(Window
);
1077 IntReleaseWindowObject(Window
);
1082 IntIsWindowInDestroy(PWINDOW_OBJECT Window
)
1084 return ((Window
->Status
& WINDOWSTATUS_DESTROYING
) == WINDOWSTATUS_DESTROYING
);
1087 /* FUNCTIONS *****************************************************************/
1093 NtUserAlterWindowStyle(DWORD Unknown0
,
1104 * As best as I can figure, this function is used by EnumWindows,
1105 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
1107 * It's supposed to build a list of HWNDs to return to the caller.
1108 * We can figure out what kind of list by what parameters are
1116 NtUserBuildHwndList(
1128 /* FIXME handle bChildren */
1132 PWINDOW_OBJECT Window
, Child
;
1133 if(!(Window
= IntGetWindowObject(hwndParent
)))
1135 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1139 IntLockRelatives(Window
);
1140 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1142 if(dwCount
++ < nBufSize
&& pWnd
)
1144 Status
= MmCopyToCaller(pWnd
++, &Child
->Self
, sizeof(HWND
));
1145 if(!NT_SUCCESS(Status
))
1147 SetLastNtError(Status
);
1152 IntUnLockRelatives(Window
);
1154 IntReleaseWindowObject(Window
);
1159 PW32THREAD W32Thread
;
1160 PLIST_ENTRY Current
;
1161 PWINDOW_OBJECT Window
;
1163 Status
= PsLookupThreadByThreadId((PVOID
)dwThreadId
, &Thread
);
1164 if(!NT_SUCCESS(Status
))
1166 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1169 if(!(W32Thread
= Thread
->Tcb
.Win32Thread
))
1171 ObDereferenceObject(Thread
);
1172 DPRINT1("Thread is not a GUI Thread!\n");
1173 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1177 IntLockThreadWindows(W32Thread
);
1178 Current
= W32Thread
->WindowListHead
.Flink
;
1179 while(Current
!= &(W32Thread
->WindowListHead
))
1181 Window
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
1184 if(dwCount
< nBufSize
&& pWnd
)
1186 Status
= MmCopyToCaller(pWnd
++, &Window
->Self
, sizeof(HWND
));
1187 if(!NT_SUCCESS(Status
))
1189 SetLastNtError(Status
);
1194 Current
= Current
->Flink
;
1196 IntUnLockThreadWindows(W32Thread
);
1198 ObDereferenceObject(Thread
);
1202 PDESKTOP_OBJECT Desktop
;
1203 PWINDOW_OBJECT Window
, Child
;
1205 if(hDesktop
== NULL
&& !(Desktop
= IntGetActiveDesktop()))
1207 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1213 Status
= IntValidateDesktopHandle(hDesktop
,
1217 if(!NT_SUCCESS(Status
))
1219 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1223 if(!(Window
= IntGetWindowObject(Desktop
->DesktopWindow
)))
1226 ObDereferenceObject(Desktop
);
1227 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1231 IntLockRelatives(Window
);
1232 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1234 if(dwCount
++ < nBufSize
&& pWnd
)
1236 Status
= MmCopyToCaller(pWnd
++, &Child
->Self
, sizeof(HWND
));
1237 if(!NT_SUCCESS(Status
))
1239 SetLastNtError(Status
);
1244 IntUnLockRelatives(Window
);
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 NtGdiIntersectRect(rc
, rc
, &Parent
->ClientRect
);
1345 Pos
.x
= Parent
->TiledCounter
* (NtUserGetSystemMetrics(SM_CXSIZE
) + NtUserGetSystemMetrics(SM_CXFRAME
));
1346 Pos
.y
= Parent
->TiledCounter
* (NtUserGetSystemMetrics(SM_CYSIZE
) + NtUserGetSystemMetrics(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 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
;
1408 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1413 CBT_CREATEWNDW CbtCreate
;
1417 PWSTR ClassNameString
;
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
= NtUserGetAncestor(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 if (IS_ATOM(ClassName
->Buffer
))
1456 ClassFound
= ClassReferenceClassByNameOrAtom(&ClassObject
, ClassName
->Buffer
, hInstance
);
1460 Status
= IntUnicodeStringToNULLTerminated(&ClassNameString
, ClassName
);
1461 if (! NT_SUCCESS(Status
))
1463 if (NULL
!= ParentWindow
)
1465 IntReleaseWindowObject(ParentWindow
);
1469 ClassFound
= ClassReferenceClassByNameOrAtom(&ClassObject
, ClassNameString
, hInstance
);
1470 IntFreeNULLTerminatedFromUnicodeString(ClassNameString
, ClassName
);
1474 if (IS_ATOM(ClassName
->Buffer
))
1476 DPRINT1("Class 0x%x not found\n", (DWORD_PTR
) ClassName
->Buffer
);
1480 DPRINT1("Class %wZ not found\n", ClassName
);
1482 if (NULL
!= ParentWindow
)
1484 IntReleaseWindowObject(ParentWindow
);
1489 /* Check the window station. */
1490 DPRINT("IoGetCurrentProcess() %X\n", IoGetCurrentProcess());
1491 DPRINT("PROCESS_WINDOW_STATION %X\n", PROCESS_WINDOW_STATION());
1492 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
1496 if (!NT_SUCCESS(Status
))
1498 ClassDereferenceObject(ClassObject
);
1499 if (NULL
!= ParentWindow
)
1501 IntReleaseWindowObject(ParentWindow
);
1503 DPRINT("Validation of window station handle (0x%X) failed\n",
1504 PROCESS_WINDOW_STATION());
1508 /* Create the window object. */
1509 WindowObject
= (PWINDOW_OBJECT
)
1510 ObmCreateObject(PsGetWin32Process()->WindowStation
->HandleTable
, &Handle
,
1511 otWindow
, sizeof(WINDOW_OBJECT
) + ClassObject
->cbWndExtra
1514 DPRINT("Created object with handle %X\n", Handle
);
1517 ObDereferenceObject(WinStaObject
);
1518 ClassDereferenceObject(ClassObject
);
1519 if (NULL
!= ParentWindow
)
1521 IntReleaseWindowObject(ParentWindow
);
1523 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1526 ObDereferenceObject(WinStaObject
);
1528 if (NULL
== PsGetWin32Thread()->Desktop
->DesktopWindow
)
1530 /* If there is no desktop window yet, we must be creating it */
1531 PsGetWin32Thread()->Desktop
->DesktopWindow
= Handle
;
1535 * Fill out the structure describing it.
1537 WindowObject
->Class
= ClassObject
;
1538 IntLockClassWindows(ClassObject
);
1539 InsertTailList(&ClassObject
->ClassWindowsListHead
, &WindowObject
->ClassListEntry
);
1540 IntUnLockClassWindows(ClassObject
);
1542 WindowObject
->ExStyle
= dwExStyle
;
1543 WindowObject
->Style
= dwStyle
& ~WS_VISIBLE
;
1544 DPRINT("1: Style is now %lx\n", WindowObject
->Style
);
1546 WindowObject
->SystemMenu
= (HMENU
)0;
1547 WindowObject
->ContextHelpId
= 0;
1548 WindowObject
->IDMenu
= 0;
1549 WindowObject
->Instance
= hInstance
;
1550 WindowObject
->Self
= Handle
;
1551 if (0 != (dwStyle
& WS_CHILD
))
1553 WindowObject
->IDMenu
= (UINT
) hMenu
;
1557 IntSetMenu(WindowObject
, hMenu
, &MenuChanged
);
1559 WindowObject
->MessageQueue
= PsGetWin32Thread()->MessageQueue
;
1560 WindowObject
->Parent
= (ParentWindow
? ParentWindow
->Self
: NULL
);
1561 if((OwnerWindow
= IntGetWindowObject(OwnerWindowHandle
)))
1563 WindowObject
->Owner
= OwnerWindowHandle
;
1564 IntReleaseWindowObject(OwnerWindow
);
1567 WindowObject
->Owner
= NULL
;
1568 WindowObject
->UserData
= 0;
1569 if ((((DWORD
)ClassObject
->lpfnWndProcA
& 0xFFFF0000) != 0xFFFF0000)
1570 && (((DWORD
)ClassObject
->lpfnWndProcW
& 0xFFFF0000) != 0xFFFF0000))
1572 WindowObject
->Unicode
= bUnicodeWindow
;
1576 WindowObject
->Unicode
= ClassObject
->Unicode
;
1578 WindowObject
->WndProcA
= ClassObject
->lpfnWndProcA
;
1579 WindowObject
->WndProcW
= ClassObject
->lpfnWndProcW
;
1580 WindowObject
->OwnerThread
= PsGetCurrentThread();
1581 WindowObject
->FirstChild
= NULL
;
1582 WindowObject
->LastChild
= NULL
;
1583 WindowObject
->PrevSibling
= NULL
;
1584 WindowObject
->NextSibling
= NULL
;
1586 /* extra window data */
1587 if (ClassObject
->cbWndExtra
!= 0)
1589 WindowObject
->ExtraData
= (PCHAR
)(WindowObject
+ 1);
1590 WindowObject
->ExtraDataSize
= ClassObject
->cbWndExtra
;
1591 RtlZeroMemory(WindowObject
->ExtraData
, WindowObject
->ExtraDataSize
);
1595 WindowObject
->ExtraData
= NULL
;
1596 WindowObject
->ExtraDataSize
= 0;
1599 InitializeListHead(&WindowObject
->PropListHead
);
1600 ExInitializeFastMutex(&WindowObject
->PropListLock
);
1601 ExInitializeFastMutex(&WindowObject
->RelativesLock
);
1602 ExInitializeFastMutex(&WindowObject
->UpdateLock
);
1604 if (NULL
!= WindowName
->Buffer
)
1606 WindowObject
->WindowName
.MaximumLength
= WindowName
->MaximumLength
;
1607 WindowObject
->WindowName
.Length
= WindowName
->Length
;
1608 WindowObject
->WindowName
.Buffer
= ExAllocatePoolWithTag(PagedPool
, WindowName
->MaximumLength
,
1610 if (NULL
== WindowObject
->WindowName
.Buffer
)
1612 ClassDereferenceObject(ClassObject
);
1613 DPRINT1("Failed to allocate mem for window name\n");
1614 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1617 RtlCopyMemory(WindowObject
->WindowName
.Buffer
, WindowName
->Buffer
, WindowName
->MaximumLength
);
1621 RtlInitUnicodeString(&WindowObject
->WindowName
, NULL
);
1626 * This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1627 * tested for WS_POPUP
1629 if ((dwExStyle
& WS_EX_DLGMODALFRAME
) ||
1630 ((!(dwExStyle
& WS_EX_STATICEDGE
)) &&
1631 (dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
))))
1632 dwExStyle
|= WS_EX_WINDOWEDGE
;
1634 dwExStyle
&= ~WS_EX_WINDOWEDGE
;
1636 /* Correct the window style. */
1637 if (!(dwStyle
& WS_CHILD
))
1639 WindowObject
->Style
|= WS_CLIPSIBLINGS
;
1640 DPRINT("3: Style is now %lx\n", WindowObject
->Style
);
1641 if (!(dwStyle
& WS_POPUP
))
1643 WindowObject
->Style
|= WS_CAPTION
;
1644 WindowObject
->Flags
|= WINDOWOBJECT_NEED_SIZE
;
1645 DPRINT("4: Style is now %lx\n", WindowObject
->Style
);
1649 /* create system menu */
1650 if((WindowObject
->Style
& WS_SYSMENU
) &&
1651 (WindowObject
->Style
& WS_CAPTION
) == WS_CAPTION
)
1653 SystemMenu
= IntGetSystemMenu(WindowObject
, TRUE
, TRUE
);
1656 WindowObject
->SystemMenu
= SystemMenu
->MenuInfo
.Self
;
1657 IntReleaseMenuObject(SystemMenu
);
1661 /* Insert the window into the thread's window list. */
1662 IntLockThreadWindows(PsGetWin32Thread());
1663 InsertTailList (&PsGetWin32Thread()->WindowListHead
,
1664 &WindowObject
->ThreadListEntry
);
1665 IntUnLockThreadWindows(PsGetWin32Thread());
1667 /* Allocate a DCE for this window. */
1668 if (dwStyle
& CS_OWNDC
)
1670 WindowObject
->Dce
= DceAllocDCE(WindowObject
->Self
, DCE_WINDOW_DC
);
1672 /* FIXME: Handle "CS_CLASSDC" */
1680 Cs
.lpCreateParams
= lpParam
;
1681 Cs
.hInstance
= hInstance
;
1683 Cs
.hwndParent
= ParentWindowHandle
;
1689 Cs
.lpszName
= (LPCWSTR
) WindowName
;
1690 Cs
.lpszClass
= (LPCWSTR
) ClassName
;
1691 Cs
.dwExStyle
= dwExStyle
;
1692 CbtCreate
.lpcs
= &Cs
;
1693 CbtCreate
.hwndInsertAfter
= HWND_TOP
;
1694 if (HOOK_CallHooks(WH_CBT
, HCBT_CREATEWND
, (WPARAM
) Handle
, (LPARAM
) &CbtCreate
))
1696 if (NULL
!= ParentWindow
)
1698 IntReleaseWindowObject(ParentWindow
);
1701 /* FIXME - Delete window object and remove it from the thread windows list */
1702 /* FIXME - delete allocated DCE */
1704 ClassDereferenceObject(ClassObject
);
1705 DPRINT1("CBT-hook returned !0\n");
1714 /* default positioning for overlapped windows */
1715 if(!(WindowObject
->Style
& (WS_POPUP
| WS_CHILD
)))
1718 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
1719 BOOL CalculatedDefPosSize
= FALSE
;
1721 IntGetDesktopWorkArea(WindowObject
->OwnerThread
->Tcb
.Win32Thread
->Desktop
, &WorkArea
);
1724 ProcessParams
= PsGetCurrentProcess()->Peb
->ProcessParameters
;
1726 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1728 CalculatedDefPosSize
= IntCalcDefPosSize(ParentWindow
, WindowObject
, &rc
, TRUE
);
1730 if(ProcessParams
->dwFlags
& STARTF_USEPOSITION
)
1732 ProcessParams
->dwFlags
&= ~STARTF_USEPOSITION
;
1733 Pos
.x
= WorkArea
.left
+ ProcessParams
->dwX
;
1734 Pos
.y
= WorkArea
.top
+ ProcessParams
->dwY
;
1742 /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
1743 y is something else */
1744 if(y
!= CW_USEDEFAULT
&& y
!= CW_USEDEFAULT16
)
1749 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1751 if(!CalculatedDefPosSize
)
1753 IntCalcDefPosSize(ParentWindow
, WindowObject
, &rc
, FALSE
);
1755 if(ProcessParams
->dwFlags
& STARTF_USESIZE
)
1757 ProcessParams
->dwFlags
&= ~STARTF_USESIZE
;
1758 Size
.cx
= ProcessParams
->dwXSize
;
1759 Size
.cy
= ProcessParams
->dwYSize
;
1763 Size
.cx
= rc
.right
- rc
.left
;
1764 Size
.cy
= rc
.bottom
- rc
.top
;
1767 /* move the window if necessary */
1769 Pos
.x
= max(rc
.left
, 0);
1771 Pos
.y
= max(rc
.top
, 0);
1776 /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
1777 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1782 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1789 /* Initialize the window dimensions. */
1790 WindowObject
->WindowRect
.left
= Pos
.x
;
1791 WindowObject
->WindowRect
.top
= Pos
.y
;
1792 WindowObject
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1793 WindowObject
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1794 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1796 NtGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1797 ParentWindow
->ClientRect
.top
);
1799 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1802 * Get the size and position of the window.
1804 if ((dwStyle
& WS_THICKFRAME
) || !(dwStyle
& (WS_POPUP
| WS_CHILD
)))
1806 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1808 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1809 WinPosGetMinMaxInfo(WindowObject
, &MaxSize
, &MaxPos
, &MinTrack
,
1811 if (MaxSize
.x
< nWidth
) nWidth
= MaxSize
.x
;
1812 if (MaxSize
.y
< nHeight
) nHeight
= MaxSize
.y
;
1813 if (nWidth
< MinTrack
.x
) nWidth
= MinTrack
.x
;
1814 if (nHeight
< MinTrack
.y
) nHeight
= MinTrack
.y
;
1815 if (nWidth
< 0) nWidth
= 0;
1816 if (nHeight
< 0) nHeight
= 0;
1819 WindowObject
->WindowRect
.left
= Pos
.x
;
1820 WindowObject
->WindowRect
.top
= Pos
.y
;
1821 WindowObject
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1822 WindowObject
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1823 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1825 NtGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1826 ParentWindow
->ClientRect
.top
);
1828 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1830 /* FIXME: Initialize the window menu. */
1832 /* Send a NCCREATE message. */
1838 DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d\n", Cs
.style
, Cs
.dwExStyle
, Cs
.hwndParent
);
1839 DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1840 DPRINT("IntCreateWindowEx(): About to send NCCREATE message.\n");
1841 Result
= IntSendMessage(WindowObject
->Self
, WM_NCCREATE
, 0, (LPARAM
) &Cs
);
1844 /* FIXME: Cleanup. */
1845 if (NULL
!= ParentWindow
)
1847 IntReleaseWindowObject(ParentWindow
);
1849 DPRINT("IntCreateWindowEx(): NCCREATE message failed.\n");
1853 /* Calculate the non-client size. */
1854 MaxPos
.x
= WindowObject
->WindowRect
.left
;
1855 MaxPos
.y
= WindowObject
->WindowRect
.top
;
1856 DPRINT("IntCreateWindowEx(): About to get non-client size.\n");
1857 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1858 Result
= WinPosGetNonClientSize(WindowObject
->Self
,
1859 &WindowObject
->WindowRect
,
1860 &WindowObject
->ClientRect
);
1861 NtGdiOffsetRect(&WindowObject
->WindowRect
,
1862 MaxPos
.x
- WindowObject
->WindowRect
.left
,
1863 MaxPos
.y
- WindowObject
->WindowRect
.top
);
1865 if (NULL
!= ParentWindow
)
1867 /* link the window into the parent's child list */
1868 if ((dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
1870 PWINDOW_OBJECT PrevSibling
;
1871 IntLockRelatives(ParentWindow
);
1872 if((PrevSibling
= ParentWindow
->LastChild
))
1873 IntReferenceWindowObject(PrevSibling
);
1874 IntUnLockRelatives(ParentWindow
);
1875 /* link window as bottom sibling */
1876 IntLinkWindow(WindowObject
, ParentWindow
, PrevSibling
/*prev sibling*/);
1878 IntReleaseWindowObject(PrevSibling
);
1882 /* link window as top sibling (but after topmost siblings) */
1883 PWINDOW_OBJECT InsertAfter
, Sibling
;
1884 if (0 == (dwExStyle
& WS_EX_TOPMOST
))
1886 IntLockRelatives(ParentWindow
);
1888 Sibling
= ParentWindow
->FirstChild
;
1889 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
1891 InsertAfter
= Sibling
;
1892 Sibling
= Sibling
->NextSibling
;
1894 IntUnLockRelatives(ParentWindow
);
1900 if (NULL
!= InsertAfter
)
1902 IntReferenceWindowObject(InsertAfter
);
1904 IntLinkWindow(WindowObject
, ParentWindow
, InsertAfter
/* prev sibling */);
1905 if (NULL
!= InsertAfter
)
1907 IntReleaseWindowObject(InsertAfter
);
1912 /* Send the WM_CREATE message. */
1913 DPRINT("IntCreateWindowEx(): about to send CREATE message.\n");
1914 Result
= IntSendMessage(WindowObject
->Self
, WM_CREATE
, 0, (LPARAM
) &Cs
);
1915 if (Result
== (LRESULT
)-1)
1917 /* FIXME: Cleanup. */
1918 if (NULL
!= ParentWindow
)
1920 IntReleaseWindowObject(ParentWindow
);
1922 ClassDereferenceObject(ClassObject
);
1923 DPRINT("IntCreateWindowEx(): send CREATE message failed.\n");
1927 /* Send move and size messages. */
1928 if (!(WindowObject
->Flags
& WINDOWOBJECT_NEED_SIZE
))
1932 DPRINT("IntCreateWindow(): About to send WM_SIZE\n");
1934 if ((WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
) < 0 ||
1935 (WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
) < 0)
1937 DPRINT("Sending bogus WM_SIZE\n");
1940 lParam
= MAKE_LONG(WindowObject
->ClientRect
.right
-
1941 WindowObject
->ClientRect
.left
,
1942 WindowObject
->ClientRect
.bottom
-
1943 WindowObject
->ClientRect
.top
);
1944 IntSendMessage(WindowObject
->Self
, WM_SIZE
, SIZE_RESTORED
,
1947 DPRINT("IntCreateWindow(): About to send WM_MOVE\n");
1949 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1951 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
- ParentWindow
->ClientRect
.left
,
1952 WindowObject
->ClientRect
.top
- ParentWindow
->ClientRect
.top
);
1956 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
,
1957 WindowObject
->ClientRect
.top
);
1959 IntSendMessage(WindowObject
->Self
, WM_MOVE
, 0, lParam
);
1962 /* Show or maybe minimize or maximize the window. */
1963 if (WindowObject
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1968 SwFlag
= (WindowObject
->Style
& WS_MINIMIZE
) ? SW_MINIMIZE
:
1970 WinPosMinMaximize(WindowObject
, SwFlag
, &NewPos
);
1972 ((WindowObject
->Style
& WS_CHILD
) || NtUserGetActiveWindow()) ?
1973 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
:
1974 SWP_NOZORDER
| SWP_FRAMECHANGED
;
1975 DPRINT("IntCreateWindow(): About to minimize/maximize\n");
1976 DPRINT("%d,%d %dx%d\n", NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
);
1977 WinPosSetWindowPos(WindowObject
->Self
, 0, NewPos
.left
, NewPos
.top
,
1978 NewPos
.right
, NewPos
.bottom
, SwFlag
);
1981 /* Notify the parent window of a new child. */
1982 if ((WindowObject
->Style
& WS_CHILD
) &&
1983 (!(WindowObject
->ExStyle
& WS_EX_NOPARENTNOTIFY
)) && ParentWindow
)
1985 DPRINT("IntCreateWindow(): About to notify parent\n");
1986 IntSendMessage(ParentWindow
->Self
,
1988 MAKEWPARAM(WM_CREATE
, WindowObject
->IDMenu
),
1989 (LPARAM
)WindowObject
->Self
);
1992 if (NULL
!= ParentWindow
)
1994 IntReleaseWindowObject(ParentWindow
);
1997 /* Initialize and show the window's scrollbars */
1998 if (WindowObject
->Style
& WS_VSCROLL
)
2000 NtUserShowScrollBar(WindowObject
->Self
, SB_VERT
, TRUE
);
2002 if (WindowObject
->Style
& WS_HSCROLL
)
2004 NtUserShowScrollBar(WindowObject
->Self
, SB_HORZ
, TRUE
);
2007 if (dwStyle
& WS_VISIBLE
)
2009 DPRINT("IntCreateWindow(): About to show window\n");
2010 WinPosShowWindow(WindowObject
->Self
, dwShowMode
);
2013 DPRINT("IntCreateWindow(): = %X\n", Handle
);
2014 DPRINT("WindowObject->SystemMenu = 0x%x\n", WindowObject
->SystemMenu
);
2015 return((HWND
)Handle
);
2019 NtUserCreateWindowEx(DWORD dwExStyle
,
2020 PUNICODE_STRING UnsafeClassName
,
2021 PUNICODE_STRING UnsafeWindowName
,
2029 HINSTANCE hInstance
,
2032 BOOL bUnicodeWindow
)
2035 UNICODE_STRING WindowName
;
2036 UNICODE_STRING ClassName
;
2039 DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
2041 /* Get the class name (string or atom) */
2042 Status
= MmCopyFromCaller(&ClassName
, UnsafeClassName
, sizeof(UNICODE_STRING
));
2043 if (! NT_SUCCESS(Status
))
2045 SetLastNtError(Status
);
2048 if (! IS_ATOM(ClassName
.Buffer
))
2050 Status
= IntSafeCopyUnicodeString(&ClassName
, UnsafeClassName
);
2051 if (! NT_SUCCESS(Status
))
2053 SetLastNtError(Status
);
2058 /* safely copy the window name */
2059 if (NULL
!= UnsafeWindowName
)
2061 Status
= IntSafeCopyUnicodeString(&WindowName
, UnsafeWindowName
);
2062 if (! NT_SUCCESS(Status
))
2064 if (! IS_ATOM(ClassName
.Buffer
))
2066 RtlFreeUnicodeString(&ClassName
);
2068 SetLastNtError(Status
);
2074 RtlInitUnicodeString(&WindowName
, NULL
);
2077 NewWindow
= IntCreateWindowEx(dwExStyle
, &ClassName
, &WindowName
, dwStyle
, x
, y
, nWidth
, nHeight
,
2078 hWndParent
, hMenu
, hInstance
, lpParam
, dwShowMode
, bUnicodeWindow
);
2080 RtlFreeUnicodeString(&WindowName
);
2081 if (! IS_ATOM(ClassName
.Buffer
))
2083 RtlFreeUnicodeString(&ClassName
);
2093 NtUserDeferWindowPos(HDWP WinPosInfo
,
2095 HWND WndInsertAfter
,
2112 NtUserDestroyWindow(HWND Wnd
)
2114 PWINDOW_OBJECT Window
;
2117 Window
= IntGetWindowObject(Wnd
);
2123 /* Check for owner thread and desktop window */
2124 if ((Window
->OwnerThread
!= PsGetCurrentThread()) || IntIsDesktopWindow(Window
))
2126 IntReleaseWindowObject(Window
);
2127 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2131 /* Look whether the focus is within the tree of windows we will
2134 if (!WinPosShowWindow(Wnd
, SW_HIDE
))
2136 if (NtUserGetActiveWindow() == Wnd
)
2138 WinPosActivateOtherWindow(Window
);
2141 IntLockMessageQueue(Window
->MessageQueue
);
2142 if (Window
->MessageQueue
->ActiveWindow
== Window
->Self
)
2143 Window
->MessageQueue
->ActiveWindow
= NULL
;
2144 if (Window
->MessageQueue
->FocusWindow
== Window
->Self
)
2145 Window
->MessageQueue
->FocusWindow
= NULL
;
2146 if (Window
->MessageQueue
->CaptureWindow
== Window
->Self
)
2147 Window
->MessageQueue
->CaptureWindow
= NULL
;
2148 IntUnLockMessageQueue(Window
->MessageQueue
);
2152 if (HOOK_CallHooks(WH_CBT
, HCBT_DESTROYWND
, (WPARAM
) hwnd
, 0, TRUE
))
2158 isChild
= (0 != (Window
->Style
& WS_CHILD
));
2163 if (! USER_IsExitingThread(GetCurrentThreadId()))
2165 send_parent_notify(hwnd
, WM_DESTROY
);
2168 else if (NULL
!= GetWindow(Wnd
, GW_OWNER
))
2170 HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
2171 /* FIXME: clean up palette - see "Internals" p.352 */
2175 if (!IntIsWindow(Wnd
))
2180 /* Recursively destroy owned windows */
2185 BOOL GotOne
= FALSE
;
2188 PWINDOW_OBJECT Child
, Desktop
;
2190 Desktop
= IntGetWindowObject(IntGetDesktopWindow());
2191 Children
= IntWinListChildren(Desktop
);
2192 IntReleaseWindowObject(Desktop
);
2195 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
2197 Child
= IntGetWindowObject(*ChildHandle
);
2200 IntLockRelatives(Child
);
2201 if (Child
->Owner
!= Window
->Self
)
2203 IntUnLockRelatives(Child
);
2204 IntReleaseWindowObject(Child
);
2207 IntUnLockRelatives(Child
);
2208 if (IntWndBelongsToThread(Child
, PsGetWin32Thread()))
2210 IntReleaseWindowObject(Child
);
2211 NtUserDestroyWindow(*ChildHandle
);
2215 IntLockRelatives(Child
);
2216 if (Child
->Owner
!= NULL
)
2218 Child
->Owner
= NULL
;
2220 IntUnLockRelatives(Child
);
2221 IntReleaseWindowObject(Child
);
2223 ExFreePool(Children
);
2232 if (!IntIsWindow(Wnd
))
2234 IntReleaseWindowObject(Window
);
2238 /* Destroy the window storage */
2239 IntDestroyWindow(Window
, PsGetWin32Process(), PsGetWin32Thread(), TRUE
);
2241 IntReleaseWindowObject(Window
);
2251 NtUserDrawMenuBarTemp(
2258 /* we'll use this function just for caching the menu bar */
2268 NtUserEndDeferWindowPosEx(DWORD Unknown0
,
2281 NtUserFillWindow(DWORD Unknown0
,
2293 IntFindWindow(PWINDOW_OBJECT Parent
,
2294 PWINDOW_OBJECT ChildAfter
,
2295 PWNDCLASS_OBJECT ClassObject
,
2296 PUNICODE_STRING WindowName
)
2298 BOOL CheckWindowName
;
2304 CheckWindowName
= (WindowName
&& (WindowName
->Length
> 0));
2306 if((List
= IntWinListChildren(Parent
)))
2311 /* skip handles before and including ChildAfter */
2312 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->Self
));
2315 /* search children */
2318 PWINDOW_OBJECT Child
;
2319 if(!(Child
= IntGetWindowObject(*(phWnd
++))))
2324 /* Do not send WM_GETTEXT messages in the kernel mode version!
2325 The user mode version however calls GetWindowText() which will
2326 send WM_GETTEXT messages to windows belonging to its processes */
2327 if(((!CheckWindowName
|| (CheckWindowName
&& !RtlCompareUnicodeString(WindowName
, &(Child
->WindowName
), FALSE
))) &&
2328 (!ClassObject
|| (ClassObject
&& (Child
->Class
== ClassObject
))))
2330 ((!CheckWindowName
|| (CheckWindowName
&& !RtlCompareUnicodeString(WindowName
, &(Child
->WindowName
), FALSE
))) &&
2331 (!ClassObject
|| (ClassObject
&& (Child
->Class
== ClassObject
)))))
2334 IntReleaseWindowObject(Child
);
2338 IntReleaseWindowObject(Child
);
2348 * Searches a window's children for a window with the specified
2351 * hwndParent = The window whose childs are to be searched.
2353 * HWND_MESSAGE = message-only windows
2355 * hwndChildAfter = Search starts after this child window.
2356 * NULL = start from beginning
2358 * ucClassName = Class name to search for
2359 * Reguired parameter.
2361 * ucWindowName = Window name
2362 * ->Buffer == NULL = don't care
2365 * The HWND of the window if it was found, otherwise NULL
2371 NtUserFindWindowEx(HWND hwndParent
,
2372 HWND hwndChildAfter
,
2373 PUNICODE_STRING ucClassName
,
2374 PUNICODE_STRING ucWindowName
)
2376 PWINDOW_OBJECT Parent
, ChildAfter
;
2377 UNICODE_STRING ClassName
, WindowName
;
2379 HWND Desktop
, Ret
= NULL
;
2380 PWNDCLASS_OBJECT ClassObject
= NULL
;
2383 Desktop
= IntGetCurrentThreadDesktopWindow();
2385 if(hwndParent
== NULL
)
2386 hwndParent
= Desktop
;
2388 else if(hwndParent == HWND_MESSAGE)
2390 hwndParent = IntGetMessageWindow();
2394 if(!(Parent
= IntGetWindowObject(hwndParent
)))
2396 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2401 if(hwndChildAfter
&& !(ChildAfter
= IntGetWindowObject(hwndChildAfter
)))
2403 IntReleaseWindowObject(hwndParent
);
2404 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2408 /* copy the window name */
2409 Status
= IntSafeCopyUnicodeString(&WindowName
, ucWindowName
);
2410 if(!NT_SUCCESS(Status
))
2412 SetLastNtError(Status
);
2416 /* safely copy the class name */
2417 Status
= MmCopyFromCaller(&ClassName
, ucClassName
, sizeof(UNICODE_STRING
));
2418 if(!NT_SUCCESS(Status
))
2420 SetLastNtError(Status
);
2423 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2426 /* safely copy the class name string (NULL terminated because class-lookup
2428 buf
= ExAllocatePoolWithTag(PagedPool
, ClassName
.Length
+ sizeof(WCHAR
), TAG_STRING
);
2431 SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES
);
2434 Status
= MmCopyFromCaller(buf
, ClassName
.Buffer
, ClassName
.Length
);
2435 if(!NT_SUCCESS(Status
))
2438 SetLastNtError(Status
);
2441 ClassName
.Buffer
= buf
;
2442 /* make sure the string is null-terminated */
2443 buf
+= ClassName
.Length
/ sizeof(WCHAR
);
2447 /* find the class object */
2448 if(ClassName
.Buffer
)
2450 /* this expects the string in ClassName to be NULL-terminated! */
2451 ClassFound
= ClassReferenceClassByNameOrAtom(&ClassObject
, ClassName
.Buffer
, NULL
);
2454 if (IS_ATOM(ClassName
.Buffer
))
2455 DPRINT1("Window class not found (%lx)\n", (ULONG_PTR
)ClassName
.Buffer
);
2457 DPRINT1("Window class not found (%S)\n", ClassName
.Buffer
);
2458 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST
);
2463 if(Parent
->Self
== Desktop
)
2466 PWINDOW_OBJECT TopLevelWindow
;
2467 BOOL CheckWindowName
;
2469 /* windows searches through all top-level windows if the parent is the desktop
2472 if((List
= IntWinListChildren(Parent
)))
2478 /* skip handles before and including ChildAfter */
2479 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->Self
));
2482 CheckWindowName
= WindowName
.Length
> 0;
2484 /* search children */
2487 if(!(TopLevelWindow
= IntGetWindowObject(*(phWnd
++))))
2492 /* Do not send WM_GETTEXT messages in the kernel mode version!
2493 The user mode version however calls GetWindowText() which will
2494 send WM_GETTEXT messages to windows belonging to its processes */
2495 if(((!CheckWindowName
|| (CheckWindowName
&& !RtlCompareUnicodeString(&WindowName
, &(TopLevelWindow
->WindowName
), FALSE
))) &&
2496 (!ClassObject
|| (ClassObject
&& (TopLevelWindow
->Class
== ClassObject
))))
2498 ((!CheckWindowName
|| (CheckWindowName
&& !RtlCompareUnicodeString(&WindowName
, &(TopLevelWindow
->WindowName
), FALSE
))) &&
2499 (!ClassObject
|| (ClassObject
&& (TopLevelWindow
->Class
== ClassObject
)))))
2501 Ret
= TopLevelWindow
->Self
;
2502 IntReleaseWindowObject(TopLevelWindow
);
2506 if(IntFindWindow(TopLevelWindow
, NULL
, ClassObject
, &WindowName
))
2508 /* window returns the handle of the top-level window, in case it found
2510 Ret
= TopLevelWindow
->Self
;
2511 IntReleaseWindowObject(TopLevelWindow
);
2515 IntReleaseWindowObject(TopLevelWindow
);
2521 Ret
= IntFindWindow(Parent
, ChildAfter
, ClassObject
, &WindowName
);
2524 if(Ret
== NULL
&& hwndParent
== NULL
&& hwndChildAfter
== NULL
)
2526 /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
2527 search the message-only windows. Should this also be done if
2528 Parent is the desktop window??? */
2529 PWINDOW_OBJECT MsgWindows
;
2531 if((MsgWindows
= IntGetWindowObject(IntGetMessageWindow())))
2533 Ret
= IntFindWindow(MsgWindows
, ChildAfter
, ClassObject
, &WindowName
);
2534 IntReleaseWindowObject(MsgWindows
);
2539 ClassDereferenceObject(ClassObject
);
2542 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2543 ExFreePool(ClassName
.Buffer
);
2546 RtlFreeUnicodeString(&WindowName
);
2550 IntReleaseWindowObject(ChildAfter
);
2551 IntReleaseWindowObject(Parent
);
2561 NtUserFlashWindowEx(DWORD Unknown0
)
2573 NtUserGetAncestor(HWND hWnd
, UINT Type
)
2575 PWINDOW_OBJECT Wnd
, WndAncestor
, Parent
;
2578 if (hWnd
== IntGetDesktopWindow())
2583 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2585 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2593 WndAncestor
= IntGetParentObject(Wnd
);
2606 if(!(Parent
= IntGetParentObject(WndAncestor
)))
2610 if(IntIsDesktopWindow(Parent
))
2612 IntReleaseWindowObject(Parent
);
2616 IntReleaseWindowObject(tmp
);
2617 WndAncestor
= Parent
;
2625 IntReferenceWindowObject(WndAncestor
);
2630 Parent
= IntGetParent(WndAncestor
);
2631 IntReleaseWindowObject(Old
);
2636 WndAncestor
= Parent
;
2643 IntReleaseWindowObject(Wnd
);
2648 hWndAncestor
= (WndAncestor
? WndAncestor
->Self
: NULL
);
2649 IntReleaseWindowObject(Wnd
);
2651 if(WndAncestor
&& (WndAncestor
!= Wnd
))
2652 IntReleaseWindowObject(WndAncestor
);
2654 return hWndAncestor
;
2659 * Returns client window rectangle relative to the upper-left corner of client area.
2661 * \param hWnd window handle.
2662 * \param Rect pointer to the buffer where the coordinates are returned.
2669 NtUserGetClientRect(HWND hWnd
, LPRECT Rect
)
2671 PWINDOW_OBJECT WindowObject
;
2674 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
2676 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2680 IntGetClientRect(WindowObject
, &SafeRect
);
2681 IntReleaseWindowObject(WindowObject
);
2683 if(!NT_SUCCESS(MmCopyToCaller(Rect
, &SafeRect
, sizeof(RECT
))))
2695 NtUserGetDesktopWindow()
2697 return IntGetDesktopWindow();
2705 NtUserGetInternalWindowPos(DWORD Unknown0
,
2719 NtUserGetLastActivePopup(HWND hWnd
)
2722 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2723 * not changed anywhere.
2724 * -- Filip, 01/nov/2003
2730 IntAcquireWinLockShared();
2732 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2734 IntReleaseWinLock();
2735 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2739 hWndLastPopup
= Wnd
->hWndLastPopup
;
2741 IntReleaseWinLock();
2743 return hWndLastPopup
;
2752 * The NtUserGetParent function retrieves a handle to the specified window's
2756 * Note that, despite its name, this function can return an owner window
2757 * instead of a parent window.
2764 NtUserGetParent(HWND hWnd
)
2766 PWINDOW_OBJECT Wnd
, WndParent
;
2767 HWND hWndParent
= NULL
;
2769 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2771 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2775 WndParent
= IntGetParent(Wnd
);
2778 hWndParent
= WndParent
->Self
;
2779 IntReleaseWindowObject(WndParent
);
2782 IntReleaseWindowObject(Wnd
);
2790 * The NtUserSetParent function changes the parent window of the specified
2794 * The new parent window and the child window must belong to the same
2795 * application. If the window identified by the hWndChild parameter is
2796 * visible, the system performs the appropriate redrawing and repainting.
2797 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2798 * or WS_POPUP window styles of the window whose parent is being changed.
2805 NtUserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2807 PWINDOW_OBJECT Wnd
= NULL
, WndParent
= NULL
, WndOldParent
;
2808 HWND hWndOldParent
= NULL
;
2810 if (IntIsBroadcastHwnd(hWndChild
) || IntIsBroadcastHwnd(hWndNewParent
))
2812 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2816 if (hWndChild
== IntGetDesktopWindow())
2818 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2824 if (!(WndParent
= IntGetWindowObject(hWndNewParent
)))
2826 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2832 if (!(WndParent
= IntGetWindowObject(IntGetDesktopWindow())))
2834 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2839 if (!(Wnd
= IntGetWindowObject(hWndChild
)))
2841 IntReleaseWindowObject(WndParent
);
2842 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2846 WndOldParent
= IntSetParent(Wnd
, WndParent
);
2850 hWndOldParent
= WndOldParent
->Self
;
2851 IntReleaseWindowObject(WndOldParent
);
2854 IntReleaseWindowObject(Wnd
);
2855 IntReleaseWindowObject(WndParent
);
2857 return hWndOldParent
;
2861 * NtUserGetShellWindow
2863 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
2870 NtUserGetShellWindow()
2872 PWINSTATION_OBJECT WinStaObject
;
2875 NTSTATUS Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
2880 if (!NT_SUCCESS(Status
))
2882 SetLastNtError(Status
);
2886 Ret
= (HWND
)WinStaObject
->ShellWindow
;
2888 ObDereferenceObject(WinStaObject
);
2893 * NtUserSetShellWindowEx
2895 * This is undocumented function to set global shell window. The global
2896 * shell window has special handling of window position.
2903 NtUserSetShellWindowEx(HWND hwndShell
, HWND hwndListView
)
2905 PWINSTATION_OBJECT WinStaObject
;
2907 NTSTATUS Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
2912 if (!NT_SUCCESS(Status
))
2914 SetLastNtError(Status
);
2919 * Test if we are permitted to change the shell window.
2921 if (WinStaObject
->ShellWindow
)
2923 ObDereferenceObject(WinStaObject
);
2928 * Move shell window into background.
2930 if (hwndListView
&& hwndListView
!= hwndShell
)
2933 * Disabled for now to get Explorer working.
2934 * -- Filip, 01/nov/2003
2937 WinPosSetWindowPos(hwndListView
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2940 if (NtUserGetWindowLong(hwndListView
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2942 ObDereferenceObject(WinStaObject
);
2947 if (NtUserGetWindowLong(hwndShell
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2949 ObDereferenceObject(WinStaObject
);
2953 WinPosSetWindowPos(hwndShell
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2955 WinStaObject
->ShellWindow
= hwndShell
;
2956 WinStaObject
->ShellListView
= hwndListView
;
2958 ObDereferenceObject(WinStaObject
);
2963 * NtUserGetSystemMenu
2965 * The NtUserGetSystemMenu function allows the application to access the
2966 * window menu (also known as the system menu or the control menu) for
2967 * copying and modifying.
2971 * Handle to the window that will own a copy of the window menu.
2973 * Specifies the action to be taken. If this parameter is FALSE,
2974 * NtUserGetSystemMenu returns a handle to the copy of the window menu
2975 * currently in use. The copy is initially identical to the window menu
2976 * but it can be modified.
2977 * If this parameter is TRUE, GetSystemMenu resets the window menu back
2978 * to the default state. The previous window menu, if any, is destroyed.
2981 * If the bRevert parameter is FALSE, the return value is a handle to a
2982 * copy of the window menu. If the bRevert parameter is TRUE, the return
2990 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
2993 PWINDOW_OBJECT WindowObject
;
2994 PMENU_OBJECT MenuObject
;
2996 WindowObject
= IntGetWindowObject((HWND
)hWnd
);
2997 if (WindowObject
== NULL
)
2999 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3003 MenuObject
= IntGetSystemMenu(WindowObject
, bRevert
, FALSE
);
3006 Result
= MenuObject
->MenuInfo
.Self
;
3007 IntReleaseMenuObject(MenuObject
);
3010 IntReleaseWindowObject(WindowObject
);
3015 * NtUserSetSystemMenu
3022 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
3024 BOOL Result
= FALSE
;
3025 PWINDOW_OBJECT WindowObject
;
3026 PMENU_OBJECT MenuObject
;
3028 WindowObject
= IntGetWindowObject(hWnd
);
3031 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3038 * Assign new menu handle.
3040 MenuObject
= IntGetMenuObject(hMenu
);
3043 IntReleaseWindowObject(WindowObject
);
3044 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
3048 Result
= IntSetSystemMenu(WindowObject
, MenuObject
);
3050 IntReleaseMenuObject(MenuObject
);
3053 IntReleaseWindowObject(WindowObject
);
3061 * The NtUserGetWindow function retrieves a handle to a window that has the
3062 * specified relationship (Z order or owner) to the specified window.
3069 NtUserGetWindow(HWND hWnd
, UINT Relationship
)
3071 PWINDOW_OBJECT WindowObject
, Parent
;
3072 HWND hWndResult
= NULL
;
3074 if (!(WindowObject
= IntGetWindowObject(hWnd
)))
3076 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3080 switch (Relationship
)
3083 if((Parent
= IntGetParentObject(WindowObject
)))
3085 IntLockRelatives(Parent
);
3086 if (Parent
->FirstChild
)
3087 hWndResult
= Parent
->FirstChild
->Self
;
3088 IntUnLockRelatives(Parent
);
3089 IntReleaseWindowObject(Parent
);
3094 if((Parent
= IntGetParentObject(WindowObject
)))
3096 IntLockRelatives(Parent
);
3097 if (Parent
->LastChild
)
3098 hWndResult
= Parent
->LastChild
->Self
;
3099 IntUnLockRelatives(Parent
);
3100 IntReleaseWindowObject(Parent
);
3105 IntLockRelatives(WindowObject
);
3106 if (WindowObject
->NextSibling
)
3107 hWndResult
= WindowObject
->NextSibling
->Self
;
3108 IntUnLockRelatives(WindowObject
);
3112 IntLockRelatives(WindowObject
);
3113 if (WindowObject
->PrevSibling
)
3114 hWndResult
= WindowObject
->PrevSibling
->Self
;
3115 IntUnLockRelatives(WindowObject
);
3119 IntLockRelatives(WindowObject
);
3120 if((Parent
= IntGetWindowObject(WindowObject
->Owner
)))
3122 hWndResult
= Parent
->Self
;
3123 IntReleaseWindowObject(Parent
);
3125 IntUnLockRelatives(WindowObject
);
3128 IntLockRelatives(WindowObject
);
3129 if (WindowObject
->FirstChild
)
3130 hWndResult
= WindowObject
->FirstChild
->Self
;
3131 IntUnLockRelatives(WindowObject
);
3135 IntReleaseWindowObject(WindowObject
);
3141 * NtUserGetWindowLong
3143 * The NtUserGetWindowLong function retrieves information about the specified
3144 * window. The function also retrieves the 32-bit (long) value at the
3145 * specified offset into the extra window memory.
3152 NtUserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3154 PWINDOW_OBJECT WindowObject
, Parent
;
3157 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3159 WindowObject
= IntGetWindowObject(hWnd
);
3160 if (WindowObject
== NULL
)
3162 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3167 * Only allow CSRSS to mess with the desktop window
3169 if (hWnd
== IntGetDesktopWindow()
3170 && WindowObject
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
3172 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3176 if ((INT
)Index
>= 0)
3178 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
3180 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3183 Result
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
3190 Result
= WindowObject
->ExStyle
;
3194 Result
= WindowObject
->Style
;
3199 Result
= (LONG
) WindowObject
->WndProcA
;
3201 Result
= (LONG
) WindowObject
->WndProcW
;
3205 Result
= (LONG
) WindowObject
->Instance
;
3208 case GWL_HWNDPARENT
:
3209 IntLockRelatives(WindowObject
);
3210 Parent
= IntGetWindowObject(WindowObject
->Parent
);
3211 IntUnLockRelatives(WindowObject
);
3214 if (Parent
&& Parent
->Self
== IntGetDesktopWindow())
3215 Result
= (LONG
) NtUserGetWindow(WindowObject
->Self
, GW_OWNER
);
3217 Result
= (LONG
) Parent
->Self
;
3218 IntReleaseWindowObject(Parent
);
3223 Result
= (LONG
) WindowObject
->IDMenu
;
3227 Result
= WindowObject
->UserData
;
3231 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index
);
3232 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3238 IntReleaseWindowObject(WindowObject
);
3244 * NtUserSetWindowLong
3246 * The NtUserSetWindowLong function changes an attribute of the specified
3247 * window. The function also sets the 32-bit (long) value at the specified
3248 * offset into the extra window memory.
3255 NtUserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3257 PWINDOW_OBJECT WindowObject
, Parent
;
3258 PW32PROCESS Process
;
3259 PWINSTATION_OBJECT WindowStation
;
3263 if (hWnd
== IntGetDesktopWindow())
3265 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3269 WindowObject
= IntGetWindowObject(hWnd
);
3270 if (WindowObject
== NULL
)
3272 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3276 if ((INT
)Index
>= 0)
3278 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
3280 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3281 IntReleaseWindowObject(WindowObject
);
3284 OldValue
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
3285 *((LONG
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
3292 OldValue
= (LONG
) WindowObject
->ExStyle
;
3293 Style
.styleOld
= OldValue
;
3294 Style
.styleNew
= NewValue
;
3297 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3299 Process
= WindowObject
->OwnerThread
->ThreadsProcess
->Win32Process
;
3300 WindowStation
= Process
->WindowStation
;
3303 if (hWnd
== WindowStation
->ShellWindow
|| hWnd
== WindowStation
->ShellListView
)
3304 Style
.styleNew
&= ~WS_EX_TOPMOST
;
3307 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3308 WindowObject
->ExStyle
= (DWORD
)Style
.styleNew
;
3309 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3313 OldValue
= (LONG
) WindowObject
->Style
;
3314 Style
.styleOld
= OldValue
;
3315 Style
.styleNew
= NewValue
;
3316 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_STYLE
, (LPARAM
) &Style
);
3317 WindowObject
->Style
= (DWORD
)Style
.styleNew
;
3318 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_STYLE
, (LPARAM
) &Style
);
3322 /* FIXME: should check if window belongs to current process */
3325 OldValue
= (LONG
) WindowObject
->WndProcA
;
3326 WindowObject
->WndProcA
= (WNDPROC
) NewValue
;
3327 WindowObject
->WndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,FALSE
);
3328 WindowObject
->Unicode
= FALSE
;
3332 OldValue
= (LONG
) WindowObject
->WndProcW
;
3333 WindowObject
->WndProcW
= (WNDPROC
) NewValue
;
3334 WindowObject
->WndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,TRUE
);
3335 WindowObject
->Unicode
= TRUE
;
3340 OldValue
= (LONG
) WindowObject
->Instance
;
3341 WindowObject
->Instance
= (HINSTANCE
) NewValue
;
3344 case GWL_HWNDPARENT
:
3345 Parent
= IntGetParentObject(WindowObject
);
3346 if (Parent
&& (Parent
->Self
== IntGetDesktopWindow()))
3347 OldValue
= (LONG
) IntSetOwner(WindowObject
->Self
, (HWND
) NewValue
);
3349 OldValue
= (LONG
) NtUserSetParent(WindowObject
->Self
, (HWND
) NewValue
);
3351 IntReleaseWindowObject(Parent
);
3355 OldValue
= (LONG
) WindowObject
->IDMenu
;
3356 WindowObject
->IDMenu
= (UINT
) NewValue
;
3360 OldValue
= WindowObject
->UserData
;
3361 WindowObject
->UserData
= NewValue
;
3365 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index
);
3366 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3372 IntReleaseWindowObject(WindowObject
);
3378 * NtUserSetWindowWord
3380 * Legacy function similar to NtUserSetWindowLong.
3387 NtUserSetWindowWord(HWND hWnd
, INT Index
, WORD NewValue
)
3389 PWINDOW_OBJECT WindowObject
;
3396 case GWL_HWNDPARENT
:
3397 return NtUserSetWindowLong(hWnd
, Index
, (UINT
)NewValue
, TRUE
);
3401 SetLastWin32Error(ERROR_INVALID_INDEX
);
3406 WindowObject
= IntGetWindowObject(hWnd
);
3407 if (WindowObject
== NULL
)
3409 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3413 if (Index
> WindowObject
->ExtraDataSize
- sizeof(WORD
))
3415 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3416 IntReleaseWindowObject(WindowObject
);
3420 OldValue
= *((WORD
*)(WindowObject
->ExtraData
+ Index
));
3421 *((WORD
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
3423 IntReleaseWindowObject(WindowObject
);
3432 NtUserGetWindowPlacement(HWND hWnd
,
3433 WINDOWPLACEMENT
*lpwndpl
)
3435 PWINDOW_OBJECT WindowObject
;
3436 PINTERNALPOS InternalPos
;
3438 WINDOWPLACEMENT Safepl
;
3441 WindowObject
= IntGetWindowObject(hWnd
);
3442 if (WindowObject
== NULL
)
3444 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3448 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3449 if(!NT_SUCCESS(Status
))
3451 SetLastNtError(Status
);
3452 IntReleaseWindowObject(WindowObject
);
3455 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3457 IntReleaseWindowObject(WindowObject
);
3462 Safepl
.showCmd
= ((WindowObject
->Flags
& WINDOWOBJECT_RESTOREMAX
) ? SW_MAXIMIZE
: SW_SHOWNORMAL
);
3464 Size
.x
= WindowObject
->WindowRect
.left
;
3465 Size
.y
= WindowObject
->WindowRect
.top
;
3466 InternalPos
= WinPosInitInternalPos(WindowObject
, &Size
,
3467 &WindowObject
->WindowRect
);
3470 Safepl
.rcNormalPosition
= InternalPos
->NormalRect
;
3471 Safepl
.ptMinPosition
= InternalPos
->IconPos
;
3472 Safepl
.ptMaxPosition
= InternalPos
->MaxPos
;
3476 IntReleaseWindowObject(WindowObject
);
3480 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3481 if(!NT_SUCCESS(Status
))
3483 SetLastNtError(Status
);
3484 IntReleaseWindowObject(WindowObject
);
3488 IntReleaseWindowObject(WindowObject
);
3494 * Return the dimension of the window in the screen coordinates.
3495 * \param hWnd window handle.
3496 * \param Rect pointer to the buffer where the coordinates are returned.
3502 NtUserGetWindowRect(HWND hWnd
, LPRECT Rect
)
3507 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3509 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3512 Status
= MmCopyToCaller(Rect
, &Wnd
->WindowRect
, sizeof(RECT
));
3513 if (!NT_SUCCESS(Status
))
3515 IntReleaseWindowObject(Wnd
);
3516 SetLastNtError(Status
);
3520 IntReleaseWindowObject(Wnd
);
3529 NtUserGetWindowThreadProcessId(HWND hWnd
, LPDWORD UnsafePid
)
3534 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3536 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3540 tid
= (DWORD
)IntGetWndThreadId(Wnd
);
3541 pid
= (DWORD
)IntGetWndProcessId(Wnd
);
3543 if (UnsafePid
) MmCopyToCaller(UnsafePid
, &pid
, sizeof(DWORD
));
3553 NtUserLockWindowUpdate(DWORD Unknown0
)
3573 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3574 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3575 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3579 QueryWindow based on KJK::Hyperion and James Tabor.
3581 0 = QWUniqueProcessId
3582 1 = QWUniqueThreadId
3583 4 = QWIsHung Implements IsHungAppWindow found
3586 9 = QWKillWindow When I called this with hWnd ==
3587 DesktopWindow, it shutdown the system
3594 NtUserQueryWindow(HWND hWnd
, DWORD Index
)
3596 PWINDOW_OBJECT Window
= IntGetWindowObject(hWnd
);
3601 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3607 case QUERY_WINDOW_UNIQUE_PROCESS_ID
:
3608 Result
= (DWORD
)IntGetWndProcessId(Window
);
3611 case QUERY_WINDOW_UNIQUE_THREAD_ID
:
3612 Result
= (DWORD
)IntGetWndThreadId(Window
);
3615 case QUERY_WINDOW_ISHUNG
:
3616 Result
= (DWORD
)MsqIsHung(Window
->MessageQueue
);
3620 Result
= (DWORD
)NULL
;
3624 IntReleaseWindowObject(Window
);
3634 NtUserRealChildWindowFromPoint(DWORD Unknown0
,
3648 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe
)
3650 UNICODE_STRING SafeMessageName
;
3654 if(MessageNameUnsafe
== NULL
)
3656 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3660 Status
= IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName
, MessageNameUnsafe
);
3661 if(!NT_SUCCESS(Status
))
3663 SetLastNtError(Status
);
3667 Ret
= (UINT
)IntAddAtom(SafeMessageName
.Buffer
);
3669 RtlFreeUnicodeString(&SafeMessageName
);
3678 NtUserSetImeOwnerWindow(DWORD Unknown0
,
3691 NtUserSetInternalWindowPos(DWORD Unknown0
,
3707 NtUserSetLayeredWindowAttributes(DWORD Unknown0
,
3722 NtUserSetLogonNotifyWindow(DWORD Unknown0
)
3739 PWINDOW_OBJECT WindowObject
;
3742 WindowObject
= IntGetWindowObject((HWND
) Wnd
);
3743 if (NULL
== WindowObject
)
3745 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3749 if (! IntSetMenu(WindowObject
, Menu
, &Changed
))
3751 IntReleaseWindowObject(WindowObject
);
3755 IntReleaseWindowObject(WindowObject
);
3757 if (Changed
&& Repaint
)
3759 WinPosSetWindowPos(Wnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
3760 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
3771 NtUserSetWindowFNID(DWORD Unknown0
,
3785 NtUserSetWindowPlacement(HWND hWnd
,
3786 WINDOWPLACEMENT
*lpwndpl
)
3788 PWINDOW_OBJECT WindowObject
;
3789 WINDOWPLACEMENT Safepl
;
3792 WindowObject
= IntGetWindowObject(hWnd
);
3793 if (WindowObject
== NULL
)
3795 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3798 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3799 if(!NT_SUCCESS(Status
))
3801 SetLastNtError(Status
);
3802 IntReleaseWindowObject(WindowObject
);
3805 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3807 IntReleaseWindowObject(WindowObject
);
3811 if ((WindowObject
->Style
& (WS_MAXIMIZE
| WS_MINIMIZE
)) == 0)
3813 WinPosSetWindowPos(WindowObject
->Self
, NULL
,
3814 Safepl
.rcNormalPosition
.left
, Safepl
.rcNormalPosition
.top
,
3815 Safepl
.rcNormalPosition
.right
- Safepl
.rcNormalPosition
.left
,
3816 Safepl
.rcNormalPosition
.bottom
- Safepl
.rcNormalPosition
.top
,
3817 SWP_NOZORDER
| SWP_NOACTIVATE
);
3820 /* FIXME - change window status */
3821 WinPosShowWindow(WindowObject
->Self
, Safepl
.showCmd
);
3823 if (WindowObject
->InternalPos
== NULL
)
3824 WindowObject
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
3825 WindowObject
->InternalPos
->NormalRect
= Safepl
.rcNormalPosition
;
3826 WindowObject
->InternalPos
->IconPos
= Safepl
.ptMinPosition
;
3827 WindowObject
->InternalPos
->MaxPos
= Safepl
.ptMaxPosition
;
3829 IntReleaseWindowObject(WindowObject
);
3840 HWND hWndInsertAfter
,
3847 return WinPosSetWindowPos(hWnd
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3852 IntGetWindowRgn(HWND hWnd
, HRGN hRgn
)
3855 PWINDOW_OBJECT WindowObject
;
3859 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
3861 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3866 IntReleaseWindowObject(WindowObject
);
3870 /* Create a new window region using the window rectangle */
3871 VisRgn
= UnsafeIntCreateRectRgnIndirect(&WindowObject
->WindowRect
);
3872 NtGdiOffsetRgn(VisRgn
, -WindowObject
->WindowRect
.left
, -WindowObject
->WindowRect
.top
);
3873 /* if there's a region assigned to the window, combine them both */
3874 if(WindowObject
->WindowRegion
&& !(WindowObject
->Style
& WS_MINIMIZE
))
3875 NtGdiCombineRgn(VisRgn
, VisRgn
, WindowObject
->WindowRegion
, RGN_AND
);
3876 /* Copy the region into hRgn */
3877 NtGdiCombineRgn(hRgn
, VisRgn
, NULL
, RGN_COPY
);
3879 if((pRgn
= RGNDATA_LockRgn(hRgn
)))
3881 Ret
= pRgn
->rdh
.iType
;
3882 RGNDATA_UnlockRgn(hRgn
);
3887 NtGdiDeleteObject(VisRgn
);
3889 IntReleaseWindowObject(WindowObject
);
3894 IntGetWindowRgnBox(HWND hWnd
, RECT
*Rect
)
3897 PWINDOW_OBJECT WindowObject
;
3901 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
3903 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3908 IntReleaseWindowObject(WindowObject
);
3912 /* Create a new window region using the window rectangle */
3913 VisRgn
= UnsafeIntCreateRectRgnIndirect(&WindowObject
->WindowRect
);
3914 NtGdiOffsetRgn(VisRgn
, -WindowObject
->WindowRect
.left
, -WindowObject
->WindowRect
.top
);
3915 /* if there's a region assigned to the window, combine them both */
3916 if(WindowObject
->WindowRegion
&& !(WindowObject
->Style
& WS_MINIMIZE
))
3917 NtGdiCombineRgn(VisRgn
, VisRgn
, WindowObject
->WindowRegion
, RGN_AND
);
3919 if((pRgn
= RGNDATA_LockRgn(VisRgn
)))
3921 Ret
= pRgn
->rdh
.iType
;
3922 *Rect
= pRgn
->rdh
.rcBound
;
3923 RGNDATA_UnlockRgn(VisRgn
);
3928 NtGdiDeleteObject(VisRgn
);
3930 IntReleaseWindowObject(WindowObject
);
3944 PWINDOW_OBJECT WindowObject
;
3946 WindowObject
= IntGetWindowObject(hWnd
);
3947 if (WindowObject
== NULL
)
3949 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3953 /* FIXME - Verify if hRgn is a valid handle!!!!
3954 Propably make this operation thread-safe, but maybe it's not necessary */
3956 if(WindowObject
->WindowRegion
)
3958 /* Delete no longer needed region handle */
3959 NtGdiDeleteObject(WindowObject
->WindowRegion
);
3961 WindowObject
->WindowRegion
= hRgn
;
3963 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
3967 IntRedrawWindow(WindowObject
, NULL
, NULL
, RDW_INVALIDATE
);
3970 IntReleaseWindowObject(WindowObject
);
3979 NtUserShowWindow(HWND hWnd
,
3982 return WinPosShowWindow(hWnd
, nCmdShow
);
3990 NtUserShowWindowAsync(DWORD Unknown0
,
4003 NtUserUpdateLayeredWindow(DWORD Unknown0
,
4023 NtUserValidateRect(HWND hWnd
, const RECT
* Rect
)
4025 return (VOID
)NtUserRedrawWindow(hWnd
, Rect
, 0, RDW_VALIDATE
| RDW_NOCHILDREN
);
4033 NtUserWindowFromPoint(LONG X
, LONG Y
)
4037 PWINDOW_OBJECT DesktopWindow
, Window
= NULL
;
4039 if ((DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow())))
4046 Hit
= WinPosWindowFromPoint(DesktopWindow
, PsGetWin32Thread()->MessageQueue
, &pt
, &Window
);
4051 IntReleaseWindowObject(Window
);
4052 IntReleaseWindowObject(DesktopWindow
);
4056 IntReleaseWindowObject(DesktopWindow
);
4066 * Undocumented function that is called from DefWindowProc to set
4074 NtUserDefSetText(HWND WindowHandle
, PUNICODE_STRING WindowText
)
4076 PWINDOW_OBJECT WindowObject
;
4077 UNICODE_STRING SafeText
;
4080 WindowObject
= IntGetWindowObject(WindowHandle
);
4083 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4089 Status
= IntSafeCopyUnicodeString(&SafeText
, WindowText
);
4090 if(!NT_SUCCESS(Status
))
4092 SetLastNtError(Status
);
4093 IntReleaseWindowObject(WindowObject
);
4099 RtlInitUnicodeString(&SafeText
, NULL
);
4102 /* FIXME - do this thread-safe! otherwise one could crash here! */
4103 RtlFreeUnicodeString(&WindowObject
->WindowName
);
4105 WindowObject
->WindowName
= SafeText
;
4107 IntReleaseWindowObject(WindowObject
);
4112 * NtUserInternalGetWindowText
4119 NtUserInternalGetWindowText(HWND hWnd
, LPWSTR lpString
, INT nMaxCount
)
4121 PWINDOW_OBJECT WindowObject
;
4125 if(lpString
&& (nMaxCount
<= 1))
4127 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
4131 WindowObject
= IntGetWindowObject(hWnd
);
4134 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4138 /* FIXME - do this thread-safe! otherwise one could crash here! */
4139 Result
= WindowObject
->WindowName
.Length
/ sizeof(WCHAR
);
4142 const WCHAR Terminator
= L
'\0';
4144 WCHAR
*Buffer
= (WCHAR
*)lpString
;
4146 Copy
= min(nMaxCount
- 1, Result
);
4149 Status
= MmCopyToCaller(Buffer
, WindowObject
->WindowName
.Buffer
, Copy
* sizeof(WCHAR
));
4150 if(!NT_SUCCESS(Status
))
4152 SetLastNtError(Status
);
4153 IntReleaseWindowObject(WindowObject
);
4159 Status
= MmCopyToCaller(Buffer
, &Terminator
, sizeof(WCHAR
));
4160 if(!NT_SUCCESS(Status
))
4162 SetLastNtError(Status
);
4163 IntReleaseWindowObject(WindowObject
);
4170 IntReleaseWindowObject(WindowObject
);
4175 NtUserDereferenceWndProcHandle(WNDPROC wpHandle
, WndProcHandle
*Data
)
4177 WndProcHandle Entry
;
4178 if (((DWORD
)wpHandle
& 0xFFFF0000) == 0xFFFF0000)
4180 Entry
= WndProcHandlesArray
[(DWORD
)wpHandle
& 0x0000FFFF];
4181 Data
->WindowProc
= Entry
.WindowProc
;
4182 Data
->IsUnicode
= Entry
.IsUnicode
;
4183 Data
->ProcessID
= Entry
.ProcessID
;
4192 IntAddWndProcHandle(WNDPROC WindowProc
, BOOL IsUnicode
)
4197 WndProcHandle
*OldArray
;
4200 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4202 if (WndProcHandlesArray
[i
].WindowProc
== NULL
)
4210 OldArray
= WndProcHandlesArray
;
4211 OldArraySize
= WndProcHandlesArraySize
;
4212 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,(OldArraySize
+ WPH_SIZE
) * sizeof(WndProcHandle
), TAG_WINPROCLST
);
4213 WndProcHandlesArraySize
= OldArraySize
+ WPH_SIZE
;
4214 RtlCopyMemory(WndProcHandlesArray
,OldArray
,OldArraySize
* sizeof(WndProcHandle
));
4215 ExFreePool(OldArray
);
4216 FreeSpot
= OldArraySize
+ 1;
4218 WndProcHandlesArray
[FreeSpot
].WindowProc
= WindowProc
;
4219 WndProcHandlesArray
[FreeSpot
].IsUnicode
= IsUnicode
;
4220 WndProcHandlesArray
[FreeSpot
].ProcessID
= PsGetCurrentProcessId();
4221 return FreeSpot
+ 0xFFFF0000;
4225 IntRemoveWndProcHandle(WNDPROC Handle
)
4228 position
= (DWORD
)Handle
& 0x0000FFFF;
4229 if (position
> WndProcHandlesArraySize
)
4233 WndProcHandlesArray
[position
].WindowProc
= NULL
;
4234 WndProcHandlesArray
[position
].IsUnicode
= FALSE
;
4235 WndProcHandlesArray
[position
].ProcessID
= NULL
;
4240 IntRemoveProcessWndProcHandles(HANDLE ProcessID
)
4243 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4245 if (WndProcHandlesArray
[i
].ProcessID
== ProcessID
)
4247 WndProcHandlesArray
[i
].WindowProc
= NULL
;
4248 WndProcHandlesArray
[i
].IsUnicode
= FALSE
;
4249 WndProcHandlesArray
[i
].ProcessID
= NULL
;