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.257 2004/12/13 00:11:59 weiden Exp $
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
24 * FILE: subsys/win32k/ntuser/window.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
27 * 06-06-2001 CSH Created
29 /* INCLUDES ******************************************************************/
32 static WndProcHandle
*WndProcHandlesArray
= 0;
33 static WORD WndProcHandlesArraySize
= 0;
34 #define WPH_SIZE 0x40 /* the size to add to the WndProcHandle array each time */
36 /* dialog resources appear to pass this in 16 bits, handle them properly */
37 #define CW_USEDEFAULT16 (0x8000)
39 #define POINT_IN_RECT(p, r) (((r.bottom >= p.y) && (r.top <= p.y))&&((r.left <= p.x )&&( r.right >= p.x )))
41 /* PRIVATE FUNCTIONS **********************************************************/
46 * Initialize windowing implementation.
52 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,WPH_SIZE
* sizeof(WndProcHandle
), TAG_WINPROCLST
);
53 WndProcHandlesArraySize
= WPH_SIZE
;
54 return STATUS_SUCCESS
;
60 * Cleanup windowing implementation.
64 CleanupWindowImpl(VOID
)
66 ExFreePool(WndProcHandlesArray
);
67 WndProcHandlesArray
= 0;
68 WndProcHandlesArraySize
= 0;
69 return STATUS_SUCCESS
;
72 /* HELPER FUNCTIONS ***********************************************************/
77 * The function determines whether the specified window handle identifies
82 * Handle to the window to test.
85 * If the window handle identifies an existing window, the return value
86 * is TRUE. If the window handle does not identify an existing window,
87 * the return value is FALSE.
91 IntIsWindow(HWND hWnd
)
93 PWINDOW_OBJECT Window
;
95 if (!(Window
= IntGetWindowObject(hWnd
)))
98 IntReleaseWindowObject(Window
);
103 * IntGetProcessWindowObject
105 * Get window object from handle of specified process.
108 PWINDOW_OBJECT FASTCALL
109 IntGetProcessWindowObject(PW32THREAD Thread
, HWND hWnd
)
111 PWINDOW_OBJECT WindowObject
;
114 if(Thread
->Desktop
!= NULL
)
116 Status
= ObmReferenceObjectByHandle(Thread
->Desktop
->WindowStation
->HandleTable
,
117 hWnd
, otWindow
, (PVOID
*)&WindowObject
);
118 if (NT_SUCCESS(Status
))
127 PWINDOW_OBJECT FASTCALL
128 IntGetParent(PWINDOW_OBJECT Wnd
)
132 if (Wnd
->Style
& WS_POPUP
)
134 IntLockRelatives(Wnd
);
136 IntUnLockRelatives(Wnd
);
137 return IntGetWindowObject(hWnd
);
139 else if (Wnd
->Style
& WS_CHILD
)
141 IntLockRelatives(Wnd
);
143 IntUnLockRelatives(Wnd
);
144 return IntGetWindowObject(hWnd
);
151 PWINDOW_OBJECT FASTCALL
152 IntGetParentObject(PWINDOW_OBJECT Wnd
)
156 IntLockRelatives(Wnd
);
157 hParent
= Wnd
->Parent
;
158 IntUnLockRelatives(Wnd
);
159 return IntGetWindowObject(hParent
);
165 * Compile a list of all child window handles from given window.
168 * This function is similar to Wine WIN_ListChildren. The caller
169 * must free the returned list with ExFreePool.
173 IntWinListChildren(PWINDOW_OBJECT Window
)
175 PWINDOW_OBJECT Child
;
177 UINT Index
, NumChildren
= 0;
179 IntLockRelatives(Window
);
181 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
184 List
= ExAllocatePoolWithTag(PagedPool
, (NumChildren
+ 1) * sizeof(HWND
), TAG_WINLIST
);
187 DPRINT1("Failed to allocate memory for children array\n");
188 IntUnLockRelatives(Window
);
189 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
192 for (Child
= Window
->FirstChild
, Index
= 0;
194 Child
= Child
->NextSibling
, ++Index
)
195 List
[Index
] = Child
->Self
;
198 IntUnLockRelatives(Window
);
203 /***********************************************************************
206 static void IntSendDestroyMsg(HWND Wnd
)
211 if (GetGUIThreadInfo(GetCurrentThreadId(), &info
))
213 if (Wnd
== info
.hwndCaret
)
221 * Send the WM_DESTROY to the window.
223 IntSendMessage(Wnd
, WM_DESTROY
, 0, 0);
226 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
227 * make sure that the window still exists when we come back.
235 if (!(pWndArray
= WIN_ListChildren( hwnd
))) return;
237 /* start from the end (FIXME: is this needed?) */
238 for (i
= 0; pWndArray
[i
]; i
++) ;
242 if (IsWindow( pWndArray
[i
] )) WIN_SendDestroyMsg( pWndArray
[i
] );
244 HeapFree(GetProcessHeap(), 0, pWndArray
);
248 DPRINT("destroyed itself while in WM_DESTROY!\n");
253 /***********************************************************************
256 * Destroy storage associated to a window. "Internals" p.358
258 static LRESULT
IntDestroyWindow(PWINDOW_OBJECT Window
,
259 PW32PROCESS ProcessData
,
260 PW32THREAD ThreadData
,
261 BOOLEAN SendMessages
)
265 PWINDOW_OBJECT Child
;
267 BOOLEAN BelongsToThreadData
;
271 RemoveTimersWindow(Window
->Self
);
273 IntLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
274 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
276 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
277 DPRINT("Tried to call IntDestroyWindow() twice\n");
280 Window
->Status
|= WINDOWSTATUS_DESTROYING
;
281 Window
->Flags
&= ~WS_VISIBLE
;
282 /* remove the window already at this point from the thread window list so we
283 don't get into trouble when destroying the thread windows while we're still
284 in IntDestroyWindow() */
285 RemoveEntryList(&Window
->ThreadListEntry
);
286 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
288 BelongsToThreadData
= IntWndBelongsToThread(Window
, ThreadData
);
292 /* Send destroy messages */
293 IntSendDestroyMsg(Window
->Self
);
296 /* free child windows */
297 Children
= IntWinListChildren(Window
);
300 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
302 if ((Child
= IntGetWindowObject(*ChildHandle
)))
304 if(!IntWndBelongsToThread(Child
, ThreadData
))
306 /* send WM_DESTROY messages to windows not belonging to the same thread */
307 IntSendDestroyMsg(Child
->Self
);
310 IntDestroyWindow(Child
, ProcessData
, ThreadData
, SendMessages
);
311 IntReleaseWindowObject(Child
);
314 ExFreePool(Children
);
320 * Clear the update region to make sure no WM_PAINT messages will be
321 * generated for this window while processing the WM_NCDESTROY.
323 IntRedrawWindow(Window
, NULL
, 0,
324 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
|
325 RDW_NOINTERNALPAINT
| RDW_NOCHILDREN
);
326 if(BelongsToThreadData
)
327 IntSendMessage(Window
->Self
, WM_NCDESTROY
, 0, 0);
330 /* flush the message queue */
331 MsqRemoveWindowMessagesFromQueue(Window
);
333 /* from now on no messages can be sent to this window anymore */
334 IntLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
335 Window
->Status
|= WINDOWSTATUS_DESTROYED
;
336 /* don't remove the WINDOWSTATUS_DESTROYING bit */
337 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
339 /* reset shell window handles */
340 if(ThreadData
->Desktop
)
342 if (Window
->Self
== ThreadData
->Desktop
->WindowStation
->ShellWindow
)
343 ThreadData
->Desktop
->WindowStation
->ShellWindow
= NULL
;
345 if (Window
->Self
== ThreadData
->Desktop
->WindowStation
->ShellListView
)
346 ThreadData
->Desktop
->WindowStation
->ShellListView
= NULL
;
349 /* Unregister hot keys */
350 UnregisterWindowHotKeys (Window
);
352 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
355 WinPosCheckInternalPos(Window
->Self
);
356 if (Window
->Self
== GetCapture())
361 /* free resources associated with the window */
362 TIMER_RemoveWindowTimers(Window
->Self
);
365 if (!(Window
->Style
& WS_CHILD
) && Window
->IDMenu
366 && (Menu
= IntGetMenuObject((HMENU
)Window
->IDMenu
)))
368 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
370 IntReleaseMenuObject(Menu
);
373 if(Window
->SystemMenu
374 && (Menu
= IntGetMenuObject(Window
->SystemMenu
)))
376 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
377 Window
->SystemMenu
= (HMENU
)0;
378 IntReleaseMenuObject(Menu
);
381 DceFreeWindowDCE(Window
); /* Always do this to catch orphaned DCs */
383 WINPROC_FreeProc(Window
->winproc
, WIN_PROC_WINDOW
);
384 CLASS_RemoveWindow(Window
->Class
);
387 IntUnlinkWindow(Window
);
389 IntReferenceWindowObject(Window
);
390 ObmCloseHandle(ThreadData
->Desktop
->WindowStation
->HandleTable
, Window
->Self
);
392 IntDestroyScrollBars(Window
);
394 /* remove the window from the class object */
395 IntLockClassWindows(Window
->Class
);
396 RemoveEntryList(&Window
->ClassListEntry
);
397 IntUnLockClassWindows(Window
->Class
);
399 /* dereference the class */
400 ClassDereferenceObject(Window
->Class
);
401 Window
->Class
= NULL
;
403 if(Window
->WindowRegion
)
405 NtGdiDeleteObject(Window
->WindowRegion
);
408 RtlFreeUnicodeString(&Window
->WindowName
);
410 IntReleaseWindowObject(Window
);
416 IntGetWindowBorderMeasures(PWINDOW_OBJECT WindowObject
, UINT
*cx
, UINT
*cy
)
418 if(HAS_DLGFRAME(WindowObject
->Style
, WindowObject
->ExStyle
) && !(WindowObject
->Style
& WS_MINIMIZE
))
420 *cx
= NtUserGetSystemMetrics(SM_CXDLGFRAME
);
421 *cy
= NtUserGetSystemMetrics(SM_CYDLGFRAME
);
425 if(HAS_THICKFRAME(WindowObject
->Style
, WindowObject
->ExStyle
)&& !(WindowObject
->Style
& WS_MINIMIZE
))
427 *cx
= NtUserGetSystemMetrics(SM_CXFRAME
);
428 *cy
= NtUserGetSystemMetrics(SM_CYFRAME
);
430 else if(HAS_THINFRAME(WindowObject
->Style
, WindowObject
->ExStyle
))
432 *cx
= NtUserGetSystemMetrics(SM_CXBORDER
);
433 *cy
= NtUserGetSystemMetrics(SM_CYBORDER
);
443 IntGetWindowInfo(PWINDOW_OBJECT WindowObject
, PWINDOWINFO pwi
)
445 pwi
->cbSize
= sizeof(WINDOWINFO
);
446 pwi
->rcWindow
= WindowObject
->WindowRect
;
447 pwi
->rcClient
= WindowObject
->ClientRect
;
448 pwi
->dwStyle
= WindowObject
->Style
;
449 pwi
->dwExStyle
= WindowObject
->ExStyle
;
450 pwi
->dwWindowStatus
= (NtUserGetForegroundWindow() == WindowObject
->Self
); /* WS_ACTIVECAPTION */
451 IntGetWindowBorderMeasures(WindowObject
, &pwi
->cxWindowBorders
, &pwi
->cyWindowBorders
);
452 pwi
->atomWindowType
= (WindowObject
->Class
? WindowObject
->Class
->Atom
: 0);
453 pwi
->wCreatorVersion
= 0x400; /* FIXME - return a real version number */
459 PWINDOW_OBJECT WindowObject
,
463 PMENU_OBJECT OldMenuObject
, NewMenuObject
= NULL
;
465 *Changed
= (WindowObject
->IDMenu
!= (UINT
) Menu
);
471 if (0 != WindowObject
->IDMenu
)
473 OldMenuObject
= IntGetMenuObject((HMENU
) WindowObject
->IDMenu
);
474 ASSERT(NULL
== OldMenuObject
|| OldMenuObject
->MenuInfo
.Wnd
== WindowObject
->Self
);
478 OldMenuObject
= NULL
;
483 NewMenuObject
= IntGetMenuObject(Menu
);
484 if (NULL
== NewMenuObject
)
486 if (NULL
!= OldMenuObject
)
488 IntReleaseMenuObject(OldMenuObject
);
490 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
493 if (NULL
!= NewMenuObject
->MenuInfo
.Wnd
)
495 /* Can't use the same menu for two windows */
496 if (NULL
!= OldMenuObject
)
498 IntReleaseMenuObject(OldMenuObject
);
500 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
506 WindowObject
->IDMenu
= (UINT
) Menu
;
507 if (NULL
!= NewMenuObject
)
509 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
510 IntReleaseMenuObject(NewMenuObject
);
512 if (NULL
!= OldMenuObject
)
514 OldMenuObject
->MenuInfo
.Wnd
= NULL
;
515 IntReleaseMenuObject(OldMenuObject
);
522 /* INTERNAL ******************************************************************/
526 DestroyThreadWindows(struct _ETHREAD
*Thread
)
529 PW32PROCESS Win32Process
;
530 PW32THREAD Win32Thread
;
531 PWINDOW_OBJECT
*List
, *pWnd
;
534 Win32Thread
= Thread
->Tcb
.Win32Thread
;
535 Win32Process
= Thread
->ThreadsProcess
->Win32Process
;
537 IntLockThreadWindows(Win32Thread
);
538 Current
= Win32Thread
->WindowListHead
.Flink
;
539 while (Current
!= &(Win32Thread
->WindowListHead
))
542 Current
= Current
->Flink
;
547 List
= ExAllocatePool(PagedPool
, (Cnt
+ 1) * sizeof(PWINDOW_OBJECT
));
550 DPRINT("Not enough memory to allocate window handle list\n");
551 IntUnLockThreadWindows(Win32Thread
);
555 Current
= Win32Thread
->WindowListHead
.Flink
;
556 while (Current
!= &(Win32Thread
->WindowListHead
))
558 *pWnd
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
559 IntReferenceWindowObject(*pWnd
);
561 Current
= Current
->Flink
;
563 IntUnLockThreadWindows(Win32Thread
);
566 for(pWnd
= List
; *pWnd
; pWnd
++)
568 NtUserDestroyWindow((*pWnd
)->Self
);
569 IntReleaseWindowObject(*pWnd
);
575 IntUnLockThreadWindows(Win32Thread
);
581 * Returns client window rectangle relative to the upper-left corner of client area.
583 * \note Does not check the validity of the parameters
586 IntGetClientRect(PWINDOW_OBJECT WindowObject
, PRECT Rect
)
588 ASSERT( WindowObject
);
591 Rect
->left
= Rect
->top
= 0;
592 Rect
->right
= WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
;
593 Rect
->bottom
= WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
;
599 IntGetFocusWindow(VOID
)
601 PUSER_MESSAGE_QUEUE Queue
;
602 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
607 Queue
= (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
612 return(Queue
->FocusWindow
);
616 PMENU_OBJECT FASTCALL
617 IntGetSystemMenu(PWINDOW_OBJECT WindowObject
, BOOL bRevert
, BOOL RetMenu
)
619 PMENU_OBJECT MenuObject
, NewMenuObject
, SysMenuObject
, ret
= NULL
;
620 PW32THREAD W32Thread
;
621 HMENU NewMenu
, SysMenu
;
622 ROSMENUITEMINFO ItemInfo
;
626 W32Thread
= PsGetWin32Thread();
628 if(!W32Thread
->Desktop
)
631 if(WindowObject
->SystemMenu
)
633 MenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
636 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
637 WindowObject
->SystemMenu
= (HMENU
)0;
638 IntReleaseMenuObject(MenuObject
);
642 if(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
)
644 /* clone system menu */
645 MenuObject
= IntGetMenuObject(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
);
649 NewMenuObject
= IntCloneMenu(MenuObject
);
652 WindowObject
->SystemMenu
= NewMenuObject
->MenuInfo
.Self
;
653 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
654 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
656 //IntReleaseMenuObject(NewMenuObject);
658 IntReleaseMenuObject(MenuObject
);
662 SysMenu
= NtUserCreateMenu(FALSE
);
667 SysMenuObject
= IntGetMenuObject(SysMenu
);
668 if (NULL
== SysMenuObject
)
670 NtUserDestroyMenu(SysMenu
);
673 SysMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
674 SysMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
675 NewMenu
= IntLoadSysMenuTemplate();
678 IntReleaseMenuObject(SysMenuObject
);
679 NtUserDestroyMenu(SysMenu
);
682 MenuObject
= IntGetMenuObject(NewMenu
);
685 IntReleaseMenuObject(SysMenuObject
);
686 NtUserDestroyMenu(SysMenu
);
690 NewMenuObject
= IntCloneMenu(MenuObject
);
693 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
| MF_POPUP
;
694 IntReleaseMenuObject(NewMenuObject
);
695 NtUserSetMenuDefaultItem(NewMenuObject
->MenuInfo
.Self
, SC_CLOSE
, FALSE
);
697 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
698 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
699 ItemInfo
.fType
= MF_POPUP
;
700 ItemInfo
.fState
= MFS_ENABLED
;
701 ItemInfo
.dwTypeData
= NULL
;
703 ItemInfo
.hSubMenu
= NewMenuObject
->MenuInfo
.Self
;
704 IntInsertMenuItem(SysMenuObject
, (UINT
) -1, TRUE
, &ItemInfo
);
706 WindowObject
->SystemMenu
= SysMenuObject
->MenuInfo
.Self
;
710 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
711 IntReleaseMenuObject(MenuObject
);
720 if(WindowObject
->SystemMenu
)
721 return IntGetMenuObject((HMENU
)WindowObject
->SystemMenu
);
729 IntIsChildWindow(HWND Parent
, HWND Child
)
731 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
733 if(!(BaseWindow
= IntGetWindowObject(Child
)))
741 if (Window
->Self
== Parent
)
743 if(Window
!= BaseWindow
)
744 IntReleaseWindowObject(Window
);
745 IntReleaseWindowObject(BaseWindow
);
748 if(!(Window
->Style
& WS_CHILD
))
750 if(Window
!= BaseWindow
)
751 IntReleaseWindowObject(Window
);
755 Window
= IntGetParentObject(Window
);
756 if(Old
!= BaseWindow
)
757 IntReleaseWindowObject(Old
);
760 IntReleaseWindowObject(BaseWindow
);
765 IntIsWindowVisible(HWND hWnd
)
767 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
769 if(!(BaseWindow
= IntGetWindowObject(hWnd
)))
777 if(!(Window
->Style
& WS_CHILD
))
781 if(!(Window
->Style
& WS_VISIBLE
))
783 if(Window
!= BaseWindow
)
784 IntReleaseWindowObject(Window
);
785 IntReleaseWindowObject(BaseWindow
);
789 Window
= IntGetParentObject(Window
);
790 if(Old
!= BaseWindow
)
791 IntReleaseWindowObject(Old
);
796 if(Window
->Style
& WS_VISIBLE
)
798 if(Window
!= BaseWindow
)
799 IntReleaseWindowObject(Window
);
800 IntReleaseWindowObject(BaseWindow
);
803 if(Window
!= BaseWindow
)
804 IntReleaseWindowObject(Window
);
806 IntReleaseWindowObject(BaseWindow
);
811 /* link the window into siblings and parent. children are kept in place. */
815 PWINDOW_OBJECT WndParent
,
816 PWINDOW_OBJECT WndPrevSibling
/* set to NULL if top sibling */
819 PWINDOW_OBJECT Parent
;
821 IntLockRelatives(Wnd
);
822 Wnd
->Parent
= WndParent
->Self
;
823 if ((Wnd
->PrevSibling
= WndPrevSibling
))
825 /* link after WndPrevSibling */
826 if ((Wnd
->NextSibling
= WndPrevSibling
->NextSibling
))
827 Wnd
->NextSibling
->PrevSibling
= Wnd
;
828 else if ((Parent
= IntGetWindowObject(Wnd
->Parent
)))
830 IntLockRelatives(Parent
);
831 if(Parent
->LastChild
== WndPrevSibling
)
832 Parent
->LastChild
= Wnd
;
833 IntUnLockRelatives(Parent
);
834 IntReleaseWindowObject(Parent
);
836 Wnd
->PrevSibling
->NextSibling
= Wnd
;
841 Parent
= IntGetWindowObject(Wnd
->Parent
);
842 if ((Wnd
->NextSibling
= WndParent
->FirstChild
))
843 Wnd
->NextSibling
->PrevSibling
= Wnd
;
846 IntLockRelatives(Parent
);
847 Parent
->LastChild
= Wnd
;
848 Parent
->FirstChild
= Wnd
;
849 IntUnLockRelatives(Parent
);
850 IntReleaseWindowObject(Parent
);
851 IntUnLockRelatives(Wnd
);
856 IntLockRelatives(Parent
);
857 Parent
->FirstChild
= Wnd
;
858 IntUnLockRelatives(Parent
);
859 IntReleaseWindowObject(Parent
);
862 IntUnLockRelatives(Wnd
);
866 IntSetOwner(HWND hWnd
, HWND hWndNewOwner
)
868 PWINDOW_OBJECT Wnd
, WndOldOwner
, WndNewOwner
;
871 Wnd
= IntGetWindowObject(hWnd
);
875 IntLockRelatives(Wnd
);
876 WndOldOwner
= IntGetWindowObject(Wnd
->Owner
);
879 ret
= WndOldOwner
->Self
;
880 IntReleaseWindowObject(WndOldOwner
);
887 if((WndNewOwner
= IntGetWindowObject(hWndNewOwner
)))
889 Wnd
->Owner
= hWndNewOwner
;
890 IntReleaseWindowObject(WndNewOwner
);
895 IntUnLockRelatives(Wnd
);
896 IntReleaseWindowObject(Wnd
);
900 PWINDOW_OBJECT FASTCALL
901 IntSetParent(PWINDOW_OBJECT Wnd
, PWINDOW_OBJECT WndNewParent
)
903 PWINDOW_OBJECT WndOldParent
, Sibling
, InsertAfter
;
904 HWND hWnd
, hWndNewParent
, hWndOldParent
;
909 ASSERT(WndNewParent
);
912 hWndNewParent
= WndNewParent
->Self
;
915 * Windows hides the window first, then shows it again
916 * including the WM_SHOWWINDOW messages and all
918 WasVisible
= WinPosShowWindow(hWnd
, SW_HIDE
);
920 /* Validate that window and parent still exist */
921 if (!IntIsWindow(hWnd
) || !IntIsWindow(hWndNewParent
))
924 /* Window must belong to current process */
925 if (Wnd
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
928 WndOldParent
= IntGetParentObject(Wnd
);
929 hWndOldParent
= (WndOldParent
? WndOldParent
->Self
: NULL
);
931 if (WndNewParent
!= WndOldParent
)
933 IntUnlinkWindow(Wnd
);
935 if (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
))
937 /* Not a TOPMOST window, put after TOPMOSTs of new parent */
938 IntLockRelatives(WndNewParent
);
939 Sibling
= WndNewParent
->FirstChild
;
940 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
942 InsertAfter
= Sibling
;
943 Sibling
= Sibling
->NextSibling
;
945 IntUnLockRelatives(WndNewParent
);
947 if (NULL
== InsertAfter
)
949 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
953 IntReferenceWindowObject(InsertAfter
);
954 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
955 IntReleaseWindowObject(InsertAfter
);
958 if (WndNewParent
->Self
!= IntGetDesktopWindow()) /* a child window */
960 if (!(Wnd
->Style
& WS_CHILD
))
962 //if ( Wnd->Menu ) DestroyMenu ( Wnd->menu );
963 IntSetMenu(Wnd
, NULL
, &MenuChanged
);
969 * SetParent additionally needs to make hwnd the top window
970 * in the z-order and send the expected WM_WINDOWPOSCHANGING and
971 * WM_WINDOWPOSCHANGED notification messages.
973 WinPosSetWindowPos(hWnd
, (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOP
: HWND_TOPMOST
),
974 0, 0, 0, 0, SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
975 | (WasVisible
? SWP_SHOWWINDOW
: 0));
978 * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
979 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
983 * Validate that the old parent still exist, since it migth have been
984 * destroyed during the last callbacks to user-mode
988 if(!IntIsWindow(WndOldParent
->Self
))
990 IntReleaseWindowObject(WndOldParent
);
994 /* don't dereference the window object here, it must be done by the caller
1002 IntSetSystemMenu(PWINDOW_OBJECT WindowObject
, PMENU_OBJECT MenuObject
)
1004 PMENU_OBJECT OldMenuObject
;
1005 if(WindowObject
->SystemMenu
)
1007 OldMenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
1010 OldMenuObject
->MenuInfo
.Flags
&= ~ MF_SYSMENU
;
1011 IntReleaseMenuObject(OldMenuObject
);
1017 /* FIXME check window style, propably return FALSE ? */
1018 WindowObject
->SystemMenu
= MenuObject
->MenuInfo
.Self
;
1019 MenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
1022 WindowObject
->SystemMenu
= (HMENU
)0;
1028 /* unlink the window from siblings and parent. children are kept in place. */
1030 IntUnlinkWindow(PWINDOW_OBJECT Wnd
)
1032 PWINDOW_OBJECT WndParent
;
1034 IntLockRelatives(Wnd
);
1035 if((WndParent
= IntGetWindowObject(Wnd
->Parent
)))
1037 IntLockRelatives(WndParent
);
1040 if (Wnd
->NextSibling
) Wnd
->NextSibling
->PrevSibling
= Wnd
->PrevSibling
;
1041 else if (WndParent
&& WndParent
->LastChild
== Wnd
) WndParent
->LastChild
= Wnd
->PrevSibling
;
1043 if (Wnd
->PrevSibling
) Wnd
->PrevSibling
->NextSibling
= Wnd
->NextSibling
;
1044 else if (WndParent
&& WndParent
->FirstChild
== Wnd
) WndParent
->FirstChild
= Wnd
->NextSibling
;
1048 IntUnLockRelatives(WndParent
);
1049 IntReleaseWindowObject(WndParent
);
1051 Wnd
->PrevSibling
= Wnd
->NextSibling
= Wnd
->Parent
= NULL
;
1052 IntUnLockRelatives(Wnd
);
1058 PWINDOW_OBJECT Window
, Child
;
1060 if(!(Window
= IntGetWindowObject(IntGetDesktopWindow())))
1062 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1066 IntLockRelatives(Window
);
1067 for(Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
1069 if(Child
->Owner
&& Child
->Style
& WS_VISIBLE
)
1072 * The desktop has a popup window if one of them has
1073 * an owner window and is visible
1075 IntUnLockRelatives(Window
);
1076 IntReleaseWindowObject(Window
);
1080 IntUnLockRelatives(Window
);
1081 IntReleaseWindowObject(Window
);
1086 IntIsWindowInDestroy(PWINDOW_OBJECT Window
)
1088 return ((Window
->Status
& WINDOWSTATUS_DESTROYING
) == WINDOWSTATUS_DESTROYING
);
1091 /* FUNCTIONS *****************************************************************/
1097 NtUserAlterWindowStyle(DWORD Unknown0
,
1108 * As best as I can figure, this function is used by EnumWindows,
1109 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
1111 * It's supposed to build a list of HWNDs to return to the caller.
1112 * We can figure out what kind of list by what parameters are
1120 NtUserBuildHwndList(
1132 /* FIXME handle bChildren */
1136 PWINDOW_OBJECT Window
, Child
;
1137 if(!(Window
= IntGetWindowObject(hwndParent
)))
1139 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1143 IntLockRelatives(Window
);
1144 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1146 if(dwCount
++ < nBufSize
&& pWnd
)
1148 Status
= MmCopyToCaller(pWnd
++, &Child
->Self
, sizeof(HWND
));
1149 if(!NT_SUCCESS(Status
))
1151 SetLastNtError(Status
);
1156 IntUnLockRelatives(Window
);
1158 IntReleaseWindowObject(Window
);
1163 PW32THREAD W32Thread
;
1164 PLIST_ENTRY Current
;
1165 PWINDOW_OBJECT Window
;
1167 Status
= PsLookupThreadByThreadId((PVOID
)dwThreadId
, &Thread
);
1168 if(!NT_SUCCESS(Status
))
1170 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1173 if(!(W32Thread
= Thread
->Tcb
.Win32Thread
))
1175 ObDereferenceObject(Thread
);
1176 DPRINT1("Thread is not a GUI Thread!\n");
1177 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1181 IntLockThreadWindows(W32Thread
);
1182 Current
= W32Thread
->WindowListHead
.Flink
;
1183 while(Current
!= &(W32Thread
->WindowListHead
))
1185 Window
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
1188 if(dwCount
< nBufSize
&& pWnd
)
1190 Status
= MmCopyToCaller(pWnd
++, &Window
->Self
, sizeof(HWND
));
1191 if(!NT_SUCCESS(Status
))
1193 SetLastNtError(Status
);
1198 Current
= Current
->Flink
;
1200 IntUnLockThreadWindows(W32Thread
);
1202 ObDereferenceObject(Thread
);
1206 PDESKTOP_OBJECT Desktop
;
1207 PWINDOW_OBJECT Window
, Child
;
1209 if(hDesktop
== NULL
&& !(Desktop
= IntGetActiveDesktop()))
1211 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1217 Status
= IntValidateDesktopHandle(hDesktop
,
1221 if(!NT_SUCCESS(Status
))
1223 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1227 if(!(Window
= IntGetWindowObject(Desktop
->DesktopWindow
)))
1230 ObDereferenceObject(Desktop
);
1231 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1235 IntLockRelatives(Window
);
1236 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1238 if(dwCount
++ < nBufSize
&& pWnd
)
1240 Status
= MmCopyToCaller(pWnd
++, &Child
->Self
, sizeof(HWND
));
1241 if(!NT_SUCCESS(Status
))
1243 SetLastNtError(Status
);
1248 IntUnLockRelatives(Window
);
1250 IntReleaseWindowObject(Window
);
1252 ObDereferenceObject(Desktop
);
1263 NtUserChildWindowFromPointEx(HWND hwndParent
,
1268 PWINDOW_OBJECT Parent
;
1273 if(!(Parent
= IntGetWindowObject(hwndParent
)))
1275 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1282 if(Parent
->Self
!= IntGetDesktopWindow())
1284 Pt
.x
+= Parent
->ClientRect
.left
;
1285 Pt
.y
+= Parent
->ClientRect
.top
;
1288 if(!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
))
1290 IntReleaseWindowObject(Parent
);
1295 if((List
= IntWinListChildren(Parent
)))
1297 for(phWnd
= List
; *phWnd
; phWnd
++)
1299 PWINDOW_OBJECT Child
;
1300 if((Child
= IntGetWindowObject(*phWnd
)))
1302 if(!(Child
->Style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
))
1304 IntReleaseWindowObject(Child
);
1307 if((Child
->Style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
))
1309 IntReleaseWindowObject(Child
);
1312 if((Child
->ExStyle
& WS_EX_TRANSPARENT
) && (uiFlags
& CWP_SKIPTRANSPARENT
))
1314 IntReleaseWindowObject(Child
);
1317 if(IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
1320 IntReleaseWindowObject(Child
);
1323 IntReleaseWindowObject(Child
);
1329 IntReleaseWindowObject(Parent
);
1335 * calculates the default position of a window
1338 IntCalcDefPosSize(PWINDOW_OBJECT Parent
, PWINDOW_OBJECT WindowObject
, RECT
*rc
, BOOL IncPos
)
1345 IntGdiIntersectRect(rc
, rc
, &Parent
->ClientRect
);
1349 Pos
.x
= Parent
->TiledCounter
* (NtUserGetSystemMetrics(SM_CXSIZE
) + NtUserGetSystemMetrics(SM_CXFRAME
));
1350 Pos
.y
= Parent
->TiledCounter
* (NtUserGetSystemMetrics(SM_CYSIZE
) + NtUserGetSystemMetrics(SM_CYFRAME
));
1351 if(Pos
.x
> ((rc
->right
- rc
->left
) / 4) ||
1352 Pos
.y
> ((rc
->bottom
- rc
->top
) / 4))
1354 /* reset counter and position */
1357 Parent
->TiledCounter
= 0;
1359 Parent
->TiledCounter
++;
1370 Sz
.cx
= EngMulDiv(rc
->right
- rc
->left
, 3, 4);
1371 Sz
.cy
= EngMulDiv(rc
->bottom
- rc
->top
, 3, 4);
1375 rc
->right
= rc
->left
+ Sz
.cx
;
1376 rc
->bottom
= rc
->top
+ Sz
.cy
;
1385 IntCreateWindowEx(DWORD dwExStyle
,
1386 PUNICODE_STRING ClassName
,
1387 PUNICODE_STRING WindowName
,
1395 HINSTANCE hInstance
,
1398 BOOL bUnicodeWindow
)
1400 PWINSTATION_OBJECT WinStaObject
;
1401 PWNDCLASS_OBJECT ClassObject
;
1402 PWINDOW_OBJECT WindowObject
;
1403 PWINDOW_OBJECT ParentWindow
, OwnerWindow
;
1404 HWND ParentWindowHandle
;
1405 HWND OwnerWindowHandle
;
1406 PMENU_OBJECT SystemMenu
;
1411 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1416 CBT_CREATEWNDW CbtCreate
;
1421 ParentWindowHandle
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
1422 OwnerWindowHandle
= NULL
;
1424 if (hWndParent
== HWND_MESSAGE
)
1427 * native ole32.OleInitialize uses HWND_MESSAGE to create the
1428 * message window (style: WS_POPUP|WS_DISABLED)
1430 DPRINT1("FIXME - Parent is HWND_MESSAGE\n");
1432 else if (hWndParent
)
1434 if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1435 ParentWindowHandle
= hWndParent
;
1437 OwnerWindowHandle
= NtUserGetAncestor(hWndParent
, GA_ROOT
);
1439 else if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1441 return (HWND
)0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1444 if (NULL
!= ParentWindowHandle
)
1446 ParentWindow
= IntGetWindowObject(ParentWindowHandle
);
1450 ParentWindow
= NULL
;
1453 /* FIXME: parent must belong to the current process */
1455 /* Check the class. */
1456 ClassFound
= ClassReferenceClassByNameOrAtom(&ClassObject
, ClassName
->Buffer
, hInstance
);
1459 if (IS_ATOM(ClassName
->Buffer
))
1461 DPRINT1("Class 0x%x not found\n", (DWORD_PTR
) ClassName
->Buffer
);
1465 DPRINT1("Class %wZ not found\n", ClassName
);
1467 if (NULL
!= ParentWindow
)
1469 IntReleaseWindowObject(ParentWindow
);
1471 SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS
);
1475 /* Check the window station. */
1476 if (PsGetWin32Thread()->Desktop
== NULL
)
1478 ClassDereferenceObject(ClassObject
);
1479 if (NULL
!= ParentWindow
)
1481 IntReleaseWindowObject(ParentWindow
);
1483 DPRINT("Thread is not attached to a desktop! Cannot create window!\n");
1486 WinStaObject
= PsGetWin32Thread()->Desktop
->WindowStation
;
1487 ObReferenceObjectByPointer(WinStaObject
, KernelMode
, ExWindowStationObjectType
, 0);
1489 /* Create the window object. */
1490 WindowObject
= (PWINDOW_OBJECT
)
1491 ObmCreateObject(PsGetWin32Thread()->Desktop
->WindowStation
->HandleTable
, &Handle
,
1492 otWindow
, sizeof(WINDOW_OBJECT
) + ClassObject
->cbWndExtra
1495 DPRINT("Created object with handle %X\n", Handle
);
1498 ObDereferenceObject(WinStaObject
);
1499 ClassDereferenceObject(ClassObject
);
1500 if (NULL
!= ParentWindow
)
1502 IntReleaseWindowObject(ParentWindow
);
1504 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1507 ObDereferenceObject(WinStaObject
);
1509 if (NULL
== PsGetWin32Thread()->Desktop
->DesktopWindow
)
1511 /* If there is no desktop window yet, we must be creating it */
1512 PsGetWin32Thread()->Desktop
->DesktopWindow
= Handle
;
1516 * Fill out the structure describing it.
1518 WindowObject
->Class
= ClassObject
;
1519 IntLockClassWindows(ClassObject
);
1520 InsertTailList(&ClassObject
->ClassWindowsListHead
, &WindowObject
->ClassListEntry
);
1521 IntUnLockClassWindows(ClassObject
);
1523 WindowObject
->ExStyle
= dwExStyle
;
1524 WindowObject
->Style
= dwStyle
& ~WS_VISIBLE
;
1525 DPRINT("1: Style is now %lx\n", WindowObject
->Style
);
1527 WindowObject
->SystemMenu
= (HMENU
)0;
1528 WindowObject
->ContextHelpId
= 0;
1529 WindowObject
->IDMenu
= 0;
1530 WindowObject
->Instance
= hInstance
;
1531 WindowObject
->Self
= Handle
;
1532 if (0 != (dwStyle
& WS_CHILD
))
1534 WindowObject
->IDMenu
= (UINT
) hMenu
;
1538 IntSetMenu(WindowObject
, hMenu
, &MenuChanged
);
1540 WindowObject
->MessageQueue
= PsGetWin32Thread()->MessageQueue
;
1541 WindowObject
->Parent
= (ParentWindow
? ParentWindow
->Self
: NULL
);
1542 if((OwnerWindow
= IntGetWindowObject(OwnerWindowHandle
)))
1544 WindowObject
->Owner
= OwnerWindowHandle
;
1545 IntReleaseWindowObject(OwnerWindow
);
1548 WindowObject
->Owner
= NULL
;
1549 WindowObject
->UserData
= 0;
1550 if ((((DWORD
)ClassObject
->lpfnWndProcA
& 0xFFFF0000) != 0xFFFF0000)
1551 && (((DWORD
)ClassObject
->lpfnWndProcW
& 0xFFFF0000) != 0xFFFF0000))
1553 WindowObject
->Unicode
= bUnicodeWindow
;
1557 WindowObject
->Unicode
= ClassObject
->Unicode
;
1559 WindowObject
->WndProcA
= ClassObject
->lpfnWndProcA
;
1560 WindowObject
->WndProcW
= ClassObject
->lpfnWndProcW
;
1561 WindowObject
->OwnerThread
= PsGetCurrentThread();
1562 WindowObject
->FirstChild
= NULL
;
1563 WindowObject
->LastChild
= NULL
;
1564 WindowObject
->PrevSibling
= NULL
;
1565 WindowObject
->NextSibling
= NULL
;
1567 /* extra window data */
1568 if (ClassObject
->cbWndExtra
!= 0)
1570 WindowObject
->ExtraData
= (PCHAR
)(WindowObject
+ 1);
1571 WindowObject
->ExtraDataSize
= ClassObject
->cbWndExtra
;
1572 RtlZeroMemory(WindowObject
->ExtraData
, WindowObject
->ExtraDataSize
);
1576 WindowObject
->ExtraData
= NULL
;
1577 WindowObject
->ExtraDataSize
= 0;
1580 InitializeListHead(&WindowObject
->PropListHead
);
1581 ExInitializeFastMutex(&WindowObject
->PropListLock
);
1582 ExInitializeFastMutex(&WindowObject
->RelativesLock
);
1583 ExInitializeFastMutex(&WindowObject
->UpdateLock
);
1585 if (NULL
!= WindowName
->Buffer
)
1587 WindowObject
->WindowName
.MaximumLength
= WindowName
->MaximumLength
;
1588 WindowObject
->WindowName
.Length
= WindowName
->Length
;
1589 WindowObject
->WindowName
.Buffer
= ExAllocatePoolWithTag(PagedPool
, WindowName
->MaximumLength
,
1591 if (NULL
== WindowObject
->WindowName
.Buffer
)
1593 ClassDereferenceObject(ClassObject
);
1594 DPRINT1("Failed to allocate mem for window name\n");
1595 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1598 RtlCopyMemory(WindowObject
->WindowName
.Buffer
, WindowName
->Buffer
, WindowName
->MaximumLength
);
1602 RtlInitUnicodeString(&WindowObject
->WindowName
, NULL
);
1607 * This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1608 * tested for WS_POPUP
1610 if ((dwExStyle
& WS_EX_DLGMODALFRAME
) ||
1611 ((!(dwExStyle
& WS_EX_STATICEDGE
)) &&
1612 (dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
))))
1613 dwExStyle
|= WS_EX_WINDOWEDGE
;
1615 dwExStyle
&= ~WS_EX_WINDOWEDGE
;
1617 /* Correct the window style. */
1618 if (!(dwStyle
& WS_CHILD
))
1620 WindowObject
->Style
|= WS_CLIPSIBLINGS
;
1621 DPRINT("3: Style is now %lx\n", WindowObject
->Style
);
1622 if (!(dwStyle
& WS_POPUP
))
1624 WindowObject
->Style
|= WS_CAPTION
;
1625 WindowObject
->Flags
|= WINDOWOBJECT_NEED_SIZE
;
1626 DPRINT("4: Style is now %lx\n", WindowObject
->Style
);
1630 /* create system menu */
1631 if((WindowObject
->Style
& WS_SYSMENU
) &&
1632 (WindowObject
->Style
& WS_CAPTION
) == WS_CAPTION
)
1634 SystemMenu
= IntGetSystemMenu(WindowObject
, TRUE
, TRUE
);
1637 WindowObject
->SystemMenu
= SystemMenu
->MenuInfo
.Self
;
1638 IntReleaseMenuObject(SystemMenu
);
1642 /* Insert the window into the thread's window list. */
1643 IntLockThreadWindows(PsGetWin32Thread());
1644 InsertTailList (&PsGetWin32Thread()->WindowListHead
,
1645 &WindowObject
->ThreadListEntry
);
1646 IntUnLockThreadWindows(PsGetWin32Thread());
1648 /* Allocate a DCE for this window. */
1649 if (dwStyle
& CS_OWNDC
)
1651 WindowObject
->Dce
= DceAllocDCE(WindowObject
->Self
, DCE_WINDOW_DC
);
1653 /* FIXME: Handle "CS_CLASSDC" */
1661 Cs
.lpCreateParams
= lpParam
;
1662 Cs
.hInstance
= hInstance
;
1664 Cs
.hwndParent
= ParentWindowHandle
;
1670 Cs
.lpszName
= (LPCWSTR
) WindowName
;
1671 Cs
.lpszClass
= (LPCWSTR
) ClassName
;
1672 Cs
.dwExStyle
= dwExStyle
;
1673 CbtCreate
.lpcs
= &Cs
;
1674 CbtCreate
.hwndInsertAfter
= HWND_TOP
;
1675 if (HOOK_CallHooks(WH_CBT
, HCBT_CREATEWND
, (WPARAM
) Handle
, (LPARAM
) &CbtCreate
))
1677 if (NULL
!= ParentWindow
)
1679 IntReleaseWindowObject(ParentWindow
);
1682 /* FIXME - Delete window object and remove it from the thread windows list */
1683 /* FIXME - delete allocated DCE */
1685 ClassDereferenceObject(ClassObject
);
1686 DPRINT1("CBT-hook returned !0\n");
1695 /* default positioning for overlapped windows */
1696 if(!(WindowObject
->Style
& (WS_POPUP
| WS_CHILD
)))
1699 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
1700 BOOL CalculatedDefPosSize
= FALSE
;
1702 IntGetDesktopWorkArea(WindowObject
->OwnerThread
->Tcb
.Win32Thread
->Desktop
, &WorkArea
);
1705 ProcessParams
= PsGetCurrentProcess()->Peb
->ProcessParameters
;
1707 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1709 CalculatedDefPosSize
= IntCalcDefPosSize(ParentWindow
, WindowObject
, &rc
, TRUE
);
1711 if(ProcessParams
->dwFlags
& STARTF_USEPOSITION
)
1713 ProcessParams
->dwFlags
&= ~STARTF_USEPOSITION
;
1714 Pos
.x
= WorkArea
.left
+ ProcessParams
->dwX
;
1715 Pos
.y
= WorkArea
.top
+ ProcessParams
->dwY
;
1723 /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
1724 y is something else */
1725 if(y
!= CW_USEDEFAULT
&& y
!= CW_USEDEFAULT16
)
1730 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1732 if(!CalculatedDefPosSize
)
1734 IntCalcDefPosSize(ParentWindow
, WindowObject
, &rc
, FALSE
);
1736 if(ProcessParams
->dwFlags
& STARTF_USESIZE
)
1738 ProcessParams
->dwFlags
&= ~STARTF_USESIZE
;
1739 Size
.cx
= ProcessParams
->dwXSize
;
1740 Size
.cy
= ProcessParams
->dwYSize
;
1744 Size
.cx
= rc
.right
- rc
.left
;
1745 Size
.cy
= rc
.bottom
- rc
.top
;
1748 /* move the window if necessary */
1750 Pos
.x
= max(rc
.left
, 0);
1752 Pos
.y
= max(rc
.top
, 0);
1757 /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
1758 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1763 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1770 /* Initialize the window dimensions. */
1771 WindowObject
->WindowRect
.left
= Pos
.x
;
1772 WindowObject
->WindowRect
.top
= Pos
.y
;
1773 WindowObject
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1774 WindowObject
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1775 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1777 IntGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1778 ParentWindow
->ClientRect
.top
);
1780 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1783 * Get the size and position of the window.
1785 if ((dwStyle
& WS_THICKFRAME
) || !(dwStyle
& (WS_POPUP
| WS_CHILD
)))
1787 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1789 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1790 WinPosGetMinMaxInfo(WindowObject
, &MaxSize
, &MaxPos
, &MinTrack
,
1792 if (MaxSize
.x
< nWidth
) nWidth
= MaxSize
.x
;
1793 if (MaxSize
.y
< nHeight
) nHeight
= MaxSize
.y
;
1794 if (nWidth
< MinTrack
.x
) nWidth
= MinTrack
.x
;
1795 if (nHeight
< MinTrack
.y
) nHeight
= MinTrack
.y
;
1796 if (nWidth
< 0) nWidth
= 0;
1797 if (nHeight
< 0) nHeight
= 0;
1800 WindowObject
->WindowRect
.left
= Pos
.x
;
1801 WindowObject
->WindowRect
.top
= Pos
.y
;
1802 WindowObject
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1803 WindowObject
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1804 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1806 IntGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1807 ParentWindow
->ClientRect
.top
);
1809 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1811 /* FIXME: Initialize the window menu. */
1813 /* Send a NCCREATE message. */
1819 DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d\n", Cs
.style
, Cs
.dwExStyle
, Cs
.hwndParent
);
1820 DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1821 DPRINT("IntCreateWindowEx(): About to send NCCREATE message.\n");
1822 Result
= IntSendMessage(WindowObject
->Self
, WM_NCCREATE
, 0, (LPARAM
) &Cs
);
1825 /* FIXME: Cleanup. */
1826 if (NULL
!= ParentWindow
)
1828 IntReleaseWindowObject(ParentWindow
);
1830 DPRINT("IntCreateWindowEx(): NCCREATE message failed.\n");
1834 /* Calculate the non-client size. */
1835 MaxPos
.x
= WindowObject
->WindowRect
.left
;
1836 MaxPos
.y
= WindowObject
->WindowRect
.top
;
1837 DPRINT("IntCreateWindowEx(): About to get non-client size.\n");
1838 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1839 Result
= WinPosGetNonClientSize(WindowObject
->Self
,
1840 &WindowObject
->WindowRect
,
1841 &WindowObject
->ClientRect
);
1842 IntGdiOffsetRect(&WindowObject
->WindowRect
,
1843 MaxPos
.x
- WindowObject
->WindowRect
.left
,
1844 MaxPos
.y
- WindowObject
->WindowRect
.top
);
1846 if (NULL
!= ParentWindow
)
1848 /* link the window into the parent's child list */
1849 if ((dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
1851 PWINDOW_OBJECT PrevSibling
;
1852 IntLockRelatives(ParentWindow
);
1853 if((PrevSibling
= ParentWindow
->LastChild
))
1854 IntReferenceWindowObject(PrevSibling
);
1855 IntUnLockRelatives(ParentWindow
);
1856 /* link window as bottom sibling */
1857 IntLinkWindow(WindowObject
, ParentWindow
, PrevSibling
/*prev sibling*/);
1859 IntReleaseWindowObject(PrevSibling
);
1863 /* link window as top sibling (but after topmost siblings) */
1864 PWINDOW_OBJECT InsertAfter
, Sibling
;
1865 if (0 == (dwExStyle
& WS_EX_TOPMOST
))
1867 IntLockRelatives(ParentWindow
);
1869 Sibling
= ParentWindow
->FirstChild
;
1870 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
1872 InsertAfter
= Sibling
;
1873 Sibling
= Sibling
->NextSibling
;
1875 IntUnLockRelatives(ParentWindow
);
1881 if (NULL
!= InsertAfter
)
1883 IntReferenceWindowObject(InsertAfter
);
1885 IntLinkWindow(WindowObject
, ParentWindow
, InsertAfter
/* prev sibling */);
1886 if (NULL
!= InsertAfter
)
1888 IntReleaseWindowObject(InsertAfter
);
1893 /* Send the WM_CREATE message. */
1894 DPRINT("IntCreateWindowEx(): about to send CREATE message.\n");
1895 Result
= IntSendMessage(WindowObject
->Self
, WM_CREATE
, 0, (LPARAM
) &Cs
);
1896 if (Result
== (LRESULT
)-1)
1898 /* FIXME: Cleanup. */
1899 if (NULL
!= ParentWindow
)
1901 IntReleaseWindowObject(ParentWindow
);
1903 ClassDereferenceObject(ClassObject
);
1904 DPRINT("IntCreateWindowEx(): send CREATE message failed.\n");
1908 /* Send move and size messages. */
1909 if (!(WindowObject
->Flags
& WINDOWOBJECT_NEED_SIZE
))
1913 DPRINT("IntCreateWindow(): About to send WM_SIZE\n");
1915 if ((WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
) < 0 ||
1916 (WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
) < 0)
1918 DPRINT("Sending bogus WM_SIZE\n");
1921 lParam
= MAKE_LONG(WindowObject
->ClientRect
.right
-
1922 WindowObject
->ClientRect
.left
,
1923 WindowObject
->ClientRect
.bottom
-
1924 WindowObject
->ClientRect
.top
);
1925 IntSendMessage(WindowObject
->Self
, WM_SIZE
, SIZE_RESTORED
,
1928 DPRINT("IntCreateWindow(): About to send WM_MOVE\n");
1930 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1932 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
- ParentWindow
->ClientRect
.left
,
1933 WindowObject
->ClientRect
.top
- ParentWindow
->ClientRect
.top
);
1937 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
,
1938 WindowObject
->ClientRect
.top
);
1940 IntSendMessage(WindowObject
->Self
, WM_MOVE
, 0, lParam
);
1943 /* Show or maybe minimize or maximize the window. */
1944 if (WindowObject
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1949 SwFlag
= (WindowObject
->Style
& WS_MINIMIZE
) ? SW_MINIMIZE
:
1951 WinPosMinMaximize(WindowObject
, SwFlag
, &NewPos
);
1953 ((WindowObject
->Style
& WS_CHILD
) || NtUserGetActiveWindow()) ?
1954 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
:
1955 SWP_NOZORDER
| SWP_FRAMECHANGED
;
1956 DPRINT("IntCreateWindow(): About to minimize/maximize\n");
1957 DPRINT("%d,%d %dx%d\n", NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
);
1958 WinPosSetWindowPos(WindowObject
->Self
, 0, NewPos
.left
, NewPos
.top
,
1959 NewPos
.right
, NewPos
.bottom
, SwFlag
);
1962 /* Notify the parent window of a new child. */
1963 if ((WindowObject
->Style
& WS_CHILD
) &&
1964 (!(WindowObject
->ExStyle
& WS_EX_NOPARENTNOTIFY
)) && ParentWindow
)
1966 DPRINT("IntCreateWindow(): About to notify parent\n");
1967 IntSendMessage(ParentWindow
->Self
,
1969 MAKEWPARAM(WM_CREATE
, WindowObject
->IDMenu
),
1970 (LPARAM
)WindowObject
->Self
);
1973 if (NULL
!= ParentWindow
)
1975 IntReleaseWindowObject(ParentWindow
);
1978 /* Initialize and show the window's scrollbars */
1979 if (WindowObject
->Style
& WS_VSCROLL
)
1981 NtUserShowScrollBar(WindowObject
->Self
, SB_VERT
, TRUE
);
1983 if (WindowObject
->Style
& WS_HSCROLL
)
1985 NtUserShowScrollBar(WindowObject
->Self
, SB_HORZ
, TRUE
);
1988 if (dwStyle
& WS_VISIBLE
)
1990 DPRINT("IntCreateWindow(): About to show window\n");
1991 WinPosShowWindow(WindowObject
->Self
, dwShowMode
);
1994 DPRINT("IntCreateWindow(): = %X\n", Handle
);
1995 DPRINT("WindowObject->SystemMenu = 0x%x\n", WindowObject
->SystemMenu
);
1996 return((HWND
)Handle
);
2000 NtUserCreateWindowEx(DWORD dwExStyle
,
2001 PUNICODE_STRING UnsafeClassName
,
2002 PUNICODE_STRING UnsafeWindowName
,
2010 HINSTANCE hInstance
,
2013 BOOL bUnicodeWindow
)
2016 UNICODE_STRING WindowName
;
2017 UNICODE_STRING ClassName
;
2020 DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
2022 /* Get the class name (string or atom) */
2023 Status
= MmCopyFromCaller(&ClassName
, UnsafeClassName
, sizeof(UNICODE_STRING
));
2024 if (! NT_SUCCESS(Status
))
2026 SetLastNtError(Status
);
2029 if (! IS_ATOM(ClassName
.Buffer
))
2031 Status
= IntSafeCopyUnicodeStringTerminateNULL(&ClassName
, UnsafeClassName
);
2032 if (! NT_SUCCESS(Status
))
2034 SetLastNtError(Status
);
2039 /* safely copy the window name */
2040 if (NULL
!= UnsafeWindowName
)
2042 Status
= IntSafeCopyUnicodeString(&WindowName
, UnsafeWindowName
);
2043 if (! NT_SUCCESS(Status
))
2045 if (! IS_ATOM(ClassName
.Buffer
))
2047 RtlFreeUnicodeString(&ClassName
);
2049 SetLastNtError(Status
);
2055 RtlInitUnicodeString(&WindowName
, NULL
);
2058 NewWindow
= IntCreateWindowEx(dwExStyle
, &ClassName
, &WindowName
, dwStyle
, x
, y
, nWidth
, nHeight
,
2059 hWndParent
, hMenu
, hInstance
, lpParam
, dwShowMode
, bUnicodeWindow
);
2061 RtlFreeUnicodeString(&WindowName
);
2062 if (! IS_ATOM(ClassName
.Buffer
))
2064 RtlFreeUnicodeString(&ClassName
);
2074 NtUserDeferWindowPos(HDWP WinPosInfo
,
2076 HWND WndInsertAfter
,
2093 NtUserDestroyWindow(HWND Wnd
)
2095 PWINDOW_OBJECT Window
;
2098 Window
= IntGetWindowObject(Wnd
);
2104 /* Check for owner thread and desktop window */
2105 if ((Window
->OwnerThread
!= PsGetCurrentThread()) || IntIsDesktopWindow(Window
))
2107 IntReleaseWindowObject(Window
);
2108 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2112 /* Look whether the focus is within the tree of windows we will
2115 if (!WinPosShowWindow(Wnd
, SW_HIDE
))
2117 if (NtUserGetActiveWindow() == Wnd
)
2119 WinPosActivateOtherWindow(Window
);
2122 IntLockMessageQueue(Window
->MessageQueue
);
2123 if (Window
->MessageQueue
->ActiveWindow
== Window
->Self
)
2124 Window
->MessageQueue
->ActiveWindow
= NULL
;
2125 if (Window
->MessageQueue
->FocusWindow
== Window
->Self
)
2126 Window
->MessageQueue
->FocusWindow
= NULL
;
2127 if (Window
->MessageQueue
->CaptureWindow
== Window
->Self
)
2128 Window
->MessageQueue
->CaptureWindow
= NULL
;
2129 IntUnLockMessageQueue(Window
->MessageQueue
);
2133 if (HOOK_CallHooks(WH_CBT
, HCBT_DESTROYWND
, (WPARAM
) hwnd
, 0, TRUE
))
2139 isChild
= (0 != (Window
->Style
& WS_CHILD
));
2144 if (! USER_IsExitingThread(GetCurrentThreadId()))
2146 send_parent_notify(hwnd
, WM_DESTROY
);
2149 else if (NULL
!= GetWindow(Wnd
, GW_OWNER
))
2151 HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
2152 /* FIXME: clean up palette - see "Internals" p.352 */
2156 if (!IntIsWindow(Wnd
))
2161 /* Recursively destroy owned windows */
2166 BOOL GotOne
= FALSE
;
2169 PWINDOW_OBJECT Child
, Desktop
;
2171 Desktop
= IntGetWindowObject(IntGetDesktopWindow());
2172 Children
= IntWinListChildren(Desktop
);
2173 IntReleaseWindowObject(Desktop
);
2176 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
2178 Child
= IntGetWindowObject(*ChildHandle
);
2181 IntLockRelatives(Child
);
2182 if (Child
->Owner
!= Window
->Self
)
2184 IntUnLockRelatives(Child
);
2185 IntReleaseWindowObject(Child
);
2188 IntUnLockRelatives(Child
);
2189 if (IntWndBelongsToThread(Child
, PsGetWin32Thread()))
2191 IntReleaseWindowObject(Child
);
2192 NtUserDestroyWindow(*ChildHandle
);
2196 IntLockRelatives(Child
);
2197 if (Child
->Owner
!= NULL
)
2199 Child
->Owner
= NULL
;
2201 IntUnLockRelatives(Child
);
2202 IntReleaseWindowObject(Child
);
2204 ExFreePool(Children
);
2213 if (!IntIsWindow(Wnd
))
2215 IntReleaseWindowObject(Window
);
2219 /* Destroy the window storage */
2220 IntDestroyWindow(Window
, PsGetWin32Process(), PsGetWin32Thread(), TRUE
);
2222 IntReleaseWindowObject(Window
);
2232 NtUserDrawMenuBarTemp(
2239 /* we'll use this function just for caching the menu bar */
2249 NtUserEndDeferWindowPosEx(DWORD Unknown0
,
2262 NtUserFillWindow(DWORD Unknown0
,
2274 IntFindWindow(PWINDOW_OBJECT Parent
,
2275 PWINDOW_OBJECT ChildAfter
,
2276 PWNDCLASS_OBJECT ClassObject
,
2277 PUNICODE_STRING WindowName
)
2279 BOOL CheckWindowName
;
2285 CheckWindowName
= (WindowName
&& (WindowName
->Length
> 0));
2287 if((List
= IntWinListChildren(Parent
)))
2292 /* skip handles before and including ChildAfter */
2293 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->Self
));
2296 /* search children */
2299 PWINDOW_OBJECT Child
;
2300 if(!(Child
= IntGetWindowObject(*(phWnd
++))))
2305 /* Do not send WM_GETTEXT messages in the kernel mode version!
2306 The user mode version however calls GetWindowText() which will
2307 send WM_GETTEXT messages to windows belonging to its processes */
2308 if(((!CheckWindowName
|| (CheckWindowName
&& !RtlCompareUnicodeString(WindowName
, &(Child
->WindowName
), FALSE
))) &&
2309 (!ClassObject
|| (ClassObject
&& (Child
->Class
== ClassObject
))))
2311 ((!CheckWindowName
|| (CheckWindowName
&& !RtlCompareUnicodeString(WindowName
, &(Child
->WindowName
), FALSE
))) &&
2312 (!ClassObject
|| (ClassObject
&& (Child
->Class
== ClassObject
)))))
2315 IntReleaseWindowObject(Child
);
2319 IntReleaseWindowObject(Child
);
2329 * Searches a window's children for a window with the specified
2332 * hwndParent = The window whose childs are to be searched.
2334 * HWND_MESSAGE = message-only windows
2336 * hwndChildAfter = Search starts after this child window.
2337 * NULL = start from beginning
2339 * ucClassName = Class name to search for
2340 * Reguired parameter.
2342 * ucWindowName = Window name
2343 * ->Buffer == NULL = don't care
2346 * The HWND of the window if it was found, otherwise NULL
2352 NtUserFindWindowEx(HWND hwndParent
,
2353 HWND hwndChildAfter
,
2354 PUNICODE_STRING ucClassName
,
2355 PUNICODE_STRING ucWindowName
)
2357 PWINDOW_OBJECT Parent
, ChildAfter
;
2358 UNICODE_STRING ClassName
, WindowName
;
2360 HWND Desktop
, Ret
= NULL
;
2361 PWNDCLASS_OBJECT ClassObject
= NULL
;
2364 Desktop
= IntGetCurrentThreadDesktopWindow();
2366 if(hwndParent
== NULL
)
2367 hwndParent
= Desktop
;
2369 else if(hwndParent == HWND_MESSAGE)
2371 hwndParent = IntGetMessageWindow();
2375 if(!(Parent
= IntGetWindowObject(hwndParent
)))
2377 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2382 if(hwndChildAfter
&& !(ChildAfter
= IntGetWindowObject(hwndChildAfter
)))
2384 IntReleaseWindowObject(Parent
);
2385 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2389 /* copy the window name */
2390 Status
= IntSafeCopyUnicodeString(&WindowName
, ucWindowName
);
2391 if(!NT_SUCCESS(Status
))
2393 SetLastNtError(Status
);
2397 /* safely copy the class name */
2398 Status
= MmCopyFromCaller(&ClassName
, ucClassName
, sizeof(UNICODE_STRING
));
2399 if(!NT_SUCCESS(Status
))
2401 SetLastNtError(Status
);
2404 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2407 /* safely copy the class name string (NULL terminated because class-lookup
2409 buf
= ExAllocatePoolWithTag(PagedPool
, ClassName
.Length
+ sizeof(WCHAR
), TAG_STRING
);
2412 SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES
);
2415 Status
= MmCopyFromCaller(buf
, ClassName
.Buffer
, ClassName
.Length
);
2416 if(!NT_SUCCESS(Status
))
2419 SetLastNtError(Status
);
2422 ClassName
.Buffer
= buf
;
2423 /* make sure the string is null-terminated */
2424 buf
+= ClassName
.Length
/ sizeof(WCHAR
);
2428 /* find the class object */
2429 if(ClassName
.Buffer
)
2431 /* this expects the string in ClassName to be NULL-terminated! */
2432 ClassFound
= ClassReferenceClassByNameOrAtom(&ClassObject
, ClassName
.Buffer
, NULL
);
2435 if (IS_ATOM(ClassName
.Buffer
))
2436 DPRINT1("Window class not found (%lx)\n", (ULONG_PTR
)ClassName
.Buffer
);
2438 DPRINT1("Window class not found (%S)\n", ClassName
.Buffer
);
2439 SetLastWin32Error(ERROR_FILE_NOT_FOUND
);
2444 if(Parent
->Self
== Desktop
)
2447 PWINDOW_OBJECT TopLevelWindow
;
2448 BOOL CheckWindowName
;
2450 /* windows searches through all top-level windows if the parent is the desktop
2453 if((List
= IntWinListChildren(Parent
)))
2459 /* skip handles before and including ChildAfter */
2460 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->Self
));
2463 CheckWindowName
= WindowName
.Length
> 0;
2465 /* search children */
2468 if(!(TopLevelWindow
= IntGetWindowObject(*(phWnd
++))))
2473 /* Do not send WM_GETTEXT messages in the kernel mode version!
2474 The user mode version however calls GetWindowText() which will
2475 send WM_GETTEXT messages to windows belonging to its processes */
2476 if(((!CheckWindowName
|| (CheckWindowName
&& !RtlCompareUnicodeString(&WindowName
, &(TopLevelWindow
->WindowName
), FALSE
))) &&
2477 (!ClassObject
|| (ClassObject
&& (TopLevelWindow
->Class
== ClassObject
))))
2479 ((!CheckWindowName
|| (CheckWindowName
&& !RtlCompareUnicodeString(&WindowName
, &(TopLevelWindow
->WindowName
), FALSE
))) &&
2480 (!ClassObject
|| (ClassObject
&& (TopLevelWindow
->Class
== ClassObject
)))))
2482 Ret
= TopLevelWindow
->Self
;
2483 IntReleaseWindowObject(TopLevelWindow
);
2487 if(IntFindWindow(TopLevelWindow
, NULL
, ClassObject
, &WindowName
))
2489 /* window returns the handle of the top-level window, in case it found
2491 Ret
= TopLevelWindow
->Self
;
2492 IntReleaseWindowObject(TopLevelWindow
);
2496 IntReleaseWindowObject(TopLevelWindow
);
2502 Ret
= IntFindWindow(Parent
, ChildAfter
, ClassObject
, &WindowName
);
2505 if(Ret
== NULL
&& hwndParent
== NULL
&& hwndChildAfter
== NULL
)
2507 /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
2508 search the message-only windows. Should this also be done if
2509 Parent is the desktop window??? */
2510 PWINDOW_OBJECT MsgWindows
;
2512 if((MsgWindows
= IntGetWindowObject(IntGetMessageWindow())))
2514 Ret
= IntFindWindow(MsgWindows
, ChildAfter
, ClassObject
, &WindowName
);
2515 IntReleaseWindowObject(MsgWindows
);
2520 if (ClassObject
!= NULL
)
2522 ClassDereferenceObject(ClassObject
);
2526 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2527 ExFreePool(ClassName
.Buffer
);
2530 RtlFreeUnicodeString(&WindowName
);
2534 IntReleaseWindowObject(ChildAfter
);
2535 IntReleaseWindowObject(Parent
);
2545 NtUserFlashWindowEx(DWORD Unknown0
)
2557 NtUserGetAncestor(HWND hWnd
, UINT Type
)
2559 PWINDOW_OBJECT Wnd
, WndAncestor
, Parent
;
2562 if (hWnd
== IntGetDesktopWindow())
2567 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2569 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2577 WndAncestor
= IntGetParentObject(Wnd
);
2590 if(!(Parent
= IntGetParentObject(WndAncestor
)))
2594 if(IntIsDesktopWindow(Parent
))
2596 IntReleaseWindowObject(Parent
);
2600 IntReleaseWindowObject(tmp
);
2601 WndAncestor
= Parent
;
2609 IntReferenceWindowObject(WndAncestor
);
2614 Parent
= IntGetParent(WndAncestor
);
2615 IntReleaseWindowObject(Old
);
2620 WndAncestor
= Parent
;
2627 IntReleaseWindowObject(Wnd
);
2632 hWndAncestor
= (WndAncestor
? WndAncestor
->Self
: NULL
);
2633 IntReleaseWindowObject(Wnd
);
2635 if(WndAncestor
&& (WndAncestor
!= Wnd
))
2636 IntReleaseWindowObject(WndAncestor
);
2638 return hWndAncestor
;
2643 * Returns client window rectangle relative to the upper-left corner of client area.
2645 * \param hWnd window handle.
2646 * \param Rect pointer to the buffer where the coordinates are returned.
2653 NtUserGetClientRect(HWND hWnd
, LPRECT Rect
)
2655 PWINDOW_OBJECT WindowObject
;
2658 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
2660 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2664 IntGetClientRect(WindowObject
, &SafeRect
);
2665 IntReleaseWindowObject(WindowObject
);
2667 if(!NT_SUCCESS(MmCopyToCaller(Rect
, &SafeRect
, sizeof(RECT
))))
2679 NtUserGetDesktopWindow()
2681 return IntGetDesktopWindow();
2689 NtUserGetInternalWindowPos(DWORD Unknown0
,
2703 NtUserGetLastActivePopup(HWND hWnd
)
2706 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2707 * not changed anywhere.
2708 * -- Filip, 01/nov/2003
2714 IntAcquireWinLockShared();
2716 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2718 IntReleaseWinLock();
2719 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2723 hWndLastPopup
= Wnd
->hWndLastPopup
;
2725 IntReleaseWinLock();
2727 return hWndLastPopup
;
2736 * The NtUserGetParent function retrieves a handle to the specified window's
2740 * Note that, despite its name, this function can return an owner window
2741 * instead of a parent window.
2748 NtUserGetParent(HWND hWnd
)
2750 PWINDOW_OBJECT Wnd
, WndParent
;
2751 HWND hWndParent
= NULL
;
2753 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2755 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2759 WndParent
= IntGetParent(Wnd
);
2762 hWndParent
= WndParent
->Self
;
2763 IntReleaseWindowObject(WndParent
);
2766 IntReleaseWindowObject(Wnd
);
2774 * The NtUserSetParent function changes the parent window of the specified
2778 * The new parent window and the child window must belong to the same
2779 * application. If the window identified by the hWndChild parameter is
2780 * visible, the system performs the appropriate redrawing and repainting.
2781 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2782 * or WS_POPUP window styles of the window whose parent is being changed.
2789 NtUserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2791 PWINDOW_OBJECT Wnd
= NULL
, WndParent
= NULL
, WndOldParent
;
2792 HWND hWndOldParent
= NULL
;
2794 if (IntIsBroadcastHwnd(hWndChild
) || IntIsBroadcastHwnd(hWndNewParent
))
2796 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2800 if (hWndChild
== IntGetDesktopWindow())
2802 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2808 if (!(WndParent
= IntGetWindowObject(hWndNewParent
)))
2810 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2816 if (!(WndParent
= IntGetWindowObject(IntGetDesktopWindow())))
2818 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2823 if (!(Wnd
= IntGetWindowObject(hWndChild
)))
2825 IntReleaseWindowObject(WndParent
);
2826 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2830 WndOldParent
= IntSetParent(Wnd
, WndParent
);
2834 hWndOldParent
= WndOldParent
->Self
;
2835 IntReleaseWindowObject(WndOldParent
);
2838 IntReleaseWindowObject(Wnd
);
2839 IntReleaseWindowObject(WndParent
);
2841 return hWndOldParent
;
2845 * NtUserGetShellWindow
2847 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
2854 NtUserGetShellWindow()
2856 PWINSTATION_OBJECT WinStaObject
;
2859 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
2864 if (!NT_SUCCESS(Status
))
2866 SetLastNtError(Status
);
2870 Ret
= (HWND
)WinStaObject
->ShellWindow
;
2872 ObDereferenceObject(WinStaObject
);
2877 * NtUserSetShellWindowEx
2879 * This is undocumented function to set global shell window. The global
2880 * shell window has special handling of window position.
2887 NtUserSetShellWindowEx(HWND hwndShell
, HWND hwndListView
)
2889 PWINSTATION_OBJECT WinStaObject
;
2891 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
2896 if (!NT_SUCCESS(Status
))
2898 SetLastNtError(Status
);
2903 * Test if we are permitted to change the shell window.
2905 if (WinStaObject
->ShellWindow
)
2907 ObDereferenceObject(WinStaObject
);
2912 * Move shell window into background.
2914 if (hwndListView
&& hwndListView
!= hwndShell
)
2917 * Disabled for now to get Explorer working.
2918 * -- Filip, 01/nov/2003
2921 WinPosSetWindowPos(hwndListView
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2924 if (NtUserGetWindowLong(hwndListView
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2926 ObDereferenceObject(WinStaObject
);
2931 if (NtUserGetWindowLong(hwndShell
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2933 ObDereferenceObject(WinStaObject
);
2937 WinPosSetWindowPos(hwndShell
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2939 WinStaObject
->ShellWindow
= hwndShell
;
2940 WinStaObject
->ShellListView
= hwndListView
;
2942 ObDereferenceObject(WinStaObject
);
2947 * NtUserGetSystemMenu
2949 * The NtUserGetSystemMenu function allows the application to access the
2950 * window menu (also known as the system menu or the control menu) for
2951 * copying and modifying.
2955 * Handle to the window that will own a copy of the window menu.
2957 * Specifies the action to be taken. If this parameter is FALSE,
2958 * NtUserGetSystemMenu returns a handle to the copy of the window menu
2959 * currently in use. The copy is initially identical to the window menu
2960 * but it can be modified.
2961 * If this parameter is TRUE, GetSystemMenu resets the window menu back
2962 * to the default state. The previous window menu, if any, is destroyed.
2965 * If the bRevert parameter is FALSE, the return value is a handle to a
2966 * copy of the window menu. If the bRevert parameter is TRUE, the return
2974 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
2977 PWINDOW_OBJECT WindowObject
;
2978 PMENU_OBJECT MenuObject
;
2980 WindowObject
= IntGetWindowObject((HWND
)hWnd
);
2981 if (WindowObject
== NULL
)
2983 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2987 MenuObject
= IntGetSystemMenu(WindowObject
, bRevert
, FALSE
);
2990 Result
= MenuObject
->MenuInfo
.Self
;
2991 IntReleaseMenuObject(MenuObject
);
2994 IntReleaseWindowObject(WindowObject
);
2999 * NtUserSetSystemMenu
3006 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
3008 BOOL Result
= FALSE
;
3009 PWINDOW_OBJECT WindowObject
;
3010 PMENU_OBJECT MenuObject
;
3012 WindowObject
= IntGetWindowObject(hWnd
);
3015 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3022 * Assign new menu handle.
3024 MenuObject
= IntGetMenuObject(hMenu
);
3027 IntReleaseWindowObject(WindowObject
);
3028 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
3032 Result
= IntSetSystemMenu(WindowObject
, MenuObject
);
3034 IntReleaseMenuObject(MenuObject
);
3037 IntReleaseWindowObject(WindowObject
);
3045 * The NtUserGetWindow function retrieves a handle to a window that has the
3046 * specified relationship (Z order or owner) to the specified window.
3053 NtUserGetWindow(HWND hWnd
, UINT Relationship
)
3055 PWINDOW_OBJECT WindowObject
, Parent
;
3056 HWND hWndResult
= NULL
;
3058 if (!(WindowObject
= IntGetWindowObject(hWnd
)))
3060 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3064 switch (Relationship
)
3067 if((Parent
= IntGetParentObject(WindowObject
)))
3069 IntLockRelatives(Parent
);
3070 if (Parent
->FirstChild
)
3071 hWndResult
= Parent
->FirstChild
->Self
;
3072 IntUnLockRelatives(Parent
);
3073 IntReleaseWindowObject(Parent
);
3078 if((Parent
= IntGetParentObject(WindowObject
)))
3080 IntLockRelatives(Parent
);
3081 if (Parent
->LastChild
)
3082 hWndResult
= Parent
->LastChild
->Self
;
3083 IntUnLockRelatives(Parent
);
3084 IntReleaseWindowObject(Parent
);
3089 IntLockRelatives(WindowObject
);
3090 if (WindowObject
->NextSibling
)
3091 hWndResult
= WindowObject
->NextSibling
->Self
;
3092 IntUnLockRelatives(WindowObject
);
3096 IntLockRelatives(WindowObject
);
3097 if (WindowObject
->PrevSibling
)
3098 hWndResult
= WindowObject
->PrevSibling
->Self
;
3099 IntUnLockRelatives(WindowObject
);
3103 IntLockRelatives(WindowObject
);
3104 if((Parent
= IntGetWindowObject(WindowObject
->Owner
)))
3106 hWndResult
= Parent
->Self
;
3107 IntReleaseWindowObject(Parent
);
3109 IntUnLockRelatives(WindowObject
);
3112 IntLockRelatives(WindowObject
);
3113 if (WindowObject
->FirstChild
)
3114 hWndResult
= WindowObject
->FirstChild
->Self
;
3115 IntUnLockRelatives(WindowObject
);
3119 IntReleaseWindowObject(WindowObject
);
3125 * NtUserGetWindowLong
3127 * The NtUserGetWindowLong function retrieves information about the specified
3128 * window. The function also retrieves the 32-bit (long) value at the
3129 * specified offset into the extra window memory.
3136 NtUserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3138 PWINDOW_OBJECT WindowObject
, Parent
;
3141 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3143 WindowObject
= IntGetWindowObject(hWnd
);
3144 if (WindowObject
== NULL
)
3146 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3151 * Only allow CSRSS to mess with the desktop window
3153 if (hWnd
== IntGetDesktopWindow()
3154 && WindowObject
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
3156 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3160 if ((INT
)Index
>= 0)
3162 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
3164 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3167 Result
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
3174 Result
= WindowObject
->ExStyle
;
3178 Result
= WindowObject
->Style
;
3183 Result
= (LONG
) WindowObject
->WndProcA
;
3185 Result
= (LONG
) WindowObject
->WndProcW
;
3189 Result
= (LONG
) WindowObject
->Instance
;
3192 case GWL_HWNDPARENT
:
3193 IntLockRelatives(WindowObject
);
3194 Parent
= IntGetWindowObject(WindowObject
->Parent
);
3195 IntUnLockRelatives(WindowObject
);
3198 if (Parent
&& Parent
->Self
== IntGetDesktopWindow())
3199 Result
= (LONG
) NtUserGetWindow(WindowObject
->Self
, GW_OWNER
);
3201 Result
= (LONG
) Parent
->Self
;
3202 IntReleaseWindowObject(Parent
);
3207 Result
= (LONG
) WindowObject
->IDMenu
;
3211 Result
= WindowObject
->UserData
;
3215 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index
);
3216 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3222 IntReleaseWindowObject(WindowObject
);
3228 * NtUserSetWindowLong
3230 * The NtUserSetWindowLong function changes an attribute of the specified
3231 * window. The function also sets the 32-bit (long) value at the specified
3232 * offset into the extra window memory.
3239 NtUserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3241 PWINDOW_OBJECT WindowObject
, Parent
;
3242 PWINSTATION_OBJECT WindowStation
;
3246 if (hWnd
== IntGetDesktopWindow())
3248 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3252 WindowObject
= IntGetWindowObject(hWnd
);
3253 if (WindowObject
== NULL
)
3255 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3259 if ((INT
)Index
>= 0)
3261 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
3263 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3264 IntReleaseWindowObject(WindowObject
);
3267 OldValue
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
3268 *((LONG
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
3275 OldValue
= (LONG
) WindowObject
->ExStyle
;
3276 Style
.styleOld
= OldValue
;
3277 Style
.styleNew
= NewValue
;
3280 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3282 WindowStation
= WindowObject
->OwnerThread
->Tcb
.Win32Thread
->Desktop
->WindowStation
;
3285 if (hWnd
== WindowStation
->ShellWindow
|| hWnd
== WindowStation
->ShellListView
)
3286 Style
.styleNew
&= ~WS_EX_TOPMOST
;
3289 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3290 WindowObject
->ExStyle
= (DWORD
)Style
.styleNew
;
3291 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3295 OldValue
= (LONG
) WindowObject
->Style
;
3296 Style
.styleOld
= OldValue
;
3297 Style
.styleNew
= NewValue
;
3298 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_STYLE
, (LPARAM
) &Style
);
3299 WindowObject
->Style
= (DWORD
)Style
.styleNew
;
3300 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_STYLE
, (LPARAM
) &Style
);
3304 /* FIXME: should check if window belongs to current process */
3307 OldValue
= (LONG
) WindowObject
->WndProcA
;
3308 WindowObject
->WndProcA
= (WNDPROC
) NewValue
;
3309 WindowObject
->WndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,FALSE
);
3310 WindowObject
->Unicode
= FALSE
;
3314 OldValue
= (LONG
) WindowObject
->WndProcW
;
3315 WindowObject
->WndProcW
= (WNDPROC
) NewValue
;
3316 WindowObject
->WndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,TRUE
);
3317 WindowObject
->Unicode
= TRUE
;
3322 OldValue
= (LONG
) WindowObject
->Instance
;
3323 WindowObject
->Instance
= (HINSTANCE
) NewValue
;
3326 case GWL_HWNDPARENT
:
3327 Parent
= IntGetParentObject(WindowObject
);
3328 if (Parent
&& (Parent
->Self
== IntGetDesktopWindow()))
3329 OldValue
= (LONG
) IntSetOwner(WindowObject
->Self
, (HWND
) NewValue
);
3331 OldValue
= (LONG
) NtUserSetParent(WindowObject
->Self
, (HWND
) NewValue
);
3333 IntReleaseWindowObject(Parent
);
3337 OldValue
= (LONG
) WindowObject
->IDMenu
;
3338 WindowObject
->IDMenu
= (UINT
) NewValue
;
3342 OldValue
= WindowObject
->UserData
;
3343 WindowObject
->UserData
= NewValue
;
3347 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index
);
3348 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3354 IntReleaseWindowObject(WindowObject
);
3360 * NtUserSetWindowWord
3362 * Legacy function similar to NtUserSetWindowLong.
3369 NtUserSetWindowWord(HWND hWnd
, INT Index
, WORD NewValue
)
3371 PWINDOW_OBJECT WindowObject
;
3378 case GWL_HWNDPARENT
:
3379 return NtUserSetWindowLong(hWnd
, Index
, (UINT
)NewValue
, TRUE
);
3383 SetLastWin32Error(ERROR_INVALID_INDEX
);
3388 WindowObject
= IntGetWindowObject(hWnd
);
3389 if (WindowObject
== NULL
)
3391 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3395 if (Index
> WindowObject
->ExtraDataSize
- sizeof(WORD
))
3397 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3398 IntReleaseWindowObject(WindowObject
);
3402 OldValue
= *((WORD
*)(WindowObject
->ExtraData
+ Index
));
3403 *((WORD
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
3405 IntReleaseWindowObject(WindowObject
);
3414 NtUserGetWindowPlacement(HWND hWnd
,
3415 WINDOWPLACEMENT
*lpwndpl
)
3417 PWINDOW_OBJECT WindowObject
;
3418 PINTERNALPOS InternalPos
;
3420 WINDOWPLACEMENT Safepl
;
3423 WindowObject
= IntGetWindowObject(hWnd
);
3424 if (WindowObject
== NULL
)
3426 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3430 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3431 if(!NT_SUCCESS(Status
))
3433 SetLastNtError(Status
);
3434 IntReleaseWindowObject(WindowObject
);
3437 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3439 IntReleaseWindowObject(WindowObject
);
3444 Safepl
.showCmd
= ((WindowObject
->Flags
& WINDOWOBJECT_RESTOREMAX
) ? SW_MAXIMIZE
: SW_SHOWNORMAL
);
3446 Size
.x
= WindowObject
->WindowRect
.left
;
3447 Size
.y
= WindowObject
->WindowRect
.top
;
3448 InternalPos
= WinPosInitInternalPos(WindowObject
, &Size
,
3449 &WindowObject
->WindowRect
);
3452 Safepl
.rcNormalPosition
= InternalPos
->NormalRect
;
3453 Safepl
.ptMinPosition
= InternalPos
->IconPos
;
3454 Safepl
.ptMaxPosition
= InternalPos
->MaxPos
;
3458 IntReleaseWindowObject(WindowObject
);
3462 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3463 if(!NT_SUCCESS(Status
))
3465 SetLastNtError(Status
);
3466 IntReleaseWindowObject(WindowObject
);
3470 IntReleaseWindowObject(WindowObject
);
3476 * Return the dimension of the window in the screen coordinates.
3477 * \param hWnd window handle.
3478 * \param Rect pointer to the buffer where the coordinates are returned.
3484 NtUserGetWindowRect(HWND hWnd
, LPRECT Rect
)
3489 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3491 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3494 Status
= MmCopyToCaller(Rect
, &Wnd
->WindowRect
, sizeof(RECT
));
3495 if (!NT_SUCCESS(Status
))
3497 IntReleaseWindowObject(Wnd
);
3498 SetLastNtError(Status
);
3502 IntReleaseWindowObject(Wnd
);
3511 NtUserGetWindowThreadProcessId(HWND hWnd
, LPDWORD UnsafePid
)
3516 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3518 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3522 tid
= (DWORD
)IntGetWndThreadId(Wnd
);
3523 pid
= (DWORD
)IntGetWndProcessId(Wnd
);
3525 if (UnsafePid
) MmCopyToCaller(UnsafePid
, &pid
, sizeof(DWORD
));
3535 NtUserLockWindowUpdate(DWORD Unknown0
)
3555 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3556 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3557 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3561 QueryWindow based on KJK::Hyperion and James Tabor.
3563 0 = QWUniqueProcessId
3564 1 = QWUniqueThreadId
3565 4 = QWIsHung Implements IsHungAppWindow found
3568 9 = QWKillWindow When I called this with hWnd ==
3569 DesktopWindow, it shutdown the system
3576 NtUserQueryWindow(HWND hWnd
, DWORD Index
)
3578 PWINDOW_OBJECT Window
= IntGetWindowObject(hWnd
);
3583 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3589 case QUERY_WINDOW_UNIQUE_PROCESS_ID
:
3590 Result
= (DWORD
)IntGetWndProcessId(Window
);
3593 case QUERY_WINDOW_UNIQUE_THREAD_ID
:
3594 Result
= (DWORD
)IntGetWndThreadId(Window
);
3597 case QUERY_WINDOW_ISHUNG
:
3598 Result
= (DWORD
)MsqIsHung(Window
->MessageQueue
);
3602 Result
= (DWORD
)NULL
;
3606 IntReleaseWindowObject(Window
);
3616 NtUserRealChildWindowFromPoint(DWORD Unknown0
,
3630 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe
)
3632 UNICODE_STRING SafeMessageName
;
3636 if(MessageNameUnsafe
== NULL
)
3638 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3642 Status
= IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName
, MessageNameUnsafe
);
3643 if(!NT_SUCCESS(Status
))
3645 SetLastNtError(Status
);
3649 Ret
= (UINT
)IntAddAtom(SafeMessageName
.Buffer
);
3651 RtlFreeUnicodeString(&SafeMessageName
);
3660 NtUserSetImeOwnerWindow(DWORD Unknown0
,
3673 NtUserSetInternalWindowPos(DWORD Unknown0
,
3689 NtUserSetLayeredWindowAttributes(DWORD Unknown0
,
3704 NtUserSetLogonNotifyWindow(DWORD Unknown0
)
3721 PWINDOW_OBJECT WindowObject
;
3724 WindowObject
= IntGetWindowObject((HWND
) Wnd
);
3725 if (NULL
== WindowObject
)
3727 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3731 if (! IntSetMenu(WindowObject
, Menu
, &Changed
))
3733 IntReleaseWindowObject(WindowObject
);
3737 IntReleaseWindowObject(WindowObject
);
3739 if (Changed
&& Repaint
)
3741 WinPosSetWindowPos(Wnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
3742 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
3753 NtUserSetWindowFNID(DWORD Unknown0
,
3767 NtUserSetWindowPlacement(HWND hWnd
,
3768 WINDOWPLACEMENT
*lpwndpl
)
3770 PWINDOW_OBJECT WindowObject
;
3771 WINDOWPLACEMENT Safepl
;
3774 WindowObject
= IntGetWindowObject(hWnd
);
3775 if (WindowObject
== NULL
)
3777 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3780 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3781 if(!NT_SUCCESS(Status
))
3783 SetLastNtError(Status
);
3784 IntReleaseWindowObject(WindowObject
);
3787 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3789 IntReleaseWindowObject(WindowObject
);
3793 if ((WindowObject
->Style
& (WS_MAXIMIZE
| WS_MINIMIZE
)) == 0)
3795 WinPosSetWindowPos(WindowObject
->Self
, NULL
,
3796 Safepl
.rcNormalPosition
.left
, Safepl
.rcNormalPosition
.top
,
3797 Safepl
.rcNormalPosition
.right
- Safepl
.rcNormalPosition
.left
,
3798 Safepl
.rcNormalPosition
.bottom
- Safepl
.rcNormalPosition
.top
,
3799 SWP_NOZORDER
| SWP_NOACTIVATE
);
3802 /* FIXME - change window status */
3803 WinPosShowWindow(WindowObject
->Self
, Safepl
.showCmd
);
3805 if (WindowObject
->InternalPos
== NULL
)
3806 WindowObject
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
3807 WindowObject
->InternalPos
->NormalRect
= Safepl
.rcNormalPosition
;
3808 WindowObject
->InternalPos
->IconPos
= Safepl
.ptMinPosition
;
3809 WindowObject
->InternalPos
->MaxPos
= Safepl
.ptMaxPosition
;
3811 IntReleaseWindowObject(WindowObject
);
3822 HWND hWndInsertAfter
,
3829 return WinPosSetWindowPos(hWnd
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3834 IntGetWindowRgn(HWND hWnd
, HRGN hRgn
)
3837 PWINDOW_OBJECT WindowObject
;
3841 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
3843 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3848 IntReleaseWindowObject(WindowObject
);
3852 /* Create a new window region using the window rectangle */
3853 VisRgn
= UnsafeIntCreateRectRgnIndirect(&WindowObject
->WindowRect
);
3854 NtGdiOffsetRgn(VisRgn
, -WindowObject
->WindowRect
.left
, -WindowObject
->WindowRect
.top
);
3855 /* if there's a region assigned to the window, combine them both */
3856 if(WindowObject
->WindowRegion
&& !(WindowObject
->Style
& WS_MINIMIZE
))
3857 NtGdiCombineRgn(VisRgn
, VisRgn
, WindowObject
->WindowRegion
, RGN_AND
);
3858 /* Copy the region into hRgn */
3859 NtGdiCombineRgn(hRgn
, VisRgn
, NULL
, RGN_COPY
);
3861 if((pRgn
= RGNDATA_LockRgn(hRgn
)))
3863 Ret
= pRgn
->rdh
.iType
;
3864 RGNDATA_UnlockRgn(hRgn
);
3869 NtGdiDeleteObject(VisRgn
);
3871 IntReleaseWindowObject(WindowObject
);
3876 IntGetWindowRgnBox(HWND hWnd
, RECT
*Rect
)
3879 PWINDOW_OBJECT WindowObject
;
3883 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
3885 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3890 IntReleaseWindowObject(WindowObject
);
3894 /* Create a new window region using the window rectangle */
3895 VisRgn
= UnsafeIntCreateRectRgnIndirect(&WindowObject
->WindowRect
);
3896 NtGdiOffsetRgn(VisRgn
, -WindowObject
->WindowRect
.left
, -WindowObject
->WindowRect
.top
);
3897 /* if there's a region assigned to the window, combine them both */
3898 if(WindowObject
->WindowRegion
&& !(WindowObject
->Style
& WS_MINIMIZE
))
3899 NtGdiCombineRgn(VisRgn
, VisRgn
, WindowObject
->WindowRegion
, RGN_AND
);
3901 if((pRgn
= RGNDATA_LockRgn(VisRgn
)))
3903 Ret
= pRgn
->rdh
.iType
;
3904 *Rect
= pRgn
->rdh
.rcBound
;
3905 RGNDATA_UnlockRgn(VisRgn
);
3910 NtGdiDeleteObject(VisRgn
);
3912 IntReleaseWindowObject(WindowObject
);
3926 PWINDOW_OBJECT WindowObject
;
3928 WindowObject
= IntGetWindowObject(hWnd
);
3929 if (WindowObject
== NULL
)
3931 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3935 /* FIXME - Verify if hRgn is a valid handle!!!!
3936 Propably make this operation thread-safe, but maybe it's not necessary */
3938 if(WindowObject
->WindowRegion
)
3940 /* Delete no longer needed region handle */
3941 NtGdiDeleteObject(WindowObject
->WindowRegion
);
3943 WindowObject
->WindowRegion
= hRgn
;
3945 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
3949 IntRedrawWindow(WindowObject
, NULL
, NULL
, RDW_INVALIDATE
);
3952 IntReleaseWindowObject(WindowObject
);
3961 NtUserShowWindow(HWND hWnd
,
3964 return WinPosShowWindow(hWnd
, nCmdShow
);
3972 NtUserShowWindowAsync(DWORD Unknown0
,
3985 NtUserUpdateLayeredWindow(DWORD Unknown0
,
4005 NtUserValidateRect(HWND hWnd
, const RECT
* Rect
)
4007 return (VOID
)NtUserRedrawWindow(hWnd
, Rect
, 0, RDW_VALIDATE
| RDW_NOCHILDREN
);
4015 NtUserWindowFromPoint(LONG X
, LONG Y
)
4019 PWINDOW_OBJECT DesktopWindow
, Window
= NULL
;
4021 if ((DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow())))
4028 Hit
= WinPosWindowFromPoint(DesktopWindow
, PsGetWin32Thread()->MessageQueue
, &pt
, &Window
);
4033 IntReleaseWindowObject(Window
);
4034 IntReleaseWindowObject(DesktopWindow
);
4038 IntReleaseWindowObject(DesktopWindow
);
4048 * Undocumented function that is called from DefWindowProc to set
4056 NtUserDefSetText(HWND WindowHandle
, PUNICODE_STRING WindowText
)
4058 PWINDOW_OBJECT WindowObject
;
4059 UNICODE_STRING SafeText
;
4062 WindowObject
= IntGetWindowObject(WindowHandle
);
4065 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4071 Status
= IntSafeCopyUnicodeString(&SafeText
, WindowText
);
4072 if(!NT_SUCCESS(Status
))
4074 SetLastNtError(Status
);
4075 IntReleaseWindowObject(WindowObject
);
4081 RtlInitUnicodeString(&SafeText
, NULL
);
4084 /* FIXME - do this thread-safe! otherwise one could crash here! */
4085 RtlFreeUnicodeString(&WindowObject
->WindowName
);
4087 WindowObject
->WindowName
= SafeText
;
4089 IntReleaseWindowObject(WindowObject
);
4094 * NtUserInternalGetWindowText
4101 NtUserInternalGetWindowText(HWND hWnd
, LPWSTR lpString
, INT nMaxCount
)
4103 PWINDOW_OBJECT WindowObject
;
4107 if(lpString
&& (nMaxCount
<= 1))
4109 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
4113 WindowObject
= IntGetWindowObject(hWnd
);
4116 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4120 /* FIXME - do this thread-safe! otherwise one could crash here! */
4121 Result
= WindowObject
->WindowName
.Length
/ sizeof(WCHAR
);
4124 const WCHAR Terminator
= L
'\0';
4126 WCHAR
*Buffer
= (WCHAR
*)lpString
;
4128 Copy
= min(nMaxCount
- 1, Result
);
4131 Status
= MmCopyToCaller(Buffer
, WindowObject
->WindowName
.Buffer
, Copy
* sizeof(WCHAR
));
4132 if(!NT_SUCCESS(Status
))
4134 SetLastNtError(Status
);
4135 IntReleaseWindowObject(WindowObject
);
4141 Status
= MmCopyToCaller(Buffer
, &Terminator
, sizeof(WCHAR
));
4142 if(!NT_SUCCESS(Status
))
4144 SetLastNtError(Status
);
4145 IntReleaseWindowObject(WindowObject
);
4152 IntReleaseWindowObject(WindowObject
);
4157 NtUserDereferenceWndProcHandle(WNDPROC wpHandle
, WndProcHandle
*Data
)
4159 WndProcHandle Entry
;
4160 if (((DWORD
)wpHandle
& 0xFFFF0000) == 0xFFFF0000)
4162 Entry
= WndProcHandlesArray
[(DWORD
)wpHandle
& 0x0000FFFF];
4163 Data
->WindowProc
= Entry
.WindowProc
;
4164 Data
->IsUnicode
= Entry
.IsUnicode
;
4165 Data
->ProcessID
= Entry
.ProcessID
;
4174 IntAddWndProcHandle(WNDPROC WindowProc
, BOOL IsUnicode
)
4179 WndProcHandle
*OldArray
;
4182 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4184 if (WndProcHandlesArray
[i
].WindowProc
== NULL
)
4192 OldArray
= WndProcHandlesArray
;
4193 OldArraySize
= WndProcHandlesArraySize
;
4194 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,(OldArraySize
+ WPH_SIZE
) * sizeof(WndProcHandle
), TAG_WINPROCLST
);
4195 WndProcHandlesArraySize
= OldArraySize
+ WPH_SIZE
;
4196 RtlCopyMemory(WndProcHandlesArray
,OldArray
,OldArraySize
* sizeof(WndProcHandle
));
4197 ExFreePool(OldArray
);
4198 FreeSpot
= OldArraySize
+ 1;
4200 WndProcHandlesArray
[FreeSpot
].WindowProc
= WindowProc
;
4201 WndProcHandlesArray
[FreeSpot
].IsUnicode
= IsUnicode
;
4202 WndProcHandlesArray
[FreeSpot
].ProcessID
= PsGetCurrentProcessId();
4203 return FreeSpot
+ 0xFFFF0000;
4207 IntRemoveWndProcHandle(WNDPROC Handle
)
4210 position
= (DWORD
)Handle
& 0x0000FFFF;
4211 if (position
> WndProcHandlesArraySize
)
4215 WndProcHandlesArray
[position
].WindowProc
= NULL
;
4216 WndProcHandlesArray
[position
].IsUnicode
= FALSE
;
4217 WndProcHandlesArray
[position
].ProcessID
= NULL
;
4222 IntRemoveProcessWndProcHandles(HANDLE ProcessID
)
4225 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4227 if (WndProcHandlesArray
[i
].ProcessID
== ProcessID
)
4229 WndProcHandlesArray
[i
].WindowProc
= NULL
;
4230 WndProcHandlesArray
[i
].IsUnicode
= FALSE
;
4231 WndProcHandlesArray
[i
].ProcessID
= NULL
;