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.228 2004/05/08 16:06:54 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 ******************************************************************/
31 #include <ddk/ntddk.h>
32 #include <internal/safe.h>
33 #include <win32k/win32k.h>
34 #include <include/object.h>
35 #include <include/guicheck.h>
36 #include <include/window.h>
37 #include <include/class.h>
38 #include <include/error.h>
39 #include <include/winsta.h>
40 #include <include/desktop.h>
41 #include <include/winpos.h>
42 #include <include/callback.h>
43 #include <include/msgqueue.h>
44 #include <include/rect.h>
45 #include <include/dce.h>
46 #include <include/paint.h>
47 #include <include/painting.h>
48 #include <include/scroll.h>
49 #include <include/intgdi.h>
50 #include <include/menu.h>
51 #include <include/hotkey.h>
52 #include <include/focus.h>
53 #include <include/hook.h>
54 #include <include/useratom.h>
55 #include <include/tags.h>
56 #include <include/timer.h>
57 #include <include/cleanup.h>
60 #include <win32k/debug1.h>
63 static WndProcHandle
*WndProcHandlesArray
= 0;
64 static WORD WndProcHandlesArraySize
= 0;
65 #define WPH_SIZE 0x40 /* the size to add to the WndProcHandle array each time */
67 /* dialog resources appear to pass this in 16 bits, handle them properly */
68 #define CW_USEDEFAULT16 (0x8000)
70 #define POINT_IN_RECT(p, r) (((r.bottom >= p.y) && (r.top <= p.y))&&((r.left <= p.x )&&( r.right >= p.x )))
72 /* PRIVATE FUNCTIONS **********************************************************/
77 * Initialize windowing implementation.
83 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,WPH_SIZE
* sizeof(WndProcHandle
), TAG_WINPROCLST
);
84 WndProcHandlesArraySize
= WPH_SIZE
;
85 return STATUS_SUCCESS
;
91 * Cleanup windowing implementation.
95 CleanupWindowImpl(VOID
)
97 ExFreePool(WndProcHandlesArray
);
98 WndProcHandlesArray
= 0;
99 WndProcHandlesArraySize
= 0;
100 return STATUS_SUCCESS
;
103 /* HELPER FUNCTIONS ***********************************************************/
108 * The function determines whether the specified window handle identifies
109 * an existing window.
113 * Handle to the window to test.
116 * If the window handle identifies an existing window, the return value
117 * is TRUE. If the window handle does not identify an existing window,
118 * the return value is FALSE.
122 IntIsWindow(HWND hWnd
)
124 PWINDOW_OBJECT Window
;
126 if (!(Window
= IntGetWindowObject(hWnd
)))
129 IntReleaseWindowObject(Window
);
134 * IntGetProcessWindowObject
136 * Get window object from handle of specified process.
139 PWINDOW_OBJECT FASTCALL
140 IntGetProcessWindowObject(PW32PROCESS ProcessData
, HWND hWnd
)
142 PWINDOW_OBJECT WindowObject
;
145 Status
= ObmReferenceObjectByHandle(ProcessData
->WindowStation
->HandleTable
,
146 hWnd
, otWindow
, (PVOID
*)&WindowObject
);
147 if (!NT_SUCCESS(Status
))
155 PWINDOW_OBJECT FASTCALL
156 IntGetParent(PWINDOW_OBJECT Wnd
)
160 if (Wnd
->Style
& WS_POPUP
)
162 IntLockRelatives(Wnd
);
164 IntUnLockRelatives(Wnd
);
165 return IntGetWindowObject(hWnd
);
167 else if (Wnd
->Style
& WS_CHILD
)
169 IntLockRelatives(Wnd
);
171 IntUnLockRelatives(Wnd
);
172 return IntGetWindowObject(hWnd
);
179 PWINDOW_OBJECT FASTCALL
180 IntGetParentObject(PWINDOW_OBJECT Wnd
)
184 IntLockRelatives(Wnd
);
185 hParent
= Wnd
->Parent
;
186 IntUnLockRelatives(Wnd
);
187 return IntGetWindowObject(hParent
);
193 * Compile a list of all child window handles from given window.
196 * This function is similar to Wine WIN_ListChildren. The caller
197 * must free the returned list with ExFreePool.
201 IntWinListChildren(PWINDOW_OBJECT Window
)
203 PWINDOW_OBJECT Child
;
205 UINT Index
, NumChildren
= 0;
207 IntLockRelatives(Window
);
209 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
212 List
= ExAllocatePoolWithTag(PagedPool
, (NumChildren
+ 1) * sizeof(HWND
), TAG_WINLIST
);
215 DPRINT1("Failed to allocate memory for children array\n");
216 IntUnLockRelatives(Window
);
217 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
220 for (Child
= Window
->FirstChild
, Index
= 0;
222 Child
= Child
->NextSibling
, ++Index
)
223 List
[Index
] = Child
->Self
;
226 IntUnLockRelatives(Window
);
231 /***********************************************************************
234 static void IntSendDestroyMsg(HWND Wnd
)
239 if (GetGUIThreadInfo(GetCurrentThreadId(), &info
))
241 if (Wnd
== info
.hwndCaret
)
249 * Send the WM_DESTROY to the window.
251 IntSendMessage(Wnd
, WM_DESTROY
, 0, 0);
254 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
255 * make sure that the window still exists when we come back.
263 if (!(pWndArray
= WIN_ListChildren( hwnd
))) return;
265 /* start from the end (FIXME: is this needed?) */
266 for (i
= 0; pWndArray
[i
]; i
++) ;
270 if (IsWindow( pWndArray
[i
] )) WIN_SendDestroyMsg( pWndArray
[i
] );
272 HeapFree(GetProcessHeap(), 0, pWndArray
);
276 DPRINT("destroyed itself while in WM_DESTROY!\n");
281 /***********************************************************************
284 * Destroy storage associated to a window. "Internals" p.358
286 static LRESULT
IntDestroyWindow(PWINDOW_OBJECT Window
,
287 PW32PROCESS ProcessData
,
288 PW32THREAD ThreadData
,
289 BOOLEAN SendMessages
)
293 PWINDOW_OBJECT Child
;
295 BOOL BelongsToThreadData
;
299 RemoveTimersWindow(Window
->Self
);
301 IntLockThreadWindows(Window
->OwnerThread
->Win32Thread
);
302 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
304 IntUnLockThreadWindows(Window
->OwnerThread
->Win32Thread
);
305 DPRINT("Tried to call IntDestroyWindow() twice\n");
308 Window
->Status
|= WINDOWSTATUS_DESTROYING
;
309 /* remove the window already at this point from the thread window list so we
310 don't get into trouble when destroying the thread windows while we're still
311 in IntDestroyWindow() */
312 RemoveEntryList(&Window
->ThreadListEntry
);
313 IntUnLockThreadWindows(Window
->OwnerThread
->Win32Thread
);
315 BelongsToThreadData
= IntWndBelongsToThread(Window
, ThreadData
);
319 /* Send destroy messages */
320 IntSendDestroyMsg(Window
->Self
);
323 /* free child windows */
324 Children
= IntWinListChildren(Window
);
327 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
329 if ((Child
= IntGetWindowObject(*ChildHandle
)))
331 if(!IntWndBelongsToThread(Child
, ThreadData
))
333 /* send WM_DESTROY messages to windows not belonging to the same thread */
334 IntSendDestroyMsg(Child
->Self
);
337 IntDestroyWindow(Child
, ProcessData
, ThreadData
, SendMessages
);
338 IntReleaseWindowObject(Child
);
341 ExFreePool(Children
);
347 * Clear the update region to make sure no WM_PAINT messages will be
348 * generated for this window while processing the WM_NCDESTROY.
350 IntRedrawWindow(Window
, NULL
, 0,
351 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
|
352 RDW_NOINTERNALPAINT
| RDW_NOCHILDREN
);
355 * Send the WM_NCDESTROY to the window being destroyed.
357 if(BelongsToThreadData
)
358 IntSendMessage(Window
->Self
, WM_NCDESTROY
, 0, 0);
361 /* reset shell window handles */
362 if(ProcessData
->WindowStation
)
364 if (Window
->Self
== ProcessData
->WindowStation
->ShellWindow
)
365 ProcessData
->WindowStation
->ShellWindow
= NULL
;
367 if (Window
->Self
== ProcessData
->WindowStation
->ShellListView
)
368 ProcessData
->WindowStation
->ShellListView
= NULL
;
371 /* Unregister hot keys */
372 UnregisterWindowHotKeys (Window
);
374 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
377 WinPosCheckInternalPos(Window
->Self
);
378 if (Window
->Self
== GetCapture())
383 /* free resources associated with the window */
384 TIMER_RemoveWindowTimers(Window
->Self
);
387 if (!(Window
->Style
& WS_CHILD
) && Window
->IDMenu
388 && (Menu
= IntGetMenuObject((HMENU
)Window
->IDMenu
)))
390 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
392 IntReleaseMenuObject(Menu
);
395 if(Window
->SystemMenu
396 && (Menu
= IntGetMenuObject(Window
->SystemMenu
)))
398 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
399 Window
->SystemMenu
= (HMENU
)0;
400 IntReleaseMenuObject(Menu
);
403 DceFreeWindowDCE(Window
); /* Always do this to catch orphaned DCs */
405 WINPROC_FreeProc(Window
->winproc
, WIN_PROC_WINDOW
);
406 CLASS_RemoveWindow(Window
->Class
);
409 IntUnlinkWindow(Window
);
411 IntReferenceWindowObject(Window
);
412 ObmCloseHandle(ProcessData
->WindowStation
->HandleTable
, Window
->Self
);
414 IntDestroyScrollBars(Window
);
416 IntLockThreadWindows(Window
->OwnerThread
->Win32Thread
);
417 Window
->Status
|= WINDOWSTATUS_DESTROYED
;
418 /* don't remove the WINDOWSTATUS_DESTROYING bit */
419 IntUnLockThreadWindows(Window
->OwnerThread
->Win32Thread
);
421 ObmDereferenceObject(Window
->Class
);
422 Window
->Class
= NULL
;
424 if(Window
->WindowRegion
)
426 NtGdiDeleteObject(Window
->WindowRegion
);
429 RtlFreeUnicodeString(&Window
->WindowName
);
431 IntReleaseWindowObject(Window
);
437 IntGetWindowBorderMeasures(PWINDOW_OBJECT WindowObject
, INT
*cx
, INT
*cy
)
439 if(HAS_DLGFRAME(WindowObject
->Style
, WindowObject
->ExStyle
) && !(WindowObject
->Style
& WS_MINIMIZE
))
441 *cx
= NtUserGetSystemMetrics(SM_CXDLGFRAME
);
442 *cy
= NtUserGetSystemMetrics(SM_CYDLGFRAME
);
446 if(HAS_THICKFRAME(WindowObject
->Style
, WindowObject
->ExStyle
)&& !(WindowObject
->Style
& WS_MINIMIZE
))
448 *cx
= NtUserGetSystemMetrics(SM_CXFRAME
);
449 *cy
= NtUserGetSystemMetrics(SM_CYFRAME
);
451 else if(HAS_THINFRAME(WindowObject
->Style
, WindowObject
->ExStyle
))
453 *cx
= NtUserGetSystemMetrics(SM_CXBORDER
);
454 *cy
= NtUserGetSystemMetrics(SM_CYBORDER
);
464 IntGetWindowInfo(PWINDOW_OBJECT WindowObject
, PWINDOWINFO pwi
)
466 pwi
->cbSize
= sizeof(WINDOWINFO
);
467 pwi
->rcWindow
= WindowObject
->WindowRect
;
468 pwi
->rcClient
= WindowObject
->ClientRect
;
469 pwi
->dwStyle
= WindowObject
->Style
;
470 pwi
->dwExStyle
= WindowObject
->ExStyle
;
471 pwi
->dwWindowStatus
= (NtUserGetForegroundWindow() == WindowObject
->Self
); /* WS_ACTIVECAPTION */
472 IntGetWindowBorderMeasures(WindowObject
, &pwi
->cxWindowBorders
, &pwi
->cyWindowBorders
);
473 pwi
->atomWindowType
= (WindowObject
->Class
? WindowObject
->Class
->Atom
: 0);
474 pwi
->wCreatorVersion
= 0x400; /* FIXME - return a real version number */
480 PWINDOW_OBJECT WindowObject
,
484 PMENU_OBJECT OldMenuObject
, NewMenuObject
;
486 *Changed
= (WindowObject
->IDMenu
!= (UINT
) Menu
);
492 if (0 != WindowObject
->IDMenu
)
494 OldMenuObject
= IntGetMenuObject((HMENU
) WindowObject
->IDMenu
);
495 ASSERT(NULL
== OldMenuObject
|| OldMenuObject
->MenuInfo
.Wnd
== WindowObject
->Self
);
499 OldMenuObject
= NULL
;
504 NewMenuObject
= IntGetMenuObject(Menu
);
505 if (NULL
== NewMenuObject
)
507 if (NULL
!= OldMenuObject
)
509 IntReleaseMenuObject(OldMenuObject
);
511 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
514 if (NULL
!= NewMenuObject
->MenuInfo
.Wnd
)
516 /* Can't use the same menu for two windows */
517 if (NULL
!= OldMenuObject
)
519 IntReleaseMenuObject(OldMenuObject
);
521 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
527 WindowObject
->IDMenu
= (UINT
) Menu
;
528 if (NULL
!= NewMenuObject
)
530 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
531 IntReleaseMenuObject(NewMenuObject
);
533 if (NULL
!= OldMenuObject
)
535 OldMenuObject
->MenuInfo
.Wnd
= NULL
;
536 IntReleaseMenuObject(OldMenuObject
);
543 /* INTERNAL ******************************************************************/
547 DestroyThreadWindows(struct _ETHREAD
*Thread
)
550 PW32PROCESS Win32Process
;
551 PW32THREAD Win32Thread
;
552 PWINDOW_OBJECT
*List
, *pWnd
;
555 Win32Thread
= Thread
->Win32Thread
;
556 Win32Process
= Thread
->ThreadsProcess
->Win32Process
;
558 IntLockThreadWindows(Win32Thread
);
559 Current
= Win32Thread
->WindowListHead
.Flink
;
560 while (Current
!= &(Win32Thread
->WindowListHead
))
563 Current
= Current
->Flink
;
568 List
= ExAllocatePool(PagedPool
, (Cnt
+ 1) * sizeof(PWINDOW_OBJECT
));
571 DPRINT("Not enough memory to allocate window handle list\n");
572 IntUnLockThreadWindows(Win32Thread
);
576 Current
= Win32Thread
->WindowListHead
.Flink
;
577 while (Current
!= &(Win32Thread
->WindowListHead
))
579 *pWnd
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
580 IntReferenceWindowObject(*pWnd
);
582 Current
= Current
->Flink
;
584 IntUnLockThreadWindows(Win32Thread
);
587 for(pWnd
= List
; *pWnd
; pWnd
++)
589 NtUserDestroyWindow((*pWnd
)->Self
);
590 IntReleaseWindowObject(*pWnd
);
596 IntUnLockThreadWindows(Win32Thread
);
602 * Returns client window rectangle relative to the upper-left corner of client area.
604 * \note Does not check the validity of the parameters
607 IntGetClientRect(PWINDOW_OBJECT WindowObject
, PRECT Rect
)
609 ASSERT( WindowObject
);
612 Rect
->left
= Rect
->top
= 0;
613 Rect
->right
= WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
;
614 Rect
->bottom
= WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
;
620 IntGetFocusWindow(VOID
)
622 PUSER_MESSAGE_QUEUE Queue
;
623 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
628 Queue
= (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
633 return(Queue
->FocusWindow
);
637 PMENU_OBJECT FASTCALL
638 IntGetSystemMenu(PWINDOW_OBJECT WindowObject
, BOOL bRevert
, BOOL RetMenu
)
640 PMENU_OBJECT MenuObject
, NewMenuObject
, SysMenuObject
, ret
= NULL
;
641 PW32PROCESS W32Process
;
642 HMENU NewMenu
, SysMenu
;
643 ROSMENUITEMINFO ItemInfo
;
647 W32Process
= PsGetWin32Process();
649 if(!W32Process
->WindowStation
)
652 if(WindowObject
->SystemMenu
)
654 MenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
657 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
658 WindowObject
->SystemMenu
= (HMENU
)0;
659 IntReleaseMenuObject(MenuObject
);
663 if(W32Process
->WindowStation
->SystemMenuTemplate
)
665 /* clone system menu */
666 MenuObject
= IntGetMenuObject(W32Process
->WindowStation
->SystemMenuTemplate
);
670 NewMenuObject
= IntCloneMenu(MenuObject
);
673 WindowObject
->SystemMenu
= NewMenuObject
->MenuInfo
.Self
;
674 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
675 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
677 //IntReleaseMenuObject(NewMenuObject);
679 IntReleaseMenuObject(MenuObject
);
683 SysMenu
= NtUserCreateMenu(FALSE
);
688 SysMenuObject
= IntGetMenuObject(SysMenu
);
689 if (NULL
== SysMenuObject
)
691 NtUserDestroyMenu(SysMenu
);
694 SysMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
695 SysMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
696 NewMenu
= IntLoadSysMenuTemplate();
699 IntReleaseMenuObject(SysMenuObject
);
700 NtUserDestroyMenu(SysMenu
);
703 MenuObject
= IntGetMenuObject(NewMenu
);
706 IntReleaseMenuObject(SysMenuObject
);
707 NtUserDestroyMenu(SysMenu
);
711 NewMenuObject
= IntCloneMenu(MenuObject
);
714 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
| MF_POPUP
;
715 IntReleaseMenuObject(NewMenuObject
);
716 NtUserSetMenuDefaultItem(NewMenuObject
->MenuInfo
.Self
, SC_CLOSE
, FALSE
);
718 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
719 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
720 ItemInfo
.fType
= MF_POPUP
;
721 ItemInfo
.fState
= MFS_ENABLED
;
722 ItemInfo
.dwTypeData
= NULL
;
724 ItemInfo
.hSubMenu
= NewMenuObject
->MenuInfo
.Self
;
725 IntInsertMenuItem(SysMenuObject
, (UINT
) -1, TRUE
, &ItemInfo
);
727 WindowObject
->SystemMenu
= SysMenuObject
->MenuInfo
.Self
;
731 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
732 IntReleaseMenuObject(MenuObject
);
741 if(WindowObject
->SystemMenu
)
742 return IntGetMenuObject((HMENU
)WindowObject
->SystemMenu
);
750 IntIsChildWindow(HWND Parent
, HWND Child
)
752 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
754 if(!(BaseWindow
= IntGetWindowObject(Child
)))
762 if (Window
->Self
== Parent
)
764 if(Window
!= BaseWindow
)
765 IntReleaseWindowObject(Window
);
766 IntReleaseWindowObject(BaseWindow
);
769 if(!(Window
->Style
& WS_CHILD
))
771 if(Window
!= BaseWindow
)
772 IntReleaseWindowObject(Window
);
776 Window
= IntGetParentObject(Window
);
777 if(Old
!= BaseWindow
)
778 IntReleaseWindowObject(Old
);
781 IntReleaseWindowObject(BaseWindow
);
786 IntIsWindowVisible(HWND hWnd
)
788 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
790 if(!(BaseWindow
= IntGetWindowObject(hWnd
)))
798 if(!(Window
->Style
& WS_CHILD
))
802 if(!(Window
->Style
& WS_VISIBLE
))
804 if(Window
!= BaseWindow
)
805 IntReleaseWindowObject(Window
);
806 IntReleaseWindowObject(BaseWindow
);
810 Window
= IntGetParentObject(Window
);
811 if(Old
!= BaseWindow
)
812 IntReleaseWindowObject(Old
);
817 if(Window
->Style
& WS_VISIBLE
)
819 if(Window
!= BaseWindow
)
820 IntReleaseWindowObject(Window
);
821 IntReleaseWindowObject(BaseWindow
);
824 if(Window
!= BaseWindow
)
825 IntReleaseWindowObject(Window
);
827 IntReleaseWindowObject(BaseWindow
);
832 /* link the window into siblings and parent. children are kept in place. */
836 PWINDOW_OBJECT WndParent
,
837 PWINDOW_OBJECT WndPrevSibling
/* set to NULL if top sibling */
840 PWINDOW_OBJECT Parent
;
842 IntLockRelatives(Wnd
);
843 Wnd
->Parent
= WndParent
->Self
;
844 if ((Wnd
->PrevSibling
= WndPrevSibling
))
846 /* link after WndPrevSibling */
847 if ((Wnd
->NextSibling
= WndPrevSibling
->NextSibling
))
848 Wnd
->NextSibling
->PrevSibling
= Wnd
;
849 else if ((Parent
= IntGetWindowObject(Wnd
->Parent
)))
851 IntLockRelatives(Parent
);
852 if(Parent
->LastChild
== WndPrevSibling
)
853 Parent
->LastChild
= Wnd
;
854 IntUnLockRelatives(Parent
);
855 IntReleaseWindowObject(Parent
);
857 Wnd
->PrevSibling
->NextSibling
= Wnd
;
862 Parent
= IntGetWindowObject(Wnd
->Parent
);
863 if ((Wnd
->NextSibling
= WndParent
->FirstChild
))
864 Wnd
->NextSibling
->PrevSibling
= Wnd
;
867 IntLockRelatives(Parent
);
868 Parent
->LastChild
= Wnd
;
869 Parent
->FirstChild
= Wnd
;
870 IntUnLockRelatives(Parent
);
871 IntReleaseWindowObject(Parent
);
872 IntUnLockRelatives(Wnd
);
877 IntLockRelatives(Parent
);
878 Parent
->FirstChild
= Wnd
;
879 IntUnLockRelatives(Parent
);
880 IntReleaseWindowObject(Parent
);
883 IntUnLockRelatives(Wnd
);
887 IntSetOwner(HWND hWnd
, HWND hWndNewOwner
)
889 PWINDOW_OBJECT Wnd
, WndOldOwner
, WndNewOwner
;
892 Wnd
= IntGetWindowObject(hWnd
);
896 IntLockRelatives(Wnd
);
897 WndOldOwner
= IntGetWindowObject(Wnd
->Owner
);
900 ret
= WndOldOwner
->Self
;
901 IntReleaseWindowObject(WndOldOwner
);
908 if((WndNewOwner
= IntGetWindowObject(hWndNewOwner
)))
910 Wnd
->Owner
= hWndNewOwner
;
911 IntReleaseWindowObject(WndNewOwner
);
916 IntUnLockRelatives(Wnd
);
917 IntReleaseWindowObject(Wnd
);
921 PWINDOW_OBJECT FASTCALL
922 IntSetParent(PWINDOW_OBJECT Wnd
, PWINDOW_OBJECT WndNewParent
)
924 PWINDOW_OBJECT WndOldParent
, Sibling
, InsertAfter
;
925 HWND hWnd
, hWndNewParent
, hWndOldParent
;
930 ASSERT(WndNewParent
);
933 hWndNewParent
= WndNewParent
->Self
;
936 * Windows hides the window first, then shows it again
937 * including the WM_SHOWWINDOW messages and all
939 WasVisible
= WinPosShowWindow(hWnd
, SW_HIDE
);
941 /* Validate that window and parent still exist */
942 if (!IntIsWindow(hWnd
) || !IntIsWindow(hWndNewParent
))
945 /* Window must belong to current process */
946 if (Wnd
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
949 WndOldParent
= IntGetParentObject(Wnd
);
950 hWndOldParent
= (WndOldParent
? WndOldParent
->Self
: NULL
);
952 if (WndNewParent
!= WndOldParent
)
954 IntUnlinkWindow(Wnd
);
956 if (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
))
958 /* Not a TOPMOST window, put after TOPMOSTs of new parent */
959 IntLockRelatives(WndNewParent
);
960 Sibling
= WndNewParent
->FirstChild
;
961 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
963 InsertAfter
= Sibling
;
964 Sibling
= Sibling
->NextSibling
;
966 IntUnLockRelatives(WndNewParent
);
968 if (NULL
== InsertAfter
)
970 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
974 IntReferenceWindowObject(InsertAfter
);
975 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
976 IntReleaseWindowObject(InsertAfter
);
979 if (WndNewParent
->Self
!= IntGetDesktopWindow()) /* a child window */
981 if (!(Wnd
->Style
& WS_CHILD
))
983 //if ( Wnd->Menu ) DestroyMenu ( Wnd->menu );
984 IntSetMenu(Wnd
, NULL
, &MenuChanged
);
990 * SetParent additionally needs to make hwnd the top window
991 * in the z-order and send the expected WM_WINDOWPOSCHANGING and
992 * WM_WINDOWPOSCHANGED notification messages.
994 WinPosSetWindowPos(hWnd
, (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOP
: HWND_TOPMOST
),
995 0, 0, 0, 0, SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
996 | (WasVisible
? SWP_SHOWWINDOW
: 0));
999 * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
1000 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
1004 * Validate that the old parent still exist, since it migth have been
1005 * destroyed during the last callbacks to user-mode
1009 if(!IntIsWindow(WndOldParent
->Self
))
1011 IntReleaseWindowObject(WndOldParent
);
1015 /* don't dereference the window object here, it must be done by the caller
1016 of IntSetParent() */
1017 return WndOldParent
;
1023 IntSetSystemMenu(PWINDOW_OBJECT WindowObject
, PMENU_OBJECT MenuObject
)
1025 PMENU_OBJECT OldMenuObject
;
1026 if(WindowObject
->SystemMenu
)
1028 OldMenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
1031 OldMenuObject
->MenuInfo
.Flags
&= ~ MF_SYSMENU
;
1032 IntReleaseMenuObject(OldMenuObject
);
1038 /* FIXME check window style, propably return FALSE ? */
1039 WindowObject
->SystemMenu
= MenuObject
->MenuInfo
.Self
;
1040 MenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
1043 WindowObject
->SystemMenu
= (HMENU
)0;
1049 /* unlink the window from siblings and parent. children are kept in place. */
1051 IntUnlinkWindow(PWINDOW_OBJECT Wnd
)
1053 PWINDOW_OBJECT WndParent
;
1055 IntLockRelatives(Wnd
);
1056 if((WndParent
= IntGetWindowObject(Wnd
->Parent
)))
1058 IntLockRelatives(WndParent
);
1061 if (Wnd
->NextSibling
) Wnd
->NextSibling
->PrevSibling
= Wnd
->PrevSibling
;
1062 else if (WndParent
&& WndParent
->LastChild
== Wnd
) WndParent
->LastChild
= Wnd
->PrevSibling
;
1064 if (Wnd
->PrevSibling
) Wnd
->PrevSibling
->NextSibling
= Wnd
->NextSibling
;
1065 else if (WndParent
&& WndParent
->FirstChild
== Wnd
) WndParent
->FirstChild
= Wnd
->NextSibling
;
1069 IntUnLockRelatives(WndParent
);
1070 IntReleaseWindowObject(WndParent
);
1072 Wnd
->PrevSibling
= Wnd
->NextSibling
= Wnd
->Parent
= NULL
;
1073 IntUnLockRelatives(Wnd
);
1079 PWINDOW_OBJECT Window
, Child
;
1081 if(!(Window
= IntGetWindowObject(IntGetDesktopWindow())))
1083 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1087 IntLockRelatives(Window
);
1088 for(Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
1090 if(Child
->Owner
&& Child
->Style
& WS_VISIBLE
)
1093 * The desktop has a popup window if one of them has
1094 * an owner window and is visible
1096 IntUnLockRelatives(Window
);
1097 IntReleaseWindowObject(Window
);
1101 IntUnLockRelatives(Window
);
1102 IntReleaseWindowObject(Window
);
1107 IntIsWindowInDestroy(PWINDOW_OBJECT Window
)
1109 return ((Window
->Status
& WINDOWSTATUS_DESTROYING
) == WINDOWSTATUS_DESTROYING
);
1112 /* FUNCTIONS *****************************************************************/
1118 NtUserAlterWindowStyle(DWORD Unknown0
,
1129 * As best as I can figure, this function is used by EnumWindows,
1130 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
1132 * It's supposed to build a list of HWNDs to return to the caller.
1133 * We can figure out what kind of list by what parameters are
1141 NtUserBuildHwndList(
1153 /* FIXME handle bChildren */
1157 PWINDOW_OBJECT Window
, Child
;
1158 if(!(Window
= IntGetWindowObject(hwndParent
)))
1160 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1164 IntLockRelatives(Window
);
1165 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1167 if(dwCount
++ < nBufSize
&& pWnd
)
1169 Status
= MmCopyToCaller(pWnd
++, &Child
->Self
, sizeof(HWND
));
1170 if(!NT_SUCCESS(Status
))
1172 SetLastNtError(Status
);
1177 IntUnLockRelatives(Window
);
1179 IntReleaseWindowObject(Window
);
1184 PW32THREAD W32Thread
;
1185 PLIST_ENTRY Current
;
1186 PWINDOW_OBJECT
*Window
;
1188 Status
= PsLookupThreadByThreadId((PVOID
)dwThreadId
, &Thread
);
1189 if(!NT_SUCCESS(Status
))
1191 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1194 if(!(W32Thread
= Thread
->Win32Thread
))
1196 ObDereferenceObject(Thread
);
1197 DPRINT1("Thread is not a GUI Thread!\n");
1198 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1202 IntLockThreadWindows(W32Thread
);
1203 Current
= W32Thread
->WindowListHead
.Flink
;
1204 while(Current
!= &(W32Thread
->WindowListHead
))
1206 *Window
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
1209 if(dwCount
< nBufSize
&& pWnd
&& ((*Window
)->Style
& WS_CHILD
))
1211 Status
= MmCopyToCaller(pWnd
++, &(*Window
)->Self
, sizeof(HWND
));
1212 if(!NT_SUCCESS(Status
))
1214 SetLastNtError(Status
);
1219 if(!((*Window
)->Style
& WS_CHILD
))
1224 Current
= Current
->Flink
;
1226 IntUnLockThreadWindows(W32Thread
);
1228 ObDereferenceObject(Thread
);
1232 PDESKTOP_OBJECT Desktop
;
1233 PWINDOW_OBJECT Window
, Child
;
1235 if(hDesktop
== NULL
&& !(Desktop
= IntGetActiveDesktop()))
1237 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1243 Status
= IntValidateDesktopHandle(hDesktop
,
1247 if(!NT_SUCCESS(Status
))
1249 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1253 if(!(Window
= IntGetWindowObject(Desktop
->DesktopWindow
)))
1256 ObDereferenceObject(Desktop
);
1257 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1261 IntLockRelatives(Window
);
1262 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1264 if(dwCount
++ < nBufSize
&& pWnd
)
1266 Status
= MmCopyToCaller(pWnd
++, &Child
->Self
, sizeof(HWND
));
1267 if(!NT_SUCCESS(Status
))
1269 SetLastNtError(Status
);
1274 IntUnLockRelatives(Window
);
1276 IntReleaseWindowObject(Window
);
1278 ObDereferenceObject(Desktop
);
1289 NtUserChildWindowFromPointEx(HWND hwndParent
,
1294 PWINDOW_OBJECT Parent
;
1299 if(!(Parent
= IntGetWindowObject(hwndParent
)))
1301 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1308 if(Parent
->Self
!= IntGetDesktopWindow())
1310 Pt
.x
+= Parent
->ClientRect
.left
;
1311 Pt
.y
+= Parent
->ClientRect
.top
;
1314 if(!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
))
1316 IntReleaseWindowObject(Parent
);
1321 if((List
= IntWinListChildren(Parent
)))
1323 for(phWnd
= List
; *phWnd
; phWnd
++)
1325 PWINDOW_OBJECT Child
;
1326 if((Child
= IntGetWindowObject(*phWnd
)))
1328 if(!(Child
->Style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
))
1330 IntReleaseWindowObject(Child
);
1333 if((Child
->Style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
))
1335 IntReleaseWindowObject(Child
);
1338 if((Child
->ExStyle
& WS_EX_TRANSPARENT
) && (uiFlags
& CWP_SKIPTRANSPARENT
))
1340 IntReleaseWindowObject(Child
);
1343 if(IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
1346 IntReleaseWindowObject(Child
);
1349 IntReleaseWindowObject(Child
);
1355 IntReleaseWindowObject(Parent
);
1361 * calculates the default position of a window
1364 IntCalcDefPosSize(PWINDOW_OBJECT Parent
, PWINDOW_OBJECT WindowObject
, RECT
*rc
, BOOL IncPos
)
1371 NtGdiIntersectRect(rc
, rc
, &Parent
->ClientRect
);
1375 Pos
.x
= Parent
->TiledCounter
* (NtUserGetSystemMetrics(SM_CXSIZE
) + NtUserGetSystemMetrics(SM_CXFRAME
));
1376 Pos
.y
= Parent
->TiledCounter
* (NtUserGetSystemMetrics(SM_CYSIZE
) + NtUserGetSystemMetrics(SM_CYFRAME
));
1377 if(Pos
.x
> ((rc
->right
- rc
->left
) / 4) ||
1378 Pos
.y
> ((rc
->bottom
- rc
->top
) / 4))
1380 /* reset counter and position */
1383 Parent
->TiledCounter
= 0;
1385 Parent
->TiledCounter
++;
1396 Sz
.cx
= EngMulDiv(rc
->right
- rc
->left
, 3, 4);
1397 Sz
.cy
= EngMulDiv(rc
->bottom
- rc
->top
, 3, 4);
1401 rc
->right
= rc
->left
+ Sz
.cx
;
1402 rc
->bottom
= rc
->top
+ Sz
.cy
;
1411 NtUserCreateWindowEx(DWORD dwExStyle
,
1412 PUNICODE_STRING lpClassName
,
1413 PUNICODE_STRING lpWindowName
,
1421 HINSTANCE hInstance
,
1424 BOOL bUnicodeWindow
)
1426 PWINSTATION_OBJECT WinStaObject
;
1427 PWNDCLASS_OBJECT ClassObject
;
1428 PWINDOW_OBJECT WindowObject
;
1429 PWINDOW_OBJECT ParentWindow
, OwnerWindow
;
1430 HWND ParentWindowHandle
;
1431 HWND OwnerWindowHandle
;
1432 PMENU_OBJECT SystemMenu
;
1433 UNICODE_STRING WindowName
;
1439 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1444 CBT_CREATEWNDW CbtCreate
;
1447 LPWSTR OrigWindowName
= NULL
;
1449 DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1451 /* safely copy the window name */
1454 Status
= MmCopyFromCaller(&WindowName
, lpWindowName
, sizeof(UNICODE_STRING
));
1455 if (!NT_SUCCESS(Status
))
1457 SetLastNtError(Status
);
1460 if(WindowName
.Buffer
)
1462 /* safe the original pointer to the window name */
1463 OrigWindowName
= WindowName
.Buffer
;
1465 if(!(WindowName
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
, WindowName
.MaximumLength
, TAG_STRING
)))
1467 SetLastNtError(STATUS_NO_MEMORY
);
1471 Status
= MmCopyFromCaller(WindowName
.Buffer
, OrigWindowName
, WindowName
.MaximumLength
);
1472 if(!NT_SUCCESS(Status
))
1474 ExFreePool(WindowName
.Buffer
);
1475 SetLastNtError(Status
);
1480 if(!WindowName
.Buffer
)
1481 RtlInitUnicodeString(&WindowName
, NULL
);
1484 RtlInitUnicodeString(&WindowName
, NULL
);
1486 ParentWindowHandle
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
1487 OwnerWindowHandle
= NULL
;
1489 if (hWndParent
== HWND_MESSAGE
)
1492 * native ole32.OleInitialize uses HWND_MESSAGE to create the
1493 * message window (style: WS_POPUP|WS_DISABLED)
1497 else if (hWndParent
)
1499 if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1500 ParentWindowHandle
= hWndParent
;
1502 OwnerWindowHandle
= NtUserGetAncestor(hWndParent
, GA_ROOT
);
1504 else if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1506 RtlFreeUnicodeString(&WindowName
);
1507 return (HWND
)0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1510 if (NULL
!= ParentWindowHandle
)
1512 ParentWindow
= IntGetWindowObject(ParentWindowHandle
);
1516 ParentWindow
= NULL
;
1519 /* FIXME: parent must belong to the current process */
1521 /* Check the class. */
1522 Status
= ClassReferenceClassByNameOrAtom(&ClassObject
, lpClassName
->Buffer
);
1523 if (!NT_SUCCESS(Status
))
1525 RtlFreeUnicodeString(&WindowName
);
1526 if (NULL
!= ParentWindow
)
1528 IntReleaseWindowObject(ParentWindow
);
1533 /* Check the window station. */
1534 DPRINT("IoGetCurrentProcess() %X\n", IoGetCurrentProcess());
1535 DPRINT("PROCESS_WINDOW_STATION %X\n", PROCESS_WINDOW_STATION());
1536 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
1540 if (!NT_SUCCESS(Status
))
1542 ObmDereferenceObject(ClassObject
);
1543 RtlFreeUnicodeString(&WindowName
);
1544 if (NULL
!= ParentWindow
)
1546 IntReleaseWindowObject(ParentWindow
);
1548 DPRINT("Validation of window station handle (0x%X) failed\n",
1549 PROCESS_WINDOW_STATION());
1553 /* Create the window object. */
1554 WindowObject
= (PWINDOW_OBJECT
)
1555 ObmCreateObject(PsGetWin32Process()->WindowStation
->HandleTable
, &Handle
,
1556 otWindow
, sizeof(WINDOW_OBJECT
) + ClassObject
->cbWndExtra
1559 DPRINT("Created object with handle %X\n", Handle
);
1562 ObDereferenceObject(WinStaObject
);
1563 ObmDereferenceObject(ClassObject
);
1564 RtlFreeUnicodeString(&WindowName
);
1565 if (NULL
!= ParentWindow
)
1567 IntReleaseWindowObject(ParentWindow
);
1569 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1572 ObDereferenceObject(WinStaObject
);
1574 if (NULL
== PsGetWin32Thread()->Desktop
->DesktopWindow
)
1576 /* If there is no desktop window yet, we must be creating it */
1577 PsGetWin32Thread()->Desktop
->DesktopWindow
= Handle
;
1581 * Fill out the structure describing it.
1583 WindowObject
->Class
= ClassObject
;
1584 WindowObject
->ExStyle
= dwExStyle
;
1585 WindowObject
->Style
= dwStyle
& ~WS_VISIBLE
;
1586 DPRINT("1: Style is now %d\n", WindowObject
->Style
);
1588 WindowObject
->SystemMenu
= (HMENU
)0;
1589 WindowObject
->ContextHelpId
= 0;
1590 WindowObject
->IDMenu
= 0;
1591 WindowObject
->Instance
= hInstance
;
1592 WindowObject
->Self
= Handle
;
1593 if (0 != (dwStyle
& WS_CHILD
))
1595 WindowObject
->IDMenu
= (UINT
) hMenu
;
1599 IntSetMenu(WindowObject
, hMenu
, &MenuChanged
);
1601 WindowObject
->MessageQueue
= PsGetWin32Thread()->MessageQueue
;
1602 WindowObject
->Parent
= (ParentWindow
? ParentWindow
->Self
: NULL
);
1603 if((OwnerWindow
= IntGetWindowObject(OwnerWindowHandle
)))
1605 WindowObject
->Owner
= OwnerWindowHandle
;
1606 IntReleaseWindowObject(OwnerWindow
);
1609 WindowObject
->Owner
= NULL
;
1610 WindowObject
->UserData
= 0;
1611 if ((((DWORD
)ClassObject
->lpfnWndProcA
& 0xFFFF0000) != 0xFFFF0000)
1612 && (((DWORD
)ClassObject
->lpfnWndProcW
& 0xFFFF0000) != 0xFFFF0000))
1614 WindowObject
->Unicode
= bUnicodeWindow
;
1618 WindowObject
->Unicode
= ClassObject
->Unicode
;
1620 WindowObject
->WndProcA
= ClassObject
->lpfnWndProcA
;
1621 WindowObject
->WndProcW
= ClassObject
->lpfnWndProcW
;
1622 WindowObject
->OwnerThread
= PsGetCurrentThread();
1623 WindowObject
->FirstChild
= NULL
;
1624 WindowObject
->LastChild
= NULL
;
1625 WindowObject
->PrevSibling
= NULL
;
1626 WindowObject
->NextSibling
= NULL
;
1628 /* extra window data */
1629 if (ClassObject
->cbWndExtra
!= 0)
1631 WindowObject
->ExtraData
= (PCHAR
)(WindowObject
+ 1);
1632 WindowObject
->ExtraDataSize
= ClassObject
->cbWndExtra
;
1633 RtlZeroMemory(WindowObject
->ExtraData
, WindowObject
->ExtraDataSize
);
1637 WindowObject
->ExtraData
= NULL
;
1638 WindowObject
->ExtraDataSize
= 0;
1641 InitializeListHead(&WindowObject
->PropListHead
);
1642 ExInitializeFastMutex(&WindowObject
->PropListLock
);
1643 ExInitializeFastMutex(&WindowObject
->RelativesLock
);
1644 ExInitializeFastMutex(&WindowObject
->UpdateLock
);
1646 WindowObject
->WindowName
= WindowName
;
1648 /* Correct the window style. */
1649 if (!(dwStyle
& WS_CHILD
))
1651 WindowObject
->Style
|= WS_CLIPSIBLINGS
;
1652 DPRINT("3: Style is now %d\n", WindowObject
->Style
);
1653 if (!(dwStyle
& WS_POPUP
))
1655 WindowObject
->Style
|= WS_CAPTION
;
1656 WindowObject
->Flags
|= WINDOWOBJECT_NEED_SIZE
;
1657 DPRINT("4: Style is now %d\n", WindowObject
->Style
);
1658 /* FIXME: Note the window needs a size. */
1662 if(!(WindowObject
->Style
& (WS_POPUP
| WS_CHILD
)))
1664 /* Automatically assign the overlapped window style. Also always
1665 clip siblings for overlapped windows. */
1666 WindowObject
->Style
|= (WS_OVERLAPPEDWINDOW
| WS_CLIPSIBLINGS
);
1669 /* create system menu */
1670 if((WindowObject
->Style
& WS_SYSMENU
) && (WindowObject
->Style
& WS_CAPTION
))
1672 SystemMenu
= IntGetSystemMenu(WindowObject
, TRUE
, TRUE
);
1675 WindowObject
->SystemMenu
= SystemMenu
->MenuInfo
.Self
;
1676 IntReleaseMenuObject(SystemMenu
);
1680 /* Insert the window into the thread's window list. */
1681 IntLockThreadWindows(PsGetWin32Thread());
1682 InsertTailList (&PsGetWin32Thread()->WindowListHead
,
1683 &WindowObject
->ThreadListEntry
);
1684 IntUnLockThreadWindows(PsGetWin32Thread());
1686 /* Allocate a DCE for this window. */
1687 if (dwStyle
& CS_OWNDC
)
1689 WindowObject
->Dce
= DceAllocDCE(WindowObject
->Self
, DCE_WINDOW_DC
);
1691 /* FIXME: Handle "CS_CLASSDC" */
1699 Cs
.lpCreateParams
= lpParam
;
1700 Cs
.hInstance
= hInstance
;
1702 Cs
.hwndParent
= ParentWindowHandle
;
1708 Cs
.lpszName
= OrigWindowName
; /* pass the original pointer to usermode! */
1709 Cs
.lpszClass
= lpClassName
->Buffer
;
1710 Cs
.dwExStyle
= dwExStyle
;
1711 CbtCreate
.lpcs
= &Cs
;
1712 CbtCreate
.hwndInsertAfter
= HWND_TOP
;
1713 if (HOOK_CallHooks(WH_CBT
, HCBT_CREATEWND
, (WPARAM
) Handle
, (LPARAM
) &CbtCreate
))
1715 if (NULL
!= ParentWindow
)
1717 IntReleaseWindowObject(ParentWindow
);
1720 /* FIXME - Delete window object and remove it from the thread windows list */
1721 /* FIXME - delete allocated DCE */
1723 DPRINT1("CBT-hook returned !0\n");
1732 /* default positioning for overlapped windows */
1733 if(!(WindowObject
->Style
& (WS_POPUP
| WS_CHILD
)))
1736 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
1737 BOOL CalculatedDefPosSize
= FALSE
;
1739 IntGetDesktopWorkArea(WindowObject
->OwnerThread
->Win32Thread
->Desktop
, &WorkArea
);
1742 ProcessParams
= PsGetCurrentProcess()->Peb
->ProcessParameters
;
1744 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1746 CalculatedDefPosSize
= IntCalcDefPosSize(ParentWindow
, WindowObject
, &rc
, TRUE
);
1748 if(ProcessParams
->dwFlags
& STARTF_USEPOSITION
)
1750 ProcessParams
->dwFlags
&= ~STARTF_USEPOSITION
;
1751 Pos
.x
= WorkArea
.left
+ ProcessParams
->dwX
;
1752 Pos
.y
= WorkArea
.top
+ ProcessParams
->dwY
;
1760 /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
1761 y is something else */
1762 if(y
!= CW_USEDEFAULT
&& y
!= CW_USEDEFAULT16
)
1767 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1769 if(!CalculatedDefPosSize
)
1771 IntCalcDefPosSize(ParentWindow
, WindowObject
, &rc
, FALSE
);
1773 if(ProcessParams
->dwFlags
& STARTF_USESIZE
)
1775 ProcessParams
->dwFlags
&= ~STARTF_USESIZE
;
1776 Size
.cx
= ProcessParams
->dwXSize
;
1777 Size
.cy
= ProcessParams
->dwYSize
;
1781 Size
.cx
= rc
.right
- rc
.left
;
1782 Size
.cy
= rc
.bottom
- rc
.top
;
1785 /* move the window if necessary */
1787 Pos
.x
= max(rc
.left
, 0);
1789 Pos
.y
= max(rc
.top
, 0);
1794 /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
1795 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1800 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1807 /* Initialize the window dimensions. */
1808 WindowObject
->WindowRect
.left
= Pos
.x
;
1809 WindowObject
->WindowRect
.top
= Pos
.y
;
1810 WindowObject
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1811 WindowObject
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1812 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1814 NtGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1815 ParentWindow
->ClientRect
.top
);
1817 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1820 * Get the size and position of the window.
1822 if ((dwStyle
& WS_THICKFRAME
) || !(dwStyle
& (WS_POPUP
| WS_CHILD
)))
1824 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1826 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1827 WinPosGetMinMaxInfo(WindowObject
, &MaxSize
, &MaxPos
, &MinTrack
,
1829 if (MaxSize
.x
< nWidth
) nWidth
= MaxSize
.x
;
1830 if (MaxSize
.y
< nHeight
) nHeight
= MaxSize
.y
;
1831 if (nWidth
< MinTrack
.x
) nWidth
= MinTrack
.x
;
1832 if (nHeight
< MinTrack
.y
) nHeight
= MinTrack
.y
;
1833 if (nWidth
< 0) nWidth
= 0;
1834 if (nHeight
< 0) nHeight
= 0;
1837 WindowObject
->WindowRect
.left
= Pos
.x
;
1838 WindowObject
->WindowRect
.top
= Pos
.y
;
1839 WindowObject
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1840 WindowObject
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1841 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1843 NtGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1844 ParentWindow
->ClientRect
.top
);
1846 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1848 /* FIXME: Initialize the window menu. */
1850 /* Send a NCCREATE message. */
1856 DPRINT("[win32k.window] NtUserCreateWindowEx style %d, exstyle %d, parent %d\n", Cs
.style
, Cs
.dwExStyle
, Cs
.hwndParent
);
1857 DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1858 DPRINT("NtUserCreateWindowEx(): About to send NCCREATE message.\n");
1859 Result
= IntSendMessage(WindowObject
->Self
, WM_NCCREATE
, 0, (LPARAM
) &Cs
);
1862 /* FIXME: Cleanup. */
1863 if (NULL
!= ParentWindow
)
1865 IntReleaseWindowObject(ParentWindow
);
1867 DPRINT("NtUserCreateWindowEx(): NCCREATE message failed.\n");
1871 /* Calculate the non-client size. */
1872 MaxPos
.x
= WindowObject
->WindowRect
.left
;
1873 MaxPos
.y
= WindowObject
->WindowRect
.top
;
1874 DPRINT("NtUserCreateWindowEx(): About to get non-client size.\n");
1875 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1876 Result
= WinPosGetNonClientSize(WindowObject
->Self
,
1877 &WindowObject
->WindowRect
,
1878 &WindowObject
->ClientRect
);
1879 NtGdiOffsetRect(&WindowObject
->WindowRect
,
1880 MaxPos
.x
- WindowObject
->WindowRect
.left
,
1881 MaxPos
.y
- WindowObject
->WindowRect
.top
);
1883 if (NULL
!= ParentWindow
)
1885 /* link the window into the parent's child list */
1886 if ((dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
1888 PWINDOW_OBJECT PrevSibling
;
1889 IntLockRelatives(ParentWindow
);
1890 if((PrevSibling
= ParentWindow
->LastChild
))
1891 IntReferenceWindowObject(PrevSibling
);
1892 IntUnLockRelatives(ParentWindow
);
1893 /* link window as bottom sibling */
1894 IntLinkWindow(WindowObject
, ParentWindow
, PrevSibling
/*prev sibling*/);
1896 IntReleaseWindowObject(PrevSibling
);
1900 /* link window as top sibling (but after topmost siblings) */
1901 PWINDOW_OBJECT InsertAfter
, Sibling
;
1902 if (0 == (dwExStyle
& WS_EX_TOPMOST
))
1904 IntLockRelatives(ParentWindow
);
1906 Sibling
= ParentWindow
->FirstChild
;
1907 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
1909 InsertAfter
= Sibling
;
1910 Sibling
= Sibling
->NextSibling
;
1912 IntUnLockRelatives(ParentWindow
);
1918 if (NULL
!= InsertAfter
)
1920 IntReferenceWindowObject(InsertAfter
);
1922 IntLinkWindow(WindowObject
, ParentWindow
, InsertAfter
/* prev sibling */);
1923 if (NULL
!= InsertAfter
)
1925 IntReleaseWindowObject(InsertAfter
);
1930 /* Send the WM_CREATE message. */
1931 DPRINT("NtUserCreateWindowEx(): about to send CREATE message.\n");
1932 Result
= IntSendMessage(WindowObject
->Self
, WM_CREATE
, 0, (LPARAM
) &Cs
);
1933 if (Result
== (LRESULT
)-1)
1935 /* FIXME: Cleanup. */
1936 if (NULL
!= ParentWindow
)
1938 IntReleaseWindowObject(ParentWindow
);
1940 DPRINT("NtUserCreateWindowEx(): send CREATE message failed.\n");
1944 /* Send move and size messages. */
1945 if (!(WindowObject
->Flags
& WINDOWOBJECT_NEED_SIZE
))
1949 DPRINT("NtUserCreateWindow(): About to send WM_SIZE\n");
1951 if ((WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
) < 0 ||
1952 (WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
) < 0)
1953 DPRINT("Sending bogus WM_SIZE\n");
1955 lParam
= MAKE_LONG(WindowObject
->ClientRect
.right
-
1956 WindowObject
->ClientRect
.left
,
1957 WindowObject
->ClientRect
.bottom
-
1958 WindowObject
->ClientRect
.top
);
1959 IntSendMessage(WindowObject
->Self
, WM_SIZE
, SIZE_RESTORED
,
1962 DPRINT("NtUserCreateWindow(): About to send WM_MOVE\n");
1964 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1966 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
- ParentWindow
->ClientRect
.left
,
1967 WindowObject
->ClientRect
.top
- ParentWindow
->ClientRect
.top
);
1971 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
,
1972 WindowObject
->ClientRect
.top
);
1974 IntSendMessage(WindowObject
->Self
, WM_MOVE
, 0, lParam
);
1977 /* Show or maybe minimize or maximize the window. */
1978 if (WindowObject
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1983 SwFlag
= (WindowObject
->Style
& WS_MINIMIZE
) ? SW_MINIMIZE
:
1985 WinPosMinMaximize(WindowObject
, SwFlag
, &NewPos
);
1987 ((WindowObject
->Style
& WS_CHILD
) || NtUserGetActiveWindow()) ?
1988 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
:
1989 SWP_NOZORDER
| SWP_FRAMECHANGED
;
1990 DPRINT("NtUserCreateWindow(): About to minimize/maximize\n");
1991 DPRINT("%d,%d %dx%d\n", NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
);
1992 WinPosSetWindowPos(WindowObject
->Self
, 0, NewPos
.left
, NewPos
.top
,
1993 NewPos
.right
, NewPos
.bottom
, SwFlag
);
1996 /* Notify the parent window of a new child. */
1997 if ((WindowObject
->Style
& WS_CHILD
) &&
1998 (!(WindowObject
->ExStyle
& WS_EX_NOPARENTNOTIFY
)) && ParentWindow
)
2000 DPRINT("NtUserCreateWindow(): About to notify parent\n");
2001 IntSendMessage(ParentWindow
->Self
,
2003 MAKEWPARAM(WM_CREATE
, WindowObject
->IDMenu
),
2004 (LPARAM
)WindowObject
->Self
);
2007 if (NULL
!= ParentWindow
)
2009 IntReleaseWindowObject(ParentWindow
);
2012 /* Initialize and show the window's scrollbars */
2013 if (WindowObject
->Style
& WS_VSCROLL
)
2015 NtUserShowScrollBar(WindowObject
->Self
, SB_VERT
, TRUE
);
2017 if (WindowObject
->Style
& WS_HSCROLL
)
2019 NtUserShowScrollBar(WindowObject
->Self
, SB_HORZ
, TRUE
);
2022 if (dwStyle
& WS_VISIBLE
)
2024 DPRINT("NtUserCreateWindow(): About to show window\n");
2025 WinPosShowWindow(WindowObject
->Self
, dwShowMode
);
2028 DPRINT("NtUserCreateWindow(): = %X\n", Handle
);
2029 DPRINT("WindowObject->SystemMenu = 0x%x\n", WindowObject
->SystemMenu
);
2030 return((HWND
)Handle
);
2038 NtUserDeferWindowPos(HDWP WinPosInfo
,
2040 HWND WndInsertAfter
,
2057 NtUserDestroyWindow(HWND Wnd
)
2059 PWINDOW_OBJECT Window
;
2062 Window
= IntGetWindowObject(Wnd
);
2068 /* Check for owner thread and desktop window */
2069 if ((Window
->OwnerThread
!= PsGetCurrentThread()) || IntIsDesktopWindow(Window
))
2071 IntReleaseWindowObject(Window
);
2072 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2076 /* Look whether the focus is within the tree of windows we will
2079 if (!WinPosShowWindow(Wnd
, SW_HIDE
))
2081 if (NtUserGetActiveWindow() == Wnd
)
2083 WinPosActivateOtherWindow(Window
);
2086 IntLockMessageQueue(Window
->MessageQueue
);
2087 if (Window
->MessageQueue
->ActiveWindow
== Window
->Self
)
2088 Window
->MessageQueue
->ActiveWindow
= NULL
;
2089 if (Window
->MessageQueue
->FocusWindow
== Window
->Self
)
2090 Window
->MessageQueue
->FocusWindow
= NULL
;
2091 if (Window
->MessageQueue
->CaptureWindow
== Window
->Self
)
2092 Window
->MessageQueue
->CaptureWindow
= NULL
;
2093 IntUnLockMessageQueue(Window
->MessageQueue
);
2097 if (HOOK_CallHooks(WH_CBT
, HCBT_DESTROYWND
, (WPARAM
) hwnd
, 0, TRUE
))
2103 isChild
= (0 != (Window
->Style
& WS_CHILD
));
2108 if (! USER_IsExitingThread(GetCurrentThreadId()))
2110 send_parent_notify(hwnd
, WM_DESTROY
);
2113 else if (NULL
!= GetWindow(Wnd
, GW_OWNER
))
2115 HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
2116 /* FIXME: clean up palette - see "Internals" p.352 */
2119 if (! IsWindow(Wnd
))
2125 if (!IntIsWindow(Wnd
))
2130 /* Recursively destroy owned windows */
2135 BOOL GotOne
= FALSE
;
2138 PWINDOW_OBJECT Child
, Desktop
;
2140 Desktop
= IntGetWindowObject(IntGetDesktopWindow());
2141 Children
= IntWinListChildren(Desktop
);
2142 IntReleaseWindowObject(Desktop
);
2145 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
2147 Child
= IntGetWindowObject(*ChildHandle
);
2152 if(Child
->Self
== Wnd
)
2154 IntReleaseWindowObject(Child
);
2157 IntLockRelatives(Child
);
2158 if (Child
->Parent
!= Window
->Self
)
2160 IntUnLockRelatives(Child
);
2161 IntReleaseWindowObject(Child
);
2164 IntUnLockRelatives(Child
);
2165 if (IntWndBelongsToThread(Child
, PsGetWin32Thread()))
2167 IntReleaseWindowObject(Child
);
2168 NtUserDestroyWindow(*ChildHandle
);
2172 IntLockRelatives(Child
);
2173 if (Child
->Owner
!= NULL
)
2175 Child
->Owner
= NULL
;
2177 IntUnLockRelatives(Child
);
2178 IntReleaseWindowObject(Child
);
2180 ExFreePool(Children
);
2189 if (!IntIsWindow(Wnd
))
2191 IntReleaseWindowObject(Window
);
2195 /* Destroy the window storage */
2196 IntDestroyWindow(Window
, PsGetWin32Process(), PsGetWin32Thread(), TRUE
);
2198 IntReleaseWindowObject(Window
);
2208 NtUserDrawMenuBarTemp(
2215 /* we'll use this function just for caching the menu bar */
2225 NtUserEndDeferWindowPosEx(DWORD Unknown0
,
2238 NtUserFillWindow(DWORD Unknown0
,
2250 IntFindWindow(PWINDOW_OBJECT Parent
,
2251 PWINDOW_OBJECT ChildAfter
,
2252 PWNDCLASS_OBJECT ClassObject
,
2253 PUNICODE_STRING WindowName
)
2255 BOOL CheckWindowName
;
2261 CheckWindowName
= (WindowName
&& (WindowName
->Length
> 0));
2263 if((List
= IntWinListChildren(Parent
)))
2268 /* skip handles before and including ChildAfter */
2269 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->Self
));
2272 /* search children */
2275 PWINDOW_OBJECT Child
;
2276 if(!(Child
= IntGetWindowObject(*(phWnd
++))))
2281 /* Do not send WM_GETTEXT messages in the kernel mode version!
2282 The user mode version however calls GetWindowText() which will
2283 send WM_GETTEXT messages to windows belonging to its processes */
2284 if(((!CheckWindowName
|| (CheckWindowName
&& !RtlCompareUnicodeString(WindowName
, &(Child
->WindowName
), FALSE
))) &&
2285 (!ClassObject
|| (ClassObject
&& (Child
->Class
== ClassObject
))))
2287 ((!CheckWindowName
|| (CheckWindowName
&& !RtlCompareUnicodeString(WindowName
, &(Child
->WindowName
), FALSE
))) &&
2288 (!ClassObject
|| (ClassObject
&& (Child
->Class
== ClassObject
)))))
2291 IntReleaseWindowObject(Child
);
2295 IntReleaseWindowObject(Child
);
2305 * Searches a window's children for a window with the specified
2308 * hwndParent = The window whose childs are to be searched.
2310 * HWND_MESSAGE = message-only windows
2312 * hwndChildAfter = Search starts after this child window.
2313 * NULL = start from beginning
2315 * ucClassName = Class name to search for
2316 * Reguired parameter.
2318 * ucWindowName = Window name
2319 * ->Buffer == NULL = don't care
2322 * The HWND of the window if it was found, otherwise NULL
2328 NtUserFindWindowEx(HWND hwndParent
,
2329 HWND hwndChildAfter
,
2330 PUNICODE_STRING ucClassName
,
2331 PUNICODE_STRING ucWindowName
)
2333 PWINDOW_OBJECT Parent
, ChildAfter
;
2334 UNICODE_STRING ClassName
, WindowName
;
2336 HWND Desktop
, Ret
= NULL
;
2337 PWNDCLASS_OBJECT ClassObject
= NULL
;
2339 Desktop
= IntGetDesktopWindow();
2341 if(hwndParent
== NULL
)
2342 hwndParent
= Desktop
;
2344 else if(hwndParent == HWND_MESSAGE)
2346 hwndParent = IntGetMessageWindow();
2350 if(!(Parent
= IntGetWindowObject(hwndParent
)))
2352 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2357 if(hwndChildAfter
&& !(ChildAfter
= IntGetWindowObject(hwndChildAfter
)))
2359 IntReleaseWindowObject(hwndParent
);
2360 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2364 /* copy the window name */
2365 Status
= IntSafeCopyUnicodeString(&WindowName
, ucWindowName
);
2366 if(!NT_SUCCESS(Status
))
2368 SetLastNtError(Status
);
2372 /* safely copy the class name */
2373 Status
= MmCopyFromCaller(&ClassName
, ucClassName
, sizeof(UNICODE_STRING
));
2374 if(!NT_SUCCESS(Status
))
2376 SetLastNtError(Status
);
2379 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2382 /* safely copy the class name string (NULL terminated because class-lookup
2384 buf
= ExAllocatePoolWithTag(NonPagedPool
, ClassName
.Length
+ sizeof(WCHAR
), TAG_STRING
);
2387 SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES
);
2390 Status
= MmCopyFromCaller(buf
, ClassName
.Buffer
, ClassName
.Length
);
2391 if(!NT_SUCCESS(Status
))
2394 SetLastNtError(Status
);
2397 ClassName
.Buffer
= buf
;
2398 /* make sure the string is null-terminated */
2399 buf
+= ClassName
.Length
/ sizeof(WCHAR
);
2403 /* find the class object */
2404 if(ClassName
.Buffer
)
2406 /* this expects the string in ClassName to be NULL-terminated! */
2407 Status
= ClassReferenceClassByNameOrAtom(&ClassObject
, ClassName
.Buffer
);
2408 if(!NT_SUCCESS(Status
))
2410 DPRINT1("Window class not found\n");
2411 /* windows returns ERROR_FILE_NOT_FOUND !? */
2412 SetLastWin32Error(ERROR_FILE_NOT_FOUND
);
2417 if(Parent
->Self
== Desktop
)
2420 PWINDOW_OBJECT TopLevelWindow
;
2421 BOOL CheckWindowName
;
2423 /* windows searches through all top-level windows if the parent is the desktop
2426 if((List
= IntWinListChildren(Parent
)))
2432 /* skip handles before and including ChildAfter */
2433 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->Self
));
2436 CheckWindowName
= WindowName
.Length
> 0;
2438 /* search children */
2441 if(!(TopLevelWindow
= IntGetWindowObject(*(phWnd
++))))
2446 /* Do not send WM_GETTEXT messages in the kernel mode version!
2447 The user mode version however calls GetWindowText() which will
2448 send WM_GETTEXT messages to windows belonging to its processes */
2449 if(((!CheckWindowName
|| (CheckWindowName
&& !RtlCompareUnicodeString(&WindowName
, &(TopLevelWindow
->WindowName
), FALSE
))) &&
2450 (!ClassObject
|| (ClassObject
&& (TopLevelWindow
->Class
== ClassObject
))))
2452 ((!CheckWindowName
|| (CheckWindowName
&& !RtlCompareUnicodeString(&WindowName
, &(TopLevelWindow
->WindowName
), FALSE
))) &&
2453 (!ClassObject
|| (ClassObject
&& (TopLevelWindow
->Class
== ClassObject
)))))
2455 Ret
= TopLevelWindow
->Self
;
2456 IntReleaseWindowObject(TopLevelWindow
);
2460 if(IntFindWindow(TopLevelWindow
, NULL
, ClassObject
, &WindowName
))
2462 /* window returns the handle of the top-level window, in case it found
2464 Ret
= TopLevelWindow
->Self
;
2465 IntReleaseWindowObject(TopLevelWindow
);
2469 IntReleaseWindowObject(TopLevelWindow
);
2475 Ret
= IntFindWindow(Parent
, ChildAfter
, ClassObject
, &WindowName
);
2478 if(Ret
== NULL
&& hwndParent
== NULL
&& hwndChildAfter
== NULL
)
2480 /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
2481 search the message-only windows. Should this also be done if
2482 Parent is the desktop window??? */
2483 PWINDOW_OBJECT MsgWindows
;
2485 if((MsgWindows
= IntGetWindowObject(IntGetMessageWindow())))
2487 Ret
= IntFindWindow(MsgWindows
, ChildAfter
, ClassObject
, &WindowName
);
2488 IntReleaseWindowObject(MsgWindows
);
2494 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2495 ExFreePool(ClassName
.Buffer
);
2498 RtlFreeUnicodeString(&WindowName
);
2502 IntReleaseWindowObject(ChildAfter
);
2503 IntReleaseWindowObject(Parent
);
2513 NtUserFlashWindowEx(DWORD Unknown0
)
2525 NtUserGetAncestor(HWND hWnd
, UINT Type
)
2527 PWINDOW_OBJECT Wnd
, WndAncestor
, Parent
;
2530 if (hWnd
== IntGetDesktopWindow())
2535 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2537 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2545 WndAncestor
= IntGetParentObject(Wnd
);
2558 if(!(Parent
= IntGetParentObject(WndAncestor
)))
2562 if(IntIsDesktopWindow(Parent
))
2564 IntReleaseWindowObject(Parent
);
2568 IntReleaseWindowObject(tmp
);
2569 WndAncestor
= Parent
;
2577 IntReferenceWindowObject(WndAncestor
);
2582 Parent
= IntGetParent(WndAncestor
);
2583 IntReleaseWindowObject(Old
);
2588 WndAncestor
= Parent
;
2595 IntReleaseWindowObject(Wnd
);
2600 hWndAncestor
= (WndAncestor
? WndAncestor
->Self
: NULL
);
2601 IntReleaseWindowObject(Wnd
);
2603 if(WndAncestor
&& (WndAncestor
!= Wnd
))
2604 IntReleaseWindowObject(WndAncestor
);
2606 return hWndAncestor
;
2611 * Returns client window rectangle relative to the upper-left corner of client area.
2613 * \param hWnd window handle.
2614 * \param Rect pointer to the buffer where the coordinates are returned.
2621 NtUserGetClientRect(HWND hWnd
, LPRECT Rect
)
2623 PWINDOW_OBJECT WindowObject
;
2626 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
2628 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2632 IntGetClientRect(WindowObject
, &SafeRect
);
2633 IntReleaseWindowObject(WindowObject
);
2635 if(!NT_SUCCESS(MmCopyToCaller(Rect
, &SafeRect
, sizeof(RECT
))))
2647 NtUserGetDesktopWindow()
2649 return IntGetDesktopWindow();
2657 NtUserGetInternalWindowPos(DWORD Unknown0
,
2671 NtUserGetLastActivePopup(HWND hWnd
)
2674 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2675 * not changed anywhere.
2676 * -- Filip, 01/nov/2003
2682 IntAcquireWinLockShared();
2684 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2686 IntReleaseWinLock();
2687 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2691 hWndLastPopup
= Wnd
->hWndLastPopup
;
2693 IntReleaseWinLock();
2695 return hWndLastPopup
;
2704 * The NtUserGetParent function retrieves a handle to the specified window's
2708 * Note that, despite its name, this function can return an owner window
2709 * instead of a parent window.
2716 NtUserGetParent(HWND hWnd
)
2718 PWINDOW_OBJECT Wnd
, WndParent
;
2719 HWND hWndParent
= NULL
;
2721 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2723 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2727 WndParent
= IntGetParent(Wnd
);
2730 hWndParent
= WndParent
->Self
;
2731 IntReleaseWindowObject(WndParent
);
2734 IntReleaseWindowObject(Wnd
);
2742 * The NtUserSetParent function changes the parent window of the specified
2746 * The new parent window and the child window must belong to the same
2747 * application. If the window identified by the hWndChild parameter is
2748 * visible, the system performs the appropriate redrawing and repainting.
2749 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2750 * or WS_POPUP window styles of the window whose parent is being changed.
2757 NtUserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2759 PWINDOW_OBJECT Wnd
= NULL
, WndParent
= NULL
, WndOldParent
;
2760 HWND hWndOldParent
= NULL
;
2762 if (IntIsBroadcastHwnd(hWndChild
) || IntIsBroadcastHwnd(hWndNewParent
))
2764 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2768 if (hWndChild
== IntGetDesktopWindow())
2770 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2776 if (!(WndParent
= IntGetWindowObject(hWndNewParent
)))
2778 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2784 if (!(WndParent
= IntGetWindowObject(IntGetDesktopWindow())))
2786 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2791 if (!(Wnd
= IntGetWindowObject(hWndChild
)))
2793 IntReleaseWindowObject(WndParent
);
2794 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2798 WndOldParent
= IntSetParent(Wnd
, WndParent
);
2802 hWndOldParent
= WndOldParent
->Self
;
2803 IntReleaseWindowObject(WndOldParent
);
2806 IntReleaseWindowObject(Wnd
);
2807 IntReleaseWindowObject(WndParent
);
2809 return hWndOldParent
;
2813 * NtUserGetShellWindow
2815 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
2822 NtUserGetShellWindow()
2824 PWINSTATION_OBJECT WinStaObject
;
2827 NTSTATUS Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
2832 if (!NT_SUCCESS(Status
))
2834 SetLastNtError(Status
);
2838 Ret
= (HWND
)WinStaObject
->ShellWindow
;
2840 ObDereferenceObject(WinStaObject
);
2845 * NtUserSetShellWindowEx
2847 * This is undocumented function to set global shell window. The global
2848 * shell window has special handling of window position.
2855 NtUserSetShellWindowEx(HWND hwndShell
, HWND hwndListView
)
2857 PWINSTATION_OBJECT WinStaObject
;
2859 NTSTATUS Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
2864 if (!NT_SUCCESS(Status
))
2866 SetLastNtError(Status
);
2871 * Test if we are permitted to change the shell window.
2873 if (WinStaObject
->ShellWindow
)
2875 ObDereferenceObject(WinStaObject
);
2880 * Move shell window into background.
2882 if (hwndListView
&& hwndListView
!= hwndShell
)
2885 * Disabled for now to get Explorer working.
2886 * -- Filip, 01/nov/2003
2889 WinPosSetWindowPos(hwndListView
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2892 if (NtUserGetWindowLong(hwndListView
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2894 ObDereferenceObject(WinStaObject
);
2899 if (NtUserGetWindowLong(hwndShell
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2901 ObDereferenceObject(WinStaObject
);
2905 WinPosSetWindowPos(hwndShell
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2907 WinStaObject
->ShellWindow
= hwndShell
;
2908 WinStaObject
->ShellListView
= hwndListView
;
2910 ObDereferenceObject(WinStaObject
);
2915 * NtUserGetSystemMenu
2917 * The NtUserGetSystemMenu function allows the application to access the
2918 * window menu (also known as the system menu or the control menu) for
2919 * copying and modifying.
2923 * Handle to the window that will own a copy of the window menu.
2925 * Specifies the action to be taken. If this parameter is FALSE,
2926 * NtUserGetSystemMenu returns a handle to the copy of the window menu
2927 * currently in use. The copy is initially identical to the window menu
2928 * but it can be modified.
2929 * If this parameter is TRUE, GetSystemMenu resets the window menu back
2930 * to the default state. The previous window menu, if any, is destroyed.
2933 * If the bRevert parameter is FALSE, the return value is a handle to a
2934 * copy of the window menu. If the bRevert parameter is TRUE, the return
2942 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
2945 PWINDOW_OBJECT WindowObject
;
2946 PMENU_OBJECT MenuObject
;
2948 WindowObject
= IntGetWindowObject((HWND
)hWnd
);
2949 if (WindowObject
== NULL
)
2951 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2955 MenuObject
= IntGetSystemMenu(WindowObject
, bRevert
, FALSE
);
2958 Result
= MenuObject
->MenuInfo
.Self
;
2959 IntReleaseMenuObject(MenuObject
);
2962 IntReleaseWindowObject(WindowObject
);
2967 * NtUserSetSystemMenu
2974 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
2976 BOOL Result
= FALSE
;
2977 PWINDOW_OBJECT WindowObject
;
2978 PMENU_OBJECT MenuObject
;
2980 WindowObject
= IntGetWindowObject(hWnd
);
2983 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2990 * Assign new menu handle.
2992 MenuObject
= IntGetMenuObject(hMenu
);
2995 IntReleaseWindowObject(WindowObject
);
2996 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
3000 Result
= IntSetSystemMenu(WindowObject
, MenuObject
);
3002 IntReleaseMenuObject(MenuObject
);
3005 IntReleaseWindowObject(WindowObject
);
3013 * The NtUserGetWindow function retrieves a handle to a window that has the
3014 * specified relationship (Z order or owner) to the specified window.
3021 NtUserGetWindow(HWND hWnd
, UINT Relationship
)
3023 PWINDOW_OBJECT WindowObject
, Parent
;
3024 HWND hWndResult
= NULL
;
3026 if (!(WindowObject
= IntGetWindowObject(hWnd
)))
3028 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3032 switch (Relationship
)
3035 if((Parent
= IntGetParentObject(WindowObject
)))
3037 IntLockRelatives(Parent
);
3038 if (Parent
->FirstChild
)
3039 hWndResult
= Parent
->FirstChild
->Self
;
3040 IntUnLockRelatives(Parent
);
3041 IntReleaseWindowObject(Parent
);
3046 if((Parent
= IntGetParentObject(WindowObject
)))
3048 IntLockRelatives(Parent
);
3049 if (Parent
->LastChild
)
3050 hWndResult
= Parent
->LastChild
->Self
;
3051 IntUnLockRelatives(Parent
);
3052 IntReleaseWindowObject(Parent
);
3057 IntLockRelatives(WindowObject
);
3058 if (WindowObject
->NextSibling
)
3059 hWndResult
= WindowObject
->NextSibling
->Self
;
3060 IntUnLockRelatives(WindowObject
);
3064 IntLockRelatives(WindowObject
);
3065 if (WindowObject
->PrevSibling
)
3066 hWndResult
= WindowObject
->PrevSibling
->Self
;
3067 IntUnLockRelatives(WindowObject
);
3071 IntLockRelatives(WindowObject
);
3072 if((Parent
= IntGetWindowObject(WindowObject
->Owner
)))
3074 hWndResult
= Parent
->Self
;
3075 IntReleaseWindowObject(Parent
);
3077 IntUnLockRelatives(WindowObject
);
3080 IntLockRelatives(WindowObject
);
3081 if (WindowObject
->FirstChild
)
3082 hWndResult
= WindowObject
->FirstChild
->Self
;
3083 IntUnLockRelatives(WindowObject
);
3087 IntReleaseWindowObject(WindowObject
);
3093 * NtUserGetWindowLong
3095 * The NtUserGetWindowLong function retrieves information about the specified
3096 * window. The function also retrieves the 32-bit (long) value at the
3097 * specified offset into the extra window memory.
3104 NtUserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3106 PWINDOW_OBJECT WindowObject
, Parent
;
3109 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3111 WindowObject
= IntGetWindowObject(hWnd
);
3112 if (WindowObject
== NULL
)
3114 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3119 * Only allow CSRSS to mess with the desktop window
3121 if (hWnd
== IntGetDesktopWindow()
3122 && WindowObject
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
3124 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3128 if ((INT
)Index
>= 0)
3130 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
3132 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3135 Result
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
3142 Result
= WindowObject
->ExStyle
;
3146 Result
= WindowObject
->Style
;
3151 Result
= (LONG
) WindowObject
->WndProcA
;
3153 Result
= (LONG
) WindowObject
->WndProcW
;
3157 Result
= (LONG
) WindowObject
->Instance
;
3160 case GWL_HWNDPARENT
:
3161 IntLockRelatives(WindowObject
);
3162 Parent
= IntGetWindowObject(WindowObject
->Parent
);
3163 IntUnLockRelatives(WindowObject
);
3166 if (Parent
&& Parent
->Self
== IntGetDesktopWindow())
3167 Result
= (LONG
) NtUserGetWindow(WindowObject
->Self
, GW_OWNER
);
3169 Result
= (LONG
) Parent
->Self
;
3170 IntReleaseWindowObject(Parent
);
3175 Result
= (LONG
) WindowObject
->IDMenu
;
3179 Result
= WindowObject
->UserData
;
3183 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index
);
3184 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3190 IntReleaseWindowObject(WindowObject
);
3196 * NtUserSetWindowLong
3198 * The NtUserSetWindowLong function changes an attribute of the specified
3199 * window. The function also sets the 32-bit (long) value at the specified
3200 * offset into the extra window memory.
3207 NtUserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3209 PWINDOW_OBJECT WindowObject
, Parent
;
3210 PW32PROCESS Process
;
3211 PWINSTATION_OBJECT WindowStation
;
3215 if (hWnd
== IntGetDesktopWindow())
3217 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3221 WindowObject
= IntGetWindowObject(hWnd
);
3222 if (WindowObject
== NULL
)
3224 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3228 if ((INT
)Index
>= 0)
3230 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
3232 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3233 IntReleaseWindowObject(WindowObject
);
3236 OldValue
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
3237 *((LONG
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
3244 OldValue
= (LONG
) WindowObject
->ExStyle
;
3245 Style
.styleOld
= OldValue
;
3246 Style
.styleNew
= NewValue
;
3249 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3251 Process
= WindowObject
->OwnerThread
->ThreadsProcess
->Win32Process
;
3252 WindowStation
= Process
->WindowStation
;
3255 if (hWnd
== WindowStation
->ShellWindow
|| hWnd
== WindowStation
->ShellListView
)
3256 Style
.styleNew
&= ~WS_EX_TOPMOST
;
3259 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3260 WindowObject
->ExStyle
= (DWORD
)Style
.styleNew
;
3261 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3265 OldValue
= (LONG
) WindowObject
->Style
;
3266 Style
.styleOld
= OldValue
;
3267 Style
.styleNew
= NewValue
;
3268 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_STYLE
, (LPARAM
) &Style
);
3269 WindowObject
->Style
= (DWORD
)Style
.styleNew
;
3270 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_STYLE
, (LPARAM
) &Style
);
3274 /* FIXME: should check if window belongs to current process */
3277 OldValue
= (LONG
) WindowObject
->WndProcA
;
3278 WindowObject
->WndProcA
= (WNDPROC
) NewValue
;
3279 WindowObject
->WndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,FALSE
);
3280 WindowObject
->Unicode
= FALSE
;
3284 OldValue
= (LONG
) WindowObject
->WndProcW
;
3285 WindowObject
->WndProcW
= (WNDPROC
) NewValue
;
3286 WindowObject
->WndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,TRUE
);
3287 WindowObject
->Unicode
= TRUE
;
3292 OldValue
= (LONG
) WindowObject
->Instance
;
3293 WindowObject
->Instance
= (HINSTANCE
) NewValue
;
3296 case GWL_HWNDPARENT
:
3297 Parent
= IntGetParentObject(WindowObject
);
3298 if (Parent
&& (Parent
->Self
== IntGetDesktopWindow()))
3299 OldValue
= (LONG
) IntSetOwner(WindowObject
->Self
, (HWND
) NewValue
);
3301 OldValue
= (LONG
) NtUserSetParent(WindowObject
->Self
, (HWND
) NewValue
);
3303 IntReleaseWindowObject(Parent
);
3307 OldValue
= (LONG
) WindowObject
->IDMenu
;
3308 WindowObject
->IDMenu
= (UINT
) NewValue
;
3312 OldValue
= WindowObject
->UserData
;
3313 WindowObject
->UserData
= NewValue
;
3317 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index
);
3318 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3324 IntReleaseWindowObject(WindowObject
);
3330 * NtUserSetWindowWord
3332 * Legacy function similar to NtUserSetWindowLong.
3339 NtUserSetWindowWord(HWND hWnd
, INT Index
, WORD NewValue
)
3341 PWINDOW_OBJECT WindowObject
;
3348 case GWL_HWNDPARENT
:
3349 return NtUserSetWindowLong(hWnd
, Index
, (UINT
)NewValue
, TRUE
);
3353 SetLastWin32Error(ERROR_INVALID_INDEX
);
3358 WindowObject
= IntGetWindowObject(hWnd
);
3359 if (WindowObject
== NULL
)
3361 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3365 if (Index
> WindowObject
->ExtraDataSize
- sizeof(WORD
))
3367 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3368 IntReleaseWindowObject(WindowObject
);
3372 OldValue
= *((WORD
*)(WindowObject
->ExtraData
+ Index
));
3373 *((WORD
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
3375 IntReleaseWindowObject(WindowObject
);
3384 NtUserGetWindowPlacement(HWND hWnd
,
3385 WINDOWPLACEMENT
*lpwndpl
)
3387 PWINDOW_OBJECT WindowObject
;
3388 PINTERNALPOS InternalPos
;
3390 WINDOWPLACEMENT Safepl
;
3393 WindowObject
= IntGetWindowObject(hWnd
);
3394 if (WindowObject
== NULL
)
3396 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3400 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3401 if(!NT_SUCCESS(Status
))
3403 SetLastNtError(Status
);
3404 IntReleaseWindowObject(WindowObject
);
3407 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3409 IntReleaseWindowObject(WindowObject
);
3414 Safepl
.showCmd
= ((WindowObject
->Flags
& WINDOWOBJECT_RESTOREMAX
) ? SW_MAXIMIZE
: SW_SHOWNORMAL
);
3416 Size
.x
= WindowObject
->WindowRect
.left
;
3417 Size
.y
= WindowObject
->WindowRect
.top
;
3418 InternalPos
= WinPosInitInternalPos(WindowObject
, &Size
,
3419 &WindowObject
->WindowRect
);
3422 Safepl
.rcNormalPosition
= InternalPos
->NormalRect
;
3423 Safepl
.ptMinPosition
= InternalPos
->IconPos
;
3424 Safepl
.ptMaxPosition
= InternalPos
->MaxPos
;
3428 IntReleaseWindowObject(WindowObject
);
3432 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3433 if(!NT_SUCCESS(Status
))
3435 SetLastNtError(Status
);
3436 IntReleaseWindowObject(WindowObject
);
3440 IntReleaseWindowObject(WindowObject
);
3446 * Return the dimension of the window in the screen coordinates.
3447 * \param hWnd window handle.
3448 * \param Rect pointer to the buffer where the coordinates are returned.
3454 NtUserGetWindowRect(HWND hWnd
, LPRECT Rect
)
3459 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3461 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3464 Status
= MmCopyToCaller(Rect
, &Wnd
->WindowRect
, sizeof(RECT
));
3465 if (!NT_SUCCESS(Status
))
3467 IntReleaseWindowObject(Wnd
);
3468 SetLastNtError(Status
);
3472 IntReleaseWindowObject(Wnd
);
3481 NtUserGetWindowThreadProcessId(HWND hWnd
, LPDWORD UnsafePid
)
3486 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3488 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3492 tid
= (DWORD
)IntGetWndThreadId(Wnd
);
3493 pid
= (DWORD
)IntGetWndProcessId(Wnd
);
3495 if (UnsafePid
) MmCopyToCaller(UnsafePid
, &pid
, sizeof(DWORD
));
3505 NtUserLockWindowUpdate(DWORD Unknown0
)
3525 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3526 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3527 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3531 QueryWindow based on KJK::Hyperion and James Tabor.
3533 0 = QWUniqueProcessId
3534 1 = QWUniqueThreadId
3535 4 = QWIsHung Implements IsHungAppWindow found
3538 9 = QWKillWindow When I called this with hWnd ==
3539 DesktopWindow, it shutdown the system
3546 NtUserQueryWindow(HWND hWnd
, DWORD Index
)
3548 PWINDOW_OBJECT Window
= IntGetWindowObject(hWnd
);
3553 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3559 case QUERY_WINDOW_UNIQUE_PROCESS_ID
:
3560 Result
= (DWORD
)IntGetWndProcessId(Window
);
3563 case QUERY_WINDOW_UNIQUE_THREAD_ID
:
3564 Result
= (DWORD
)IntGetWndThreadId(Window
);
3567 case QUERY_WINDOW_ISHUNG
:
3568 Result
= (DWORD
)MsqIsHung(Window
->MessageQueue
);
3572 Result
= (DWORD
)NULL
;
3576 IntReleaseWindowObject(Window
);
3586 NtUserRealChildWindowFromPoint(DWORD Unknown0
,
3600 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe
)
3603 PLIST_ENTRY Current
;
3604 PREGISTERED_MESSAGE NewMsg
, RegMsg
;
3605 UINT Msg
= REGISTERED_MESSAGE_MIN
;
3606 UNICODE_STRING MessageName
;
3609 Status
= MmCopyFromCaller(&MessageName
, MessageNameUnsafe
, sizeof(UNICODE_STRING
));
3610 if (! NT_SUCCESS(Status
))
3612 SetLastNtError(Status
);
3616 NewMsg
= ExAllocatePoolWithTag(PagedPool
,
3617 sizeof(REGISTERED_MESSAGE
) +
3622 SetLastNtError(STATUS_NO_MEMORY
);
3626 Status
= MmCopyFromCaller(NewMsg
->MessageName
, MessageName
.Buffer
, MessageName
.Length
);
3627 if (! NT_SUCCESS(Status
))
3630 SetLastNtError(Status
);
3633 NewMsg
->MessageName
[MessageName
.Length
/ sizeof(WCHAR
)] = L
'\0';
3634 if (wcslen(NewMsg
->MessageName
) != MessageName
.Length
/ sizeof(WCHAR
))
3637 SetLastNtError(STATUS_INVALID_PARAMETER
);
3641 Current
= RegisteredMessageListHead
.Flink
;
3642 while (Current
!= &RegisteredMessageListHead
)
3644 RegMsg
= CONTAINING_RECORD(Current
, REGISTERED_MESSAGE
, ListEntry
);
3645 if (0 == wcscmp(NewMsg
->MessageName
, RegMsg
->MessageName
))
3651 Current
= Current
->Flink
;
3654 if (REGISTERED_MESSAGE_MAX
< Msg
)
3657 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
3661 InsertTailList(&RegisteredMessageListHead
, &(NewMsg
->ListEntry
));
3667 * - There's no need to call MmSafe*, because it should be done in kernel.
3668 * - The passed UNICODE_STRING is expected to be NULL-terminated.
3670 return (UINT
)IntAddAtom(MessageNameUnsafe
->Buffer
);
3679 NtUserSetImeOwnerWindow(DWORD Unknown0
,
3692 NtUserSetInternalWindowPos(DWORD Unknown0
,
3708 NtUserSetLayeredWindowAttributes(DWORD Unknown0
,
3723 NtUserSetLogonNotifyWindow(DWORD Unknown0
)
3740 PWINDOW_OBJECT WindowObject
;
3743 WindowObject
= IntGetWindowObject((HWND
) Wnd
);
3744 if (NULL
== WindowObject
)
3746 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3750 if (! IntSetMenu(WindowObject
, Menu
, &Changed
))
3752 IntReleaseWindowObject(WindowObject
);
3756 IntReleaseWindowObject(WindowObject
);
3758 if (Changed
&& Repaint
)
3760 WinPosSetWindowPos(Wnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
3761 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
3772 NtUserSetWindowFNID(DWORD Unknown0
,
3786 NtUserSetWindowPlacement(HWND hWnd
,
3787 WINDOWPLACEMENT
*lpwndpl
)
3789 PWINDOW_OBJECT WindowObject
;
3790 WINDOWPLACEMENT Safepl
;
3793 WindowObject
= IntGetWindowObject(hWnd
);
3794 if (WindowObject
== NULL
)
3796 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3799 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3800 if(!NT_SUCCESS(Status
))
3802 SetLastNtError(Status
);
3803 IntReleaseWindowObject(WindowObject
);
3806 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3808 IntReleaseWindowObject(WindowObject
);
3812 if ((WindowObject
->Style
& (WS_MAXIMIZE
| WS_MINIMIZE
)) == 0)
3814 WinPosSetWindowPos(WindowObject
->Self
, NULL
,
3815 Safepl
.rcNormalPosition
.left
, Safepl
.rcNormalPosition
.top
,
3816 Safepl
.rcNormalPosition
.right
- Safepl
.rcNormalPosition
.left
,
3817 Safepl
.rcNormalPosition
.bottom
- Safepl
.rcNormalPosition
.top
,
3818 SWP_NOZORDER
| SWP_NOACTIVATE
);
3821 /* FIXME - change window status */
3822 WinPosShowWindow(WindowObject
->Self
, Safepl
.showCmd
);
3824 if (WindowObject
->InternalPos
== NULL
)
3825 WindowObject
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
3826 WindowObject
->InternalPos
->NormalRect
= Safepl
.rcNormalPosition
;
3827 WindowObject
->InternalPos
->IconPos
= Safepl
.ptMinPosition
;
3828 WindowObject
->InternalPos
->MaxPos
= Safepl
.ptMaxPosition
;
3830 IntReleaseWindowObject(WindowObject
);
3841 HWND hWndInsertAfter
,
3848 return WinPosSetWindowPos(hWnd
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3853 IntGetWindowRgn(HWND hWnd
, HRGN hRgn
)
3856 PWINDOW_OBJECT WindowObject
;
3860 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
3862 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3867 IntReleaseWindowObject(WindowObject
);
3871 /* Create a new window region using the window rectangle */
3872 VisRgn
= UnsafeIntCreateRectRgnIndirect(&WindowObject
->WindowRect
);
3873 NtGdiOffsetRgn(VisRgn
, -WindowObject
->WindowRect
.left
, -WindowObject
->WindowRect
.top
);
3874 /* if there's a region assigned to the window, combine them both */
3875 if(WindowObject
->WindowRegion
&& !(WindowObject
->Style
& WS_MINIMIZE
))
3876 NtGdiCombineRgn(VisRgn
, VisRgn
, WindowObject
->WindowRegion
, RGN_AND
);
3877 /* Copy the region into hRgn */
3878 NtGdiCombineRgn(hRgn
, VisRgn
, NULL
, RGN_COPY
);
3880 if((pRgn
= RGNDATA_LockRgn(hRgn
)))
3882 Ret
= pRgn
->rdh
.iType
;
3883 RGNDATA_UnlockRgn(hRgn
);
3888 NtGdiDeleteObject(VisRgn
);
3890 IntReleaseWindowObject(WindowObject
);
3895 IntGetWindowRgnBox(HWND hWnd
, RECT
*Rect
)
3898 PWINDOW_OBJECT WindowObject
;
3902 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
3904 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3909 IntReleaseWindowObject(WindowObject
);
3913 /* Create a new window region using the window rectangle */
3914 VisRgn
= UnsafeIntCreateRectRgnIndirect(&WindowObject
->WindowRect
);
3915 NtGdiOffsetRgn(VisRgn
, -WindowObject
->WindowRect
.left
, -WindowObject
->WindowRect
.top
);
3916 /* if there's a region assigned to the window, combine them both */
3917 if(WindowObject
->WindowRegion
&& !(WindowObject
->Style
& WS_MINIMIZE
))
3918 NtGdiCombineRgn(VisRgn
, VisRgn
, WindowObject
->WindowRegion
, RGN_AND
);
3920 if((pRgn
= RGNDATA_LockRgn(VisRgn
)))
3922 Ret
= pRgn
->rdh
.iType
;
3923 *Rect
= pRgn
->rdh
.rcBound
;
3924 RGNDATA_UnlockRgn(VisRgn
);
3929 NtGdiDeleteObject(VisRgn
);
3931 IntReleaseWindowObject(WindowObject
);
3945 PWINDOW_OBJECT WindowObject
;
3947 WindowObject
= IntGetWindowObject(hWnd
);
3948 if (WindowObject
== NULL
)
3950 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3954 /* FIXME - Verify if hRgn is a valid handle!!!!
3955 Propably make this operation thread-safe, but maybe it's not necessary */
3957 if(WindowObject
->WindowRegion
)
3959 /* Delete no longer needed region handle */
3960 NtGdiDeleteObject(WindowObject
->WindowRegion
);
3962 WindowObject
->WindowRegion
= hRgn
;
3964 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
3968 IntRedrawWindow(WindowObject
, NULL
, NULL
, RDW_INVALIDATE
);
3971 IntReleaseWindowObject(WindowObject
);
3980 NtUserShowWindow(HWND hWnd
,
3983 return WinPosShowWindow(hWnd
, nCmdShow
);
3991 NtUserShowWindowAsync(DWORD Unknown0
,
4004 NtUserUpdateLayeredWindow(DWORD Unknown0
,
4024 NtUserValidateRect(HWND hWnd
, const RECT
* Rect
)
4026 return (VOID
)NtUserRedrawWindow(hWnd
, Rect
, 0, RDW_VALIDATE
| RDW_NOCHILDREN
);
4034 NtUserWindowFromPoint(LONG X
, LONG Y
)
4038 PWINDOW_OBJECT DesktopWindow
, Window
= NULL
;
4040 if ((DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow())))
4047 Hit
= WinPosWindowFromPoint(DesktopWindow
, PsGetWin32Thread()->MessageQueue
, &pt
, &Window
);
4052 IntReleaseWindowObject(Window
);
4053 IntReleaseWindowObject(DesktopWindow
);
4057 IntReleaseWindowObject(DesktopWindow
);
4067 * Undocumented function that is called from DefWindowProc to set
4075 NtUserDefSetText(HWND WindowHandle
, PUNICODE_STRING WindowText
)
4077 PWINDOW_OBJECT WindowObject
;
4078 UNICODE_STRING SafeText
;
4081 WindowObject
= IntGetWindowObject(WindowHandle
);
4084 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4090 Status
= IntSafeCopyUnicodeString(&SafeText
, WindowText
);
4091 if(!NT_SUCCESS(Status
))
4093 SetLastNtError(Status
);
4094 IntReleaseWindowObject(WindowObject
);
4100 RtlInitUnicodeString(&SafeText
, NULL
);
4103 /* FIXME - do this thread-safe! otherwise one could crash here! */
4104 RtlFreeUnicodeString(&WindowObject
->WindowName
);
4106 WindowObject
->WindowName
= SafeText
;
4108 IntReleaseWindowObject(WindowObject
);
4113 * NtUserInternalGetWindowText
4120 NtUserInternalGetWindowText(HWND hWnd
, LPWSTR lpString
, INT nMaxCount
)
4122 PWINDOW_OBJECT WindowObject
;
4126 if(lpString
&& (nMaxCount
<= 1))
4128 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
4132 WindowObject
= IntGetWindowObject(hWnd
);
4135 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4139 /* FIXME - do this thread-safe! otherwise one could crash here! */
4140 Result
= WindowObject
->WindowName
.Length
/ sizeof(WCHAR
);
4143 const WCHAR Terminator
= L
'\0';
4145 WCHAR
*Buffer
= (WCHAR
*)lpString
;
4147 Copy
= min(nMaxCount
- 1, Result
);
4150 Status
= MmCopyToCaller(Buffer
, WindowObject
->WindowName
.Buffer
, Copy
* sizeof(WCHAR
));
4151 if(!NT_SUCCESS(Status
))
4153 SetLastNtError(Status
);
4154 IntReleaseWindowObject(WindowObject
);
4160 Status
= MmCopyToCaller(Buffer
, &Terminator
, sizeof(WCHAR
));
4161 if(!NT_SUCCESS(Status
))
4163 SetLastNtError(Status
);
4164 IntReleaseWindowObject(WindowObject
);
4171 IntReleaseWindowObject(WindowObject
);
4176 NtUserDereferenceWndProcHandle(WNDPROC wpHandle
, WndProcHandle
*Data
)
4178 WndProcHandle Entry
;
4179 if (((DWORD
)wpHandle
& 0xFFFF0000) == 0xFFFF0000)
4181 Entry
= WndProcHandlesArray
[(DWORD
)wpHandle
& 0x0000FFFF];
4182 Data
->WindowProc
= Entry
.WindowProc
;
4183 Data
->IsUnicode
= Entry
.IsUnicode
;
4184 Data
->ProcessID
= Entry
.ProcessID
;
4193 IntAddWndProcHandle(WNDPROC WindowProc
, BOOL IsUnicode
)
4198 WndProcHandle
*OldArray
;
4201 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4203 if (WndProcHandlesArray
[i
].WindowProc
== NULL
)
4211 OldArray
= WndProcHandlesArray
;
4212 OldArraySize
= WndProcHandlesArraySize
;
4213 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,(OldArraySize
+ WPH_SIZE
) * sizeof(WndProcHandle
), TAG_WINPROCLST
);
4214 WndProcHandlesArraySize
= OldArraySize
+ WPH_SIZE
;
4215 RtlCopyMemory(WndProcHandlesArray
,OldArray
,OldArraySize
* sizeof(WndProcHandle
));
4216 ExFreePool(OldArray
);
4217 FreeSpot
= OldArraySize
+ 1;
4219 WndProcHandlesArray
[FreeSpot
].WindowProc
= WindowProc
;
4220 WndProcHandlesArray
[FreeSpot
].IsUnicode
= IsUnicode
;
4221 WndProcHandlesArray
[FreeSpot
].ProcessID
= PsGetCurrentProcessId();
4222 return FreeSpot
+ 0xFFFF0000;
4226 IntRemoveWndProcHandle(WNDPROC Handle
)
4229 position
= (DWORD
)Handle
& 0x0000FFFF;
4230 if (position
> WndProcHandlesArraySize
)
4234 WndProcHandlesArray
[position
].WindowProc
= NULL
;
4235 WndProcHandlesArray
[position
].IsUnicode
= FALSE
;
4236 WndProcHandlesArray
[position
].ProcessID
= NULL
;
4241 IntRemoveProcessWndProcHandles(HANDLE ProcessID
)
4244 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4246 if (WndProcHandlesArray
[i
].ProcessID
== ProcessID
)
4248 WndProcHandlesArray
[i
].WindowProc
= NULL
;
4249 WndProcHandlesArray
[i
].IsUnicode
= FALSE
;
4250 WndProcHandlesArray
[i
].ProcessID
= NULL
;