2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
23 * FILE: subsys/win32k/ntuser/window.c
24 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * 06-06-2001 CSH Created
29 /* INCLUDES ******************************************************************/
36 static WndProcHandle
*WndProcHandlesArray
= 0;
37 static WORD WndProcHandlesArraySize
= 0;
38 #define WPH_SIZE 0x40 /* the size to add to the WndProcHandle array each time */
40 /* dialog resources appear to pass this in 16 bits, handle them properly */
41 #define CW_USEDEFAULT16 (0x8000)
43 #define POINT_IN_RECT(p, r) (((r.bottom >= p.y) && (r.top <= p.y))&&((r.left <= p.x )&&( r.right >= p.x )))
45 /* PRIVATE FUNCTIONS **********************************************************/
50 * Initialize windowing implementation.
56 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,WPH_SIZE
* sizeof(WndProcHandle
), TAG_WINPROCLST
);
57 WndProcHandlesArraySize
= WPH_SIZE
;
58 return STATUS_SUCCESS
;
64 * Cleanup windowing implementation.
68 CleanupWindowImpl(VOID
)
70 ExFreePool(WndProcHandlesArray
);
71 WndProcHandlesArray
= 0;
72 WndProcHandlesArraySize
= 0;
73 return STATUS_SUCCESS
;
76 /* HELPER FUNCTIONS ***********************************************************/
81 * The function determines whether the specified window handle identifies
86 * Handle to the window to test.
89 * If the window handle identifies an existing window, the return value
90 * is TRUE. If the window handle does not identify an existing window,
91 * the return value is FALSE.
95 IntIsWindow(HWND hWnd
)
97 PWINDOW_OBJECT Window
;
99 if (!(Window
= IntGetWindowObject(hWnd
)))
102 IntReleaseWindowObject(Window
);
107 * IntGetProcessWindowObject
109 * Get window object from handle of specified process.
112 PWINDOW_OBJECT FASTCALL
113 IntGetProcessWindowObject(PW32THREAD Thread
, HWND hWnd
)
115 PWINDOW_OBJECT WindowObject
;
118 if(Thread
->Desktop
!= NULL
)
120 Status
= ObmReferenceObjectByHandle(Thread
->Desktop
->WindowStation
->HandleTable
,
121 hWnd
, otWindow
, (PVOID
*)&WindowObject
);
122 if (NT_SUCCESS(Status
))
131 PWINDOW_OBJECT FASTCALL
132 IntGetParent(PWINDOW_OBJECT Wnd
)
136 if (Wnd
->Style
& WS_POPUP
)
138 IntLockRelatives(Wnd
);
140 IntUnLockRelatives(Wnd
);
141 return IntGetWindowObject(hWnd
);
143 else if (Wnd
->Style
& WS_CHILD
)
145 IntLockRelatives(Wnd
);
147 IntUnLockRelatives(Wnd
);
148 return IntGetWindowObject(hWnd
);
154 PWINDOW_OBJECT FASTCALL
155 IntGetOwner(PWINDOW_OBJECT Wnd
)
159 IntLockRelatives(Wnd
);
161 IntUnLockRelatives(Wnd
);
163 return IntGetWindowObject(hWnd
);
166 PWINDOW_OBJECT FASTCALL
167 IntGetParentObject(PWINDOW_OBJECT Wnd
)
171 IntLockRelatives(Wnd
);
172 hParent
= Wnd
->Parent
;
173 IntUnLockRelatives(Wnd
);
174 return IntGetWindowObject(hParent
);
180 * Compile a list of all child window handles from given window.
183 * This function is similar to Wine WIN_ListChildren. The caller
184 * must free the returned list with ExFreePool.
188 IntWinListChildren(PWINDOW_OBJECT Window
)
190 PWINDOW_OBJECT Child
;
192 UINT Index
, NumChildren
= 0;
194 IntLockRelatives(Window
);
196 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
199 List
= ExAllocatePoolWithTag(PagedPool
, (NumChildren
+ 1) * sizeof(HWND
), TAG_WINLIST
);
202 DPRINT1("Failed to allocate memory for children array\n");
203 IntUnLockRelatives(Window
);
204 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
207 for (Child
= Window
->FirstChild
, Index
= 0;
209 Child
= Child
->NextSibling
, ++Index
)
210 List
[Index
] = Child
->Self
;
213 IntUnLockRelatives(Window
);
218 /***********************************************************************
221 static void IntSendDestroyMsg(HWND Wnd
)
224 PWINDOW_OBJECT Window
, Owner
, Parent
;
228 if (GetGUIThreadInfo(GetCurrentThreadId(), &info
))
230 if (Wnd
== info
.hwndCaret
)
237 Window
= IntGetWindowObject(Wnd
);
239 Owner
= IntGetOwner(Window
);
241 Parent
= IntGetParent(Window
);
243 IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
) Wnd
);
245 IntReleaseWindowObject(Parent
);
247 IntReleaseWindowObject(Owner
);
250 IntReleaseWindowObject(Window
);
253 /* The window could already be destroyed here */
256 * Send the WM_DESTROY to the window.
259 IntSendMessage(Wnd
, WM_DESTROY
, 0, 0);
262 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
263 * make sure that the window still exists when we come back.
271 if (!(pWndArray
= WIN_ListChildren( hwnd
))) return;
273 /* start from the end (FIXME: is this needed?) */
274 for (i
= 0; pWndArray
[i
]; i
++) ;
278 if (IsWindow( pWndArray
[i
] )) WIN_SendDestroyMsg( pWndArray
[i
] );
280 HeapFree(GetProcessHeap(), 0, pWndArray
);
284 DPRINT("destroyed itself while in WM_DESTROY!\n");
289 /***********************************************************************
292 * Destroy storage associated to a window. "Internals" p.358
294 static LRESULT
IntDestroyWindow(PWINDOW_OBJECT Window
,
295 PW32PROCESS ProcessData
,
296 PW32THREAD ThreadData
,
297 BOOLEAN SendMessages
)
301 PWINDOW_OBJECT Child
;
303 BOOLEAN BelongsToThreadData
;
307 IntLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
308 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
310 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
311 DPRINT("Tried to call IntDestroyWindow() twice\n");
314 Window
->Status
|= WINDOWSTATUS_DESTROYING
;
315 Window
->Flags
&= ~WS_VISIBLE
;
316 /* remove the window already at this point from the thread window list so we
317 don't get into trouble when destroying the thread windows while we're still
318 in IntDestroyWindow() */
319 RemoveEntryList(&Window
->ThreadListEntry
);
320 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
322 BelongsToThreadData
= IntWndBelongsToThread(Window
, ThreadData
);
324 IntDeRegisterShellHookWindow(Window
->Self
);
328 /* Send destroy messages */
329 IntSendDestroyMsg(Window
->Self
);
332 /* free child windows */
333 Children
= IntWinListChildren(Window
);
336 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
338 if ((Child
= IntGetWindowObject(*ChildHandle
)))
340 if(!IntWndBelongsToThread(Child
, ThreadData
))
342 /* send WM_DESTROY messages to windows not belonging to the same thread */
343 IntSendDestroyMsg(Child
->Self
);
346 IntDestroyWindow(Child
, ProcessData
, ThreadData
, SendMessages
);
347 IntReleaseWindowObject(Child
);
350 ExFreePool(Children
);
356 * Clear the update region to make sure no WM_PAINT messages will be
357 * generated for this window while processing the WM_NCDESTROY.
359 IntRedrawWindow(Window
, NULL
, 0,
360 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
|
361 RDW_NOINTERNALPAINT
| RDW_NOCHILDREN
);
362 if(BelongsToThreadData
)
363 IntSendMessage(Window
->Self
, WM_NCDESTROY
, 0, 0);
365 MsqRemoveTimersWindow(ThreadData
->MessageQueue
, Window
->Self
);
367 /* flush the message queue */
368 MsqRemoveWindowMessagesFromQueue(Window
);
370 /* from now on no messages can be sent to this window anymore */
371 IntLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
372 Window
->Status
|= WINDOWSTATUS_DESTROYED
;
373 /* don't remove the WINDOWSTATUS_DESTROYING bit */
374 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
376 /* reset shell window handles */
377 if(ThreadData
->Desktop
)
379 if (Window
->Self
== ThreadData
->Desktop
->WindowStation
->ShellWindow
)
380 ThreadData
->Desktop
->WindowStation
->ShellWindow
= NULL
;
382 if (Window
->Self
== ThreadData
->Desktop
->WindowStation
->ShellListView
)
383 ThreadData
->Desktop
->WindowStation
->ShellListView
= NULL
;
386 /* Unregister hot keys */
387 UnregisterWindowHotKeys (Window
);
389 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
392 WinPosCheckInternalPos(Window
->Self
);
393 if (Window
->Self
== GetCapture())
398 /* free resources associated with the window */
399 TIMER_RemoveWindowTimers(Window
->Self
);
402 if (!(Window
->Style
& WS_CHILD
) && Window
->IDMenu
403 && (Menu
= IntGetMenuObject((HMENU
)Window
->IDMenu
)))
405 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
407 IntReleaseMenuObject(Menu
);
410 if(Window
->SystemMenu
411 && (Menu
= IntGetMenuObject(Window
->SystemMenu
)))
413 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
414 Window
->SystemMenu
= (HMENU
)0;
415 IntReleaseMenuObject(Menu
);
418 DceFreeWindowDCE(Window
); /* Always do this to catch orphaned DCs */
420 WINPROC_FreeProc(Window
->winproc
, WIN_PROC_WINDOW
);
421 CLASS_RemoveWindow(Window
->Class
);
424 IntUnlinkWindow(Window
);
426 IntReferenceWindowObject(Window
);
427 ObmCloseHandle(ThreadData
->Desktop
->WindowStation
->HandleTable
, Window
->Self
);
429 IntDestroyScrollBars(Window
);
431 /* remove the window from the class object */
432 IntLockClassWindows(Window
->Class
);
433 RemoveEntryList(&Window
->ClassListEntry
);
434 IntUnLockClassWindows(Window
->Class
);
436 /* dereference the class */
437 ClassDereferenceObject(Window
->Class
);
438 Window
->Class
= NULL
;
440 if(Window
->WindowRegion
)
442 NtGdiDeleteObject(Window
->WindowRegion
);
445 RtlFreeUnicodeString(&Window
->WindowName
);
447 IntReleaseWindowObject(Window
);
453 IntGetWindowBorderMeasures(PWINDOW_OBJECT WindowObject
, UINT
*cx
, UINT
*cy
)
455 if(HAS_DLGFRAME(WindowObject
->Style
, WindowObject
->ExStyle
) && !(WindowObject
->Style
& WS_MINIMIZE
))
457 *cx
= NtUserGetSystemMetrics(SM_CXDLGFRAME
);
458 *cy
= NtUserGetSystemMetrics(SM_CYDLGFRAME
);
462 if(HAS_THICKFRAME(WindowObject
->Style
, WindowObject
->ExStyle
)&& !(WindowObject
->Style
& WS_MINIMIZE
))
464 *cx
= NtUserGetSystemMetrics(SM_CXFRAME
);
465 *cy
= NtUserGetSystemMetrics(SM_CYFRAME
);
467 else if(HAS_THINFRAME(WindowObject
->Style
, WindowObject
->ExStyle
))
469 *cx
= NtUserGetSystemMetrics(SM_CXBORDER
);
470 *cy
= NtUserGetSystemMetrics(SM_CYBORDER
);
480 IntGetWindowInfo(PWINDOW_OBJECT WindowObject
, PWINDOWINFO pwi
)
482 pwi
->cbSize
= sizeof(WINDOWINFO
);
483 pwi
->rcWindow
= WindowObject
->WindowRect
;
484 pwi
->rcClient
= WindowObject
->ClientRect
;
485 pwi
->dwStyle
= WindowObject
->Style
;
486 pwi
->dwExStyle
= WindowObject
->ExStyle
;
487 pwi
->dwWindowStatus
= (NtUserGetForegroundWindow() == WindowObject
->Self
); /* WS_ACTIVECAPTION */
488 IntGetWindowBorderMeasures(WindowObject
, &pwi
->cxWindowBorders
, &pwi
->cyWindowBorders
);
489 pwi
->atomWindowType
= (WindowObject
->Class
? WindowObject
->Class
->Atom
: 0);
490 pwi
->wCreatorVersion
= 0x400; /* FIXME - return a real version number */
496 PWINDOW_OBJECT WindowObject
,
500 PMENU_OBJECT OldMenuObject
, NewMenuObject
= NULL
;
502 if ((WindowObject
->Style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
504 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
508 *Changed
= (WindowObject
->IDMenu
!= (UINT
) Menu
);
514 if (WindowObject
->IDMenu
)
516 OldMenuObject
= IntGetMenuObject((HMENU
) WindowObject
->IDMenu
);
517 ASSERT(NULL
== OldMenuObject
|| OldMenuObject
->MenuInfo
.Wnd
== WindowObject
->Self
);
521 OldMenuObject
= NULL
;
526 NewMenuObject
= IntGetMenuObject(Menu
);
527 if (NULL
== NewMenuObject
)
529 if (NULL
!= OldMenuObject
)
531 IntReleaseMenuObject(OldMenuObject
);
533 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
536 if (NULL
!= NewMenuObject
->MenuInfo
.Wnd
)
538 /* Can't use the same menu for two windows */
539 if (NULL
!= OldMenuObject
)
541 IntReleaseMenuObject(OldMenuObject
);
543 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
549 WindowObject
->IDMenu
= (UINT
) Menu
;
550 if (NULL
!= NewMenuObject
)
552 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
553 IntReleaseMenuObject(NewMenuObject
);
555 if (NULL
!= OldMenuObject
)
557 OldMenuObject
->MenuInfo
.Wnd
= NULL
;
558 IntReleaseMenuObject(OldMenuObject
);
565 /* INTERNAL ******************************************************************/
569 DestroyThreadWindows(struct _ETHREAD
*Thread
)
572 PW32PROCESS Win32Process
;
573 PW32THREAD Win32Thread
;
574 PWINDOW_OBJECT
*List
, *pWnd
;
577 Win32Thread
= Thread
->Tcb
.Win32Thread
;
578 Win32Process
= (PW32PROCESS
)Thread
->ThreadsProcess
->Win32Process
;
580 IntLockThreadWindows(Win32Thread
);
581 Current
= Win32Thread
->WindowListHead
.Flink
;
582 while (Current
!= &(Win32Thread
->WindowListHead
))
585 Current
= Current
->Flink
;
590 List
= ExAllocatePool(PagedPool
, (Cnt
+ 1) * sizeof(PWINDOW_OBJECT
));
593 DPRINT("Not enough memory to allocate window handle list\n");
594 IntUnLockThreadWindows(Win32Thread
);
598 Current
= Win32Thread
->WindowListHead
.Flink
;
599 while (Current
!= &(Win32Thread
->WindowListHead
))
601 *pWnd
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
602 IntReferenceWindowObject(*pWnd
);
604 Current
= Current
->Flink
;
606 IntUnLockThreadWindows(Win32Thread
);
609 for(pWnd
= List
; *pWnd
; pWnd
++)
611 NtUserDestroyWindow((*pWnd
)->Self
);
612 IntReleaseWindowObject(*pWnd
);
618 IntUnLockThreadWindows(Win32Thread
);
624 * Returns client window rectangle relative to the upper-left corner of client area.
626 * \note Does not check the validity of the parameters
629 IntGetClientRect(PWINDOW_OBJECT WindowObject
, PRECT Rect
)
631 ASSERT( WindowObject
);
634 Rect
->left
= Rect
->top
= 0;
635 Rect
->right
= WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
;
636 Rect
->bottom
= WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
;
642 IntGetFocusWindow(VOID
)
644 PUSER_MESSAGE_QUEUE Queue
;
645 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
650 Queue
= (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
655 return(Queue
->FocusWindow
);
659 PMENU_OBJECT FASTCALL
660 IntGetSystemMenu(PWINDOW_OBJECT WindowObject
, BOOL bRevert
, BOOL RetMenu
)
662 PMENU_OBJECT MenuObject
, NewMenuObject
, SysMenuObject
, ret
= NULL
;
663 PW32THREAD W32Thread
;
664 HMENU NewMenu
, SysMenu
;
665 ROSMENUITEMINFO ItemInfo
;
669 W32Thread
= PsGetWin32Thread();
671 if(!W32Thread
->Desktop
)
674 if(WindowObject
->SystemMenu
)
676 MenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
679 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
680 WindowObject
->SystemMenu
= (HMENU
)0;
681 IntReleaseMenuObject(MenuObject
);
685 if(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
)
687 /* clone system menu */
688 MenuObject
= IntGetMenuObject(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
);
692 NewMenuObject
= IntCloneMenu(MenuObject
);
695 WindowObject
->SystemMenu
= NewMenuObject
->MenuInfo
.Self
;
696 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
697 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
699 //IntReleaseMenuObject(NewMenuObject);
701 IntReleaseMenuObject(MenuObject
);
705 SysMenu
= NtUserCreateMenu(FALSE
);
710 SysMenuObject
= IntGetMenuObject(SysMenu
);
711 if (NULL
== SysMenuObject
)
713 NtUserDestroyMenu(SysMenu
);
716 SysMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
717 SysMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
718 NewMenu
= IntLoadSysMenuTemplate();
721 IntReleaseMenuObject(SysMenuObject
);
722 NtUserDestroyMenu(SysMenu
);
725 MenuObject
= IntGetMenuObject(NewMenu
);
728 IntReleaseMenuObject(SysMenuObject
);
729 NtUserDestroyMenu(SysMenu
);
733 NewMenuObject
= IntCloneMenu(MenuObject
);
736 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
| MF_POPUP
;
737 IntReleaseMenuObject(NewMenuObject
);
738 NtUserSetMenuDefaultItem(NewMenuObject
->MenuInfo
.Self
, SC_CLOSE
, FALSE
);
740 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
741 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
742 ItemInfo
.fType
= MF_POPUP
;
743 ItemInfo
.fState
= MFS_ENABLED
;
744 ItemInfo
.dwTypeData
= NULL
;
746 ItemInfo
.hSubMenu
= NewMenuObject
->MenuInfo
.Self
;
747 IntInsertMenuItem(SysMenuObject
, (UINT
) -1, TRUE
, &ItemInfo
);
749 WindowObject
->SystemMenu
= SysMenuObject
->MenuInfo
.Self
;
753 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
754 IntReleaseMenuObject(MenuObject
);
763 if(WindowObject
->SystemMenu
)
764 return IntGetMenuObject((HMENU
)WindowObject
->SystemMenu
);
772 IntIsChildWindow(HWND Parent
, HWND Child
)
774 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
776 if(!(BaseWindow
= IntGetWindowObject(Child
)))
784 if (Window
->Self
== Parent
)
786 if(Window
!= BaseWindow
)
787 IntReleaseWindowObject(Window
);
788 IntReleaseWindowObject(BaseWindow
);
791 if(!(Window
->Style
& WS_CHILD
))
793 if(Window
!= BaseWindow
)
794 IntReleaseWindowObject(Window
);
798 Window
= IntGetParentObject(Window
);
799 if(Old
!= BaseWindow
)
800 IntReleaseWindowObject(Old
);
803 IntReleaseWindowObject(BaseWindow
);
808 IntIsWindowVisible(HWND hWnd
)
810 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
812 if(!(BaseWindow
= IntGetWindowObject(hWnd
)))
820 if(!(Window
->Style
& WS_CHILD
))
824 if(!(Window
->Style
& WS_VISIBLE
))
826 if(Window
!= BaseWindow
)
827 IntReleaseWindowObject(Window
);
828 IntReleaseWindowObject(BaseWindow
);
832 Window
= IntGetParentObject(Window
);
833 if(Old
!= BaseWindow
)
834 IntReleaseWindowObject(Old
);
839 if(Window
->Style
& WS_VISIBLE
)
841 if(Window
!= BaseWindow
)
842 IntReleaseWindowObject(Window
);
843 IntReleaseWindowObject(BaseWindow
);
846 if(Window
!= BaseWindow
)
847 IntReleaseWindowObject(Window
);
849 IntReleaseWindowObject(BaseWindow
);
854 /* link the window into siblings and parent. children are kept in place. */
858 PWINDOW_OBJECT WndParent
,
859 PWINDOW_OBJECT WndPrevSibling
/* set to NULL if top sibling */
862 PWINDOW_OBJECT Parent
;
864 IntLockRelatives(Wnd
);
865 Wnd
->Parent
= WndParent
->Self
;
866 if ((Wnd
->PrevSibling
= WndPrevSibling
))
868 /* link after WndPrevSibling */
869 if ((Wnd
->NextSibling
= WndPrevSibling
->NextSibling
))
870 Wnd
->NextSibling
->PrevSibling
= Wnd
;
871 else if ((Parent
= IntGetWindowObject(Wnd
->Parent
)))
873 IntLockRelatives(Parent
);
874 if(Parent
->LastChild
== WndPrevSibling
)
875 Parent
->LastChild
= Wnd
;
876 IntUnLockRelatives(Parent
);
877 IntReleaseWindowObject(Parent
);
879 Wnd
->PrevSibling
->NextSibling
= Wnd
;
884 Parent
= IntGetWindowObject(Wnd
->Parent
);
885 if ((Wnd
->NextSibling
= WndParent
->FirstChild
))
886 Wnd
->NextSibling
->PrevSibling
= Wnd
;
889 IntLockRelatives(Parent
);
890 Parent
->LastChild
= Wnd
;
891 Parent
->FirstChild
= Wnd
;
892 IntUnLockRelatives(Parent
);
893 IntReleaseWindowObject(Parent
);
894 IntUnLockRelatives(Wnd
);
899 IntLockRelatives(Parent
);
900 Parent
->FirstChild
= Wnd
;
901 IntUnLockRelatives(Parent
);
902 IntReleaseWindowObject(Parent
);
905 IntUnLockRelatives(Wnd
);
909 IntSetOwner(HWND hWnd
, HWND hWndNewOwner
)
911 PWINDOW_OBJECT Wnd
, WndOldOwner
, WndNewOwner
;
914 Wnd
= IntGetWindowObject(hWnd
);
918 IntLockRelatives(Wnd
);
919 WndOldOwner
= IntGetWindowObject(Wnd
->Owner
);
922 ret
= WndOldOwner
->Self
;
923 IntReleaseWindowObject(WndOldOwner
);
930 if((WndNewOwner
= IntGetWindowObject(hWndNewOwner
)))
932 Wnd
->Owner
= hWndNewOwner
;
933 IntReleaseWindowObject(WndNewOwner
);
938 IntUnLockRelatives(Wnd
);
939 IntReleaseWindowObject(Wnd
);
943 PWINDOW_OBJECT FASTCALL
944 IntSetParent(PWINDOW_OBJECT Wnd
, PWINDOW_OBJECT WndNewParent
)
946 PWINDOW_OBJECT WndOldParent
, Sibling
, InsertAfter
;
947 HWND hWnd
, hWndNewParent
, hWndOldParent
;
952 ASSERT(WndNewParent
);
955 hWndNewParent
= WndNewParent
->Self
;
958 * Windows hides the window first, then shows it again
959 * including the WM_SHOWWINDOW messages and all
961 WasVisible
= WinPosShowWindow(hWnd
, SW_HIDE
);
963 /* Validate that window and parent still exist */
964 if (!IntIsWindow(hWnd
) || !IntIsWindow(hWndNewParent
))
967 /* Window must belong to current process */
968 if (Wnd
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
971 WndOldParent
= IntGetParentObject(Wnd
);
972 hWndOldParent
= (WndOldParent
? WndOldParent
->Self
: NULL
);
974 if (WndNewParent
!= WndOldParent
)
976 IntUnlinkWindow(Wnd
);
978 if (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
))
980 /* Not a TOPMOST window, put after TOPMOSTs of new parent */
981 IntLockRelatives(WndNewParent
);
982 Sibling
= WndNewParent
->FirstChild
;
983 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
985 InsertAfter
= Sibling
;
986 Sibling
= Sibling
->NextSibling
;
988 IntUnLockRelatives(WndNewParent
);
990 if (NULL
== InsertAfter
)
992 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
996 IntReferenceWindowObject(InsertAfter
);
997 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
998 IntReleaseWindowObject(InsertAfter
);
1001 if (WndNewParent
->Self
!= IntGetDesktopWindow()) /* a child window */
1003 if (!(Wnd
->Style
& WS_CHILD
))
1005 //if ( Wnd->Menu ) DestroyMenu ( Wnd->menu );
1006 IntSetMenu(Wnd
, NULL
, &MenuChanged
);
1012 * SetParent additionally needs to make hwnd the top window
1013 * in the z-order and send the expected WM_WINDOWPOSCHANGING and
1014 * WM_WINDOWPOSCHANGED notification messages.
1016 WinPosSetWindowPos(hWnd
, (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOP
: HWND_TOPMOST
),
1017 0, 0, 0, 0, SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
1018 | (WasVisible
? SWP_SHOWWINDOW
: 0));
1021 * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
1022 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
1026 * Validate that the old parent still exist, since it migth have been
1027 * destroyed during the last callbacks to user-mode
1031 if(!IntIsWindow(WndOldParent
->Self
))
1033 IntReleaseWindowObject(WndOldParent
);
1037 /* don't dereference the window object here, it must be done by the caller
1038 of IntSetParent() */
1039 return WndOldParent
;
1045 IntSetSystemMenu(PWINDOW_OBJECT WindowObject
, PMENU_OBJECT MenuObject
)
1047 PMENU_OBJECT OldMenuObject
;
1048 if(WindowObject
->SystemMenu
)
1050 OldMenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
1053 OldMenuObject
->MenuInfo
.Flags
&= ~ MF_SYSMENU
;
1054 IntReleaseMenuObject(OldMenuObject
);
1060 /* FIXME check window style, propably return FALSE ? */
1061 WindowObject
->SystemMenu
= MenuObject
->MenuInfo
.Self
;
1062 MenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
1065 WindowObject
->SystemMenu
= (HMENU
)0;
1071 /* unlink the window from siblings and parent. children are kept in place. */
1073 IntUnlinkWindow(PWINDOW_OBJECT Wnd
)
1075 PWINDOW_OBJECT WndParent
;
1077 IntLockRelatives(Wnd
);
1078 if((WndParent
= IntGetWindowObject(Wnd
->Parent
)))
1080 IntLockRelatives(WndParent
);
1083 if (Wnd
->NextSibling
) Wnd
->NextSibling
->PrevSibling
= Wnd
->PrevSibling
;
1084 else if (WndParent
&& WndParent
->LastChild
== Wnd
) WndParent
->LastChild
= Wnd
->PrevSibling
;
1086 if (Wnd
->PrevSibling
) Wnd
->PrevSibling
->NextSibling
= Wnd
->NextSibling
;
1087 else if (WndParent
&& WndParent
->FirstChild
== Wnd
) WndParent
->FirstChild
= Wnd
->NextSibling
;
1091 IntUnLockRelatives(WndParent
);
1092 IntReleaseWindowObject(WndParent
);
1094 Wnd
->PrevSibling
= Wnd
->NextSibling
= Wnd
->Parent
= NULL
;
1095 IntUnLockRelatives(Wnd
);
1101 PWINDOW_OBJECT Window
, Child
;
1103 if(!(Window
= IntGetWindowObject(IntGetDesktopWindow())))
1105 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1109 IntLockRelatives(Window
);
1110 for(Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
1112 if(Child
->Owner
&& Child
->Style
& WS_VISIBLE
)
1115 * The desktop has a popup window if one of them has
1116 * an owner window and is visible
1118 IntUnLockRelatives(Window
);
1119 IntReleaseWindowObject(Window
);
1123 IntUnLockRelatives(Window
);
1124 IntReleaseWindowObject(Window
);
1129 IntIsWindowInDestroy(PWINDOW_OBJECT Window
)
1131 return ((Window
->Status
& WINDOWSTATUS_DESTROYING
) == WINDOWSTATUS_DESTROYING
);
1134 /* FUNCTIONS *****************************************************************/
1140 NtUserAlterWindowStyle(DWORD Unknown0
,
1151 * As best as I can figure, this function is used by EnumWindows,
1152 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
1154 * It's supposed to build a list of HWNDs to return to the caller.
1155 * We can figure out what kind of list by what parameters are
1163 NtUserBuildHwndList(
1175 /* FIXME handle bChildren */
1179 PWINDOW_OBJECT Window
, Child
;
1180 if(!(Window
= IntGetWindowObject(hwndParent
)))
1182 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1186 IntLockRelatives(Window
);
1187 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1189 if(dwCount
++ < nBufSize
&& pWnd
)
1191 Status
= MmCopyToCaller(pWnd
++, &Child
->Self
, sizeof(HWND
));
1192 if(!NT_SUCCESS(Status
))
1194 SetLastNtError(Status
);
1199 IntUnLockRelatives(Window
);
1201 IntReleaseWindowObject(Window
);
1206 PW32THREAD W32Thread
;
1207 PLIST_ENTRY Current
;
1208 PWINDOW_OBJECT Window
;
1210 Status
= PsLookupThreadByThreadId((HANDLE
)dwThreadId
, &Thread
);
1211 if(!NT_SUCCESS(Status
))
1213 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1216 if(!(W32Thread
= Thread
->Tcb
.Win32Thread
))
1218 ObDereferenceObject(Thread
);
1219 DPRINT("Thread is not a GUI Thread!\n");
1220 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1224 IntLockThreadWindows(W32Thread
);
1225 Current
= W32Thread
->WindowListHead
.Flink
;
1226 while(Current
!= &(W32Thread
->WindowListHead
))
1228 Window
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
1231 if(dwCount
< nBufSize
&& pWnd
)
1233 Status
= MmCopyToCaller(pWnd
++, &Window
->Self
, sizeof(HWND
));
1234 if(!NT_SUCCESS(Status
))
1236 SetLastNtError(Status
);
1241 Current
= Current
->Flink
;
1243 IntUnLockThreadWindows(W32Thread
);
1245 ObDereferenceObject(Thread
);
1249 PDESKTOP_OBJECT Desktop
;
1250 PWINDOW_OBJECT Window
, Child
;
1252 if(hDesktop
== NULL
&& !(Desktop
= IntGetActiveDesktop()))
1254 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1260 Status
= IntValidateDesktopHandle(hDesktop
,
1264 if(!NT_SUCCESS(Status
))
1266 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1270 if(!(Window
= IntGetWindowObject(Desktop
->DesktopWindow
)))
1273 ObDereferenceObject(Desktop
);
1274 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1278 IntLockRelatives(Window
);
1279 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1281 if(dwCount
++ < nBufSize
&& pWnd
)
1283 Status
= MmCopyToCaller(pWnd
++, &Child
->Self
, sizeof(HWND
));
1284 if(!NT_SUCCESS(Status
))
1286 SetLastNtError(Status
);
1291 IntUnLockRelatives(Window
);
1293 IntReleaseWindowObject(Window
);
1295 ObDereferenceObject(Desktop
);
1306 NtUserChildWindowFromPointEx(HWND hwndParent
,
1311 PWINDOW_OBJECT Parent
;
1316 if(!(Parent
= IntGetWindowObject(hwndParent
)))
1318 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1325 if(Parent
->Self
!= IntGetDesktopWindow())
1327 Pt
.x
+= Parent
->ClientRect
.left
;
1328 Pt
.y
+= Parent
->ClientRect
.top
;
1331 if(!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
))
1333 IntReleaseWindowObject(Parent
);
1338 if((List
= IntWinListChildren(Parent
)))
1340 for(phWnd
= List
; *phWnd
; phWnd
++)
1342 PWINDOW_OBJECT Child
;
1343 if((Child
= IntGetWindowObject(*phWnd
)))
1345 if(!(Child
->Style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
))
1347 IntReleaseWindowObject(Child
);
1350 if((Child
->Style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
))
1352 IntReleaseWindowObject(Child
);
1355 if((Child
->ExStyle
& WS_EX_TRANSPARENT
) && (uiFlags
& CWP_SKIPTRANSPARENT
))
1357 IntReleaseWindowObject(Child
);
1360 if(IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
1363 IntReleaseWindowObject(Child
);
1366 IntReleaseWindowObject(Child
);
1372 IntReleaseWindowObject(Parent
);
1378 * calculates the default position of a window
1381 IntCalcDefPosSize(PWINDOW_OBJECT Parent
, PWINDOW_OBJECT WindowObject
, RECT
*rc
, BOOL IncPos
)
1388 IntGdiIntersectRect(rc
, rc
, &Parent
->ClientRect
);
1392 Pos
.x
= Parent
->TiledCounter
* (NtUserGetSystemMetrics(SM_CXSIZE
) + NtUserGetSystemMetrics(SM_CXFRAME
));
1393 Pos
.y
= Parent
->TiledCounter
* (NtUserGetSystemMetrics(SM_CYSIZE
) + NtUserGetSystemMetrics(SM_CYFRAME
));
1394 if(Pos
.x
> ((rc
->right
- rc
->left
) / 4) ||
1395 Pos
.y
> ((rc
->bottom
- rc
->top
) / 4))
1397 /* reset counter and position */
1400 Parent
->TiledCounter
= 0;
1402 Parent
->TiledCounter
++;
1413 Sz
.cx
= EngMulDiv(rc
->right
- rc
->left
, 3, 4);
1414 Sz
.cy
= EngMulDiv(rc
->bottom
- rc
->top
, 3, 4);
1418 rc
->right
= rc
->left
+ Sz
.cx
;
1419 rc
->bottom
= rc
->top
+ Sz
.cy
;
1428 IntCreateWindowEx(DWORD dwExStyle
,
1429 PUNICODE_STRING ClassName
,
1430 PUNICODE_STRING WindowName
,
1438 HINSTANCE hInstance
,
1441 BOOL bUnicodeWindow
)
1443 PWINSTATION_OBJECT WinStaObject
;
1444 PWNDCLASS_OBJECT ClassObject
;
1445 PWINDOW_OBJECT WindowObject
;
1446 PWINDOW_OBJECT ParentWindow
, OwnerWindow
;
1447 HWND ParentWindowHandle
;
1448 HWND OwnerWindowHandle
;
1449 PMENU_OBJECT SystemMenu
;
1454 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1459 CBT_CREATEWNDW CbtCreate
;
1466 ParentWindowHandle
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
1467 OwnerWindowHandle
= NULL
;
1469 if (hWndParent
== HWND_MESSAGE
)
1472 * native ole32.OleInitialize uses HWND_MESSAGE to create the
1473 * message window (style: WS_POPUP|WS_DISABLED)
1475 DPRINT1("FIXME - Parent is HWND_MESSAGE\n");
1477 else if (hWndParent
)
1479 if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1480 ParentWindowHandle
= hWndParent
;
1482 OwnerWindowHandle
= NtUserGetAncestor(hWndParent
, GA_ROOT
);
1484 else if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1486 return (HWND
)0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1489 if (NULL
!= ParentWindowHandle
)
1491 ParentWindow
= IntGetWindowObject(ParentWindowHandle
);
1495 ParentWindow
= NULL
;
1498 /* FIXME: parent must belong to the current process */
1500 /* Check the class. */
1501 ClassFound
= ClassReferenceClassByNameOrAtom(&ClassObject
, ClassName
->Buffer
, hInstance
);
1504 if (IS_ATOM(ClassName
->Buffer
))
1506 DPRINT1("Class 0x%x not found\n", (DWORD_PTR
) ClassName
->Buffer
);
1510 DPRINT1("Class %wZ not found\n", ClassName
);
1512 if (NULL
!= ParentWindow
)
1514 IntReleaseWindowObject(ParentWindow
);
1516 SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS
);
1520 /* Check the window station. */
1521 if (PsGetWin32Thread()->Desktop
== NULL
)
1523 ClassDereferenceObject(ClassObject
);
1524 if (NULL
!= ParentWindow
)
1526 IntReleaseWindowObject(ParentWindow
);
1528 DPRINT("Thread is not attached to a desktop! Cannot create window!\n");
1531 WinStaObject
= PsGetWin32Thread()->Desktop
->WindowStation
;
1532 ObReferenceObjectByPointer(WinStaObject
, KernelMode
, ExWindowStationObjectType
, 0);
1534 /* Create the window object. */
1535 WindowObject
= (PWINDOW_OBJECT
)
1536 ObmCreateObject(PsGetWin32Thread()->Desktop
->WindowStation
->HandleTable
, &Handle
,
1537 otWindow
, sizeof(WINDOW_OBJECT
) + ClassObject
->cbWndExtra
1540 DPRINT("Created object with handle %X\n", Handle
);
1543 ObDereferenceObject(WinStaObject
);
1544 ClassDereferenceObject(ClassObject
);
1545 if (NULL
!= ParentWindow
)
1547 IntReleaseWindowObject(ParentWindow
);
1549 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1552 ObDereferenceObject(WinStaObject
);
1554 if (NULL
== PsGetWin32Thread()->Desktop
->DesktopWindow
)
1556 /* If there is no desktop window yet, we must be creating it */
1557 PsGetWin32Thread()->Desktop
->DesktopWindow
= Handle
;
1561 * Fill out the structure describing it.
1563 WindowObject
->Class
= ClassObject
;
1564 IntLockClassWindows(ClassObject
);
1565 InsertTailList(&ClassObject
->ClassWindowsListHead
, &WindowObject
->ClassListEntry
);
1566 IntUnLockClassWindows(ClassObject
);
1568 WindowObject
->ExStyle
= dwExStyle
;
1569 WindowObject
->Style
= dwStyle
& ~WS_VISIBLE
;
1570 DPRINT("1: Style is now %lx\n", WindowObject
->Style
);
1572 WindowObject
->SystemMenu
= (HMENU
)0;
1573 WindowObject
->ContextHelpId
= 0;
1574 WindowObject
->IDMenu
= 0;
1575 WindowObject
->Instance
= hInstance
;
1576 WindowObject
->Self
= Handle
;
1577 if (0 != (dwStyle
& WS_CHILD
))
1579 WindowObject
->IDMenu
= (UINT
) hMenu
;
1583 IntSetMenu(WindowObject
, hMenu
, &MenuChanged
);
1585 WindowObject
->MessageQueue
= PsGetWin32Thread()->MessageQueue
;
1586 IntReferenceMessageQueue(WindowObject
->MessageQueue
);
1587 WindowObject
->Parent
= (ParentWindow
? ParentWindow
->Self
: NULL
);
1588 if((OwnerWindow
= IntGetWindowObject(OwnerWindowHandle
)))
1590 WindowObject
->Owner
= OwnerWindowHandle
;
1591 IntReleaseWindowObject(OwnerWindow
);
1594 WindowObject
->Owner
= NULL
;
1597 WindowObject
->UserData
= 0;
1598 if ((((DWORD
)ClassObject
->lpfnWndProcA
& 0xFFFF0000) != 0xFFFF0000)
1599 && (((DWORD
)ClassObject
->lpfnWndProcW
& 0xFFFF0000) != 0xFFFF0000))
1601 WindowObject
->Unicode
= bUnicodeWindow
;
1605 WindowObject
->Unicode
= ClassObject
->Unicode
;
1607 WindowObject
->WndProcA
= ClassObject
->lpfnWndProcA
;
1608 WindowObject
->WndProcW
= ClassObject
->lpfnWndProcW
;
1609 WindowObject
->OwnerThread
= PsGetCurrentThread();
1610 WindowObject
->FirstChild
= NULL
;
1611 WindowObject
->LastChild
= NULL
;
1612 WindowObject
->PrevSibling
= NULL
;
1613 WindowObject
->NextSibling
= NULL
;
1615 /* extra window data */
1616 if (ClassObject
->cbWndExtra
!= 0)
1618 WindowObject
->ExtraData
= (PCHAR
)(WindowObject
+ 1);
1619 WindowObject
->ExtraDataSize
= ClassObject
->cbWndExtra
;
1620 RtlZeroMemory(WindowObject
->ExtraData
, WindowObject
->ExtraDataSize
);
1624 WindowObject
->ExtraData
= NULL
;
1625 WindowObject
->ExtraDataSize
= 0;
1628 InitializeListHead(&WindowObject
->PropListHead
);
1629 ExInitializeFastMutex(&WindowObject
->PropListLock
);
1630 ExInitializeFastMutex(&WindowObject
->RelativesLock
);
1631 ExInitializeFastMutex(&WindowObject
->UpdateLock
);
1632 InitializeListHead(&WindowObject
->WndObjListHead
);
1633 ExInitializeFastMutex(&WindowObject
->WndObjListLock
);
1635 if (NULL
!= WindowName
->Buffer
)
1637 WindowObject
->WindowName
.MaximumLength
= WindowName
->MaximumLength
;
1638 WindowObject
->WindowName
.Length
= WindowName
->Length
;
1639 WindowObject
->WindowName
.Buffer
= ExAllocatePoolWithTag(PagedPool
, WindowName
->MaximumLength
,
1641 if (NULL
== WindowObject
->WindowName
.Buffer
)
1643 ClassDereferenceObject(ClassObject
);
1644 DPRINT1("Failed to allocate mem for window name\n");
1645 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1648 RtlCopyMemory(WindowObject
->WindowName
.Buffer
, WindowName
->Buffer
, WindowName
->MaximumLength
);
1652 RtlInitUnicodeString(&WindowObject
->WindowName
, NULL
);
1657 * This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1658 * tested for WS_POPUP
1660 if ((dwExStyle
& WS_EX_DLGMODALFRAME
) ||
1661 ((!(dwExStyle
& WS_EX_STATICEDGE
)) &&
1662 (dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
))))
1663 dwExStyle
|= WS_EX_WINDOWEDGE
;
1665 dwExStyle
&= ~WS_EX_WINDOWEDGE
;
1667 /* Correct the window style. */
1668 if (!(dwStyle
& WS_CHILD
))
1670 WindowObject
->Style
|= WS_CLIPSIBLINGS
;
1671 DPRINT("3: Style is now %lx\n", WindowObject
->Style
);
1672 if (!(dwStyle
& WS_POPUP
))
1674 WindowObject
->Style
|= WS_CAPTION
;
1675 WindowObject
->Flags
|= WINDOWOBJECT_NEED_SIZE
;
1676 DPRINT("4: Style is now %lx\n", WindowObject
->Style
);
1680 /* create system menu */
1681 if((WindowObject
->Style
& WS_SYSMENU
) &&
1682 (WindowObject
->Style
& WS_CAPTION
) == WS_CAPTION
)
1684 SystemMenu
= IntGetSystemMenu(WindowObject
, TRUE
, TRUE
);
1687 WindowObject
->SystemMenu
= SystemMenu
->MenuInfo
.Self
;
1688 IntReleaseMenuObject(SystemMenu
);
1692 /* Insert the window into the thread's window list. */
1693 IntLockThreadWindows(PsGetWin32Thread());
1694 InsertTailList (&PsGetWin32Thread()->WindowListHead
,
1695 &WindowObject
->ThreadListEntry
);
1696 IntUnLockThreadWindows(PsGetWin32Thread());
1698 /* Allocate a DCE for this window. */
1699 if (dwStyle
& CS_OWNDC
)
1701 WindowObject
->Dce
= DceAllocDCE(WindowObject
->Self
, DCE_WINDOW_DC
);
1703 /* FIXME: Handle "CS_CLASSDC" */
1711 Cs
.lpCreateParams
= lpParam
;
1712 Cs
.hInstance
= hInstance
;
1714 Cs
.hwndParent
= ParentWindowHandle
;
1720 Cs
.lpszName
= (LPCWSTR
) WindowName
;
1721 Cs
.lpszClass
= (LPCWSTR
) ClassName
;
1722 Cs
.dwExStyle
= dwExStyle
;
1723 CbtCreate
.lpcs
= &Cs
;
1724 CbtCreate
.hwndInsertAfter
= HWND_TOP
;
1725 if (HOOK_CallHooks(WH_CBT
, HCBT_CREATEWND
, (WPARAM
) Handle
, (LPARAM
) &CbtCreate
))
1727 if (NULL
!= ParentWindow
)
1729 IntReleaseWindowObject(ParentWindow
);
1732 /* FIXME - Delete window object and remove it from the thread windows list */
1733 /* FIXME - delete allocated DCE */
1735 ClassDereferenceObject(ClassObject
);
1736 DPRINT1("CBT-hook returned !0\n");
1745 /* default positioning for overlapped windows */
1746 if(!(WindowObject
->Style
& (WS_POPUP
| WS_CHILD
)))
1749 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
1750 BOOL CalculatedDefPosSize
= FALSE
;
1752 IntGetDesktopWorkArea(WindowObject
->OwnerThread
->Tcb
.Win32Thread
->Desktop
, &WorkArea
);
1755 ProcessParams
= PsGetCurrentProcess()->Peb
->ProcessParameters
;
1757 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1759 CalculatedDefPosSize
= IntCalcDefPosSize(ParentWindow
, WindowObject
, &rc
, TRUE
);
1761 if(ProcessParams
->WindowFlags
& STARTF_USEPOSITION
)
1763 ProcessParams
->WindowFlags
&= ~STARTF_USEPOSITION
;
1764 Pos
.x
= WorkArea
.left
+ ProcessParams
->StartingX
;
1765 Pos
.y
= WorkArea
.top
+ ProcessParams
->StartingY
;
1773 /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
1774 y is something else */
1775 if(y
!= CW_USEDEFAULT
&& y
!= CW_USEDEFAULT16
)
1780 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1782 if(!CalculatedDefPosSize
)
1784 IntCalcDefPosSize(ParentWindow
, WindowObject
, &rc
, FALSE
);
1786 if(ProcessParams
->WindowFlags
& STARTF_USESIZE
)
1788 ProcessParams
->WindowFlags
&= ~STARTF_USESIZE
;
1789 Size
.cx
= ProcessParams
->CountX
;
1790 Size
.cy
= ProcessParams
->CountY
;
1794 Size
.cx
= rc
.right
- rc
.left
;
1795 Size
.cy
= rc
.bottom
- rc
.top
;
1798 /* move the window if necessary */
1800 Pos
.x
= max(rc
.left
, 0);
1802 Pos
.y
= max(rc
.top
, 0);
1807 /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
1808 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1813 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1820 /* Initialize the window dimensions. */
1821 WindowObject
->WindowRect
.left
= Pos
.x
;
1822 WindowObject
->WindowRect
.top
= Pos
.y
;
1823 WindowObject
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1824 WindowObject
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1825 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1827 IntGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1828 ParentWindow
->ClientRect
.top
);
1830 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1833 * Get the size and position of the window.
1835 if ((dwStyle
& WS_THICKFRAME
) || !(dwStyle
& (WS_POPUP
| WS_CHILD
)))
1837 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1839 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1840 WinPosGetMinMaxInfo(WindowObject
, &MaxSize
, &MaxPos
, &MinTrack
,
1842 if (MaxSize
.x
< nWidth
) nWidth
= MaxSize
.x
;
1843 if (MaxSize
.y
< nHeight
) nHeight
= MaxSize
.y
;
1844 if (nWidth
< MinTrack
.x
) nWidth
= MinTrack
.x
;
1845 if (nHeight
< MinTrack
.y
) nHeight
= MinTrack
.y
;
1846 if (nWidth
< 0) nWidth
= 0;
1847 if (nHeight
< 0) nHeight
= 0;
1850 WindowObject
->WindowRect
.left
= Pos
.x
;
1851 WindowObject
->WindowRect
.top
= Pos
.y
;
1852 WindowObject
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1853 WindowObject
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1854 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1856 IntGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1857 ParentWindow
->ClientRect
.top
);
1859 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1861 /* FIXME: Initialize the window menu. */
1863 /* Send a NCCREATE message. */
1869 DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d\n", Cs
.style
, Cs
.dwExStyle
, Cs
.hwndParent
);
1870 DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1871 DPRINT("IntCreateWindowEx(): About to send NCCREATE message.\n");
1872 Result
= IntSendMessage(WindowObject
->Self
, WM_NCCREATE
, 0, (LPARAM
) &Cs
);
1875 /* FIXME: Cleanup. */
1876 if (NULL
!= ParentWindow
)
1878 IntReleaseWindowObject(ParentWindow
);
1880 DPRINT("IntCreateWindowEx(): NCCREATE message failed.\n");
1884 /* Calculate the non-client size. */
1885 MaxPos
.x
= WindowObject
->WindowRect
.left
;
1886 MaxPos
.y
= WindowObject
->WindowRect
.top
;
1887 DPRINT("IntCreateWindowEx(): About to get non-client size.\n");
1888 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1889 Result
= WinPosGetNonClientSize(WindowObject
->Self
,
1890 &WindowObject
->WindowRect
,
1891 &WindowObject
->ClientRect
);
1892 IntGdiOffsetRect(&WindowObject
->WindowRect
,
1893 MaxPos
.x
- WindowObject
->WindowRect
.left
,
1894 MaxPos
.y
- WindowObject
->WindowRect
.top
);
1896 if (NULL
!= ParentWindow
)
1898 /* link the window into the parent's child list */
1899 if ((dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
1901 PWINDOW_OBJECT PrevSibling
;
1902 IntLockRelatives(ParentWindow
);
1903 if((PrevSibling
= ParentWindow
->LastChild
))
1904 IntReferenceWindowObject(PrevSibling
);
1905 IntUnLockRelatives(ParentWindow
);
1906 /* link window as bottom sibling */
1907 IntLinkWindow(WindowObject
, ParentWindow
, PrevSibling
/*prev sibling*/);
1909 IntReleaseWindowObject(PrevSibling
);
1913 /* link window as top sibling (but after topmost siblings) */
1914 PWINDOW_OBJECT InsertAfter
, Sibling
;
1915 if (0 == (dwExStyle
& WS_EX_TOPMOST
))
1917 IntLockRelatives(ParentWindow
);
1919 Sibling
= ParentWindow
->FirstChild
;
1920 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
1922 InsertAfter
= Sibling
;
1923 Sibling
= Sibling
->NextSibling
;
1925 IntUnLockRelatives(ParentWindow
);
1931 if (NULL
!= InsertAfter
)
1933 IntReferenceWindowObject(InsertAfter
);
1935 IntLinkWindow(WindowObject
, ParentWindow
, InsertAfter
/* prev sibling */);
1936 if (NULL
!= InsertAfter
)
1938 IntReleaseWindowObject(InsertAfter
);
1943 /* Send the WM_CREATE message. */
1944 DPRINT("IntCreateWindowEx(): about to send CREATE message.\n");
1945 Result
= IntSendMessage(WindowObject
->Self
, WM_CREATE
, 0, (LPARAM
) &Cs
);
1946 if (Result
== (LRESULT
)-1)
1948 /* FIXME: Cleanup. */
1949 if (NULL
!= ParentWindow
)
1951 IntReleaseWindowObject(ParentWindow
);
1953 ClassDereferenceObject(ClassObject
);
1954 DPRINT("IntCreateWindowEx(): send CREATE message failed.\n");
1958 /* Send move and size messages. */
1959 if (!(WindowObject
->Flags
& WINDOWOBJECT_NEED_SIZE
))
1963 DPRINT("IntCreateWindow(): About to send WM_SIZE\n");
1965 if ((WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
) < 0 ||
1966 (WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
) < 0)
1968 DPRINT("Sending bogus WM_SIZE\n");
1971 lParam
= MAKE_LONG(WindowObject
->ClientRect
.right
-
1972 WindowObject
->ClientRect
.left
,
1973 WindowObject
->ClientRect
.bottom
-
1974 WindowObject
->ClientRect
.top
);
1975 IntSendMessage(WindowObject
->Self
, WM_SIZE
, SIZE_RESTORED
,
1978 DPRINT("IntCreateWindow(): About to send WM_MOVE\n");
1980 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1982 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
- ParentWindow
->ClientRect
.left
,
1983 WindowObject
->ClientRect
.top
- ParentWindow
->ClientRect
.top
);
1987 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
,
1988 WindowObject
->ClientRect
.top
);
1990 IntSendMessage(WindowObject
->Self
, WM_MOVE
, 0, lParam
);
1992 /* Call WNDOBJ change procs */
1993 IntEngWindowChanged(WindowObject
, WOC_RGN_CLIENT
);
1996 /* Show or maybe minimize or maximize the window. */
1997 if (WindowObject
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
2002 SwFlag
= (WindowObject
->Style
& WS_MINIMIZE
) ? SW_MINIMIZE
:
2004 WinPosMinMaximize(WindowObject
, SwFlag
, &NewPos
);
2006 ((WindowObject
->Style
& WS_CHILD
) || NtUserGetActiveWindow()) ?
2007 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
:
2008 SWP_NOZORDER
| SWP_FRAMECHANGED
;
2009 DPRINT("IntCreateWindow(): About to minimize/maximize\n");
2010 DPRINT("%d,%d %dx%d\n", NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
);
2011 WinPosSetWindowPos(WindowObject
->Self
, 0, NewPos
.left
, NewPos
.top
,
2012 NewPos
.right
, NewPos
.bottom
, SwFlag
);
2015 /* Notify the parent window of a new child. */
2016 if ((WindowObject
->Style
& WS_CHILD
) &&
2017 (!(WindowObject
->ExStyle
& WS_EX_NOPARENTNOTIFY
)) && ParentWindow
)
2019 DPRINT("IntCreateWindow(): About to notify parent\n");
2020 IntSendMessage(ParentWindow
->Self
,
2022 MAKEWPARAM(WM_CREATE
, WindowObject
->IDMenu
),
2023 (LPARAM
)WindowObject
->Self
);
2026 if ((!hWndParent
) && (!HasOwner
)) {
2027 DPRINT("Sending CREATED notify\n");
2028 IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Handle
);
2030 DPRINT("Not sending CREATED notify, %x %d\n", ParentWindow
, HasOwner
);
2033 if (NULL
!= ParentWindow
)
2035 IntReleaseWindowObject(ParentWindow
);
2038 /* Initialize and show the window's scrollbars */
2039 if (WindowObject
->Style
& WS_VSCROLL
)
2041 NtUserShowScrollBar(WindowObject
->Self
, SB_VERT
, TRUE
);
2043 if (WindowObject
->Style
& WS_HSCROLL
)
2045 NtUserShowScrollBar(WindowObject
->Self
, SB_HORZ
, TRUE
);
2048 if (dwStyle
& WS_VISIBLE
)
2050 DPRINT("IntCreateWindow(): About to show window\n");
2051 WinPosShowWindow(WindowObject
->Self
, dwShowMode
);
2054 DPRINT("IntCreateWindow(): = %X\n", Handle
);
2055 DPRINT("WindowObject->SystemMenu = 0x%x\n", WindowObject
->SystemMenu
);
2056 return((HWND
)Handle
);
2060 NtUserCreateWindowEx(DWORD dwExStyle
,
2061 PUNICODE_STRING UnsafeClassName
,
2062 PUNICODE_STRING UnsafeWindowName
,
2070 HINSTANCE hInstance
,
2073 BOOL bUnicodeWindow
)
2076 UNICODE_STRING WindowName
;
2077 UNICODE_STRING ClassName
;
2080 DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
2082 /* Get the class name (string or atom) */
2083 Status
= MmCopyFromCaller(&ClassName
, UnsafeClassName
, sizeof(UNICODE_STRING
));
2084 if (! NT_SUCCESS(Status
))
2086 SetLastNtError(Status
);
2089 if (! IS_ATOM(ClassName
.Buffer
))
2091 Status
= IntSafeCopyUnicodeStringTerminateNULL(&ClassName
, UnsafeClassName
);
2092 if (! NT_SUCCESS(Status
))
2094 SetLastNtError(Status
);
2099 /* safely copy the window name */
2100 if (NULL
!= UnsafeWindowName
)
2102 Status
= IntSafeCopyUnicodeString(&WindowName
, UnsafeWindowName
);
2103 if (! NT_SUCCESS(Status
))
2105 if (! IS_ATOM(ClassName
.Buffer
))
2107 RtlFreeUnicodeString(&ClassName
);
2109 SetLastNtError(Status
);
2115 RtlInitUnicodeString(&WindowName
, NULL
);
2118 NewWindow
= IntCreateWindowEx(dwExStyle
, &ClassName
, &WindowName
, dwStyle
, x
, y
, nWidth
, nHeight
,
2119 hWndParent
, hMenu
, hInstance
, lpParam
, dwShowMode
, bUnicodeWindow
);
2121 RtlFreeUnicodeString(&WindowName
);
2122 if (! IS_ATOM(ClassName
.Buffer
))
2124 RtlFreeUnicodeString(&ClassName
);
2134 NtUserDeferWindowPos(HDWP WinPosInfo
,
2136 HWND WndInsertAfter
,
2153 NtUserDestroyWindow(HWND Wnd
)
2155 PWINDOW_OBJECT Window
;
2158 Window
= IntGetWindowObject(Wnd
);
2164 /* Check for owner thread and desktop window */
2165 if ((Window
->OwnerThread
!= PsGetCurrentThread()) || IntIsDesktopWindow(Window
))
2167 IntReleaseWindowObject(Window
);
2168 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2172 /* Look whether the focus is within the tree of windows we will
2175 if (!WinPosShowWindow(Wnd
, SW_HIDE
))
2177 if (NtUserGetActiveWindow() == Wnd
)
2179 WinPosActivateOtherWindow(Window
);
2182 IntLockMessageQueue(Window
->MessageQueue
);
2183 if (Window
->MessageQueue
->ActiveWindow
== Window
->Self
)
2184 Window
->MessageQueue
->ActiveWindow
= NULL
;
2185 if (Window
->MessageQueue
->FocusWindow
== Window
->Self
)
2186 Window
->MessageQueue
->FocusWindow
= NULL
;
2187 if (Window
->MessageQueue
->CaptureWindow
== Window
->Self
)
2188 Window
->MessageQueue
->CaptureWindow
= NULL
;
2189 IntUnLockMessageQueue(Window
->MessageQueue
);
2190 IntDereferenceMessageQueue(Window
->MessageQueue
);
2193 if (HOOK_CallHooks(WH_CBT
, HCBT_DESTROYWND
, (WPARAM
) hwnd
, 0, TRUE
))
2199 IntEngWindowChanged(Window
, WOC_DELETE
);
2200 isChild
= (0 != (Window
->Style
& WS_CHILD
));
2205 if (! USER_IsExitingThread(GetCurrentThreadId()))
2207 send_parent_notify(hwnd
, WM_DESTROY
);
2210 else if (NULL
!= GetWindow(Wnd
, GW_OWNER
))
2212 HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
2213 /* FIXME: clean up palette - see "Internals" p.352 */
2217 if (!IntIsWindow(Wnd
))
2222 /* Recursively destroy owned windows */
2227 BOOL GotOne
= FALSE
;
2230 PWINDOW_OBJECT Child
, Desktop
;
2232 Desktop
= IntGetWindowObject(IntGetDesktopWindow());
2233 Children
= IntWinListChildren(Desktop
);
2234 IntReleaseWindowObject(Desktop
);
2237 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
2239 Child
= IntGetWindowObject(*ChildHandle
);
2242 IntLockRelatives(Child
);
2243 if (Child
->Owner
!= Window
->Self
)
2245 IntUnLockRelatives(Child
);
2246 IntReleaseWindowObject(Child
);
2249 IntUnLockRelatives(Child
);
2250 if (IntWndBelongsToThread(Child
, PsGetWin32Thread()))
2252 IntReleaseWindowObject(Child
);
2253 NtUserDestroyWindow(*ChildHandle
);
2257 IntLockRelatives(Child
);
2258 if (Child
->Owner
!= NULL
)
2260 Child
->Owner
= NULL
;
2262 IntUnLockRelatives(Child
);
2263 IntReleaseWindowObject(Child
);
2265 ExFreePool(Children
);
2274 if (!IntIsWindow(Wnd
))
2276 IntReleaseWindowObject(Window
);
2280 /* Destroy the window storage */
2281 IntDestroyWindow(Window
, PsGetWin32Process(), PsGetWin32Thread(), TRUE
);
2283 IntReleaseWindowObject(Window
);
2293 NtUserDrawMenuBarTemp(
2300 /* we'll use this function just for caching the menu bar */
2310 NtUserEndDeferWindowPosEx(DWORD Unknown0
,
2323 NtUserFillWindow(DWORD Unknown0
,
2335 IntFindWindow(PWINDOW_OBJECT Parent
,
2336 PWINDOW_OBJECT ChildAfter
,
2338 PUNICODE_STRING WindowName
)
2340 BOOL CheckWindowName
;
2346 CheckWindowName
= (WindowName
&& (WindowName
->Length
> 0));
2348 if((List
= IntWinListChildren(Parent
)))
2353 /* skip handles before and including ChildAfter */
2354 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->Self
));
2357 /* search children */
2360 PWINDOW_OBJECT Child
;
2361 if(!(Child
= IntGetWindowObject(*(phWnd
++))))
2366 /* Do not send WM_GETTEXT messages in the kernel mode version!
2367 The user mode version however calls GetWindowText() which will
2368 send WM_GETTEXT messages to windows belonging to its processes */
2369 if((!CheckWindowName
|| !RtlCompareUnicodeString(WindowName
, &(Child
->WindowName
), FALSE
)) &&
2370 (!ClassAtom
|| Child
->Class
->Atom
== ClassAtom
))
2373 IntReleaseWindowObject(Child
);
2377 IntReleaseWindowObject(Child
);
2387 * Searches a window's children for a window with the specified
2390 * hwndParent = The window whose childs are to be searched.
2392 * HWND_MESSAGE = message-only windows
2394 * hwndChildAfter = Search starts after this child window.
2395 * NULL = start from beginning
2397 * ucClassName = Class name to search for
2398 * Reguired parameter.
2400 * ucWindowName = Window name
2401 * ->Buffer == NULL = don't care
2404 * The HWND of the window if it was found, otherwise NULL
2410 NtUserFindWindowEx(HWND hwndParent
,
2411 HWND hwndChildAfter
,
2412 PUNICODE_STRING ucClassName
,
2413 PUNICODE_STRING ucWindowName
)
2415 PWINDOW_OBJECT Parent
, ChildAfter
;
2416 UNICODE_STRING ClassName
, WindowName
;
2418 HWND Desktop
, Ret
= NULL
;
2421 Desktop
= IntGetCurrentThreadDesktopWindow();
2423 if(hwndParent
== NULL
)
2424 hwndParent
= Desktop
;
2426 else if(hwndParent == HWND_MESSAGE)
2428 hwndParent = IntGetMessageWindow();
2432 if(!(Parent
= IntGetWindowObject(hwndParent
)))
2434 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2439 if(hwndChildAfter
&& !(ChildAfter
= IntGetWindowObject(hwndChildAfter
)))
2441 IntReleaseWindowObject(Parent
);
2442 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2446 /* copy the window name */
2447 Status
= IntSafeCopyUnicodeString(&WindowName
, ucWindowName
);
2448 if(!NT_SUCCESS(Status
))
2450 SetLastNtError(Status
);
2454 /* safely copy the class name */
2455 Status
= MmCopyFromCaller(&ClassName
, ucClassName
, sizeof(UNICODE_STRING
));
2456 if(!NT_SUCCESS(Status
))
2458 SetLastNtError(Status
);
2461 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2464 /* safely copy the class name string (NULL terminated because class-lookup
2466 buf
= ExAllocatePoolWithTag(PagedPool
, ClassName
.Length
+ sizeof(WCHAR
), TAG_STRING
);
2469 SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES
);
2472 Status
= MmCopyFromCaller(buf
, ClassName
.Buffer
, ClassName
.Length
);
2473 if(!NT_SUCCESS(Status
))
2476 SetLastNtError(Status
);
2479 ClassName
.Buffer
= buf
;
2480 /* make sure the string is null-terminated */
2481 buf
+= ClassName
.Length
/ sizeof(WCHAR
);
2485 /* find the class object */
2486 if(ClassName
.Buffer
)
2488 PWINSTATION_OBJECT WinStaObject
;
2490 if (PsGetWin32Thread()->Desktop
== NULL
)
2492 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2496 WinStaObject
= PsGetWin32Thread()->Desktop
->WindowStation
;
2498 Status
= RtlLookupAtomInAtomTable(
2499 WinStaObject
->AtomTable
,
2503 if (!NT_SUCCESS(Status
))
2505 DPRINT1("Failed to lookup class atom!\n");
2506 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST
);
2511 if(Parent
->Self
== Desktop
)
2514 PWINDOW_OBJECT TopLevelWindow
;
2515 BOOLEAN CheckWindowName
;
2516 BOOLEAN CheckClassName
;
2517 BOOLEAN WindowMatches
;
2518 BOOLEAN ClassMatches
;
2520 /* windows searches through all top-level windows if the parent is the desktop
2523 if((List
= IntWinListChildren(Parent
)))
2529 /* skip handles before and including ChildAfter */
2530 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->Self
));
2533 CheckWindowName
= WindowName
.Length
> 0;
2534 CheckClassName
= ClassName
.Buffer
!= NULL
;
2536 /* search children */
2539 if(!(TopLevelWindow
= IntGetWindowObject(*(phWnd
++))))
2544 /* Do not send WM_GETTEXT messages in the kernel mode version!
2545 The user mode version however calls GetWindowText() which will
2546 send WM_GETTEXT messages to windows belonging to its processes */
2547 WindowMatches
= !CheckWindowName
|| !RtlCompareUnicodeString(
2548 &WindowName
, &TopLevelWindow
->WindowName
, FALSE
);
2549 ClassMatches
= !CheckClassName
||
2550 ClassAtom
== TopLevelWindow
->Class
->Atom
;
2552 if (WindowMatches
&& ClassMatches
)
2554 Ret
= TopLevelWindow
->Self
;
2555 IntReleaseWindowObject(TopLevelWindow
);
2559 if (IntFindWindow(TopLevelWindow
, NULL
, ClassAtom
, &WindowName
))
2561 /* window returns the handle of the top-level window, in case it found
2563 Ret
= TopLevelWindow
->Self
;
2564 IntReleaseWindowObject(TopLevelWindow
);
2568 IntReleaseWindowObject(TopLevelWindow
);
2574 Ret
= IntFindWindow(Parent
, ChildAfter
, ClassAtom
, &WindowName
);
2577 if(Ret
== NULL
&& hwndParent
== NULL
&& hwndChildAfter
== NULL
)
2579 /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
2580 search the message-only windows. Should this also be done if
2581 Parent is the desktop window??? */
2582 PWINDOW_OBJECT MsgWindows
;
2584 if((MsgWindows
= IntGetWindowObject(IntGetMessageWindow())))
2586 Ret
= IntFindWindow(MsgWindows
, ChildAfter
, ClassAtom
, &WindowName
);
2587 IntReleaseWindowObject(MsgWindows
);
2593 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2594 ExFreePool(ClassName
.Buffer
);
2597 RtlFreeUnicodeString(&WindowName
);
2601 IntReleaseWindowObject(ChildAfter
);
2602 IntReleaseWindowObject(Parent
);
2612 NtUserFlashWindowEx(DWORD Unknown0
)
2624 NtUserGetAncestor(HWND hWnd
, UINT Type
)
2626 PWINDOW_OBJECT Wnd
, WndAncestor
, Parent
;
2629 if (hWnd
== IntGetDesktopWindow())
2634 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2636 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2644 WndAncestor
= IntGetParentObject(Wnd
);
2657 if(!(Parent
= IntGetParentObject(WndAncestor
)))
2661 if(IntIsDesktopWindow(Parent
))
2663 IntReleaseWindowObject(Parent
);
2667 IntReleaseWindowObject(tmp
);
2668 WndAncestor
= Parent
;
2676 IntReferenceWindowObject(WndAncestor
);
2681 Parent
= IntGetParent(WndAncestor
);
2682 IntReleaseWindowObject(Old
);
2687 WndAncestor
= Parent
;
2694 IntReleaseWindowObject(Wnd
);
2699 hWndAncestor
= (WndAncestor
? WndAncestor
->Self
: NULL
);
2700 IntReleaseWindowObject(Wnd
);
2702 if(WndAncestor
&& (WndAncestor
!= Wnd
))
2703 IntReleaseWindowObject(WndAncestor
);
2705 return hWndAncestor
;
2710 * Returns client window rectangle relative to the upper-left corner of client area.
2712 * \param hWnd window handle.
2713 * \param Rect pointer to the buffer where the coordinates are returned.
2720 NtUserGetClientRect(HWND hWnd
, LPRECT Rect
)
2722 PWINDOW_OBJECT WindowObject
;
2725 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
2727 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2731 IntGetClientRect(WindowObject
, &SafeRect
);
2732 IntReleaseWindowObject(WindowObject
);
2734 if(!NT_SUCCESS(MmCopyToCaller(Rect
, &SafeRect
, sizeof(RECT
))))
2746 NtUserGetDesktopWindow()
2748 return IntGetDesktopWindow();
2756 NtUserGetInternalWindowPos(DWORD Unknown0
,
2770 NtUserGetLastActivePopup(HWND hWnd
)
2773 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2774 * not changed anywhere.
2775 * -- Filip, 01/nov/2003
2781 IntAcquireWinLockShared();
2783 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2785 IntReleaseWinLock();
2786 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2790 hWndLastPopup
= Wnd
->hWndLastPopup
;
2792 IntReleaseWinLock();
2794 return hWndLastPopup
;
2803 * The NtUserGetParent function retrieves a handle to the specified window's
2807 * Note that, despite its name, this function can return an owner window
2808 * instead of a parent window.
2815 NtUserGetParent(HWND hWnd
)
2817 PWINDOW_OBJECT Wnd
, WndParent
;
2818 HWND hWndParent
= NULL
;
2820 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2822 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2826 WndParent
= IntGetParent(Wnd
);
2829 hWndParent
= WndParent
->Self
;
2830 IntReleaseWindowObject(WndParent
);
2833 IntReleaseWindowObject(Wnd
);
2841 * The NtUserSetParent function changes the parent window of the specified
2845 * The new parent window and the child window must belong to the same
2846 * application. If the window identified by the hWndChild parameter is
2847 * visible, the system performs the appropriate redrawing and repainting.
2848 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2849 * or WS_POPUP window styles of the window whose parent is being changed.
2856 NtUserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2858 PWINDOW_OBJECT Wnd
= NULL
, WndParent
= NULL
, WndOldParent
;
2859 HWND hWndOldParent
= NULL
;
2861 if (IntIsBroadcastHwnd(hWndChild
) || IntIsBroadcastHwnd(hWndNewParent
))
2863 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2867 if (hWndChild
== IntGetDesktopWindow())
2869 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2875 if (!(WndParent
= IntGetWindowObject(hWndNewParent
)))
2877 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2883 if (!(WndParent
= IntGetWindowObject(IntGetDesktopWindow())))
2885 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2890 if (!(Wnd
= IntGetWindowObject(hWndChild
)))
2892 IntReleaseWindowObject(WndParent
);
2893 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2897 WndOldParent
= IntSetParent(Wnd
, WndParent
);
2901 hWndOldParent
= WndOldParent
->Self
;
2902 IntReleaseWindowObject(WndOldParent
);
2905 IntReleaseWindowObject(Wnd
);
2906 IntReleaseWindowObject(WndParent
);
2908 return hWndOldParent
;
2912 * NtUserGetShellWindow
2914 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
2921 NtUserGetShellWindow()
2923 PWINSTATION_OBJECT WinStaObject
;
2926 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
2931 if (!NT_SUCCESS(Status
))
2933 SetLastNtError(Status
);
2937 Ret
= (HWND
)WinStaObject
->ShellWindow
;
2939 ObDereferenceObject(WinStaObject
);
2944 * NtUserSetShellWindowEx
2946 * This is undocumented function to set global shell window. The global
2947 * shell window has special handling of window position.
2954 NtUserSetShellWindowEx(HWND hwndShell
, HWND hwndListView
)
2956 PWINSTATION_OBJECT WinStaObject
;
2958 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
2963 if (!NT_SUCCESS(Status
))
2965 SetLastNtError(Status
);
2970 * Test if we are permitted to change the shell window.
2972 if (WinStaObject
->ShellWindow
)
2974 ObDereferenceObject(WinStaObject
);
2979 * Move shell window into background.
2981 if (hwndListView
&& hwndListView
!= hwndShell
)
2984 * Disabled for now to get Explorer working.
2985 * -- Filip, 01/nov/2003
2988 WinPosSetWindowPos(hwndListView
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2991 if (NtUserGetWindowLong(hwndListView
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2993 ObDereferenceObject(WinStaObject
);
2998 if (NtUserGetWindowLong(hwndShell
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
3000 ObDereferenceObject(WinStaObject
);
3004 WinPosSetWindowPos(hwndShell
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
3006 WinStaObject
->ShellWindow
= hwndShell
;
3007 WinStaObject
->ShellListView
= hwndListView
;
3009 ObDereferenceObject(WinStaObject
);
3014 * NtUserGetSystemMenu
3016 * The NtUserGetSystemMenu function allows the application to access the
3017 * window menu (also known as the system menu or the control menu) for
3018 * copying and modifying.
3022 * Handle to the window that will own a copy of the window menu.
3024 * Specifies the action to be taken. If this parameter is FALSE,
3025 * NtUserGetSystemMenu returns a handle to the copy of the window menu
3026 * currently in use. The copy is initially identical to the window menu
3027 * but it can be modified.
3028 * If this parameter is TRUE, GetSystemMenu resets the window menu back
3029 * to the default state. The previous window menu, if any, is destroyed.
3032 * If the bRevert parameter is FALSE, the return value is a handle to a
3033 * copy of the window menu. If the bRevert parameter is TRUE, the return
3041 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
3044 PWINDOW_OBJECT WindowObject
;
3045 PMENU_OBJECT MenuObject
;
3047 WindowObject
= IntGetWindowObject((HWND
)hWnd
);
3048 if (WindowObject
== NULL
)
3050 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3054 MenuObject
= IntGetSystemMenu(WindowObject
, bRevert
, FALSE
);
3057 Result
= MenuObject
->MenuInfo
.Self
;
3058 IntReleaseMenuObject(MenuObject
);
3061 IntReleaseWindowObject(WindowObject
);
3066 * NtUserSetSystemMenu
3073 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
3075 BOOL Result
= FALSE
;
3076 PWINDOW_OBJECT WindowObject
;
3077 PMENU_OBJECT MenuObject
;
3079 WindowObject
= IntGetWindowObject(hWnd
);
3082 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3089 * Assign new menu handle.
3091 MenuObject
= IntGetMenuObject(hMenu
);
3094 IntReleaseWindowObject(WindowObject
);
3095 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
3099 Result
= IntSetSystemMenu(WindowObject
, MenuObject
);
3101 IntReleaseMenuObject(MenuObject
);
3104 IntReleaseWindowObject(WindowObject
);
3112 * The NtUserGetWindow function retrieves a handle to a window that has the
3113 * specified relationship (Z order or owner) to the specified window.
3120 NtUserGetWindow(HWND hWnd
, UINT Relationship
)
3122 PWINDOW_OBJECT WindowObject
, Parent
;
3123 HWND hWndResult
= NULL
;
3125 if (!(WindowObject
= IntGetWindowObject(hWnd
)))
3127 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3131 switch (Relationship
)
3134 if((Parent
= IntGetParentObject(WindowObject
)))
3136 IntLockRelatives(Parent
);
3137 if (Parent
->FirstChild
)
3138 hWndResult
= Parent
->FirstChild
->Self
;
3139 IntUnLockRelatives(Parent
);
3140 IntReleaseWindowObject(Parent
);
3145 if((Parent
= IntGetParentObject(WindowObject
)))
3147 IntLockRelatives(Parent
);
3148 if (Parent
->LastChild
)
3149 hWndResult
= Parent
->LastChild
->Self
;
3150 IntUnLockRelatives(Parent
);
3151 IntReleaseWindowObject(Parent
);
3156 IntLockRelatives(WindowObject
);
3157 if (WindowObject
->NextSibling
)
3158 hWndResult
= WindowObject
->NextSibling
->Self
;
3159 IntUnLockRelatives(WindowObject
);
3163 IntLockRelatives(WindowObject
);
3164 if (WindowObject
->PrevSibling
)
3165 hWndResult
= WindowObject
->PrevSibling
->Self
;
3166 IntUnLockRelatives(WindowObject
);
3170 IntLockRelatives(WindowObject
);
3171 if((Parent
= IntGetWindowObject(WindowObject
->Owner
)))
3173 hWndResult
= Parent
->Self
;
3174 IntReleaseWindowObject(Parent
);
3176 IntUnLockRelatives(WindowObject
);
3179 IntLockRelatives(WindowObject
);
3180 if (WindowObject
->FirstChild
)
3181 hWndResult
= WindowObject
->FirstChild
->Self
;
3182 IntUnLockRelatives(WindowObject
);
3186 IntReleaseWindowObject(WindowObject
);
3192 * NtUserGetWindowLong
3194 * The NtUserGetWindowLong function retrieves information about the specified
3195 * window. The function also retrieves the 32-bit (long) value at the
3196 * specified offset into the extra window memory.
3203 NtUserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3205 PWINDOW_OBJECT WindowObject
, Parent
;
3208 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3210 WindowObject
= IntGetWindowObject(hWnd
);
3211 if (WindowObject
== NULL
)
3213 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3218 * WndProc is only available to the owner process
3220 if (GWL_WNDPROC
== Index
3221 && WindowObject
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
3223 SetLastWin32Error(ERROR_ACCESS_DENIED
);
3227 if ((INT
)Index
>= 0)
3229 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
3231 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3234 Result
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
3241 Result
= WindowObject
->ExStyle
;
3245 Result
= WindowObject
->Style
;
3250 Result
= (LONG
) WindowObject
->WndProcA
;
3252 Result
= (LONG
) WindowObject
->WndProcW
;
3256 Result
= (LONG
) WindowObject
->Instance
;
3259 case GWL_HWNDPARENT
:
3260 IntLockRelatives(WindowObject
);
3261 Parent
= IntGetWindowObject(WindowObject
->Parent
);
3262 IntUnLockRelatives(WindowObject
);
3265 if (Parent
&& Parent
->Self
== IntGetDesktopWindow())
3266 Result
= (LONG
) NtUserGetWindow(WindowObject
->Self
, GW_OWNER
);
3268 Result
= (LONG
) Parent
->Self
;
3269 IntReleaseWindowObject(Parent
);
3274 Result
= (LONG
) WindowObject
->IDMenu
;
3278 Result
= WindowObject
->UserData
;
3282 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index
);
3283 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3289 IntReleaseWindowObject(WindowObject
);
3295 * NtUserSetWindowLong
3297 * The NtUserSetWindowLong function changes an attribute of the specified
3298 * window. The function also sets the 32-bit (long) value at the specified
3299 * offset into the extra window memory.
3306 NtUserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3308 PWINDOW_OBJECT WindowObject
, Parent
;
3309 PWINSTATION_OBJECT WindowStation
;
3313 if (hWnd
== IntGetDesktopWindow())
3315 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3319 WindowObject
= IntGetWindowObject(hWnd
);
3320 if (WindowObject
== NULL
)
3322 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3326 if ((INT
)Index
>= 0)
3328 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
3330 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3331 IntReleaseWindowObject(WindowObject
);
3334 OldValue
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
3335 *((LONG
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
3342 OldValue
= (LONG
) WindowObject
->ExStyle
;
3343 Style
.styleOld
= OldValue
;
3344 Style
.styleNew
= NewValue
;
3347 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3349 WindowStation
= WindowObject
->OwnerThread
->Tcb
.Win32Thread
->Desktop
->WindowStation
;
3352 if (hWnd
== WindowStation
->ShellWindow
|| hWnd
== WindowStation
->ShellListView
)
3353 Style
.styleNew
&= ~WS_EX_TOPMOST
;
3356 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3357 WindowObject
->ExStyle
= (DWORD
)Style
.styleNew
;
3358 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3362 OldValue
= (LONG
) WindowObject
->Style
;
3363 Style
.styleOld
= OldValue
;
3364 Style
.styleNew
= NewValue
;
3365 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_STYLE
, (LPARAM
) &Style
);
3366 WindowObject
->Style
= (DWORD
)Style
.styleNew
;
3367 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_STYLE
, (LPARAM
) &Style
);
3371 /* FIXME: should check if window belongs to current process */
3374 OldValue
= (LONG
) WindowObject
->WndProcA
;
3375 WindowObject
->WndProcA
= (WNDPROC
) NewValue
;
3376 WindowObject
->WndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,FALSE
);
3377 WindowObject
->Unicode
= FALSE
;
3381 OldValue
= (LONG
) WindowObject
->WndProcW
;
3382 WindowObject
->WndProcW
= (WNDPROC
) NewValue
;
3383 WindowObject
->WndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,TRUE
);
3384 WindowObject
->Unicode
= TRUE
;
3389 OldValue
= (LONG
) WindowObject
->Instance
;
3390 WindowObject
->Instance
= (HINSTANCE
) NewValue
;
3393 case GWL_HWNDPARENT
:
3394 Parent
= IntGetParentObject(WindowObject
);
3395 if (Parent
&& (Parent
->Self
== IntGetDesktopWindow()))
3396 OldValue
= (LONG
) IntSetOwner(WindowObject
->Self
, (HWND
) NewValue
);
3398 OldValue
= (LONG
) NtUserSetParent(WindowObject
->Self
, (HWND
) NewValue
);
3400 IntReleaseWindowObject(Parent
);
3404 OldValue
= (LONG
) WindowObject
->IDMenu
;
3405 WindowObject
->IDMenu
= (UINT
) NewValue
;
3409 OldValue
= WindowObject
->UserData
;
3410 WindowObject
->UserData
= NewValue
;
3414 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index
);
3415 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3421 IntReleaseWindowObject(WindowObject
);
3427 * NtUserSetWindowWord
3429 * Legacy function similar to NtUserSetWindowLong.
3436 NtUserSetWindowWord(HWND hWnd
, INT Index
, WORD NewValue
)
3438 PWINDOW_OBJECT WindowObject
;
3445 case GWL_HWNDPARENT
:
3446 return NtUserSetWindowLong(hWnd
, Index
, (UINT
)NewValue
, TRUE
);
3450 SetLastWin32Error(ERROR_INVALID_INDEX
);
3455 WindowObject
= IntGetWindowObject(hWnd
);
3456 if (WindowObject
== NULL
)
3458 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3462 if (Index
> WindowObject
->ExtraDataSize
- sizeof(WORD
))
3464 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3465 IntReleaseWindowObject(WindowObject
);
3469 OldValue
= *((WORD
*)(WindowObject
->ExtraData
+ Index
));
3470 *((WORD
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
3472 IntReleaseWindowObject(WindowObject
);
3481 NtUserGetWindowPlacement(HWND hWnd
,
3482 WINDOWPLACEMENT
*lpwndpl
)
3484 PWINDOW_OBJECT WindowObject
;
3485 PINTERNALPOS InternalPos
;
3487 WINDOWPLACEMENT Safepl
;
3490 WindowObject
= IntGetWindowObject(hWnd
);
3491 if (WindowObject
== NULL
)
3493 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3497 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3498 if(!NT_SUCCESS(Status
))
3500 SetLastNtError(Status
);
3501 IntReleaseWindowObject(WindowObject
);
3504 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3506 IntReleaseWindowObject(WindowObject
);
3511 Safepl
.showCmd
= ((WindowObject
->Flags
& WINDOWOBJECT_RESTOREMAX
) ? SW_MAXIMIZE
: SW_SHOWNORMAL
);
3513 Size
.x
= WindowObject
->WindowRect
.left
;
3514 Size
.y
= WindowObject
->WindowRect
.top
;
3515 InternalPos
= WinPosInitInternalPos(WindowObject
, &Size
,
3516 &WindowObject
->WindowRect
);
3519 Safepl
.rcNormalPosition
= InternalPos
->NormalRect
;
3520 Safepl
.ptMinPosition
= InternalPos
->IconPos
;
3521 Safepl
.ptMaxPosition
= InternalPos
->MaxPos
;
3525 IntReleaseWindowObject(WindowObject
);
3529 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3530 if(!NT_SUCCESS(Status
))
3532 SetLastNtError(Status
);
3533 IntReleaseWindowObject(WindowObject
);
3537 IntReleaseWindowObject(WindowObject
);
3543 * Return the dimension of the window in the screen coordinates.
3544 * \param hWnd window handle.
3545 * \param Rect pointer to the buffer where the coordinates are returned.
3551 NtUserGetWindowRect(HWND hWnd
, LPRECT Rect
)
3556 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3558 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3561 Status
= MmCopyToCaller(Rect
, &Wnd
->WindowRect
, sizeof(RECT
));
3562 if (!NT_SUCCESS(Status
))
3564 IntReleaseWindowObject(Wnd
);
3565 SetLastNtError(Status
);
3569 IntReleaseWindowObject(Wnd
);
3578 NtUserGetWindowThreadProcessId(HWND hWnd
, LPDWORD UnsafePid
)
3583 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3585 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3589 tid
= (DWORD
)IntGetWndThreadId(Wnd
);
3590 pid
= (DWORD
)IntGetWndProcessId(Wnd
);
3592 if (UnsafePid
) MmCopyToCaller(UnsafePid
, &pid
, sizeof(DWORD
));
3602 NtUserLockWindowUpdate(DWORD Unknown0
)
3622 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3623 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3624 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3628 QueryWindow based on KJK::Hyperion and James Tabor.
3630 0 = QWUniqueProcessId
3631 1 = QWUniqueThreadId
3632 4 = QWIsHung Implements IsHungAppWindow found
3635 9 = QWKillWindow When I called this with hWnd ==
3636 DesktopWindow, it shutdown the system
3643 NtUserQueryWindow(HWND hWnd
, DWORD Index
)
3645 PWINDOW_OBJECT Window
= IntGetWindowObject(hWnd
);
3650 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3656 case QUERY_WINDOW_UNIQUE_PROCESS_ID
:
3657 Result
= (DWORD
)IntGetWndProcessId(Window
);
3660 case QUERY_WINDOW_UNIQUE_THREAD_ID
:
3661 Result
= (DWORD
)IntGetWndThreadId(Window
);
3664 case QUERY_WINDOW_ISHUNG
:
3665 Result
= (DWORD
)MsqIsHung(Window
->MessageQueue
);
3669 Result
= (DWORD
)NULL
;
3673 IntReleaseWindowObject(Window
);
3683 NtUserRealChildWindowFromPoint(DWORD Unknown0
,
3697 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe
)
3699 UNICODE_STRING SafeMessageName
;
3703 if(MessageNameUnsafe
== NULL
)
3705 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3709 Status
= IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName
, MessageNameUnsafe
);
3710 if(!NT_SUCCESS(Status
))
3712 SetLastNtError(Status
);
3716 Ret
= (UINT
)IntAddAtom(SafeMessageName
.Buffer
);
3718 RtlFreeUnicodeString(&SafeMessageName
);
3727 NtUserSetImeOwnerWindow(DWORD Unknown0
,
3740 NtUserSetInternalWindowPos(DWORD Unknown0
,
3756 NtUserSetLayeredWindowAttributes(DWORD Unknown0
,
3771 NtUserSetLogonNotifyWindow(DWORD Unknown0
)
3788 PWINDOW_OBJECT WindowObject
;
3791 WindowObject
= IntGetWindowObject((HWND
) Wnd
);
3792 if (NULL
== WindowObject
)
3794 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3798 if (! IntSetMenu(WindowObject
, Menu
, &Changed
))
3800 IntReleaseWindowObject(WindowObject
);
3804 IntReleaseWindowObject(WindowObject
);
3806 if (Changed
&& Repaint
)
3808 WinPosSetWindowPos(Wnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
3809 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
3820 NtUserSetWindowFNID(DWORD Unknown0
,
3834 NtUserSetWindowPlacement(HWND hWnd
,
3835 WINDOWPLACEMENT
*lpwndpl
)
3837 PWINDOW_OBJECT WindowObject
;
3838 WINDOWPLACEMENT Safepl
;
3841 WindowObject
= IntGetWindowObject(hWnd
);
3842 if (WindowObject
== NULL
)
3844 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3847 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3848 if(!NT_SUCCESS(Status
))
3850 SetLastNtError(Status
);
3851 IntReleaseWindowObject(WindowObject
);
3854 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3856 IntReleaseWindowObject(WindowObject
);
3860 if ((WindowObject
->Style
& (WS_MAXIMIZE
| WS_MINIMIZE
)) == 0)
3862 WinPosSetWindowPos(WindowObject
->Self
, NULL
,
3863 Safepl
.rcNormalPosition
.left
, Safepl
.rcNormalPosition
.top
,
3864 Safepl
.rcNormalPosition
.right
- Safepl
.rcNormalPosition
.left
,
3865 Safepl
.rcNormalPosition
.bottom
- Safepl
.rcNormalPosition
.top
,
3866 SWP_NOZORDER
| SWP_NOACTIVATE
);
3869 /* FIXME - change window status */
3870 WinPosShowWindow(WindowObject
->Self
, Safepl
.showCmd
);
3872 if (WindowObject
->InternalPos
== NULL
)
3873 WindowObject
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
3874 WindowObject
->InternalPos
->NormalRect
= Safepl
.rcNormalPosition
;
3875 WindowObject
->InternalPos
->IconPos
= Safepl
.ptMinPosition
;
3876 WindowObject
->InternalPos
->MaxPos
= Safepl
.ptMaxPosition
;
3878 IntReleaseWindowObject(WindowObject
);
3889 HWND hWndInsertAfter
,
3896 return WinPosSetWindowPos(hWnd
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3901 IntGetWindowRgn(HWND hWnd
, HRGN hRgn
)
3904 PWINDOW_OBJECT WindowObject
;
3908 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
3910 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3915 IntReleaseWindowObject(WindowObject
);
3919 /* Create a new window region using the window rectangle */
3920 VisRgn
= UnsafeIntCreateRectRgnIndirect(&WindowObject
->WindowRect
);
3921 NtGdiOffsetRgn(VisRgn
, -WindowObject
->WindowRect
.left
, -WindowObject
->WindowRect
.top
);
3922 /* if there's a region assigned to the window, combine them both */
3923 if(WindowObject
->WindowRegion
&& !(WindowObject
->Style
& WS_MINIMIZE
))
3924 NtGdiCombineRgn(VisRgn
, VisRgn
, WindowObject
->WindowRegion
, RGN_AND
);
3925 /* Copy the region into hRgn */
3926 NtGdiCombineRgn(hRgn
, VisRgn
, NULL
, RGN_COPY
);
3928 if((pRgn
= RGNDATA_LockRgn(hRgn
)))
3930 Ret
= pRgn
->rdh
.iType
;
3931 RGNDATA_UnlockRgn(pRgn
);
3936 NtGdiDeleteObject(VisRgn
);
3938 IntReleaseWindowObject(WindowObject
);
3943 IntGetWindowRgnBox(HWND hWnd
, RECT
*Rect
)
3946 PWINDOW_OBJECT WindowObject
;
3950 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
3952 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3957 IntReleaseWindowObject(WindowObject
);
3961 /* Create a new window region using the window rectangle */
3962 VisRgn
= UnsafeIntCreateRectRgnIndirect(&WindowObject
->WindowRect
);
3963 NtGdiOffsetRgn(VisRgn
, -WindowObject
->WindowRect
.left
, -WindowObject
->WindowRect
.top
);
3964 /* if there's a region assigned to the window, combine them both */
3965 if(WindowObject
->WindowRegion
&& !(WindowObject
->Style
& WS_MINIMIZE
))
3966 NtGdiCombineRgn(VisRgn
, VisRgn
, WindowObject
->WindowRegion
, RGN_AND
);
3968 if((pRgn
= RGNDATA_LockRgn(VisRgn
)))
3970 Ret
= pRgn
->rdh
.iType
;
3971 *Rect
= pRgn
->rdh
.rcBound
;
3972 RGNDATA_UnlockRgn(pRgn
);
3977 NtGdiDeleteObject(VisRgn
);
3979 IntReleaseWindowObject(WindowObject
);
3993 PWINDOW_OBJECT WindowObject
;
3995 WindowObject
= IntGetWindowObject(hWnd
);
3996 if (WindowObject
== NULL
)
3998 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4002 /* FIXME - Verify if hRgn is a valid handle!!!!
4003 Propably make this operation thread-safe, but maybe it's not necessary */
4005 if(WindowObject
->WindowRegion
)
4007 /* Delete no longer needed region handle */
4008 NtGdiDeleteObject(WindowObject
->WindowRegion
);
4010 WindowObject
->WindowRegion
= hRgn
;
4012 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
4016 IntRedrawWindow(WindowObject
, NULL
, NULL
, RDW_INVALIDATE
);
4019 IntReleaseWindowObject(WindowObject
);
4028 NtUserShowWindow(HWND hWnd
,
4031 return WinPosShowWindow(hWnd
, nCmdShow
);
4039 NtUserShowWindowAsync(DWORD Unknown0
,
4052 NtUserUpdateLayeredWindow(DWORD Unknown0
,
4072 NtUserValidateRect(HWND hWnd
, const RECT
* Rect
)
4074 return (VOID
)NtUserRedrawWindow(hWnd
, Rect
, 0, RDW_VALIDATE
| RDW_NOCHILDREN
);
4082 NtUserWindowFromPoint(LONG X
, LONG Y
)
4086 PWINDOW_OBJECT DesktopWindow
, Window
= NULL
;
4088 if ((DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow())))
4095 Hit
= WinPosWindowFromPoint(DesktopWindow
, PsGetWin32Thread()->MessageQueue
, &pt
, &Window
);
4100 IntReleaseWindowObject(Window
);
4101 IntReleaseWindowObject(DesktopWindow
);
4105 IntReleaseWindowObject(DesktopWindow
);
4115 * Undocumented function that is called from DefWindowProc to set
4123 NtUserDefSetText(HWND WindowHandle
, PUNICODE_STRING WindowText
)
4125 PWINDOW_OBJECT WindowObject
, Parent
, Owner
;
4126 UNICODE_STRING SafeText
;
4129 WindowObject
= IntGetWindowObject(WindowHandle
);
4132 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4138 Status
= IntSafeCopyUnicodeString(&SafeText
, WindowText
);
4139 if(!NT_SUCCESS(Status
))
4141 SetLastNtError(Status
);
4142 IntReleaseWindowObject(WindowObject
);
4148 RtlInitUnicodeString(&SafeText
, NULL
);
4151 /* FIXME - do this thread-safe! otherwise one could crash here! */
4152 RtlFreeUnicodeString(&WindowObject
->WindowName
);
4154 WindowObject
->WindowName
= SafeText
;
4156 /* Send shell notifications */
4158 Owner
= IntGetOwner(WindowObject
);
4159 Parent
= IntGetParent(WindowObject
);
4161 if ((!Owner
) && (!Parent
))
4163 IntShellHookNotify(HSHELL_REDRAW
, (LPARAM
) WindowHandle
);
4168 IntReleaseWindowObject(Owner
);
4173 IntReleaseWindowObject(Parent
);
4176 IntReleaseWindowObject(WindowObject
);
4181 * NtUserInternalGetWindowText
4188 NtUserInternalGetWindowText(HWND hWnd
, LPWSTR lpString
, INT nMaxCount
)
4190 PWINDOW_OBJECT WindowObject
;
4194 if(lpString
&& (nMaxCount
<= 1))
4196 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
4200 WindowObject
= IntGetWindowObject(hWnd
);
4203 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4207 /* FIXME - do this thread-safe! otherwise one could crash here! */
4208 Result
= WindowObject
->WindowName
.Length
/ sizeof(WCHAR
);
4211 const WCHAR Terminator
= L
'\0';
4213 WCHAR
*Buffer
= (WCHAR
*)lpString
;
4215 Copy
= min(nMaxCount
- 1, Result
);
4218 Status
= MmCopyToCaller(Buffer
, WindowObject
->WindowName
.Buffer
, Copy
* sizeof(WCHAR
));
4219 if(!NT_SUCCESS(Status
))
4221 SetLastNtError(Status
);
4222 IntReleaseWindowObject(WindowObject
);
4228 Status
= MmCopyToCaller(Buffer
, &Terminator
, sizeof(WCHAR
));
4229 if(!NT_SUCCESS(Status
))
4231 SetLastNtError(Status
);
4232 IntReleaseWindowObject(WindowObject
);
4239 IntReleaseWindowObject(WindowObject
);
4244 NtUserDereferenceWndProcHandle(WNDPROC wpHandle
, WndProcHandle
*Data
)
4246 WndProcHandle Entry
;
4247 if (((DWORD
)wpHandle
& 0xFFFF0000) == 0xFFFF0000)
4249 Entry
= WndProcHandlesArray
[(DWORD
)wpHandle
& 0x0000FFFF];
4250 Data
->WindowProc
= Entry
.WindowProc
;
4251 Data
->IsUnicode
= Entry
.IsUnicode
;
4252 Data
->ProcessID
= Entry
.ProcessID
;
4261 IntAddWndProcHandle(WNDPROC WindowProc
, BOOL IsUnicode
)
4266 WndProcHandle
*OldArray
;
4269 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4271 if (WndProcHandlesArray
[i
].WindowProc
== NULL
)
4279 OldArray
= WndProcHandlesArray
;
4280 OldArraySize
= WndProcHandlesArraySize
;
4281 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,(OldArraySize
+ WPH_SIZE
) * sizeof(WndProcHandle
), TAG_WINPROCLST
);
4282 WndProcHandlesArraySize
= OldArraySize
+ WPH_SIZE
;
4283 RtlCopyMemory(WndProcHandlesArray
,OldArray
,OldArraySize
* sizeof(WndProcHandle
));
4284 ExFreePool(OldArray
);
4285 FreeSpot
= OldArraySize
+ 1;
4287 WndProcHandlesArray
[FreeSpot
].WindowProc
= WindowProc
;
4288 WndProcHandlesArray
[FreeSpot
].IsUnicode
= IsUnicode
;
4289 WndProcHandlesArray
[FreeSpot
].ProcessID
= PsGetCurrentProcessId();
4290 return FreeSpot
+ 0xFFFF0000;
4294 IntRemoveWndProcHandle(WNDPROC Handle
)
4297 position
= (DWORD
)Handle
& 0x0000FFFF;
4298 if (position
> WndProcHandlesArraySize
)
4302 WndProcHandlesArray
[position
].WindowProc
= NULL
;
4303 WndProcHandlesArray
[position
].IsUnicode
= FALSE
;
4304 WndProcHandlesArray
[position
].ProcessID
= NULL
;
4309 IntRemoveProcessWndProcHandles(HANDLE ProcessID
)
4312 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4314 if (WndProcHandlesArray
[i
].ProcessID
== ProcessID
)
4316 WndProcHandlesArray
[i
].WindowProc
= NULL
;
4317 WndProcHandlesArray
[i
].IsUnicode
= FALSE
;
4318 WndProcHandlesArray
[i
].ProcessID
= NULL
;
4324 #define WIN_NEEDS_SHOW_OWNEDPOPUP (0x00000040)
4328 IntShowOwnedPopups( HWND owner
, BOOL fShow
)
4331 PWINDOW_OBJECT Window
, pWnd
;
4334 if(!(Window
= IntGetWindowObject(owner
)))
4336 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4340 win_array
= IntWinListChildren( Window
);
4341 IntReleaseWindowObject(Window
);
4343 if (!win_array
) return TRUE
;
4345 while (win_array
[count
]) count
++;
4346 while (--count
>= 0)
4348 if (NtUserGetWindow( win_array
[count
], GW_OWNER
) != owner
) continue;
4349 if (!(pWnd
= IntGetWindowObject( win_array
[count
] ))) continue;
4350 // if (pWnd == WND_OTHER_PROCESS) continue;
4354 if (pWnd
->Flags
& WIN_NEEDS_SHOW_OWNEDPOPUP
)
4356 IntReleaseWindowObject( pWnd
);
4357 /* In Windows, ShowOwnedPopups(TRUE) generates
4358 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
4359 * regardless of the state of the owner
4361 IntSendMessage(win_array
[count
], WM_SHOWWINDOW
, SW_SHOWNORMAL
, SW_PARENTOPENING
);
4367 if (pWnd
->Style
& WS_VISIBLE
)
4369 IntReleaseWindowObject( pWnd
);
4370 /* In Windows, ShowOwnedPopups(FALSE) generates
4371 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
4372 * regardless of the state of the owner
4374 IntSendMessage(win_array
[count
], WM_SHOWWINDOW
, SW_HIDE
, SW_PARENTCLOSING
);
4378 IntReleaseWindowObject( pWnd
);
4380 ExFreePool( win_array
);