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 ******************************************************************/
33 static WndProcHandle
*WndProcHandlesArray
= 0;
34 static WORD WndProcHandlesArraySize
= 0;
35 #define WPH_SIZE 0x40 /* the size to add to the WndProcHandle array each time */
37 /* dialog resources appear to pass this in 16 bits, handle them properly */
38 #define CW_USEDEFAULT16 (0x8000)
40 #define POINT_IN_RECT(p, r) (((r.bottom >= p.y) && (r.top <= p.y))&&((r.left <= p.x )&&( r.right >= p.x )))
42 /* PRIVATE FUNCTIONS **********************************************************/
47 * Initialize windowing implementation.
53 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,WPH_SIZE
* sizeof(WndProcHandle
), TAG_WINPROCLST
);
54 WndProcHandlesArraySize
= WPH_SIZE
;
55 return STATUS_SUCCESS
;
61 * Cleanup windowing implementation.
65 CleanupWindowImpl(VOID
)
67 ExFreePool(WndProcHandlesArray
);
68 WndProcHandlesArray
= 0;
69 WndProcHandlesArraySize
= 0;
70 return STATUS_SUCCESS
;
73 /* HELPER FUNCTIONS ***********************************************************/
78 * The function determines whether the specified window handle identifies
83 * Handle to the window to test.
86 * If the window handle identifies an existing window, the return value
87 * is TRUE. If the window handle does not identify an existing window,
88 * the return value is FALSE.
92 IntIsWindow(HWND hWnd
)
94 PWINDOW_OBJECT Window
;
96 if (!(Window
= IntGetWindowObject(hWnd
)))
99 IntReleaseWindowObject(Window
);
104 * IntGetProcessWindowObject
106 * Get window object from handle of specified process.
109 PWINDOW_OBJECT FASTCALL
110 IntGetProcessWindowObject(PW32THREAD Thread
, HWND hWnd
)
112 PWINDOW_OBJECT WindowObject
;
115 if(Thread
->Desktop
!= NULL
)
117 Status
= ObmReferenceObjectByHandle(Thread
->Desktop
->WindowStation
->HandleTable
,
118 hWnd
, otWindow
, (PVOID
*)&WindowObject
);
119 if (NT_SUCCESS(Status
))
128 PWINDOW_OBJECT FASTCALL
129 IntGetParent(PWINDOW_OBJECT Wnd
)
133 if (Wnd
->Style
& WS_POPUP
)
135 IntLockRelatives(Wnd
);
137 IntUnLockRelatives(Wnd
);
138 return IntGetWindowObject(hWnd
);
140 else if (Wnd
->Style
& WS_CHILD
)
142 IntLockRelatives(Wnd
);
144 IntUnLockRelatives(Wnd
);
145 return IntGetWindowObject(hWnd
);
151 PWINDOW_OBJECT FASTCALL
152 IntGetOwner(PWINDOW_OBJECT Wnd
)
156 IntLockRelatives(Wnd
);
158 IntUnLockRelatives(Wnd
);
160 return IntGetWindowObject(hWnd
);
163 PWINDOW_OBJECT FASTCALL
164 IntGetParentObject(PWINDOW_OBJECT Wnd
)
168 IntLockRelatives(Wnd
);
169 hParent
= Wnd
->Parent
;
170 IntUnLockRelatives(Wnd
);
171 return IntGetWindowObject(hParent
);
177 * Compile a list of all child window handles from given window.
180 * This function is similar to Wine WIN_ListChildren. The caller
181 * must free the returned list with ExFreePool.
185 IntWinListChildren(PWINDOW_OBJECT Window
)
187 PWINDOW_OBJECT Child
;
189 UINT Index
, NumChildren
= 0;
191 IntLockRelatives(Window
);
193 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
196 List
= ExAllocatePoolWithTag(PagedPool
, (NumChildren
+ 1) * sizeof(HWND
), TAG_WINLIST
);
199 DPRINT1("Failed to allocate memory for children array\n");
200 IntUnLockRelatives(Window
);
201 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
204 for (Child
= Window
->FirstChild
, Index
= 0;
206 Child
= Child
->NextSibling
, ++Index
)
207 List
[Index
] = Child
->Self
;
210 IntUnLockRelatives(Window
);
215 /***********************************************************************
218 static void IntSendDestroyMsg(HWND Wnd
)
221 PWINDOW_OBJECT Window
, Owner
, Parent
;
225 if (GetGUIThreadInfo(GetCurrentThreadId(), &info
))
227 if (Wnd
== info
.hwndCaret
)
234 Window
= IntGetWindowObject(Wnd
);
236 Owner
= IntGetOwner(Window
);
238 Parent
= IntGetParent(Window
);
240 IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
) Wnd
);
242 IntReleaseWindowObject(Parent
);
244 IntReleaseWindowObject(Owner
);
247 IntReleaseWindowObject(Window
);
250 /* The window could already be destroyed here */
253 * Send the WM_DESTROY to the window.
256 IntSendMessage(Wnd
, WM_DESTROY
, 0, 0);
259 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
260 * make sure that the window still exists when we come back.
268 if (!(pWndArray
= WIN_ListChildren( hwnd
))) return;
270 /* start from the end (FIXME: is this needed?) */
271 for (i
= 0; pWndArray
[i
]; i
++) ;
275 if (IsWindow( pWndArray
[i
] )) WIN_SendDestroyMsg( pWndArray
[i
] );
277 HeapFree(GetProcessHeap(), 0, pWndArray
);
281 DPRINT("destroyed itself while in WM_DESTROY!\n");
286 /***********************************************************************
289 * Destroy storage associated to a window. "Internals" p.358
291 static LRESULT
IntDestroyWindow(PWINDOW_OBJECT Window
,
292 PW32PROCESS ProcessData
,
293 PW32THREAD ThreadData
,
294 BOOLEAN SendMessages
)
298 PWINDOW_OBJECT Child
;
300 BOOLEAN BelongsToThreadData
;
304 IntLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
305 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
307 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
308 DPRINT("Tried to call IntDestroyWindow() twice\n");
311 Window
->Status
|= WINDOWSTATUS_DESTROYING
;
312 Window
->Flags
&= ~WS_VISIBLE
;
313 /* remove the window already at this point from the thread window list so we
314 don't get into trouble when destroying the thread windows while we're still
315 in IntDestroyWindow() */
316 RemoveEntryList(&Window
->ThreadListEntry
);
317 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
319 BelongsToThreadData
= IntWndBelongsToThread(Window
, ThreadData
);
321 IntDeRegisterShellHookWindow(Window
->Self
);
325 /* Send destroy messages */
326 IntSendDestroyMsg(Window
->Self
);
329 /* free child windows */
330 Children
= IntWinListChildren(Window
);
333 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
335 if ((Child
= IntGetWindowObject(*ChildHandle
)))
337 if(!IntWndBelongsToThread(Child
, ThreadData
))
339 /* send WM_DESTROY messages to windows not belonging to the same thread */
340 IntSendDestroyMsg(Child
->Self
);
343 IntDestroyWindow(Child
, ProcessData
, ThreadData
, SendMessages
);
344 IntReleaseWindowObject(Child
);
347 ExFreePool(Children
);
353 * Clear the update region to make sure no WM_PAINT messages will be
354 * generated for this window while processing the WM_NCDESTROY.
356 IntRedrawWindow(Window
, NULL
, 0,
357 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
|
358 RDW_NOINTERNALPAINT
| RDW_NOCHILDREN
);
359 if(BelongsToThreadData
)
360 IntSendMessage(Window
->Self
, WM_NCDESTROY
, 0, 0);
362 MsqRemoveTimersWindow(ThreadData
->MessageQueue
, Window
->Self
);
364 /* flush the message queue */
365 MsqRemoveWindowMessagesFromQueue(Window
);
367 /* from now on no messages can be sent to this window anymore */
368 IntLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
369 Window
->Status
|= WINDOWSTATUS_DESTROYED
;
370 /* don't remove the WINDOWSTATUS_DESTROYING bit */
371 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
373 /* reset shell window handles */
374 if(ThreadData
->Desktop
)
376 if (Window
->Self
== ThreadData
->Desktop
->WindowStation
->ShellWindow
)
377 ThreadData
->Desktop
->WindowStation
->ShellWindow
= NULL
;
379 if (Window
->Self
== ThreadData
->Desktop
->WindowStation
->ShellListView
)
380 ThreadData
->Desktop
->WindowStation
->ShellListView
= NULL
;
383 /* Unregister hot keys */
384 UnregisterWindowHotKeys (Window
);
386 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
389 WinPosCheckInternalPos(Window
->Self
);
390 if (Window
->Self
== GetCapture())
395 /* free resources associated with the window */
396 TIMER_RemoveWindowTimers(Window
->Self
);
399 if (!(Window
->Style
& WS_CHILD
) && Window
->IDMenu
400 && (Menu
= IntGetMenuObject((HMENU
)Window
->IDMenu
)))
402 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
404 IntReleaseMenuObject(Menu
);
407 if(Window
->SystemMenu
408 && (Menu
= IntGetMenuObject(Window
->SystemMenu
)))
410 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
411 Window
->SystemMenu
= (HMENU
)0;
412 IntReleaseMenuObject(Menu
);
415 DceFreeWindowDCE(Window
); /* Always do this to catch orphaned DCs */
417 WINPROC_FreeProc(Window
->winproc
, WIN_PROC_WINDOW
);
418 CLASS_RemoveWindow(Window
->Class
);
421 IntUnlinkWindow(Window
);
423 IntReferenceWindowObject(Window
);
424 ObmCloseHandle(ThreadData
->Desktop
->WindowStation
->HandleTable
, Window
->Self
);
426 IntDestroyScrollBars(Window
);
428 /* remove the window from the class object */
429 IntLockClassWindows(Window
->Class
);
430 RemoveEntryList(&Window
->ClassListEntry
);
431 IntUnLockClassWindows(Window
->Class
);
433 /* dereference the class */
434 ClassDereferenceObject(Window
->Class
);
435 Window
->Class
= NULL
;
437 if(Window
->WindowRegion
)
439 NtGdiDeleteObject(Window
->WindowRegion
);
442 RtlFreeUnicodeString(&Window
->WindowName
);
444 IntReleaseWindowObject(Window
);
450 IntGetWindowBorderMeasures(PWINDOW_OBJECT WindowObject
, UINT
*cx
, UINT
*cy
)
452 if(HAS_DLGFRAME(WindowObject
->Style
, WindowObject
->ExStyle
) && !(WindowObject
->Style
& WS_MINIMIZE
))
454 *cx
= NtUserGetSystemMetrics(SM_CXDLGFRAME
);
455 *cy
= NtUserGetSystemMetrics(SM_CYDLGFRAME
);
459 if(HAS_THICKFRAME(WindowObject
->Style
, WindowObject
->ExStyle
)&& !(WindowObject
->Style
& WS_MINIMIZE
))
461 *cx
= NtUserGetSystemMetrics(SM_CXFRAME
);
462 *cy
= NtUserGetSystemMetrics(SM_CYFRAME
);
464 else if(HAS_THINFRAME(WindowObject
->Style
, WindowObject
->ExStyle
))
466 *cx
= NtUserGetSystemMetrics(SM_CXBORDER
);
467 *cy
= NtUserGetSystemMetrics(SM_CYBORDER
);
477 IntGetWindowInfo(PWINDOW_OBJECT WindowObject
, PWINDOWINFO pwi
)
479 pwi
->cbSize
= sizeof(WINDOWINFO
);
480 pwi
->rcWindow
= WindowObject
->WindowRect
;
481 pwi
->rcClient
= WindowObject
->ClientRect
;
482 pwi
->dwStyle
= WindowObject
->Style
;
483 pwi
->dwExStyle
= WindowObject
->ExStyle
;
484 pwi
->dwWindowStatus
= (NtUserGetForegroundWindow() == WindowObject
->Self
); /* WS_ACTIVECAPTION */
485 IntGetWindowBorderMeasures(WindowObject
, &pwi
->cxWindowBorders
, &pwi
->cyWindowBorders
);
486 pwi
->atomWindowType
= (WindowObject
->Class
? WindowObject
->Class
->Atom
: 0);
487 pwi
->wCreatorVersion
= 0x400; /* FIXME - return a real version number */
493 PWINDOW_OBJECT WindowObject
,
497 PMENU_OBJECT OldMenuObject
, NewMenuObject
= NULL
;
499 *Changed
= (WindowObject
->IDMenu
!= (UINT
) Menu
);
505 if (0 != WindowObject
->IDMenu
)
507 OldMenuObject
= IntGetMenuObject((HMENU
) WindowObject
->IDMenu
);
508 ASSERT(NULL
== OldMenuObject
|| OldMenuObject
->MenuInfo
.Wnd
== WindowObject
->Self
);
512 OldMenuObject
= NULL
;
517 NewMenuObject
= IntGetMenuObject(Menu
);
518 if (NULL
== NewMenuObject
)
520 if (NULL
!= OldMenuObject
)
522 IntReleaseMenuObject(OldMenuObject
);
524 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
527 if (NULL
!= NewMenuObject
->MenuInfo
.Wnd
)
529 /* Can't use the same menu for two windows */
530 if (NULL
!= OldMenuObject
)
532 IntReleaseMenuObject(OldMenuObject
);
534 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
540 WindowObject
->IDMenu
= (UINT
) Menu
;
541 if (NULL
!= NewMenuObject
)
543 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
544 IntReleaseMenuObject(NewMenuObject
);
546 if (NULL
!= OldMenuObject
)
548 OldMenuObject
->MenuInfo
.Wnd
= NULL
;
549 IntReleaseMenuObject(OldMenuObject
);
556 /* INTERNAL ******************************************************************/
560 DestroyThreadWindows(struct _ETHREAD
*Thread
)
563 PW32PROCESS Win32Process
;
564 PW32THREAD Win32Thread
;
565 PWINDOW_OBJECT
*List
, *pWnd
;
568 Win32Thread
= Thread
->Tcb
.Win32Thread
;
569 Win32Process
= (PW32PROCESS
)Thread
->ThreadsProcess
->Win32Process
;
571 IntLockThreadWindows(Win32Thread
);
572 Current
= Win32Thread
->WindowListHead
.Flink
;
573 while (Current
!= &(Win32Thread
->WindowListHead
))
576 Current
= Current
->Flink
;
581 List
= ExAllocatePool(PagedPool
, (Cnt
+ 1) * sizeof(PWINDOW_OBJECT
));
584 DPRINT("Not enough memory to allocate window handle list\n");
585 IntUnLockThreadWindows(Win32Thread
);
589 Current
= Win32Thread
->WindowListHead
.Flink
;
590 while (Current
!= &(Win32Thread
->WindowListHead
))
592 *pWnd
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
593 IntReferenceWindowObject(*pWnd
);
595 Current
= Current
->Flink
;
597 IntUnLockThreadWindows(Win32Thread
);
600 for(pWnd
= List
; *pWnd
; pWnd
++)
602 NtUserDestroyWindow((*pWnd
)->Self
);
603 IntReleaseWindowObject(*pWnd
);
609 IntUnLockThreadWindows(Win32Thread
);
615 * Returns client window rectangle relative to the upper-left corner of client area.
617 * \note Does not check the validity of the parameters
620 IntGetClientRect(PWINDOW_OBJECT WindowObject
, PRECT Rect
)
622 ASSERT( WindowObject
);
625 Rect
->left
= Rect
->top
= 0;
626 Rect
->right
= WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
;
627 Rect
->bottom
= WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
;
633 IntGetFocusWindow(VOID
)
635 PUSER_MESSAGE_QUEUE Queue
;
636 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
641 Queue
= (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
646 return(Queue
->FocusWindow
);
650 PMENU_OBJECT FASTCALL
651 IntGetSystemMenu(PWINDOW_OBJECT WindowObject
, BOOL bRevert
, BOOL RetMenu
)
653 PMENU_OBJECT MenuObject
, NewMenuObject
, SysMenuObject
, ret
= NULL
;
654 PW32THREAD W32Thread
;
655 HMENU NewMenu
, SysMenu
;
656 ROSMENUITEMINFO ItemInfo
;
660 W32Thread
= PsGetWin32Thread();
662 if(!W32Thread
->Desktop
)
665 if(WindowObject
->SystemMenu
)
667 MenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
670 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
671 WindowObject
->SystemMenu
= (HMENU
)0;
672 IntReleaseMenuObject(MenuObject
);
676 if(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
)
678 /* clone system menu */
679 MenuObject
= IntGetMenuObject(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
);
683 NewMenuObject
= IntCloneMenu(MenuObject
);
686 WindowObject
->SystemMenu
= NewMenuObject
->MenuInfo
.Self
;
687 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
688 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
690 //IntReleaseMenuObject(NewMenuObject);
692 IntReleaseMenuObject(MenuObject
);
696 SysMenu
= NtUserCreateMenu(FALSE
);
701 SysMenuObject
= IntGetMenuObject(SysMenu
);
702 if (NULL
== SysMenuObject
)
704 NtUserDestroyMenu(SysMenu
);
707 SysMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
708 SysMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
709 NewMenu
= IntLoadSysMenuTemplate();
712 IntReleaseMenuObject(SysMenuObject
);
713 NtUserDestroyMenu(SysMenu
);
716 MenuObject
= IntGetMenuObject(NewMenu
);
719 IntReleaseMenuObject(SysMenuObject
);
720 NtUserDestroyMenu(SysMenu
);
724 NewMenuObject
= IntCloneMenu(MenuObject
);
727 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
| MF_POPUP
;
728 IntReleaseMenuObject(NewMenuObject
);
729 NtUserSetMenuDefaultItem(NewMenuObject
->MenuInfo
.Self
, SC_CLOSE
, FALSE
);
731 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
732 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
733 ItemInfo
.fType
= MF_POPUP
;
734 ItemInfo
.fState
= MFS_ENABLED
;
735 ItemInfo
.dwTypeData
= NULL
;
737 ItemInfo
.hSubMenu
= NewMenuObject
->MenuInfo
.Self
;
738 IntInsertMenuItem(SysMenuObject
, (UINT
) -1, TRUE
, &ItemInfo
);
740 WindowObject
->SystemMenu
= SysMenuObject
->MenuInfo
.Self
;
744 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
745 IntReleaseMenuObject(MenuObject
);
754 if(WindowObject
->SystemMenu
)
755 return IntGetMenuObject((HMENU
)WindowObject
->SystemMenu
);
763 IntIsChildWindow(HWND Parent
, HWND Child
)
765 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
767 if(!(BaseWindow
= IntGetWindowObject(Child
)))
775 if (Window
->Self
== Parent
)
777 if(Window
!= BaseWindow
)
778 IntReleaseWindowObject(Window
);
779 IntReleaseWindowObject(BaseWindow
);
782 if(!(Window
->Style
& WS_CHILD
))
784 if(Window
!= BaseWindow
)
785 IntReleaseWindowObject(Window
);
789 Window
= IntGetParentObject(Window
);
790 if(Old
!= BaseWindow
)
791 IntReleaseWindowObject(Old
);
794 IntReleaseWindowObject(BaseWindow
);
799 IntIsWindowVisible(HWND hWnd
)
801 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
803 if(!(BaseWindow
= IntGetWindowObject(hWnd
)))
811 if(!(Window
->Style
& WS_CHILD
))
815 if(!(Window
->Style
& WS_VISIBLE
))
817 if(Window
!= BaseWindow
)
818 IntReleaseWindowObject(Window
);
819 IntReleaseWindowObject(BaseWindow
);
823 Window
= IntGetParentObject(Window
);
824 if(Old
!= BaseWindow
)
825 IntReleaseWindowObject(Old
);
830 if(Window
->Style
& WS_VISIBLE
)
832 if(Window
!= BaseWindow
)
833 IntReleaseWindowObject(Window
);
834 IntReleaseWindowObject(BaseWindow
);
837 if(Window
!= BaseWindow
)
838 IntReleaseWindowObject(Window
);
840 IntReleaseWindowObject(BaseWindow
);
845 /* link the window into siblings and parent. children are kept in place. */
849 PWINDOW_OBJECT WndParent
,
850 PWINDOW_OBJECT WndPrevSibling
/* set to NULL if top sibling */
853 PWINDOW_OBJECT Parent
;
855 IntLockRelatives(Wnd
);
856 Wnd
->Parent
= WndParent
->Self
;
857 if ((Wnd
->PrevSibling
= WndPrevSibling
))
859 /* link after WndPrevSibling */
860 if ((Wnd
->NextSibling
= WndPrevSibling
->NextSibling
))
861 Wnd
->NextSibling
->PrevSibling
= Wnd
;
862 else if ((Parent
= IntGetWindowObject(Wnd
->Parent
)))
864 IntLockRelatives(Parent
);
865 if(Parent
->LastChild
== WndPrevSibling
)
866 Parent
->LastChild
= Wnd
;
867 IntUnLockRelatives(Parent
);
868 IntReleaseWindowObject(Parent
);
870 Wnd
->PrevSibling
->NextSibling
= Wnd
;
875 Parent
= IntGetWindowObject(Wnd
->Parent
);
876 if ((Wnd
->NextSibling
= WndParent
->FirstChild
))
877 Wnd
->NextSibling
->PrevSibling
= Wnd
;
880 IntLockRelatives(Parent
);
881 Parent
->LastChild
= Wnd
;
882 Parent
->FirstChild
= Wnd
;
883 IntUnLockRelatives(Parent
);
884 IntReleaseWindowObject(Parent
);
885 IntUnLockRelatives(Wnd
);
890 IntLockRelatives(Parent
);
891 Parent
->FirstChild
= Wnd
;
892 IntUnLockRelatives(Parent
);
893 IntReleaseWindowObject(Parent
);
896 IntUnLockRelatives(Wnd
);
900 IntSetOwner(HWND hWnd
, HWND hWndNewOwner
)
902 PWINDOW_OBJECT Wnd
, WndOldOwner
, WndNewOwner
;
905 Wnd
= IntGetWindowObject(hWnd
);
909 IntLockRelatives(Wnd
);
910 WndOldOwner
= IntGetWindowObject(Wnd
->Owner
);
913 ret
= WndOldOwner
->Self
;
914 IntReleaseWindowObject(WndOldOwner
);
921 if((WndNewOwner
= IntGetWindowObject(hWndNewOwner
)))
923 Wnd
->Owner
= hWndNewOwner
;
924 IntReleaseWindowObject(WndNewOwner
);
929 IntUnLockRelatives(Wnd
);
930 IntReleaseWindowObject(Wnd
);
934 PWINDOW_OBJECT FASTCALL
935 IntSetParent(PWINDOW_OBJECT Wnd
, PWINDOW_OBJECT WndNewParent
)
937 PWINDOW_OBJECT WndOldParent
, Sibling
, InsertAfter
;
938 HWND hWnd
, hWndNewParent
, hWndOldParent
;
943 ASSERT(WndNewParent
);
946 hWndNewParent
= WndNewParent
->Self
;
949 * Windows hides the window first, then shows it again
950 * including the WM_SHOWWINDOW messages and all
952 WasVisible
= WinPosShowWindow(hWnd
, SW_HIDE
);
954 /* Validate that window and parent still exist */
955 if (!IntIsWindow(hWnd
) || !IntIsWindow(hWndNewParent
))
958 /* Window must belong to current process */
959 if (Wnd
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
962 WndOldParent
= IntGetParentObject(Wnd
);
963 hWndOldParent
= (WndOldParent
? WndOldParent
->Self
: NULL
);
965 if (WndNewParent
!= WndOldParent
)
967 IntUnlinkWindow(Wnd
);
969 if (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
))
971 /* Not a TOPMOST window, put after TOPMOSTs of new parent */
972 IntLockRelatives(WndNewParent
);
973 Sibling
= WndNewParent
->FirstChild
;
974 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
976 InsertAfter
= Sibling
;
977 Sibling
= Sibling
->NextSibling
;
979 IntUnLockRelatives(WndNewParent
);
981 if (NULL
== InsertAfter
)
983 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
987 IntReferenceWindowObject(InsertAfter
);
988 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
989 IntReleaseWindowObject(InsertAfter
);
992 if (WndNewParent
->Self
!= IntGetDesktopWindow()) /* a child window */
994 if (!(Wnd
->Style
& WS_CHILD
))
996 //if ( Wnd->Menu ) DestroyMenu ( Wnd->menu );
997 IntSetMenu(Wnd
, NULL
, &MenuChanged
);
1003 * SetParent additionally needs to make hwnd the top window
1004 * in the z-order and send the expected WM_WINDOWPOSCHANGING and
1005 * WM_WINDOWPOSCHANGED notification messages.
1007 WinPosSetWindowPos(hWnd
, (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOP
: HWND_TOPMOST
),
1008 0, 0, 0, 0, SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
1009 | (WasVisible
? SWP_SHOWWINDOW
: 0));
1012 * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
1013 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
1017 * Validate that the old parent still exist, since it migth have been
1018 * destroyed during the last callbacks to user-mode
1022 if(!IntIsWindow(WndOldParent
->Self
))
1024 IntReleaseWindowObject(WndOldParent
);
1028 /* don't dereference the window object here, it must be done by the caller
1029 of IntSetParent() */
1030 return WndOldParent
;
1036 IntSetSystemMenu(PWINDOW_OBJECT WindowObject
, PMENU_OBJECT MenuObject
)
1038 PMENU_OBJECT OldMenuObject
;
1039 if(WindowObject
->SystemMenu
)
1041 OldMenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
1044 OldMenuObject
->MenuInfo
.Flags
&= ~ MF_SYSMENU
;
1045 IntReleaseMenuObject(OldMenuObject
);
1051 /* FIXME check window style, propably return FALSE ? */
1052 WindowObject
->SystemMenu
= MenuObject
->MenuInfo
.Self
;
1053 MenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
1056 WindowObject
->SystemMenu
= (HMENU
)0;
1062 /* unlink the window from siblings and parent. children are kept in place. */
1064 IntUnlinkWindow(PWINDOW_OBJECT Wnd
)
1066 PWINDOW_OBJECT WndParent
;
1068 IntLockRelatives(Wnd
);
1069 if((WndParent
= IntGetWindowObject(Wnd
->Parent
)))
1071 IntLockRelatives(WndParent
);
1074 if (Wnd
->NextSibling
) Wnd
->NextSibling
->PrevSibling
= Wnd
->PrevSibling
;
1075 else if (WndParent
&& WndParent
->LastChild
== Wnd
) WndParent
->LastChild
= Wnd
->PrevSibling
;
1077 if (Wnd
->PrevSibling
) Wnd
->PrevSibling
->NextSibling
= Wnd
->NextSibling
;
1078 else if (WndParent
&& WndParent
->FirstChild
== Wnd
) WndParent
->FirstChild
= Wnd
->NextSibling
;
1082 IntUnLockRelatives(WndParent
);
1083 IntReleaseWindowObject(WndParent
);
1085 Wnd
->PrevSibling
= Wnd
->NextSibling
= Wnd
->Parent
= NULL
;
1086 IntUnLockRelatives(Wnd
);
1092 PWINDOW_OBJECT Window
, Child
;
1094 if(!(Window
= IntGetWindowObject(IntGetDesktopWindow())))
1096 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1100 IntLockRelatives(Window
);
1101 for(Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
1103 if(Child
->Owner
&& Child
->Style
& WS_VISIBLE
)
1106 * The desktop has a popup window if one of them has
1107 * an owner window and is visible
1109 IntUnLockRelatives(Window
);
1110 IntReleaseWindowObject(Window
);
1114 IntUnLockRelatives(Window
);
1115 IntReleaseWindowObject(Window
);
1120 IntIsWindowInDestroy(PWINDOW_OBJECT Window
)
1122 return ((Window
->Status
& WINDOWSTATUS_DESTROYING
) == WINDOWSTATUS_DESTROYING
);
1125 /* FUNCTIONS *****************************************************************/
1131 NtUserAlterWindowStyle(DWORD Unknown0
,
1142 * As best as I can figure, this function is used by EnumWindows,
1143 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
1145 * It's supposed to build a list of HWNDs to return to the caller.
1146 * We can figure out what kind of list by what parameters are
1154 NtUserBuildHwndList(
1166 /* FIXME handle bChildren */
1170 PWINDOW_OBJECT Window
, Child
;
1171 if(!(Window
= IntGetWindowObject(hwndParent
)))
1173 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1177 IntLockRelatives(Window
);
1178 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1180 if(dwCount
++ < nBufSize
&& pWnd
)
1182 Status
= MmCopyToCaller(pWnd
++, &Child
->Self
, sizeof(HWND
));
1183 if(!NT_SUCCESS(Status
))
1185 SetLastNtError(Status
);
1190 IntUnLockRelatives(Window
);
1192 IntReleaseWindowObject(Window
);
1197 PW32THREAD W32Thread
;
1198 PLIST_ENTRY Current
;
1199 PWINDOW_OBJECT Window
;
1201 Status
= PsLookupThreadByThreadId((HANDLE
)dwThreadId
, &Thread
);
1202 if(!NT_SUCCESS(Status
))
1204 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1207 if(!(W32Thread
= Thread
->Tcb
.Win32Thread
))
1209 ObDereferenceObject(Thread
);
1210 DPRINT("Thread is not a GUI Thread!\n");
1211 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1215 IntLockThreadWindows(W32Thread
);
1216 Current
= W32Thread
->WindowListHead
.Flink
;
1217 while(Current
!= &(W32Thread
->WindowListHead
))
1219 Window
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
1222 if(dwCount
< nBufSize
&& pWnd
)
1224 Status
= MmCopyToCaller(pWnd
++, &Window
->Self
, sizeof(HWND
));
1225 if(!NT_SUCCESS(Status
))
1227 SetLastNtError(Status
);
1232 Current
= Current
->Flink
;
1234 IntUnLockThreadWindows(W32Thread
);
1236 ObDereferenceObject(Thread
);
1240 PDESKTOP_OBJECT Desktop
;
1241 PWINDOW_OBJECT Window
, Child
;
1243 if(hDesktop
== NULL
&& !(Desktop
= IntGetActiveDesktop()))
1245 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1251 Status
= IntValidateDesktopHandle(hDesktop
,
1255 if(!NT_SUCCESS(Status
))
1257 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1261 if(!(Window
= IntGetWindowObject(Desktop
->DesktopWindow
)))
1264 ObDereferenceObject(Desktop
);
1265 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1269 IntLockRelatives(Window
);
1270 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1272 if(dwCount
++ < nBufSize
&& pWnd
)
1274 Status
= MmCopyToCaller(pWnd
++, &Child
->Self
, sizeof(HWND
));
1275 if(!NT_SUCCESS(Status
))
1277 SetLastNtError(Status
);
1282 IntUnLockRelatives(Window
);
1284 IntReleaseWindowObject(Window
);
1286 ObDereferenceObject(Desktop
);
1297 NtUserChildWindowFromPointEx(HWND hwndParent
,
1302 PWINDOW_OBJECT Parent
;
1307 if(!(Parent
= IntGetWindowObject(hwndParent
)))
1309 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1316 if(Parent
->Self
!= IntGetDesktopWindow())
1318 Pt
.x
+= Parent
->ClientRect
.left
;
1319 Pt
.y
+= Parent
->ClientRect
.top
;
1322 if(!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
))
1324 IntReleaseWindowObject(Parent
);
1329 if((List
= IntWinListChildren(Parent
)))
1331 for(phWnd
= List
; *phWnd
; phWnd
++)
1333 PWINDOW_OBJECT Child
;
1334 if((Child
= IntGetWindowObject(*phWnd
)))
1336 if(!(Child
->Style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
))
1338 IntReleaseWindowObject(Child
);
1341 if((Child
->Style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
))
1343 IntReleaseWindowObject(Child
);
1346 if((Child
->ExStyle
& WS_EX_TRANSPARENT
) && (uiFlags
& CWP_SKIPTRANSPARENT
))
1348 IntReleaseWindowObject(Child
);
1351 if(IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
1354 IntReleaseWindowObject(Child
);
1357 IntReleaseWindowObject(Child
);
1363 IntReleaseWindowObject(Parent
);
1369 * calculates the default position of a window
1372 IntCalcDefPosSize(PWINDOW_OBJECT Parent
, PWINDOW_OBJECT WindowObject
, RECT
*rc
, BOOL IncPos
)
1379 IntGdiIntersectRect(rc
, rc
, &Parent
->ClientRect
);
1383 Pos
.x
= Parent
->TiledCounter
* (NtUserGetSystemMetrics(SM_CXSIZE
) + NtUserGetSystemMetrics(SM_CXFRAME
));
1384 Pos
.y
= Parent
->TiledCounter
* (NtUserGetSystemMetrics(SM_CYSIZE
) + NtUserGetSystemMetrics(SM_CYFRAME
));
1385 if(Pos
.x
> ((rc
->right
- rc
->left
) / 4) ||
1386 Pos
.y
> ((rc
->bottom
- rc
->top
) / 4))
1388 /* reset counter and position */
1391 Parent
->TiledCounter
= 0;
1393 Parent
->TiledCounter
++;
1404 Sz
.cx
= EngMulDiv(rc
->right
- rc
->left
, 3, 4);
1405 Sz
.cy
= EngMulDiv(rc
->bottom
- rc
->top
, 3, 4);
1409 rc
->right
= rc
->left
+ Sz
.cx
;
1410 rc
->bottom
= rc
->top
+ Sz
.cy
;
1419 IntCreateWindowEx(DWORD dwExStyle
,
1420 PUNICODE_STRING ClassName
,
1421 PUNICODE_STRING WindowName
,
1429 HINSTANCE hInstance
,
1432 BOOL bUnicodeWindow
)
1434 PWINSTATION_OBJECT WinStaObject
;
1435 PWNDCLASS_OBJECT ClassObject
;
1436 PWINDOW_OBJECT WindowObject
;
1437 PWINDOW_OBJECT ParentWindow
, OwnerWindow
;
1438 HWND ParentWindowHandle
;
1439 HWND OwnerWindowHandle
;
1440 PMENU_OBJECT SystemMenu
;
1445 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1450 CBT_CREATEWNDW CbtCreate
;
1457 ParentWindowHandle
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
1458 OwnerWindowHandle
= NULL
;
1460 if (hWndParent
== HWND_MESSAGE
)
1463 * native ole32.OleInitialize uses HWND_MESSAGE to create the
1464 * message window (style: WS_POPUP|WS_DISABLED)
1466 DPRINT1("FIXME - Parent is HWND_MESSAGE\n");
1468 else if (hWndParent
)
1470 if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1471 ParentWindowHandle
= hWndParent
;
1473 OwnerWindowHandle
= NtUserGetAncestor(hWndParent
, GA_ROOT
);
1475 else if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1477 return (HWND
)0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1480 if (NULL
!= ParentWindowHandle
)
1482 ParentWindow
= IntGetWindowObject(ParentWindowHandle
);
1486 ParentWindow
= NULL
;
1489 /* FIXME: parent must belong to the current process */
1491 /* Check the class. */
1492 ClassFound
= ClassReferenceClassByNameOrAtom(&ClassObject
, ClassName
->Buffer
, hInstance
);
1495 if (IS_ATOM(ClassName
->Buffer
))
1497 DPRINT1("Class 0x%x not found\n", (DWORD_PTR
) ClassName
->Buffer
);
1501 DPRINT1("Class %wZ not found\n", ClassName
);
1503 if (NULL
!= ParentWindow
)
1505 IntReleaseWindowObject(ParentWindow
);
1507 SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS
);
1511 /* Check the window station. */
1512 if (PsGetWin32Thread()->Desktop
== NULL
)
1514 ClassDereferenceObject(ClassObject
);
1515 if (NULL
!= ParentWindow
)
1517 IntReleaseWindowObject(ParentWindow
);
1519 DPRINT("Thread is not attached to a desktop! Cannot create window!\n");
1522 WinStaObject
= PsGetWin32Thread()->Desktop
->WindowStation
;
1523 ObReferenceObjectByPointer(WinStaObject
, KernelMode
, ExWindowStationObjectType
, 0);
1525 /* Create the window object. */
1526 WindowObject
= (PWINDOW_OBJECT
)
1527 ObmCreateObject(PsGetWin32Thread()->Desktop
->WindowStation
->HandleTable
, &Handle
,
1528 otWindow
, sizeof(WINDOW_OBJECT
) + ClassObject
->cbWndExtra
1531 DPRINT("Created object with handle %X\n", Handle
);
1534 ObDereferenceObject(WinStaObject
);
1535 ClassDereferenceObject(ClassObject
);
1536 if (NULL
!= ParentWindow
)
1538 IntReleaseWindowObject(ParentWindow
);
1540 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1543 ObDereferenceObject(WinStaObject
);
1545 if (NULL
== PsGetWin32Thread()->Desktop
->DesktopWindow
)
1547 /* If there is no desktop window yet, we must be creating it */
1548 PsGetWin32Thread()->Desktop
->DesktopWindow
= Handle
;
1552 * Fill out the structure describing it.
1554 WindowObject
->Class
= ClassObject
;
1555 IntLockClassWindows(ClassObject
);
1556 InsertTailList(&ClassObject
->ClassWindowsListHead
, &WindowObject
->ClassListEntry
);
1557 IntUnLockClassWindows(ClassObject
);
1559 WindowObject
->ExStyle
= dwExStyle
;
1560 WindowObject
->Style
= dwStyle
& ~WS_VISIBLE
;
1561 DPRINT("1: Style is now %lx\n", WindowObject
->Style
);
1563 WindowObject
->SystemMenu
= (HMENU
)0;
1564 WindowObject
->ContextHelpId
= 0;
1565 WindowObject
->IDMenu
= 0;
1566 WindowObject
->Instance
= hInstance
;
1567 WindowObject
->Self
= Handle
;
1568 if (0 != (dwStyle
& WS_CHILD
))
1570 WindowObject
->IDMenu
= (UINT
) hMenu
;
1574 IntSetMenu(WindowObject
, hMenu
, &MenuChanged
);
1576 WindowObject
->MessageQueue
= PsGetWin32Thread()->MessageQueue
;
1577 WindowObject
->Parent
= (ParentWindow
? ParentWindow
->Self
: NULL
);
1578 if((OwnerWindow
= IntGetWindowObject(OwnerWindowHandle
)))
1580 WindowObject
->Owner
= OwnerWindowHandle
;
1581 IntReleaseWindowObject(OwnerWindow
);
1584 WindowObject
->Owner
= NULL
;
1587 WindowObject
->UserData
= 0;
1588 if ((((DWORD
)ClassObject
->lpfnWndProcA
& 0xFFFF0000) != 0xFFFF0000)
1589 && (((DWORD
)ClassObject
->lpfnWndProcW
& 0xFFFF0000) != 0xFFFF0000))
1591 WindowObject
->Unicode
= bUnicodeWindow
;
1595 WindowObject
->Unicode
= ClassObject
->Unicode
;
1597 WindowObject
->WndProcA
= ClassObject
->lpfnWndProcA
;
1598 WindowObject
->WndProcW
= ClassObject
->lpfnWndProcW
;
1599 WindowObject
->OwnerThread
= PsGetCurrentThread();
1600 WindowObject
->FirstChild
= NULL
;
1601 WindowObject
->LastChild
= NULL
;
1602 WindowObject
->PrevSibling
= NULL
;
1603 WindowObject
->NextSibling
= NULL
;
1605 /* extra window data */
1606 if (ClassObject
->cbWndExtra
!= 0)
1608 WindowObject
->ExtraData
= (PCHAR
)(WindowObject
+ 1);
1609 WindowObject
->ExtraDataSize
= ClassObject
->cbWndExtra
;
1610 RtlZeroMemory(WindowObject
->ExtraData
, WindowObject
->ExtraDataSize
);
1614 WindowObject
->ExtraData
= NULL
;
1615 WindowObject
->ExtraDataSize
= 0;
1618 InitializeListHead(&WindowObject
->PropListHead
);
1619 ExInitializeFastMutex(&WindowObject
->PropListLock
);
1620 ExInitializeFastMutex(&WindowObject
->RelativesLock
);
1621 ExInitializeFastMutex(&WindowObject
->UpdateLock
);
1622 InitializeListHead(&WindowObject
->WndObjListHead
);
1623 ExInitializeFastMutex(&WindowObject
->WndObjListLock
);
1625 if (NULL
!= WindowName
->Buffer
)
1627 WindowObject
->WindowName
.MaximumLength
= WindowName
->MaximumLength
;
1628 WindowObject
->WindowName
.Length
= WindowName
->Length
;
1629 WindowObject
->WindowName
.Buffer
= ExAllocatePoolWithTag(PagedPool
, WindowName
->MaximumLength
,
1631 if (NULL
== WindowObject
->WindowName
.Buffer
)
1633 ClassDereferenceObject(ClassObject
);
1634 DPRINT1("Failed to allocate mem for window name\n");
1635 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1638 RtlCopyMemory(WindowObject
->WindowName
.Buffer
, WindowName
->Buffer
, WindowName
->MaximumLength
);
1642 RtlInitUnicodeString(&WindowObject
->WindowName
, NULL
);
1647 * This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1648 * tested for WS_POPUP
1650 if ((dwExStyle
& WS_EX_DLGMODALFRAME
) ||
1651 ((!(dwExStyle
& WS_EX_STATICEDGE
)) &&
1652 (dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
))))
1653 dwExStyle
|= WS_EX_WINDOWEDGE
;
1655 dwExStyle
&= ~WS_EX_WINDOWEDGE
;
1657 /* Correct the window style. */
1658 if (!(dwStyle
& WS_CHILD
))
1660 WindowObject
->Style
|= WS_CLIPSIBLINGS
;
1661 DPRINT("3: Style is now %lx\n", WindowObject
->Style
);
1662 if (!(dwStyle
& WS_POPUP
))
1664 WindowObject
->Style
|= WS_CAPTION
;
1665 WindowObject
->Flags
|= WINDOWOBJECT_NEED_SIZE
;
1666 DPRINT("4: Style is now %lx\n", WindowObject
->Style
);
1670 /* create system menu */
1671 if((WindowObject
->Style
& WS_SYSMENU
) &&
1672 (WindowObject
->Style
& WS_CAPTION
) == WS_CAPTION
)
1674 SystemMenu
= IntGetSystemMenu(WindowObject
, TRUE
, TRUE
);
1677 WindowObject
->SystemMenu
= SystemMenu
->MenuInfo
.Self
;
1678 IntReleaseMenuObject(SystemMenu
);
1682 /* Insert the window into the thread's window list. */
1683 IntLockThreadWindows(PsGetWin32Thread());
1684 InsertTailList (&PsGetWin32Thread()->WindowListHead
,
1685 &WindowObject
->ThreadListEntry
);
1686 IntUnLockThreadWindows(PsGetWin32Thread());
1688 /* Allocate a DCE for this window. */
1689 if (dwStyle
& CS_OWNDC
)
1691 WindowObject
->Dce
= DceAllocDCE(WindowObject
->Self
, DCE_WINDOW_DC
);
1693 /* FIXME: Handle "CS_CLASSDC" */
1701 Cs
.lpCreateParams
= lpParam
;
1702 Cs
.hInstance
= hInstance
;
1704 Cs
.hwndParent
= ParentWindowHandle
;
1710 Cs
.lpszName
= (LPCWSTR
) WindowName
;
1711 Cs
.lpszClass
= (LPCWSTR
) ClassName
;
1712 Cs
.dwExStyle
= dwExStyle
;
1713 CbtCreate
.lpcs
= &Cs
;
1714 CbtCreate
.hwndInsertAfter
= HWND_TOP
;
1715 if (HOOK_CallHooks(WH_CBT
, HCBT_CREATEWND
, (WPARAM
) Handle
, (LPARAM
) &CbtCreate
))
1717 if (NULL
!= ParentWindow
)
1719 IntReleaseWindowObject(ParentWindow
);
1722 /* FIXME - Delete window object and remove it from the thread windows list */
1723 /* FIXME - delete allocated DCE */
1725 ClassDereferenceObject(ClassObject
);
1726 DPRINT1("CBT-hook returned !0\n");
1735 /* default positioning for overlapped windows */
1736 if(!(WindowObject
->Style
& (WS_POPUP
| WS_CHILD
)))
1739 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
1740 BOOL CalculatedDefPosSize
= FALSE
;
1742 IntGetDesktopWorkArea(WindowObject
->OwnerThread
->Tcb
.Win32Thread
->Desktop
, &WorkArea
);
1745 ProcessParams
= PsGetCurrentProcess()->Peb
->ProcessParameters
;
1747 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1749 CalculatedDefPosSize
= IntCalcDefPosSize(ParentWindow
, WindowObject
, &rc
, TRUE
);
1751 if(ProcessParams
->dwFlags
& STARTF_USEPOSITION
)
1753 ProcessParams
->dwFlags
&= ~STARTF_USEPOSITION
;
1754 Pos
.x
= WorkArea
.left
+ ProcessParams
->dwX
;
1755 Pos
.y
= WorkArea
.top
+ ProcessParams
->dwY
;
1763 /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
1764 y is something else */
1765 if(y
!= CW_USEDEFAULT
&& y
!= CW_USEDEFAULT16
)
1770 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1772 if(!CalculatedDefPosSize
)
1774 IntCalcDefPosSize(ParentWindow
, WindowObject
, &rc
, FALSE
);
1776 if(ProcessParams
->dwFlags
& STARTF_USESIZE
)
1778 ProcessParams
->dwFlags
&= ~STARTF_USESIZE
;
1779 Size
.cx
= ProcessParams
->dwXSize
;
1780 Size
.cy
= ProcessParams
->dwYSize
;
1784 Size
.cx
= rc
.right
- rc
.left
;
1785 Size
.cy
= rc
.bottom
- rc
.top
;
1788 /* move the window if necessary */
1790 Pos
.x
= max(rc
.left
, 0);
1792 Pos
.y
= max(rc
.top
, 0);
1797 /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
1798 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1803 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1810 /* Initialize the window dimensions. */
1811 WindowObject
->WindowRect
.left
= Pos
.x
;
1812 WindowObject
->WindowRect
.top
= Pos
.y
;
1813 WindowObject
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1814 WindowObject
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1815 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1817 IntGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1818 ParentWindow
->ClientRect
.top
);
1820 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1823 * Get the size and position of the window.
1825 if ((dwStyle
& WS_THICKFRAME
) || !(dwStyle
& (WS_POPUP
| WS_CHILD
)))
1827 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1829 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1830 WinPosGetMinMaxInfo(WindowObject
, &MaxSize
, &MaxPos
, &MinTrack
,
1832 if (MaxSize
.x
< nWidth
) nWidth
= MaxSize
.x
;
1833 if (MaxSize
.y
< nHeight
) nHeight
= MaxSize
.y
;
1834 if (nWidth
< MinTrack
.x
) nWidth
= MinTrack
.x
;
1835 if (nHeight
< MinTrack
.y
) nHeight
= MinTrack
.y
;
1836 if (nWidth
< 0) nWidth
= 0;
1837 if (nHeight
< 0) nHeight
= 0;
1840 WindowObject
->WindowRect
.left
= Pos
.x
;
1841 WindowObject
->WindowRect
.top
= Pos
.y
;
1842 WindowObject
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1843 WindowObject
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1844 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1846 IntGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1847 ParentWindow
->ClientRect
.top
);
1849 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1851 /* FIXME: Initialize the window menu. */
1853 /* Send a NCCREATE message. */
1859 DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d\n", Cs
.style
, Cs
.dwExStyle
, Cs
.hwndParent
);
1860 DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1861 DPRINT("IntCreateWindowEx(): About to send NCCREATE message.\n");
1862 Result
= IntSendMessage(WindowObject
->Self
, WM_NCCREATE
, 0, (LPARAM
) &Cs
);
1865 /* FIXME: Cleanup. */
1866 if (NULL
!= ParentWindow
)
1868 IntReleaseWindowObject(ParentWindow
);
1870 DPRINT("IntCreateWindowEx(): NCCREATE message failed.\n");
1874 /* Calculate the non-client size. */
1875 MaxPos
.x
= WindowObject
->WindowRect
.left
;
1876 MaxPos
.y
= WindowObject
->WindowRect
.top
;
1877 DPRINT("IntCreateWindowEx(): About to get non-client size.\n");
1878 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1879 Result
= WinPosGetNonClientSize(WindowObject
->Self
,
1880 &WindowObject
->WindowRect
,
1881 &WindowObject
->ClientRect
);
1882 IntGdiOffsetRect(&WindowObject
->WindowRect
,
1883 MaxPos
.x
- WindowObject
->WindowRect
.left
,
1884 MaxPos
.y
- WindowObject
->WindowRect
.top
);
1886 if (NULL
!= ParentWindow
)
1888 /* link the window into the parent's child list */
1889 if ((dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
1891 PWINDOW_OBJECT PrevSibling
;
1892 IntLockRelatives(ParentWindow
);
1893 if((PrevSibling
= ParentWindow
->LastChild
))
1894 IntReferenceWindowObject(PrevSibling
);
1895 IntUnLockRelatives(ParentWindow
);
1896 /* link window as bottom sibling */
1897 IntLinkWindow(WindowObject
, ParentWindow
, PrevSibling
/*prev sibling*/);
1899 IntReleaseWindowObject(PrevSibling
);
1903 /* link window as top sibling (but after topmost siblings) */
1904 PWINDOW_OBJECT InsertAfter
, Sibling
;
1905 if (0 == (dwExStyle
& WS_EX_TOPMOST
))
1907 IntLockRelatives(ParentWindow
);
1909 Sibling
= ParentWindow
->FirstChild
;
1910 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
1912 InsertAfter
= Sibling
;
1913 Sibling
= Sibling
->NextSibling
;
1915 IntUnLockRelatives(ParentWindow
);
1921 if (NULL
!= InsertAfter
)
1923 IntReferenceWindowObject(InsertAfter
);
1925 IntLinkWindow(WindowObject
, ParentWindow
, InsertAfter
/* prev sibling */);
1926 if (NULL
!= InsertAfter
)
1928 IntReleaseWindowObject(InsertAfter
);
1933 /* Send the WM_CREATE message. */
1934 DPRINT("IntCreateWindowEx(): about to send CREATE message.\n");
1935 Result
= IntSendMessage(WindowObject
->Self
, WM_CREATE
, 0, (LPARAM
) &Cs
);
1936 if (Result
== (LRESULT
)-1)
1938 /* FIXME: Cleanup. */
1939 if (NULL
!= ParentWindow
)
1941 IntReleaseWindowObject(ParentWindow
);
1943 ClassDereferenceObject(ClassObject
);
1944 DPRINT("IntCreateWindowEx(): send CREATE message failed.\n");
1948 /* Send move and size messages. */
1949 if (!(WindowObject
->Flags
& WINDOWOBJECT_NEED_SIZE
))
1953 DPRINT("IntCreateWindow(): About to send WM_SIZE\n");
1955 if ((WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
) < 0 ||
1956 (WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
) < 0)
1958 DPRINT("Sending bogus WM_SIZE\n");
1961 lParam
= MAKE_LONG(WindowObject
->ClientRect
.right
-
1962 WindowObject
->ClientRect
.left
,
1963 WindowObject
->ClientRect
.bottom
-
1964 WindowObject
->ClientRect
.top
);
1965 IntSendMessage(WindowObject
->Self
, WM_SIZE
, SIZE_RESTORED
,
1968 DPRINT("IntCreateWindow(): About to send WM_MOVE\n");
1970 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1972 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
- ParentWindow
->ClientRect
.left
,
1973 WindowObject
->ClientRect
.top
- ParentWindow
->ClientRect
.top
);
1977 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
,
1978 WindowObject
->ClientRect
.top
);
1980 IntSendMessage(WindowObject
->Self
, WM_MOVE
, 0, lParam
);
1982 /* Call WNDOBJ change procs */
1983 IntEngWindowChanged(WindowObject
, WOC_RGN_CLIENT
);
1986 /* Show or maybe minimize or maximize the window. */
1987 if (WindowObject
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1992 SwFlag
= (WindowObject
->Style
& WS_MINIMIZE
) ? SW_MINIMIZE
:
1994 WinPosMinMaximize(WindowObject
, SwFlag
, &NewPos
);
1996 ((WindowObject
->Style
& WS_CHILD
) || NtUserGetActiveWindow()) ?
1997 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
:
1998 SWP_NOZORDER
| SWP_FRAMECHANGED
;
1999 DPRINT("IntCreateWindow(): About to minimize/maximize\n");
2000 DPRINT("%d,%d %dx%d\n", NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
);
2001 WinPosSetWindowPos(WindowObject
->Self
, 0, NewPos
.left
, NewPos
.top
,
2002 NewPos
.right
, NewPos
.bottom
, SwFlag
);
2005 /* Notify the parent window of a new child. */
2006 if ((WindowObject
->Style
& WS_CHILD
) &&
2007 (!(WindowObject
->ExStyle
& WS_EX_NOPARENTNOTIFY
)) && ParentWindow
)
2009 DPRINT("IntCreateWindow(): About to notify parent\n");
2010 IntSendMessage(ParentWindow
->Self
,
2012 MAKEWPARAM(WM_CREATE
, WindowObject
->IDMenu
),
2013 (LPARAM
)WindowObject
->Self
);
2016 if ((!hWndParent
) && (!HasOwner
)) {
2017 DPRINT("Sending CREATED notify\n");
2018 IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Handle
);
2020 DPRINT("Not sending CREATED notify, %x %d\n", ParentWindow
, HasOwner
);
2023 if (NULL
!= ParentWindow
)
2025 IntReleaseWindowObject(ParentWindow
);
2028 /* Initialize and show the window's scrollbars */
2029 if (WindowObject
->Style
& WS_VSCROLL
)
2031 NtUserShowScrollBar(WindowObject
->Self
, SB_VERT
, TRUE
);
2033 if (WindowObject
->Style
& WS_HSCROLL
)
2035 NtUserShowScrollBar(WindowObject
->Self
, SB_HORZ
, TRUE
);
2038 if (dwStyle
& WS_VISIBLE
)
2040 DPRINT("IntCreateWindow(): About to show window\n");
2041 WinPosShowWindow(WindowObject
->Self
, dwShowMode
);
2044 DPRINT("IntCreateWindow(): = %X\n", Handle
);
2045 DPRINT("WindowObject->SystemMenu = 0x%x\n", WindowObject
->SystemMenu
);
2046 return((HWND
)Handle
);
2050 NtUserCreateWindowEx(DWORD dwExStyle
,
2051 PUNICODE_STRING UnsafeClassName
,
2052 PUNICODE_STRING UnsafeWindowName
,
2060 HINSTANCE hInstance
,
2063 BOOL bUnicodeWindow
)
2066 UNICODE_STRING WindowName
;
2067 UNICODE_STRING ClassName
;
2070 DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
2072 /* Get the class name (string or atom) */
2073 Status
= MmCopyFromCaller(&ClassName
, UnsafeClassName
, sizeof(UNICODE_STRING
));
2074 if (! NT_SUCCESS(Status
))
2076 SetLastNtError(Status
);
2079 if (! IS_ATOM(ClassName
.Buffer
))
2081 Status
= IntSafeCopyUnicodeStringTerminateNULL(&ClassName
, UnsafeClassName
);
2082 if (! NT_SUCCESS(Status
))
2084 SetLastNtError(Status
);
2089 /* safely copy the window name */
2090 if (NULL
!= UnsafeWindowName
)
2092 Status
= IntSafeCopyUnicodeString(&WindowName
, UnsafeWindowName
);
2093 if (! NT_SUCCESS(Status
))
2095 if (! IS_ATOM(ClassName
.Buffer
))
2097 RtlFreeUnicodeString(&ClassName
);
2099 SetLastNtError(Status
);
2105 RtlInitUnicodeString(&WindowName
, NULL
);
2108 NewWindow
= IntCreateWindowEx(dwExStyle
, &ClassName
, &WindowName
, dwStyle
, x
, y
, nWidth
, nHeight
,
2109 hWndParent
, hMenu
, hInstance
, lpParam
, dwShowMode
, bUnicodeWindow
);
2111 RtlFreeUnicodeString(&WindowName
);
2112 if (! IS_ATOM(ClassName
.Buffer
))
2114 RtlFreeUnicodeString(&ClassName
);
2124 NtUserDeferWindowPos(HDWP WinPosInfo
,
2126 HWND WndInsertAfter
,
2143 NtUserDestroyWindow(HWND Wnd
)
2145 PWINDOW_OBJECT Window
;
2148 Window
= IntGetWindowObject(Wnd
);
2154 /* Check for owner thread and desktop window */
2155 if ((Window
->OwnerThread
!= PsGetCurrentThread()) || IntIsDesktopWindow(Window
))
2157 IntReleaseWindowObject(Window
);
2158 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2162 /* Look whether the focus is within the tree of windows we will
2165 if (!WinPosShowWindow(Wnd
, SW_HIDE
))
2167 if (NtUserGetActiveWindow() == Wnd
)
2169 WinPosActivateOtherWindow(Window
);
2172 IntLockMessageQueue(Window
->MessageQueue
);
2173 if (Window
->MessageQueue
->ActiveWindow
== Window
->Self
)
2174 Window
->MessageQueue
->ActiveWindow
= NULL
;
2175 if (Window
->MessageQueue
->FocusWindow
== Window
->Self
)
2176 Window
->MessageQueue
->FocusWindow
= NULL
;
2177 if (Window
->MessageQueue
->CaptureWindow
== Window
->Self
)
2178 Window
->MessageQueue
->CaptureWindow
= NULL
;
2179 IntUnLockMessageQueue(Window
->MessageQueue
);
2183 if (HOOK_CallHooks(WH_CBT
, HCBT_DESTROYWND
, (WPARAM
) hwnd
, 0, TRUE
))
2189 IntEngWindowChanged(Window
, WOC_DELETE
);
2190 isChild
= (0 != (Window
->Style
& WS_CHILD
));
2195 if (! USER_IsExitingThread(GetCurrentThreadId()))
2197 send_parent_notify(hwnd
, WM_DESTROY
);
2200 else if (NULL
!= GetWindow(Wnd
, GW_OWNER
))
2202 HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
2203 /* FIXME: clean up palette - see "Internals" p.352 */
2207 if (!IntIsWindow(Wnd
))
2212 /* Recursively destroy owned windows */
2217 BOOL GotOne
= FALSE
;
2220 PWINDOW_OBJECT Child
, Desktop
;
2222 Desktop
= IntGetWindowObject(IntGetDesktopWindow());
2223 Children
= IntWinListChildren(Desktop
);
2224 IntReleaseWindowObject(Desktop
);
2227 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
2229 Child
= IntGetWindowObject(*ChildHandle
);
2232 IntLockRelatives(Child
);
2233 if (Child
->Owner
!= Window
->Self
)
2235 IntUnLockRelatives(Child
);
2236 IntReleaseWindowObject(Child
);
2239 IntUnLockRelatives(Child
);
2240 if (IntWndBelongsToThread(Child
, PsGetWin32Thread()))
2242 IntReleaseWindowObject(Child
);
2243 NtUserDestroyWindow(*ChildHandle
);
2247 IntLockRelatives(Child
);
2248 if (Child
->Owner
!= NULL
)
2250 Child
->Owner
= NULL
;
2252 IntUnLockRelatives(Child
);
2253 IntReleaseWindowObject(Child
);
2255 ExFreePool(Children
);
2264 if (!IntIsWindow(Wnd
))
2266 IntReleaseWindowObject(Window
);
2270 /* Destroy the window storage */
2271 IntDestroyWindow(Window
, PsGetWin32Process(), PsGetWin32Thread(), TRUE
);
2273 IntReleaseWindowObject(Window
);
2283 NtUserDrawMenuBarTemp(
2290 /* we'll use this function just for caching the menu bar */
2300 NtUserEndDeferWindowPosEx(DWORD Unknown0
,
2313 NtUserFillWindow(DWORD Unknown0
,
2325 IntFindWindow(PWINDOW_OBJECT Parent
,
2326 PWINDOW_OBJECT ChildAfter
,
2328 PUNICODE_STRING WindowName
)
2330 BOOL CheckWindowName
;
2336 CheckWindowName
= (WindowName
&& (WindowName
->Length
> 0));
2338 if((List
= IntWinListChildren(Parent
)))
2343 /* skip handles before and including ChildAfter */
2344 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->Self
));
2347 /* search children */
2350 PWINDOW_OBJECT Child
;
2351 if(!(Child
= IntGetWindowObject(*(phWnd
++))))
2356 /* Do not send WM_GETTEXT messages in the kernel mode version!
2357 The user mode version however calls GetWindowText() which will
2358 send WM_GETTEXT messages to windows belonging to its processes */
2359 if((!CheckWindowName
|| !RtlCompareUnicodeString(WindowName
, &(Child
->WindowName
), FALSE
)) &&
2360 (!ClassAtom
|| Child
->Class
->Atom
== ClassAtom
))
2363 IntReleaseWindowObject(Child
);
2367 IntReleaseWindowObject(Child
);
2377 * Searches a window's children for a window with the specified
2380 * hwndParent = The window whose childs are to be searched.
2382 * HWND_MESSAGE = message-only windows
2384 * hwndChildAfter = Search starts after this child window.
2385 * NULL = start from beginning
2387 * ucClassName = Class name to search for
2388 * Reguired parameter.
2390 * ucWindowName = Window name
2391 * ->Buffer == NULL = don't care
2394 * The HWND of the window if it was found, otherwise NULL
2400 NtUserFindWindowEx(HWND hwndParent
,
2401 HWND hwndChildAfter
,
2402 PUNICODE_STRING ucClassName
,
2403 PUNICODE_STRING ucWindowName
)
2405 PWINDOW_OBJECT Parent
, ChildAfter
;
2406 UNICODE_STRING ClassName
, WindowName
;
2408 HWND Desktop
, Ret
= NULL
;
2411 Desktop
= IntGetCurrentThreadDesktopWindow();
2413 if(hwndParent
== NULL
)
2414 hwndParent
= Desktop
;
2416 else if(hwndParent == HWND_MESSAGE)
2418 hwndParent = IntGetMessageWindow();
2422 if(!(Parent
= IntGetWindowObject(hwndParent
)))
2424 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2429 if(hwndChildAfter
&& !(ChildAfter
= IntGetWindowObject(hwndChildAfter
)))
2431 IntReleaseWindowObject(Parent
);
2432 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2436 /* copy the window name */
2437 Status
= IntSafeCopyUnicodeString(&WindowName
, ucWindowName
);
2438 if(!NT_SUCCESS(Status
))
2440 SetLastNtError(Status
);
2444 /* safely copy the class name */
2445 Status
= MmCopyFromCaller(&ClassName
, ucClassName
, sizeof(UNICODE_STRING
));
2446 if(!NT_SUCCESS(Status
))
2448 SetLastNtError(Status
);
2451 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2454 /* safely copy the class name string (NULL terminated because class-lookup
2456 buf
= ExAllocatePoolWithTag(PagedPool
, ClassName
.Length
+ sizeof(WCHAR
), TAG_STRING
);
2459 SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES
);
2462 Status
= MmCopyFromCaller(buf
, ClassName
.Buffer
, ClassName
.Length
);
2463 if(!NT_SUCCESS(Status
))
2466 SetLastNtError(Status
);
2469 ClassName
.Buffer
= buf
;
2470 /* make sure the string is null-terminated */
2471 buf
+= ClassName
.Length
/ sizeof(WCHAR
);
2475 /* find the class object */
2476 if(ClassName
.Buffer
)
2478 PWINSTATION_OBJECT WinStaObject
;
2480 if (PsGetWin32Thread()->Desktop
== NULL
)
2482 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2486 WinStaObject
= PsGetWin32Thread()->Desktop
->WindowStation
;
2488 Status
= RtlLookupAtomInAtomTable(
2489 WinStaObject
->AtomTable
,
2493 if (!NT_SUCCESS(Status
))
2495 DPRINT1("Failed to lookup class atom!\n");
2496 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST
);
2501 if(Parent
->Self
== Desktop
)
2504 PWINDOW_OBJECT TopLevelWindow
;
2505 BOOLEAN CheckWindowName
;
2506 BOOLEAN CheckClassName
;
2507 BOOLEAN WindowMatches
;
2508 BOOLEAN ClassMatches
;
2510 /* windows searches through all top-level windows if the parent is the desktop
2513 if((List
= IntWinListChildren(Parent
)))
2519 /* skip handles before and including ChildAfter */
2520 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->Self
));
2523 CheckWindowName
= WindowName
.Length
> 0;
2524 CheckClassName
= ClassName
.Buffer
!= NULL
;
2526 /* search children */
2529 if(!(TopLevelWindow
= IntGetWindowObject(*(phWnd
++))))
2534 /* Do not send WM_GETTEXT messages in the kernel mode version!
2535 The user mode version however calls GetWindowText() which will
2536 send WM_GETTEXT messages to windows belonging to its processes */
2537 WindowMatches
= !CheckWindowName
|| !RtlCompareUnicodeString(
2538 &WindowName
, &TopLevelWindow
->WindowName
, FALSE
);
2539 ClassMatches
= !CheckClassName
||
2540 ClassAtom
== TopLevelWindow
->Class
->Atom
;
2542 if (WindowMatches
&& ClassMatches
)
2544 Ret
= TopLevelWindow
->Self
;
2545 IntReleaseWindowObject(TopLevelWindow
);
2549 if (IntFindWindow(TopLevelWindow
, NULL
, ClassAtom
, &WindowName
))
2551 /* window returns the handle of the top-level window, in case it found
2553 Ret
= TopLevelWindow
->Self
;
2554 IntReleaseWindowObject(TopLevelWindow
);
2558 IntReleaseWindowObject(TopLevelWindow
);
2564 Ret
= IntFindWindow(Parent
, ChildAfter
, ClassAtom
, &WindowName
);
2567 if(Ret
== NULL
&& hwndParent
== NULL
&& hwndChildAfter
== NULL
)
2569 /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
2570 search the message-only windows. Should this also be done if
2571 Parent is the desktop window??? */
2572 PWINDOW_OBJECT MsgWindows
;
2574 if((MsgWindows
= IntGetWindowObject(IntGetMessageWindow())))
2576 Ret
= IntFindWindow(MsgWindows
, ChildAfter
, ClassAtom
, &WindowName
);
2577 IntReleaseWindowObject(MsgWindows
);
2583 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2584 ExFreePool(ClassName
.Buffer
);
2587 RtlFreeUnicodeString(&WindowName
);
2591 IntReleaseWindowObject(ChildAfter
);
2592 IntReleaseWindowObject(Parent
);
2602 NtUserFlashWindowEx(DWORD Unknown0
)
2614 NtUserGetAncestor(HWND hWnd
, UINT Type
)
2616 PWINDOW_OBJECT Wnd
, WndAncestor
, Parent
;
2619 if (hWnd
== IntGetDesktopWindow())
2624 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2626 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2634 WndAncestor
= IntGetParentObject(Wnd
);
2647 if(!(Parent
= IntGetParentObject(WndAncestor
)))
2651 if(IntIsDesktopWindow(Parent
))
2653 IntReleaseWindowObject(Parent
);
2657 IntReleaseWindowObject(tmp
);
2658 WndAncestor
= Parent
;
2666 IntReferenceWindowObject(WndAncestor
);
2671 Parent
= IntGetParent(WndAncestor
);
2672 IntReleaseWindowObject(Old
);
2677 WndAncestor
= Parent
;
2684 IntReleaseWindowObject(Wnd
);
2689 hWndAncestor
= (WndAncestor
? WndAncestor
->Self
: NULL
);
2690 IntReleaseWindowObject(Wnd
);
2692 if(WndAncestor
&& (WndAncestor
!= Wnd
))
2693 IntReleaseWindowObject(WndAncestor
);
2695 return hWndAncestor
;
2700 * Returns client window rectangle relative to the upper-left corner of client area.
2702 * \param hWnd window handle.
2703 * \param Rect pointer to the buffer where the coordinates are returned.
2710 NtUserGetClientRect(HWND hWnd
, LPRECT Rect
)
2712 PWINDOW_OBJECT WindowObject
;
2715 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
2717 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2721 IntGetClientRect(WindowObject
, &SafeRect
);
2722 IntReleaseWindowObject(WindowObject
);
2724 if(!NT_SUCCESS(MmCopyToCaller(Rect
, &SafeRect
, sizeof(RECT
))))
2736 NtUserGetDesktopWindow()
2738 return IntGetDesktopWindow();
2746 NtUserGetInternalWindowPos(DWORD Unknown0
,
2760 NtUserGetLastActivePopup(HWND hWnd
)
2763 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2764 * not changed anywhere.
2765 * -- Filip, 01/nov/2003
2771 IntAcquireWinLockShared();
2773 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2775 IntReleaseWinLock();
2776 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2780 hWndLastPopup
= Wnd
->hWndLastPopup
;
2782 IntReleaseWinLock();
2784 return hWndLastPopup
;
2793 * The NtUserGetParent function retrieves a handle to the specified window's
2797 * Note that, despite its name, this function can return an owner window
2798 * instead of a parent window.
2805 NtUserGetParent(HWND hWnd
)
2807 PWINDOW_OBJECT Wnd
, WndParent
;
2808 HWND hWndParent
= NULL
;
2810 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2812 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2816 WndParent
= IntGetParent(Wnd
);
2819 hWndParent
= WndParent
->Self
;
2820 IntReleaseWindowObject(WndParent
);
2823 IntReleaseWindowObject(Wnd
);
2831 * The NtUserSetParent function changes the parent window of the specified
2835 * The new parent window and the child window must belong to the same
2836 * application. If the window identified by the hWndChild parameter is
2837 * visible, the system performs the appropriate redrawing and repainting.
2838 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2839 * or WS_POPUP window styles of the window whose parent is being changed.
2846 NtUserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2848 PWINDOW_OBJECT Wnd
= NULL
, WndParent
= NULL
, WndOldParent
;
2849 HWND hWndOldParent
= NULL
;
2851 if (IntIsBroadcastHwnd(hWndChild
) || IntIsBroadcastHwnd(hWndNewParent
))
2853 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2857 if (hWndChild
== IntGetDesktopWindow())
2859 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2865 if (!(WndParent
= IntGetWindowObject(hWndNewParent
)))
2867 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2873 if (!(WndParent
= IntGetWindowObject(IntGetDesktopWindow())))
2875 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2880 if (!(Wnd
= IntGetWindowObject(hWndChild
)))
2882 IntReleaseWindowObject(WndParent
);
2883 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2887 WndOldParent
= IntSetParent(Wnd
, WndParent
);
2891 hWndOldParent
= WndOldParent
->Self
;
2892 IntReleaseWindowObject(WndOldParent
);
2895 IntReleaseWindowObject(Wnd
);
2896 IntReleaseWindowObject(WndParent
);
2898 return hWndOldParent
;
2902 * NtUserGetShellWindow
2904 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
2911 NtUserGetShellWindow()
2913 PWINSTATION_OBJECT WinStaObject
;
2916 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
2921 if (!NT_SUCCESS(Status
))
2923 SetLastNtError(Status
);
2927 Ret
= (HWND
)WinStaObject
->ShellWindow
;
2929 ObDereferenceObject(WinStaObject
);
2934 * NtUserSetShellWindowEx
2936 * This is undocumented function to set global shell window. The global
2937 * shell window has special handling of window position.
2944 NtUserSetShellWindowEx(HWND hwndShell
, HWND hwndListView
)
2946 PWINSTATION_OBJECT WinStaObject
;
2948 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
2953 if (!NT_SUCCESS(Status
))
2955 SetLastNtError(Status
);
2960 * Test if we are permitted to change the shell window.
2962 if (WinStaObject
->ShellWindow
)
2964 ObDereferenceObject(WinStaObject
);
2969 * Move shell window into background.
2971 if (hwndListView
&& hwndListView
!= hwndShell
)
2974 * Disabled for now to get Explorer working.
2975 * -- Filip, 01/nov/2003
2978 WinPosSetWindowPos(hwndListView
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2981 if (NtUserGetWindowLong(hwndListView
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2983 ObDereferenceObject(WinStaObject
);
2988 if (NtUserGetWindowLong(hwndShell
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2990 ObDereferenceObject(WinStaObject
);
2994 WinPosSetWindowPos(hwndShell
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2996 WinStaObject
->ShellWindow
= hwndShell
;
2997 WinStaObject
->ShellListView
= hwndListView
;
2999 ObDereferenceObject(WinStaObject
);
3004 * NtUserGetSystemMenu
3006 * The NtUserGetSystemMenu function allows the application to access the
3007 * window menu (also known as the system menu or the control menu) for
3008 * copying and modifying.
3012 * Handle to the window that will own a copy of the window menu.
3014 * Specifies the action to be taken. If this parameter is FALSE,
3015 * NtUserGetSystemMenu returns a handle to the copy of the window menu
3016 * currently in use. The copy is initially identical to the window menu
3017 * but it can be modified.
3018 * If this parameter is TRUE, GetSystemMenu resets the window menu back
3019 * to the default state. The previous window menu, if any, is destroyed.
3022 * If the bRevert parameter is FALSE, the return value is a handle to a
3023 * copy of the window menu. If the bRevert parameter is TRUE, the return
3031 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
3034 PWINDOW_OBJECT WindowObject
;
3035 PMENU_OBJECT MenuObject
;
3037 WindowObject
= IntGetWindowObject((HWND
)hWnd
);
3038 if (WindowObject
== NULL
)
3040 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3044 MenuObject
= IntGetSystemMenu(WindowObject
, bRevert
, FALSE
);
3047 Result
= MenuObject
->MenuInfo
.Self
;
3048 IntReleaseMenuObject(MenuObject
);
3051 IntReleaseWindowObject(WindowObject
);
3056 * NtUserSetSystemMenu
3063 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
3065 BOOL Result
= FALSE
;
3066 PWINDOW_OBJECT WindowObject
;
3067 PMENU_OBJECT MenuObject
;
3069 WindowObject
= IntGetWindowObject(hWnd
);
3072 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3079 * Assign new menu handle.
3081 MenuObject
= IntGetMenuObject(hMenu
);
3084 IntReleaseWindowObject(WindowObject
);
3085 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
3089 Result
= IntSetSystemMenu(WindowObject
, MenuObject
);
3091 IntReleaseMenuObject(MenuObject
);
3094 IntReleaseWindowObject(WindowObject
);
3102 * The NtUserGetWindow function retrieves a handle to a window that has the
3103 * specified relationship (Z order or owner) to the specified window.
3110 NtUserGetWindow(HWND hWnd
, UINT Relationship
)
3112 PWINDOW_OBJECT WindowObject
, Parent
;
3113 HWND hWndResult
= NULL
;
3115 if (!(WindowObject
= IntGetWindowObject(hWnd
)))
3117 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3121 switch (Relationship
)
3124 if((Parent
= IntGetParentObject(WindowObject
)))
3126 IntLockRelatives(Parent
);
3127 if (Parent
->FirstChild
)
3128 hWndResult
= Parent
->FirstChild
->Self
;
3129 IntUnLockRelatives(Parent
);
3130 IntReleaseWindowObject(Parent
);
3135 if((Parent
= IntGetParentObject(WindowObject
)))
3137 IntLockRelatives(Parent
);
3138 if (Parent
->LastChild
)
3139 hWndResult
= Parent
->LastChild
->Self
;
3140 IntUnLockRelatives(Parent
);
3141 IntReleaseWindowObject(Parent
);
3146 IntLockRelatives(WindowObject
);
3147 if (WindowObject
->NextSibling
)
3148 hWndResult
= WindowObject
->NextSibling
->Self
;
3149 IntUnLockRelatives(WindowObject
);
3153 IntLockRelatives(WindowObject
);
3154 if (WindowObject
->PrevSibling
)
3155 hWndResult
= WindowObject
->PrevSibling
->Self
;
3156 IntUnLockRelatives(WindowObject
);
3160 IntLockRelatives(WindowObject
);
3161 if((Parent
= IntGetWindowObject(WindowObject
->Owner
)))
3163 hWndResult
= Parent
->Self
;
3164 IntReleaseWindowObject(Parent
);
3166 IntUnLockRelatives(WindowObject
);
3169 IntLockRelatives(WindowObject
);
3170 if (WindowObject
->FirstChild
)
3171 hWndResult
= WindowObject
->FirstChild
->Self
;
3172 IntUnLockRelatives(WindowObject
);
3176 IntReleaseWindowObject(WindowObject
);
3182 * NtUserGetWindowLong
3184 * The NtUserGetWindowLong function retrieves information about the specified
3185 * window. The function also retrieves the 32-bit (long) value at the
3186 * specified offset into the extra window memory.
3193 NtUserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3195 PWINDOW_OBJECT WindowObject
, Parent
;
3198 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3200 WindowObject
= IntGetWindowObject(hWnd
);
3201 if (WindowObject
== NULL
)
3203 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3208 * WndProc is only available to the owner process
3210 if (GWL_WNDPROC
== Index
3211 && WindowObject
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
3213 SetLastWin32Error(ERROR_ACCESS_DENIED
);
3217 if ((INT
)Index
>= 0)
3219 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
3221 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3224 Result
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
3231 Result
= WindowObject
->ExStyle
;
3235 Result
= WindowObject
->Style
;
3240 Result
= (LONG
) WindowObject
->WndProcA
;
3242 Result
= (LONG
) WindowObject
->WndProcW
;
3246 Result
= (LONG
) WindowObject
->Instance
;
3249 case GWL_HWNDPARENT
:
3250 IntLockRelatives(WindowObject
);
3251 Parent
= IntGetWindowObject(WindowObject
->Parent
);
3252 IntUnLockRelatives(WindowObject
);
3255 if (Parent
&& Parent
->Self
== IntGetDesktopWindow())
3256 Result
= (LONG
) NtUserGetWindow(WindowObject
->Self
, GW_OWNER
);
3258 Result
= (LONG
) Parent
->Self
;
3259 IntReleaseWindowObject(Parent
);
3264 Result
= (LONG
) WindowObject
->IDMenu
;
3268 Result
= WindowObject
->UserData
;
3272 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index
);
3273 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3279 IntReleaseWindowObject(WindowObject
);
3285 * NtUserSetWindowLong
3287 * The NtUserSetWindowLong function changes an attribute of the specified
3288 * window. The function also sets the 32-bit (long) value at the specified
3289 * offset into the extra window memory.
3296 NtUserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3298 PWINDOW_OBJECT WindowObject
, Parent
;
3299 PWINSTATION_OBJECT WindowStation
;
3303 if (hWnd
== IntGetDesktopWindow())
3305 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3309 WindowObject
= IntGetWindowObject(hWnd
);
3310 if (WindowObject
== NULL
)
3312 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3316 if ((INT
)Index
>= 0)
3318 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
3320 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3321 IntReleaseWindowObject(WindowObject
);
3324 OldValue
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
3325 *((LONG
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
3332 OldValue
= (LONG
) WindowObject
->ExStyle
;
3333 Style
.styleOld
= OldValue
;
3334 Style
.styleNew
= NewValue
;
3337 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3339 WindowStation
= WindowObject
->OwnerThread
->Tcb
.Win32Thread
->Desktop
->WindowStation
;
3342 if (hWnd
== WindowStation
->ShellWindow
|| hWnd
== WindowStation
->ShellListView
)
3343 Style
.styleNew
&= ~WS_EX_TOPMOST
;
3346 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3347 WindowObject
->ExStyle
= (DWORD
)Style
.styleNew
;
3348 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3352 OldValue
= (LONG
) WindowObject
->Style
;
3353 Style
.styleOld
= OldValue
;
3354 Style
.styleNew
= NewValue
;
3355 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_STYLE
, (LPARAM
) &Style
);
3356 WindowObject
->Style
= (DWORD
)Style
.styleNew
;
3357 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_STYLE
, (LPARAM
) &Style
);
3361 /* FIXME: should check if window belongs to current process */
3364 OldValue
= (LONG
) WindowObject
->WndProcA
;
3365 WindowObject
->WndProcA
= (WNDPROC
) NewValue
;
3366 WindowObject
->WndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,FALSE
);
3367 WindowObject
->Unicode
= FALSE
;
3371 OldValue
= (LONG
) WindowObject
->WndProcW
;
3372 WindowObject
->WndProcW
= (WNDPROC
) NewValue
;
3373 WindowObject
->WndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,TRUE
);
3374 WindowObject
->Unicode
= TRUE
;
3379 OldValue
= (LONG
) WindowObject
->Instance
;
3380 WindowObject
->Instance
= (HINSTANCE
) NewValue
;
3383 case GWL_HWNDPARENT
:
3384 Parent
= IntGetParentObject(WindowObject
);
3385 if (Parent
&& (Parent
->Self
== IntGetDesktopWindow()))
3386 OldValue
= (LONG
) IntSetOwner(WindowObject
->Self
, (HWND
) NewValue
);
3388 OldValue
= (LONG
) NtUserSetParent(WindowObject
->Self
, (HWND
) NewValue
);
3390 IntReleaseWindowObject(Parent
);
3394 OldValue
= (LONG
) WindowObject
->IDMenu
;
3395 WindowObject
->IDMenu
= (UINT
) NewValue
;
3399 OldValue
= WindowObject
->UserData
;
3400 WindowObject
->UserData
= NewValue
;
3404 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index
);
3405 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3411 IntReleaseWindowObject(WindowObject
);
3417 * NtUserSetWindowWord
3419 * Legacy function similar to NtUserSetWindowLong.
3426 NtUserSetWindowWord(HWND hWnd
, INT Index
, WORD NewValue
)
3428 PWINDOW_OBJECT WindowObject
;
3435 case GWL_HWNDPARENT
:
3436 return NtUserSetWindowLong(hWnd
, Index
, (UINT
)NewValue
, TRUE
);
3440 SetLastWin32Error(ERROR_INVALID_INDEX
);
3445 WindowObject
= IntGetWindowObject(hWnd
);
3446 if (WindowObject
== NULL
)
3448 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3452 if (Index
> WindowObject
->ExtraDataSize
- sizeof(WORD
))
3454 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3455 IntReleaseWindowObject(WindowObject
);
3459 OldValue
= *((WORD
*)(WindowObject
->ExtraData
+ Index
));
3460 *((WORD
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
3462 IntReleaseWindowObject(WindowObject
);
3471 NtUserGetWindowPlacement(HWND hWnd
,
3472 WINDOWPLACEMENT
*lpwndpl
)
3474 PWINDOW_OBJECT WindowObject
;
3475 PINTERNALPOS InternalPos
;
3477 WINDOWPLACEMENT Safepl
;
3480 WindowObject
= IntGetWindowObject(hWnd
);
3481 if (WindowObject
== NULL
)
3483 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3487 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3488 if(!NT_SUCCESS(Status
))
3490 SetLastNtError(Status
);
3491 IntReleaseWindowObject(WindowObject
);
3494 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3496 IntReleaseWindowObject(WindowObject
);
3501 Safepl
.showCmd
= ((WindowObject
->Flags
& WINDOWOBJECT_RESTOREMAX
) ? SW_MAXIMIZE
: SW_SHOWNORMAL
);
3503 Size
.x
= WindowObject
->WindowRect
.left
;
3504 Size
.y
= WindowObject
->WindowRect
.top
;
3505 InternalPos
= WinPosInitInternalPos(WindowObject
, &Size
,
3506 &WindowObject
->WindowRect
);
3509 Safepl
.rcNormalPosition
= InternalPos
->NormalRect
;
3510 Safepl
.ptMinPosition
= InternalPos
->IconPos
;
3511 Safepl
.ptMaxPosition
= InternalPos
->MaxPos
;
3515 IntReleaseWindowObject(WindowObject
);
3519 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3520 if(!NT_SUCCESS(Status
))
3522 SetLastNtError(Status
);
3523 IntReleaseWindowObject(WindowObject
);
3527 IntReleaseWindowObject(WindowObject
);
3533 * Return the dimension of the window in the screen coordinates.
3534 * \param hWnd window handle.
3535 * \param Rect pointer to the buffer where the coordinates are returned.
3541 NtUserGetWindowRect(HWND hWnd
, LPRECT Rect
)
3546 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3548 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3551 Status
= MmCopyToCaller(Rect
, &Wnd
->WindowRect
, sizeof(RECT
));
3552 if (!NT_SUCCESS(Status
))
3554 IntReleaseWindowObject(Wnd
);
3555 SetLastNtError(Status
);
3559 IntReleaseWindowObject(Wnd
);
3568 NtUserGetWindowThreadProcessId(HWND hWnd
, LPDWORD UnsafePid
)
3573 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3575 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3579 tid
= (DWORD
)IntGetWndThreadId(Wnd
);
3580 pid
= (DWORD
)IntGetWndProcessId(Wnd
);
3582 if (UnsafePid
) MmCopyToCaller(UnsafePid
, &pid
, sizeof(DWORD
));
3592 NtUserLockWindowUpdate(DWORD Unknown0
)
3612 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3613 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3614 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3618 QueryWindow based on KJK::Hyperion and James Tabor.
3620 0 = QWUniqueProcessId
3621 1 = QWUniqueThreadId
3622 4 = QWIsHung Implements IsHungAppWindow found
3625 9 = QWKillWindow When I called this with hWnd ==
3626 DesktopWindow, it shutdown the system
3633 NtUserQueryWindow(HWND hWnd
, DWORD Index
)
3635 PWINDOW_OBJECT Window
= IntGetWindowObject(hWnd
);
3640 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3646 case QUERY_WINDOW_UNIQUE_PROCESS_ID
:
3647 Result
= (DWORD
)IntGetWndProcessId(Window
);
3650 case QUERY_WINDOW_UNIQUE_THREAD_ID
:
3651 Result
= (DWORD
)IntGetWndThreadId(Window
);
3654 case QUERY_WINDOW_ISHUNG
:
3655 Result
= (DWORD
)MsqIsHung(Window
->MessageQueue
);
3659 Result
= (DWORD
)NULL
;
3663 IntReleaseWindowObject(Window
);
3673 NtUserRealChildWindowFromPoint(DWORD Unknown0
,
3687 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe
)
3689 UNICODE_STRING SafeMessageName
;
3693 if(MessageNameUnsafe
== NULL
)
3695 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3699 Status
= IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName
, MessageNameUnsafe
);
3700 if(!NT_SUCCESS(Status
))
3702 SetLastNtError(Status
);
3706 Ret
= (UINT
)IntAddAtom(SafeMessageName
.Buffer
);
3708 RtlFreeUnicodeString(&SafeMessageName
);
3717 NtUserSetImeOwnerWindow(DWORD Unknown0
,
3730 NtUserSetInternalWindowPos(DWORD Unknown0
,
3746 NtUserSetLayeredWindowAttributes(DWORD Unknown0
,
3761 NtUserSetLogonNotifyWindow(DWORD Unknown0
)
3778 PWINDOW_OBJECT WindowObject
;
3781 WindowObject
= IntGetWindowObject((HWND
) Wnd
);
3782 if (NULL
== WindowObject
)
3784 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3788 if (! IntSetMenu(WindowObject
, Menu
, &Changed
))
3790 IntReleaseWindowObject(WindowObject
);
3794 IntReleaseWindowObject(WindowObject
);
3796 if (Changed
&& Repaint
)
3798 WinPosSetWindowPos(Wnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
3799 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
3810 NtUserSetWindowFNID(DWORD Unknown0
,
3824 NtUserSetWindowPlacement(HWND hWnd
,
3825 WINDOWPLACEMENT
*lpwndpl
)
3827 PWINDOW_OBJECT WindowObject
;
3828 WINDOWPLACEMENT Safepl
;
3831 WindowObject
= IntGetWindowObject(hWnd
);
3832 if (WindowObject
== NULL
)
3834 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3837 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3838 if(!NT_SUCCESS(Status
))
3840 SetLastNtError(Status
);
3841 IntReleaseWindowObject(WindowObject
);
3844 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3846 IntReleaseWindowObject(WindowObject
);
3850 if ((WindowObject
->Style
& (WS_MAXIMIZE
| WS_MINIMIZE
)) == 0)
3852 WinPosSetWindowPos(WindowObject
->Self
, NULL
,
3853 Safepl
.rcNormalPosition
.left
, Safepl
.rcNormalPosition
.top
,
3854 Safepl
.rcNormalPosition
.right
- Safepl
.rcNormalPosition
.left
,
3855 Safepl
.rcNormalPosition
.bottom
- Safepl
.rcNormalPosition
.top
,
3856 SWP_NOZORDER
| SWP_NOACTIVATE
);
3859 /* FIXME - change window status */
3860 WinPosShowWindow(WindowObject
->Self
, Safepl
.showCmd
);
3862 if (WindowObject
->InternalPos
== NULL
)
3863 WindowObject
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
3864 WindowObject
->InternalPos
->NormalRect
= Safepl
.rcNormalPosition
;
3865 WindowObject
->InternalPos
->IconPos
= Safepl
.ptMinPosition
;
3866 WindowObject
->InternalPos
->MaxPos
= Safepl
.ptMaxPosition
;
3868 IntReleaseWindowObject(WindowObject
);
3879 HWND hWndInsertAfter
,
3886 return WinPosSetWindowPos(hWnd
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3891 IntGetWindowRgn(HWND hWnd
, HRGN hRgn
)
3894 PWINDOW_OBJECT WindowObject
;
3898 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
3900 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3905 IntReleaseWindowObject(WindowObject
);
3909 /* Create a new window region using the window rectangle */
3910 VisRgn
= UnsafeIntCreateRectRgnIndirect(&WindowObject
->WindowRect
);
3911 NtGdiOffsetRgn(VisRgn
, -WindowObject
->WindowRect
.left
, -WindowObject
->WindowRect
.top
);
3912 /* if there's a region assigned to the window, combine them both */
3913 if(WindowObject
->WindowRegion
&& !(WindowObject
->Style
& WS_MINIMIZE
))
3914 NtGdiCombineRgn(VisRgn
, VisRgn
, WindowObject
->WindowRegion
, RGN_AND
);
3915 /* Copy the region into hRgn */
3916 NtGdiCombineRgn(hRgn
, VisRgn
, NULL
, RGN_COPY
);
3918 if((pRgn
= RGNDATA_LockRgn(hRgn
)))
3920 Ret
= pRgn
->rdh
.iType
;
3921 RGNDATA_UnlockRgn(pRgn
);
3926 NtGdiDeleteObject(VisRgn
);
3928 IntReleaseWindowObject(WindowObject
);
3933 IntGetWindowRgnBox(HWND hWnd
, RECT
*Rect
)
3936 PWINDOW_OBJECT WindowObject
;
3940 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
3942 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3947 IntReleaseWindowObject(WindowObject
);
3951 /* Create a new window region using the window rectangle */
3952 VisRgn
= UnsafeIntCreateRectRgnIndirect(&WindowObject
->WindowRect
);
3953 NtGdiOffsetRgn(VisRgn
, -WindowObject
->WindowRect
.left
, -WindowObject
->WindowRect
.top
);
3954 /* if there's a region assigned to the window, combine them both */
3955 if(WindowObject
->WindowRegion
&& !(WindowObject
->Style
& WS_MINIMIZE
))
3956 NtGdiCombineRgn(VisRgn
, VisRgn
, WindowObject
->WindowRegion
, RGN_AND
);
3958 if((pRgn
= RGNDATA_LockRgn(VisRgn
)))
3960 Ret
= pRgn
->rdh
.iType
;
3961 *Rect
= pRgn
->rdh
.rcBound
;
3962 RGNDATA_UnlockRgn(pRgn
);
3967 NtGdiDeleteObject(VisRgn
);
3969 IntReleaseWindowObject(WindowObject
);
3983 PWINDOW_OBJECT WindowObject
;
3985 WindowObject
= IntGetWindowObject(hWnd
);
3986 if (WindowObject
== NULL
)
3988 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3992 /* FIXME - Verify if hRgn is a valid handle!!!!
3993 Propably make this operation thread-safe, but maybe it's not necessary */
3995 if(WindowObject
->WindowRegion
)
3997 /* Delete no longer needed region handle */
3998 NtGdiDeleteObject(WindowObject
->WindowRegion
);
4000 WindowObject
->WindowRegion
= hRgn
;
4002 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
4006 IntRedrawWindow(WindowObject
, NULL
, NULL
, RDW_INVALIDATE
);
4009 IntReleaseWindowObject(WindowObject
);
4018 NtUserShowWindow(HWND hWnd
,
4021 return WinPosShowWindow(hWnd
, nCmdShow
);
4029 NtUserShowWindowAsync(DWORD Unknown0
,
4042 NtUserUpdateLayeredWindow(DWORD Unknown0
,
4062 NtUserValidateRect(HWND hWnd
, const RECT
* Rect
)
4064 return (VOID
)NtUserRedrawWindow(hWnd
, Rect
, 0, RDW_VALIDATE
| RDW_NOCHILDREN
);
4072 NtUserWindowFromPoint(LONG X
, LONG Y
)
4076 PWINDOW_OBJECT DesktopWindow
, Window
= NULL
;
4078 if ((DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow())))
4085 Hit
= WinPosWindowFromPoint(DesktopWindow
, PsGetWin32Thread()->MessageQueue
, &pt
, &Window
);
4090 IntReleaseWindowObject(Window
);
4091 IntReleaseWindowObject(DesktopWindow
);
4095 IntReleaseWindowObject(DesktopWindow
);
4105 * Undocumented function that is called from DefWindowProc to set
4113 NtUserDefSetText(HWND WindowHandle
, PUNICODE_STRING WindowText
)
4115 PWINDOW_OBJECT WindowObject
, Parent
, Owner
;
4116 UNICODE_STRING SafeText
;
4119 WindowObject
= IntGetWindowObject(WindowHandle
);
4122 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4128 Status
= IntSafeCopyUnicodeString(&SafeText
, WindowText
);
4129 if(!NT_SUCCESS(Status
))
4131 SetLastNtError(Status
);
4132 IntReleaseWindowObject(WindowObject
);
4138 RtlInitUnicodeString(&SafeText
, NULL
);
4141 /* FIXME - do this thread-safe! otherwise one could crash here! */
4142 RtlFreeUnicodeString(&WindowObject
->WindowName
);
4144 WindowObject
->WindowName
= SafeText
;
4146 /* Send shell notifications */
4148 Owner
= IntGetOwner(WindowObject
);
4149 Parent
= IntGetParent(WindowObject
);
4151 if ((!Owner
) && (!Parent
))
4153 IntShellHookNotify(HSHELL_REDRAW
, (LPARAM
) WindowHandle
);
4158 IntReleaseWindowObject(Owner
);
4163 IntReleaseWindowObject(Parent
);
4166 IntReleaseWindowObject(WindowObject
);
4171 * NtUserInternalGetWindowText
4178 NtUserInternalGetWindowText(HWND hWnd
, LPWSTR lpString
, INT nMaxCount
)
4180 PWINDOW_OBJECT WindowObject
;
4184 if(lpString
&& (nMaxCount
<= 1))
4186 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
4190 WindowObject
= IntGetWindowObject(hWnd
);
4193 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4197 /* FIXME - do this thread-safe! otherwise one could crash here! */
4198 Result
= WindowObject
->WindowName
.Length
/ sizeof(WCHAR
);
4201 const WCHAR Terminator
= L
'\0';
4203 WCHAR
*Buffer
= (WCHAR
*)lpString
;
4205 Copy
= min(nMaxCount
- 1, Result
);
4208 Status
= MmCopyToCaller(Buffer
, WindowObject
->WindowName
.Buffer
, Copy
* sizeof(WCHAR
));
4209 if(!NT_SUCCESS(Status
))
4211 SetLastNtError(Status
);
4212 IntReleaseWindowObject(WindowObject
);
4218 Status
= MmCopyToCaller(Buffer
, &Terminator
, sizeof(WCHAR
));
4219 if(!NT_SUCCESS(Status
))
4221 SetLastNtError(Status
);
4222 IntReleaseWindowObject(WindowObject
);
4229 IntReleaseWindowObject(WindowObject
);
4234 NtUserDereferenceWndProcHandle(WNDPROC wpHandle
, WndProcHandle
*Data
)
4236 WndProcHandle Entry
;
4237 if (((DWORD
)wpHandle
& 0xFFFF0000) == 0xFFFF0000)
4239 Entry
= WndProcHandlesArray
[(DWORD
)wpHandle
& 0x0000FFFF];
4240 Data
->WindowProc
= Entry
.WindowProc
;
4241 Data
->IsUnicode
= Entry
.IsUnicode
;
4242 Data
->ProcessID
= Entry
.ProcessID
;
4251 IntAddWndProcHandle(WNDPROC WindowProc
, BOOL IsUnicode
)
4256 WndProcHandle
*OldArray
;
4259 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4261 if (WndProcHandlesArray
[i
].WindowProc
== NULL
)
4269 OldArray
= WndProcHandlesArray
;
4270 OldArraySize
= WndProcHandlesArraySize
;
4271 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,(OldArraySize
+ WPH_SIZE
) * sizeof(WndProcHandle
), TAG_WINPROCLST
);
4272 WndProcHandlesArraySize
= OldArraySize
+ WPH_SIZE
;
4273 RtlCopyMemory(WndProcHandlesArray
,OldArray
,OldArraySize
* sizeof(WndProcHandle
));
4274 ExFreePool(OldArray
);
4275 FreeSpot
= OldArraySize
+ 1;
4277 WndProcHandlesArray
[FreeSpot
].WindowProc
= WindowProc
;
4278 WndProcHandlesArray
[FreeSpot
].IsUnicode
= IsUnicode
;
4279 WndProcHandlesArray
[FreeSpot
].ProcessID
= PsGetCurrentProcessId();
4280 return FreeSpot
+ 0xFFFF0000;
4284 IntRemoveWndProcHandle(WNDPROC Handle
)
4287 position
= (DWORD
)Handle
& 0x0000FFFF;
4288 if (position
> WndProcHandlesArraySize
)
4292 WndProcHandlesArray
[position
].WindowProc
= NULL
;
4293 WndProcHandlesArray
[position
].IsUnicode
= FALSE
;
4294 WndProcHandlesArray
[position
].ProcessID
= NULL
;
4299 IntRemoveProcessWndProcHandles(HANDLE ProcessID
)
4302 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4304 if (WndProcHandlesArray
[i
].ProcessID
== ProcessID
)
4306 WndProcHandlesArray
[i
].WindowProc
= NULL
;
4307 WndProcHandlesArray
[i
].IsUnicode
= FALSE
;
4308 WndProcHandlesArray
[i
].ProcessID
= NULL
;