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.198 2004/03/09 21:21:39 dwelch Exp $
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
24 * FILE: subsys/win32k/ntuser/window.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
27 * 06-06-2001 CSH Created
29 /* INCLUDES ******************************************************************/
31 #include <ddk/ntddk.h>
32 #include <internal/safe.h>
33 #include <win32k/win32k.h>
34 #include <include/object.h>
35 #include <include/guicheck.h>
36 #include <include/window.h>
37 #include <include/class.h>
38 #include <include/error.h>
39 #include <include/winsta.h>
40 #include <include/desktop.h>
41 #include <include/winpos.h>
42 #include <include/callback.h>
43 #include <include/msgqueue.h>
44 #include <include/rect.h>
45 #include <include/dce.h>
46 #include <include/paint.h>
47 #include <include/painting.h>
48 #include <include/scroll.h>
49 #include <include/vis.h>
50 #include <include/menu.h>
51 #include <include/hotkey.h>
52 #include <include/focus.h>
53 #include <include/hook.h>
54 #include <include/useratom.h>
55 #include <include/tags.h>
58 #include <win32k/debug1.h>
61 static WndProcHandle
*WndProcHandlesArray
= 0;
62 static WORD WndProcHandlesArraySize
= 0;
63 #define WPH_SIZE 0x40 /* the size to add to the WndProcHandle array each time */
65 #define POINT_IN_RECT(p, r) (((r.bottom >= p.y) && (r.top <= p.y))&&((r.left <= p.x )&&( r.right >= p.x )))
67 /* PRIVATE FUNCTIONS **********************************************************/
72 * Initialize windowing implementation.
78 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,WPH_SIZE
* sizeof(WndProcHandle
), TAG_WINPROCLST
);
79 WndProcHandlesArraySize
= WPH_SIZE
;
80 return STATUS_SUCCESS
;
86 * Cleanup windowing implementation.
90 CleanupWindowImpl(VOID
)
92 ExFreePool(WndProcHandlesArray
);
93 WndProcHandlesArray
= 0;
94 WndProcHandlesArraySize
= 0;
95 return STATUS_SUCCESS
;
98 /* HELPER FUNCTIONS ***********************************************************/
103 * The function determines whether the specified window handle identifies
104 * an existing window.
108 * Handle to the window to test.
111 * If the window handle identifies an existing window, the return value
112 * is TRUE. If the window handle does not identify an existing window,
113 * the return value is FALSE.
117 IntIsWindow(HWND hWnd
)
119 PWINDOW_OBJECT Window
;
121 if (!(Window
= IntGetWindowObject(hWnd
)))
124 IntReleaseWindowObject(Window
);
129 * IntGetProcessWindowObject
131 * Get window object from handle of specified process.
134 PWINDOW_OBJECT FASTCALL
135 IntGetProcessWindowObject(PW32PROCESS ProcessData
, HWND hWnd
)
137 PWINDOW_OBJECT WindowObject
;
140 Status
= ObmReferenceObjectByHandle(ProcessData
->WindowStation
->HandleTable
,
141 hWnd
, otWindow
, (PVOID
*)&WindowObject
);
142 if (!NT_SUCCESS(Status
))
150 PWINDOW_OBJECT FASTCALL
151 IntGetParent(PWINDOW_OBJECT Wnd
)
155 if (Wnd
->Style
& WS_POPUP
)
157 IntLockRelatives(Wnd
);
159 IntUnLockRelatives(Wnd
);
160 return IntGetWindowObject(hWnd
);
162 else if (Wnd
->Style
& WS_CHILD
)
164 IntLockRelatives(Wnd
);
166 IntUnLockRelatives(Wnd
);
167 return IntGetWindowObject(hWnd
);
174 PWINDOW_OBJECT FASTCALL
175 IntGetParentObject(PWINDOW_OBJECT Wnd
)
179 IntLockRelatives(Wnd
);
180 hParent
= Wnd
->Parent
;
181 IntUnLockRelatives(Wnd
);
182 return IntGetWindowObject(hParent
);
188 * Compile a list of all child window handles from given window.
191 * This function is similar to Wine WIN_ListChildren. The caller
192 * must free the returned list with ExFreePool.
196 IntWinListChildren(PWINDOW_OBJECT Window
)
198 PWINDOW_OBJECT Child
;
200 UINT Index
, NumChildren
= 0;
202 IntLockRelatives(Window
);
204 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
207 if (NumChildren
!= 0)
209 List
= ExAllocatePoolWithTag(PagedPool
, (NumChildren
+ 1) * sizeof(HWND
), TAG_WINLIST
);
212 DPRINT1("Failed to allocate memory for children array\n");
213 IntUnLockRelatives(Window
);
216 for (Child
= Window
->FirstChild
, Index
= 0;
218 Child
= Child
->NextSibling
, ++Index
)
219 List
[Index
] = Child
->Self
;
223 IntUnLockRelatives(Window
);
225 return (NumChildren
> 0) ? List
: NULL
;
228 /***********************************************************************
231 static void IntSendDestroyMsg(HWND Wnd
)
236 if (GetGUIThreadInfo(GetCurrentThreadId(), &info
))
238 if (Wnd
== info
.hwndCaret
)
246 * Send the WM_DESTROY to the window.
248 IntSendMessage(Wnd
, WM_DESTROY
, 0, 0);
251 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
252 * make sure that the window still exists when we come back.
260 if (!(pWndArray
= WIN_ListChildren( hwnd
))) return;
262 /* start from the end (FIXME: is this needed?) */
263 for (i
= 0; pWndArray
[i
]; i
++) ;
267 if (IsWindow( pWndArray
[i
] )) WIN_SendDestroyMsg( pWndArray
[i
] );
269 HeapFree(GetProcessHeap(), 0, pWndArray
);
273 DPRINT("destroyed itself while in WM_DESTROY!\n");
278 /***********************************************************************
281 * Destroy storage associated to a window. "Internals" p.358
283 static LRESULT
IntDestroyWindow(PWINDOW_OBJECT Window
,
284 PW32PROCESS ProcessData
,
285 PW32THREAD ThreadData
,
286 BOOLEAN SendMessages
)
290 PWINDOW_OBJECT Child
;
292 BOOL BelongsToThreadData
;
296 IntLockThreadWindows(Window
->OwnerThread
->Win32Thread
);
297 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
299 IntUnLockThreadWindows(Window
->OwnerThread
->Win32Thread
);
300 DPRINT("Tried to call IntDestroyWindow() twice\n");
303 Window
->Status
|= WINDOWSTATUS_DESTROYING
;
304 /* remove the window already at this point from the thread window list so we
305 don't get into trouble when destroying the thread windows while we're still
306 in IntDestroyWindow() */
307 RemoveEntryList(&Window
->ThreadListEntry
);
308 IntUnLockThreadWindows(Window
->OwnerThread
->Win32Thread
);
310 BelongsToThreadData
= IntWndBelongsToThread(Window
, ThreadData
);
314 /* Send destroy messages */
315 IntSendDestroyMsg(Window
->Self
);
318 /* free child windows */
319 Children
= IntWinListChildren(Window
);
322 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
324 if ((Child
= IntGetWindowObject(*ChildHandle
)))
326 if(!IntWndBelongsToThread(Child
, ThreadData
))
328 /* send WM_DESTROY messages to windows not belonging to the same thread */
329 IntSendDestroyMsg(Child
->Self
);
332 IntDestroyWindow(Child
, ProcessData
, ThreadData
, SendMessages
);
333 IntReleaseWindowObject(Child
);
336 ExFreePool(Children
);
342 * Clear the update region to make sure no WM_PAINT messages will be
343 * generated for this window while processing the WM_NCDESTROY.
345 IntRedrawWindow(Window
, NULL
, 0,
346 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
|
347 RDW_NOINTERNALPAINT
| RDW_NOCHILDREN
);
350 * Send the WM_NCDESTROY to the window being destroyed.
352 if(BelongsToThreadData
)
353 IntSendMessage(Window
->Self
, WM_NCDESTROY
, 0, 0);
356 /* reset shell window handles */
357 if(ProcessData
->WindowStation
)
359 if (Window
->Self
== ProcessData
->WindowStation
->ShellWindow
)
360 ProcessData
->WindowStation
->ShellWindow
= NULL
;
362 if (Window
->Self
== ProcessData
->WindowStation
->ShellListView
)
363 ProcessData
->WindowStation
->ShellListView
= NULL
;
366 /* Unregister hot keys */
367 UnregisterWindowHotKeys (Window
);
369 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
372 WinPosCheckInternalPos(Window
->Self
);
373 if (Window
->Self
== GetCapture())
378 /* free resources associated with the window */
379 TIMER_RemoveWindowTimers(Window
->Self
);
382 if (!(Window
->Style
& WS_CHILD
) && Window
->IDMenu
383 && (Menu
= IntGetMenuObject((HMENU
)Window
->IDMenu
)))
385 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
387 IntReleaseMenuObject(Menu
);
390 if(Window
->SystemMenu
391 && (Menu
= IntGetMenuObject(Window
->SystemMenu
)))
393 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
394 Window
->SystemMenu
= (HMENU
)0;
395 IntReleaseMenuObject(Menu
);
398 DceFreeWindowDCE(Window
); /* Always do this to catch orphaned DCs */
400 WINPROC_FreeProc(Window
->winproc
, WIN_PROC_WINDOW
);
401 CLASS_RemoveWindow(Window
->Class
);
404 IntUnlinkWindow(Window
);
406 IntReferenceWindowObject(Window
);
407 ObmCloseHandle(ProcessData
->WindowStation
->HandleTable
, Window
->Self
);
409 IntDestroyScrollBar(Window
, SB_VERT
);
410 IntDestroyScrollBar(Window
, SB_HORZ
);
412 IntLockThreadWindows(Window
->OwnerThread
->Win32Thread
);
413 Window
->Status
|= WINDOWSTATUS_DESTROYED
;
414 /* don't remove the WINDOWSTATUS_DESTROYING bit */
415 IntUnLockThreadWindows(Window
->OwnerThread
->Win32Thread
);
417 ObmDereferenceObject(Window
->Class
);
418 Window
->Class
= NULL
;
420 IntReleaseWindowObject(Window
);
427 PWINDOW_OBJECT WindowObject
,
431 PMENU_OBJECT OldMenuObject
, NewMenuObject
;
433 *Changed
= (WindowObject
->IDMenu
!= (UINT
) Menu
);
439 if (0 != WindowObject
->IDMenu
)
441 OldMenuObject
= IntGetMenuObject((HMENU
) WindowObject
->IDMenu
);
442 ASSERT(NULL
== OldMenuObject
|| OldMenuObject
->MenuInfo
.Wnd
== WindowObject
->Self
);
446 OldMenuObject
= NULL
;
451 NewMenuObject
= IntGetMenuObject(Menu
);
452 if (NULL
== NewMenuObject
)
454 if (NULL
!= OldMenuObject
)
456 IntReleaseMenuObject(OldMenuObject
);
458 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
461 if (NULL
!= NewMenuObject
->MenuInfo
.Wnd
)
463 /* Can't use the same menu for two windows */
464 if (NULL
!= OldMenuObject
)
466 IntReleaseMenuObject(OldMenuObject
);
468 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
474 WindowObject
->IDMenu
= (UINT
) Menu
;
475 if (NULL
!= NewMenuObject
)
477 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
478 IntReleaseMenuObject(NewMenuObject
);
480 if (NULL
!= OldMenuObject
)
482 OldMenuObject
->MenuInfo
.Wnd
= NULL
;
483 IntReleaseMenuObject(OldMenuObject
);
490 /* INTERNAL ******************************************************************/
494 DestroyThreadWindows(struct _ETHREAD
*Thread
)
497 PW32PROCESS Win32Process
;
498 PW32THREAD Win32Thread
;
499 PWINDOW_OBJECT
*List
, *pWnd
;
502 Win32Thread
= Thread
->Win32Thread
;
503 Win32Process
= Thread
->ThreadsProcess
->Win32Process
;
505 IntLockThreadWindows(Win32Thread
);
506 Current
= Win32Thread
->WindowListHead
.Flink
;
507 while (Current
!= &(Win32Thread
->WindowListHead
))
510 Current
= Current
->Flink
;
515 List
= ExAllocatePool(PagedPool
, (Cnt
+ 1) * sizeof(PWINDOW_OBJECT
));
518 DPRINT("Not enough memory to allocate window handle list\n");
519 IntUnLockThreadWindows(Win32Thread
);
523 Current
= Win32Thread
->WindowListHead
.Flink
;
524 while (Current
!= &(Win32Thread
->WindowListHead
))
526 *pWnd
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
527 IntReferenceWindowObject(*pWnd
);
529 Current
= Current
->Flink
;
531 IntUnLockThreadWindows(Win32Thread
);
534 for(pWnd
= List
; *pWnd
; pWnd
++)
536 IntDestroyWindow(*pWnd
, Win32Process
, Win32Thread
, FALSE
);
537 IntReleaseWindowObject(*pWnd
);
543 IntUnLockThreadWindows(Win32Thread
);
549 * Returns client window rectangle relative to the upper-left corner of client area.
551 * \note Does not check the validity of the parameters
554 IntGetClientRect(PWINDOW_OBJECT WindowObject
, PRECT Rect
)
556 ASSERT( WindowObject
);
559 Rect
->left
= Rect
->top
= 0;
560 Rect
->right
= WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
;
561 Rect
->bottom
= WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
;
567 IntGetFocusWindow(VOID
)
569 PUSER_MESSAGE_QUEUE Queue
;
570 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
575 Queue
= (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
580 return(Queue
->FocusWindow
);
584 PMENU_OBJECT FASTCALL
585 IntGetSystemMenu(PWINDOW_OBJECT WindowObject
, BOOL bRevert
, BOOL RetMenu
)
587 PMENU_OBJECT MenuObject
, NewMenuObject
, SysMenuObject
, ret
= NULL
;
588 PW32PROCESS W32Process
;
589 HMENU NewMenu
, SysMenu
;
590 ROSMENUITEMINFO ItemInfo
;
594 W32Process
= PsGetWin32Process();
596 if(!W32Process
->WindowStation
)
599 if(WindowObject
->SystemMenu
)
601 MenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
604 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
605 WindowObject
->SystemMenu
= (HMENU
)0;
606 IntReleaseMenuObject(MenuObject
);
610 if(W32Process
->WindowStation
->SystemMenuTemplate
)
612 /* clone system menu */
613 MenuObject
= IntGetMenuObject(W32Process
->WindowStation
->SystemMenuTemplate
);
617 NewMenuObject
= IntCloneMenu(MenuObject
);
620 WindowObject
->SystemMenu
= NewMenuObject
->MenuInfo
.Self
;
621 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
622 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
624 //IntReleaseMenuObject(NewMenuObject);
626 IntReleaseMenuObject(MenuObject
);
630 SysMenu
= NtUserCreateMenu(FALSE
);
635 SysMenuObject
= IntGetMenuObject(SysMenu
);
636 if (NULL
== SysMenuObject
)
638 NtUserDestroyMenu(SysMenu
);
641 SysMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
642 SysMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
643 NewMenu
= IntLoadSysMenuTemplate();
646 IntReleaseMenuObject(SysMenuObject
);
647 NtUserDestroyMenu(SysMenu
);
650 MenuObject
= IntGetMenuObject(NewMenu
);
653 IntReleaseMenuObject(SysMenuObject
);
654 NtUserDestroyMenu(SysMenu
);
658 NewMenuObject
= IntCloneMenu(MenuObject
);
661 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
| MF_POPUP
;
662 IntReleaseMenuObject(NewMenuObject
);
663 NtUserSetMenuDefaultItem(NewMenuObject
->MenuInfo
.Self
, SC_CLOSE
, FALSE
);
665 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
666 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
667 ItemInfo
.fType
= MF_POPUP
;
668 ItemInfo
.fState
= MFS_ENABLED
;
669 ItemInfo
.dwTypeData
= NULL
;
671 ItemInfo
.hSubMenu
= NewMenuObject
->MenuInfo
.Self
;
672 IntInsertMenuItem(SysMenuObject
, (UINT
) -1, TRUE
, &ItemInfo
);
674 WindowObject
->SystemMenu
= SysMenuObject
->MenuInfo
.Self
;
678 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
679 IntReleaseMenuObject(MenuObject
);
688 if(WindowObject
->SystemMenu
)
689 return IntGetMenuObject((HMENU
)WindowObject
->SystemMenu
);
697 IntIsChildWindow(HWND Parent
, HWND Child
)
699 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
701 if(!(BaseWindow
= IntGetWindowObject(Child
)))
709 if(!(Window
->Style
& WS_CHILD
))
711 if(Window
!= BaseWindow
)
712 IntReleaseWindowObject(Window
);
715 if (Window
->Self
== Parent
)
717 if(Window
!= BaseWindow
)
718 IntReleaseWindowObject(Window
);
719 IntReleaseWindowObject(BaseWindow
);
723 Window
= IntGetParentObject(Window
);
724 if(Old
!= BaseWindow
)
725 IntReleaseWindowObject(Old
);
728 IntReleaseWindowObject(BaseWindow
);
733 IntIsWindowVisible(HWND hWnd
)
735 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
737 if(!(BaseWindow
= IntGetWindowObject(hWnd
)))
745 if(!(Window
->Style
& WS_CHILD
))
749 if(!(Window
->Style
& WS_VISIBLE
))
751 if(Window
!= BaseWindow
)
752 IntReleaseWindowObject(Window
);
753 IntReleaseWindowObject(BaseWindow
);
757 Window
= IntGetParentObject(Window
);
758 if(Old
!= BaseWindow
)
759 IntReleaseWindowObject(Old
);
764 if(Window
->Style
& WS_VISIBLE
)
766 if(Window
!= BaseWindow
)
767 IntReleaseWindowObject(Window
);
768 IntReleaseWindowObject(BaseWindow
);
771 if(Window
!= BaseWindow
)
772 IntReleaseWindowObject(Window
);
774 IntReleaseWindowObject(BaseWindow
);
779 /* link the window into siblings and parent. children are kept in place. */
783 PWINDOW_OBJECT WndParent
,
784 PWINDOW_OBJECT WndPrevSibling
/* set to NULL if top sibling */
787 PWINDOW_OBJECT Parent
;
789 IntLockRelatives(Wnd
);
790 Wnd
->Parent
= WndParent
->Self
;
791 if ((Wnd
->PrevSibling
= WndPrevSibling
))
793 /* link after WndPrevSibling */
794 if ((Wnd
->NextSibling
= WndPrevSibling
->NextSibling
))
795 Wnd
->NextSibling
->PrevSibling
= Wnd
;
796 else if ((Parent
= IntGetWindowObject(Wnd
->Parent
)))
798 IntLockRelatives(Parent
);
799 if(Parent
->LastChild
== WndPrevSibling
)
800 Parent
->LastChild
= Wnd
;
801 IntUnLockRelatives(Parent
);
802 IntReleaseWindowObject(Parent
);
804 Wnd
->PrevSibling
->NextSibling
= Wnd
;
809 Parent
= IntGetWindowObject(Wnd
->Parent
);
810 if ((Wnd
->NextSibling
= WndParent
->FirstChild
))
811 Wnd
->NextSibling
->PrevSibling
= Wnd
;
814 IntLockRelatives(Parent
);
815 Parent
->LastChild
= Wnd
;
816 Parent
->FirstChild
= Wnd
;
817 IntUnLockRelatives(Parent
);
818 IntReleaseWindowObject(Parent
);
819 IntUnLockRelatives(Wnd
);
824 IntLockRelatives(Parent
);
825 Parent
->FirstChild
= Wnd
;
826 IntUnLockRelatives(Parent
);
827 IntReleaseWindowObject(Parent
);
830 IntUnLockRelatives(Wnd
);
834 IntSetOwner(HWND hWnd
, HWND hWndNewOwner
)
836 PWINDOW_OBJECT Wnd
, WndOldOwner
, WndNewOwner
;
839 Wnd
= IntGetWindowObject(hWnd
);
843 IntLockRelatives(Wnd
);
844 WndOldOwner
= IntGetWindowObject(Wnd
->Owner
);
847 ret
= WndOldOwner
->Self
;
848 IntReleaseWindowObject(WndOldOwner
);
855 if((WndNewOwner
= IntGetWindowObject(hWndNewOwner
)))
857 Wnd
->Owner
= hWndNewOwner
;
858 IntReleaseWindowObject(WndNewOwner
);
863 IntUnLockRelatives(Wnd
);
864 IntReleaseWindowObject(Wnd
);
868 PWINDOW_OBJECT FASTCALL
869 IntSetParent(PWINDOW_OBJECT Wnd
, PWINDOW_OBJECT WndNewParent
)
871 PWINDOW_OBJECT WndOldParent
;
872 HWND hWnd
, hWndNewParent
, hWndOldParent
;
877 ASSERT(WndNewParent
);
880 hWndNewParent
= WndNewParent
->Self
;
883 * Windows hides the window first, then shows it again
884 * including the WM_SHOWWINDOW messages and all
886 WasVisible
= WinPosShowWindow(hWnd
, SW_HIDE
);
888 /* Validate that window and parent still exist */
889 if (!IntIsWindow(hWnd
) || !IntIsWindow(hWndNewParent
))
892 /* Window must belong to current process */
893 if (Wnd
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
896 WndOldParent
= IntGetParentObject(Wnd
);
897 hWndOldParent
= (WndOldParent
? WndOldParent
->Self
: NULL
);
899 if (WndNewParent
!= WndOldParent
)
901 IntUnlinkWindow(Wnd
);
902 IntLinkWindow(Wnd
, WndNewParent
, NULL
/*prev sibling*/);
904 if (WndNewParent
->Self
!= IntGetDesktopWindow()) /* a child window */
906 if (!(Wnd
->Style
& WS_CHILD
))
908 //if ( Wnd->Menu ) DestroyMenu ( Wnd->menu );
909 IntSetMenu(Wnd
, NULL
, &MenuChanged
);
915 * SetParent additionally needs to make hwnd the topmost window
916 * in the x-order and send the expected WM_WINDOWPOSCHANGING and
917 * WM_WINDOWPOSCHANGED notification messages.
919 WinPosSetWindowPos(hWnd
, HWND_TOPMOST
, 0, 0, 0, 0,
920 SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
| (WasVisible
? SWP_SHOWWINDOW
: 0));
923 * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
924 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
928 * Validate that the old parent still exist, since it migth have been
929 * destroyed during the last callbacks to user-mode
933 if(!IntIsWindow(WndOldParent
->Self
))
935 IntReleaseWindowObject(WndOldParent
);
939 /* don't dereference the window object here, it must be done by the caller
947 IntSetSystemMenu(PWINDOW_OBJECT WindowObject
, PMENU_OBJECT MenuObject
)
949 PMENU_OBJECT OldMenuObject
;
950 if(WindowObject
->SystemMenu
)
952 OldMenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
955 OldMenuObject
->MenuInfo
.Flags
&= ~ MF_SYSMENU
;
956 IntReleaseMenuObject(OldMenuObject
);
962 /* FIXME check window style, propably return FALSE ? */
963 WindowObject
->SystemMenu
= MenuObject
->MenuInfo
.Self
;
964 MenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
967 WindowObject
->SystemMenu
= (HMENU
)0;
973 /* unlink the window from siblings and parent. children are kept in place. */
975 IntUnlinkWindow(PWINDOW_OBJECT Wnd
)
977 PWINDOW_OBJECT WndParent
;
979 IntLockRelatives(Wnd
);
980 if((WndParent
= IntGetWindowObject(Wnd
->Parent
)))
982 IntLockRelatives(WndParent
);
985 if (Wnd
->NextSibling
) Wnd
->NextSibling
->PrevSibling
= Wnd
->PrevSibling
;
986 else if (WndParent
&& WndParent
->LastChild
== Wnd
) WndParent
->LastChild
= Wnd
->PrevSibling
;
988 if (Wnd
->PrevSibling
) Wnd
->PrevSibling
->NextSibling
= Wnd
->NextSibling
;
989 else if (WndParent
&& WndParent
->FirstChild
== Wnd
) WndParent
->FirstChild
= Wnd
->NextSibling
;
993 IntUnLockRelatives(WndParent
);
994 IntReleaseWindowObject(WndParent
);
996 Wnd
->PrevSibling
= Wnd
->NextSibling
= Wnd
->Parent
= NULL
;
997 IntUnLockRelatives(Wnd
);
1000 /* FUNCTIONS *****************************************************************/
1006 NtUserAlterWindowStyle(DWORD Unknown0
,
1017 * As best as I can figure, this function is used by EnumWindows,
1018 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
1020 * It's supposed to build a list of HWNDs to return to the caller.
1021 * We can figure out what kind of list by what parameters are
1029 NtUserBuildHwndList(
1040 /* FIXME handle bChildren */
1043 PWINDOW_OBJECT WindowObject
= NULL
;
1044 PWINDOW_OBJECT Child
;
1046 WindowObject
= IntGetWindowObject ( hwndParent
);
1047 if ( !WindowObject
)
1049 DPRINT("Bad window handle 0x%x\n", hwndParent
);
1050 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1054 IntLockRelatives(WindowObject
);
1055 Child
= WindowObject
->FirstChild
;
1058 if ( pWnd
&& dwCount
< nBufSize
)
1059 pWnd
[dwCount
] = Child
->Self
;
1061 Child
= Child
->NextSibling
;
1063 IntUnLockRelatives(WindowObject
);
1064 IntReleaseWindowObject ( WindowObject
);
1066 else if ( dwThreadId
)
1069 struct _ETHREAD
* Thread
;
1070 struct _EPROCESS
* ThreadsProcess
;
1071 struct _W32PROCESS
* Win32Process
;
1072 struct _WINSTATION_OBJECT
* WindowStation
;
1073 PUSER_HANDLE_TABLE HandleTable
;
1074 PLIST_ENTRY Current
;
1075 PUSER_HANDLE_BLOCK Block
= NULL
;
1078 Status
= PsLookupThreadByThreadId ( (PVOID
)dwThreadId
, &Thread
);
1079 if ( !NT_SUCCESS(Status
) || !Thread
)
1081 DPRINT("Bad ThreadId 0x%x\n", dwThreadId
);
1082 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1085 ThreadsProcess
= Thread
->ThreadsProcess
;
1086 ASSERT(ThreadsProcess
);
1087 Win32Process
= ThreadsProcess
->Win32Process
;
1088 ASSERT(Win32Process
);
1089 WindowStation
= Win32Process
->WindowStation
;
1090 ASSERT(WindowStation
);
1091 HandleTable
= (PUSER_HANDLE_TABLE
)(WindowStation
->HandleTable
);
1092 ASSERT(HandleTable
);
1094 ObDereferenceObject(Thread
);
1096 ObmpLockHandleTable(HandleTable
);
1098 Current
= HandleTable
->ListHead
.Flink
;
1099 while ( Current
!= &HandleTable
->ListHead
)
1101 Block
= CONTAINING_RECORD(Current
, USER_HANDLE_BLOCK
, ListEntry
);
1102 for ( i
= 0; i
< HANDLE_BLOCK_ENTRIES
; i
++ )
1104 PVOID ObjectBody
= Block
->Handles
[i
].ObjectBody
;
1107 if ( pWnd
&& dwCount
< nBufSize
)
1110 (HWND
)IntReferenceWindowObject(ObjectBody
);
1115 Current
= Current
->Flink
;
1118 ObmpUnlockHandleTable(HandleTable
);
1122 PDESKTOP_OBJECT DesktopObject
= NULL
;
1124 PWINDOW_OBJECT Child
, WndDesktop
;
1128 DesktopObject
= IntGetDesktopObject ( hDesktop
);
1131 DesktopObject
= IntGetActiveDesktop();
1134 DPRINT("Bad desktop handle 0x%x\n", hDesktop
);
1135 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1139 KeAcquireSpinLock ( &DesktopObject
->Lock
, &OldIrql
);
1141 WndDesktop
= IntGetWindowObject(DesktopObject
->DesktopWindow
);
1142 Child
= (WndDesktop
? WndDesktop
->FirstChild
: NULL
);
1145 if ( pWnd
&& dwCount
< nBufSize
)
1146 pWnd
[dwCount
] = Child
->Self
;
1148 Child
= Child
->NextSibling
;
1150 KeReleaseSpinLock ( &DesktopObject
->Lock
, OldIrql
);
1161 /* FIXME - NEEDS TO BE FIXED - UNSAFE !!! */
1163 NtUserChildWindowFromPointEx(HWND hwndParent
,
1168 PWINDOW_OBJECT pParent
, pCurrent
, pLast
, pPar
;
1171 BOOL bFirstRun
= TRUE
;
1175 pParent
= IntGetWindowObject(hwndParent
);
1178 IntLockRelatives(pParent
);
1180 pLast
= IntGetWindowObject(pParent
->LastChild
->Self
);
1181 pCurrent
= IntGetWindowObject(pParent
->FirstChild
->Self
);
1187 pCurrent
= IntGetWindowObject(pCurrent
->NextSibling
->Self
);
1194 IntUnLockRelatives(pParent
);
1197 if(!(pPar
= IntGetWindowObject(pCurrent
->Parent
)))
1199 IntUnLockRelatives(pParent
);
1202 rc
.left
= pCurrent
->WindowRect
.left
- pPar
->ClientRect
.left
;
1203 rc
.top
= pCurrent
->WindowRect
.top
- pPar
->ClientRect
.top
;
1204 rc
.right
= rc
.left
+ (pCurrent
->WindowRect
.right
- pCurrent
->WindowRect
.left
);
1205 rc
.bottom
= rc
.top
+ (pCurrent
->WindowRect
.bottom
- pCurrent
->WindowRect
.top
);
1206 DbgPrint("Rect: %i,%i,%i,%i\n",rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
1207 IntReleaseWindowObject(pPar
);
1208 if (POINT_IN_RECT(p
,rc
)) /* Found a match */
1210 if ( (uiFlags
& CWP_SKIPDISABLED
) && (pCurrent
->Style
& WS_DISABLED
) )
1212 if( (uiFlags
& CWP_SKIPTRANSPARENT
) && (pCurrent
->ExStyle
& WS_EX_TRANSPARENT
) )
1214 if( (uiFlags
& CWP_SKIPINVISIBLE
) && !(pCurrent
->Style
& WS_VISIBLE
) )
1217 IntUnLockRelatives(pParent
);
1218 return pCurrent
->Self
;
1221 while(pCurrent
!= pLast
);
1223 IntUnLockRelatives(pParent
);
1226 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1237 NtUserCreateWindowEx(DWORD dwExStyle
,
1238 PUNICODE_STRING lpClassName
,
1239 PUNICODE_STRING lpWindowName
,
1247 HINSTANCE hInstance
,
1250 BOOL bUnicodeWindow
)
1252 PWINSTATION_OBJECT WinStaObject
;
1253 PWNDCLASS_OBJECT ClassObject
;
1254 PWINDOW_OBJECT WindowObject
;
1255 PWINDOW_OBJECT ParentWindow
, OwnerWindow
;
1256 HWND ParentWindowHandle
;
1257 HWND OwnerWindowHandle
;
1258 PMENU_OBJECT SystemMenu
;
1259 UNICODE_STRING WindowName
;
1263 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1268 CBT_CREATEWNDW CbtCreate
;
1272 DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1274 if (! RtlCreateUnicodeString(&WindowName
,
1275 NULL
== lpWindowName
->Buffer
?
1276 L
"" : lpWindowName
->Buffer
))
1278 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1282 ParentWindowHandle
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
1283 OwnerWindowHandle
= NULL
;
1285 if (hWndParent
== HWND_MESSAGE
)
1288 * native ole32.OleInitialize uses HWND_MESSAGE to create the
1289 * message window (style: WS_POPUP|WS_DISABLED)
1293 else if (hWndParent
)
1295 if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1296 ParentWindowHandle
= hWndParent
;
1298 OwnerWindowHandle
= NtUserGetAncestor(hWndParent
, GA_ROOT
);
1300 else if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1302 RtlFreeUnicodeString(&WindowName
);
1303 return (HWND
)0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1306 if (NULL
!= ParentWindowHandle
)
1308 ParentWindow
= IntGetWindowObject(ParentWindowHandle
);
1312 ParentWindow
= NULL
;
1315 /* FIXME: parent must belong to the current process */
1317 /* Check the class. */
1318 Status
= ClassReferenceClassByNameOrAtom(&ClassObject
, lpClassName
->Buffer
);
1319 if (!NT_SUCCESS(Status
))
1321 RtlFreeUnicodeString(&WindowName
);
1322 if (NULL
!= ParentWindow
)
1324 IntReleaseWindowObject(ParentWindow
);
1329 /* Check the window station. */
1330 DPRINT("IoGetCurrentProcess() %X\n", IoGetCurrentProcess());
1331 DPRINT("PROCESS_WINDOW_STATION %X\n", PROCESS_WINDOW_STATION());
1332 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
1336 if (!NT_SUCCESS(Status
))
1338 ObmDereferenceObject(ClassObject
);
1339 RtlFreeUnicodeString(&WindowName
);
1340 if (NULL
!= ParentWindow
)
1342 IntReleaseWindowObject(ParentWindow
);
1344 DPRINT("Validation of window station handle (0x%X) failed\n",
1345 PROCESS_WINDOW_STATION());
1349 /* Create the window object. */
1350 WindowObject
= (PWINDOW_OBJECT
)
1351 ObmCreateObject(PsGetWin32Process()->WindowStation
->HandleTable
, &Handle
,
1352 otWindow
, sizeof(WINDOW_OBJECT
) + ClassObject
->cbWndExtra
1355 DPRINT("Created object with handle %X\n", Handle
);
1358 ObDereferenceObject(WinStaObject
);
1359 ObmDereferenceObject(ClassObject
);
1360 RtlFreeUnicodeString(&WindowName
);
1361 if (NULL
!= ParentWindow
)
1363 IntReleaseWindowObject(ParentWindow
);
1365 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1368 ObDereferenceObject(WinStaObject
);
1370 if (NULL
== PsGetWin32Thread()->Desktop
->DesktopWindow
)
1372 /* If there is no desktop window yet, we must be creating it */
1373 PsGetWin32Thread()->Desktop
->DesktopWindow
= Handle
;
1377 * Fill out the structure describing it.
1379 WindowObject
->Class
= ClassObject
;
1380 WindowObject
->ExStyle
= dwExStyle
;
1381 WindowObject
->Style
= dwStyle
& ~WS_VISIBLE
;
1382 DPRINT("1: Style is now %d\n", WindowObject
->Style
);
1384 WindowObject
->SystemMenu
= (HMENU
)0;
1385 WindowObject
->ContextHelpId
= 0;
1386 WindowObject
->IDMenu
= 0;
1387 WindowObject
->Instance
= hInstance
;
1388 WindowObject
->Self
= Handle
;
1389 if (0 != (dwStyle
& WS_CHILD
))
1391 WindowObject
->IDMenu
= (UINT
) hMenu
;
1395 IntSetMenu(WindowObject
, hMenu
, &MenuChanged
);
1397 WindowObject
->MessageQueue
= PsGetWin32Thread()->MessageQueue
;
1398 WindowObject
->Parent
= (ParentWindow
? ParentWindow
->Self
: NULL
);
1399 if((OwnerWindow
= IntGetWindowObject(OwnerWindowHandle
)))
1401 WindowObject
->Owner
= OwnerWindowHandle
;
1402 IntReleaseWindowObject(OwnerWindow
);
1405 WindowObject
->Owner
= NULL
;
1406 WindowObject
->UserData
= 0;
1407 if ((((DWORD
)ClassObject
->lpfnWndProcA
& 0xFFFF0000) != 0xFFFF0000)
1408 && (((DWORD
)ClassObject
->lpfnWndProcW
& 0xFFFF0000) != 0xFFFF0000))
1410 WindowObject
->Unicode
= bUnicodeWindow
;
1414 WindowObject
->Unicode
= ClassObject
->Unicode
;
1416 WindowObject
->WndProcA
= ClassObject
->lpfnWndProcA
;
1417 WindowObject
->WndProcW
= ClassObject
->lpfnWndProcW
;
1418 WindowObject
->OwnerThread
= PsGetCurrentThread();
1419 WindowObject
->FirstChild
= NULL
;
1420 WindowObject
->LastChild
= NULL
;
1421 WindowObject
->PrevSibling
= NULL
;
1422 WindowObject
->NextSibling
= NULL
;
1424 /* extra window data */
1425 if (ClassObject
->cbWndExtra
!= 0)
1427 WindowObject
->ExtraData
= (PCHAR
)(WindowObject
+ 1);
1428 WindowObject
->ExtraDataSize
= ClassObject
->cbWndExtra
;
1429 RtlZeroMemory(WindowObject
->ExtraData
, WindowObject
->ExtraDataSize
);
1433 WindowObject
->ExtraData
= NULL
;
1434 WindowObject
->ExtraDataSize
= 0;
1437 InitializeListHead(&WindowObject
->PropListHead
);
1438 ExInitializeFastMutex(&WindowObject
->PropListLock
);
1439 ExInitializeFastMutex(&WindowObject
->RelativesLock
);
1440 ExInitializeFastMutex(&WindowObject
->UpdateLock
);
1442 RtlInitUnicodeString(&WindowObject
->WindowName
, WindowName
.Buffer
);
1444 /* Correct the window style. */
1445 if (!(dwStyle
& WS_CHILD
))
1447 WindowObject
->Style
|= WS_CLIPSIBLINGS
;
1448 DPRINT("3: Style is now %d\n", WindowObject
->Style
);
1449 if (!(dwStyle
& WS_POPUP
))
1451 WindowObject
->Style
|= WS_CAPTION
;
1452 WindowObject
->Flags
|= WINDOWOBJECT_NEED_SIZE
;
1453 DPRINT("4: Style is now %d\n", WindowObject
->Style
);
1454 /* FIXME: Note the window needs a size. */
1458 /* create system menu */
1459 if((WindowObject
->Style
& WS_SYSMENU
) && (WindowObject
->Style
& WS_CAPTION
))
1461 SystemMenu
= IntGetSystemMenu(WindowObject
, TRUE
, TRUE
);
1464 WindowObject
->SystemMenu
= SystemMenu
->MenuInfo
.Self
;
1465 IntReleaseMenuObject(SystemMenu
);
1469 /* Insert the window into the thread's window list. */
1470 IntLockThreadWindows(PsGetWin32Thread());
1471 InsertTailList (&PsGetWin32Thread()->WindowListHead
,
1472 &WindowObject
->ThreadListEntry
);
1473 IntUnLockThreadWindows(PsGetWin32Thread());
1475 /* Allocate a DCE for this window. */
1476 if (dwStyle
& CS_OWNDC
)
1478 WindowObject
->Dce
= DceAllocDCE(WindowObject
->Self
, DCE_WINDOW_DC
);
1480 /* FIXME: Handle "CS_CLASSDC" */
1482 /* Initialize the window dimensions. */
1483 WindowObject
->WindowRect
.left
= x
;
1484 WindowObject
->WindowRect
.top
= y
;
1485 WindowObject
->WindowRect
.right
= x
+ nWidth
;
1486 WindowObject
->WindowRect
.bottom
= y
+ nHeight
;
1487 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1489 NtGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1490 ParentWindow
->ClientRect
.top
);
1492 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1494 Cs
.lpCreateParams
= lpParam
;
1495 Cs
.hInstance
= hInstance
;
1497 Cs
.hwndParent
= ParentWindowHandle
;
1503 Cs
.lpszName
= lpWindowName
->Buffer
;
1504 Cs
.lpszClass
= lpClassName
->Buffer
;
1505 Cs
.dwExStyle
= dwExStyle
;
1506 CbtCreate
.lpcs
= &Cs
;
1507 CbtCreate
.hwndInsertAfter
= HWND_TOP
;
1508 if (HOOK_CallHooks(WH_CBT
, HCBT_CREATEWND
, (WPARAM
) Handle
, (LPARAM
) &CbtCreate
))
1510 if (NULL
!= ParentWindow
)
1512 IntReleaseWindowObject(ParentWindow
);
1514 DPRINT1("CBT-hook returned !0\n");
1519 * Get the size and position of the window.
1521 if ((dwStyle
& WS_THICKFRAME
) || !(dwStyle
& (WS_POPUP
| WS_CHILD
)))
1523 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1525 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1526 WinPosGetMinMaxInfo(WindowObject
, &MaxSize
, &MaxPos
, &MinTrack
,
1528 if (MaxSize
.x
< nWidth
) nWidth
= MaxSize
.x
;
1529 if (MaxSize
.y
< nHeight
) nHeight
= MaxSize
.y
;
1530 if (nWidth
< MinTrack
.x
) nWidth
= MinTrack
.x
;
1531 if (nHeight
< MinTrack
.y
) nHeight
= MinTrack
.y
;
1532 if (nWidth
< 0) nWidth
= 0;
1533 if (nHeight
< 0) nHeight
= 0;
1536 WindowObject
->WindowRect
.left
= x
;
1537 WindowObject
->WindowRect
.top
= y
;
1538 WindowObject
->WindowRect
.right
= x
+ nWidth
;
1539 WindowObject
->WindowRect
.bottom
= y
+ nHeight
;
1540 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1542 NtGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1543 ParentWindow
->ClientRect
.top
);
1545 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1547 /* FIXME: Initialize the window menu. */
1549 /* Initialize the window's scrollbars */
1550 if (dwStyle
& WS_VSCROLL
)
1552 WindowObject
->Style
&= ~WS_VSCROLL
;
1553 NtUserShowScrollBar(WindowObject
->Self
, SB_VERT
, TRUE
);
1555 if (dwStyle
& WS_HSCROLL
)
1557 WindowObject
->Style
&= ~WS_HSCROLL
;
1558 NtUserShowScrollBar(WindowObject
->Self
, SB_HORZ
, TRUE
);
1561 /* Send a NCCREATE message. */
1567 DPRINT("[win32k.window] NtUserCreateWindowEx style %d, exstyle %d, parent %d\n", Cs
.style
, Cs
.dwExStyle
, Cs
.hwndParent
);
1568 DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1569 DPRINT("NtUserCreateWindowEx(): About to send NCCREATE message.\n");
1570 Result
= IntSendMessage(WindowObject
->Self
, WM_NCCREATE
, 0, (LPARAM
) &Cs
);
1573 /* FIXME: Cleanup. */
1574 if (NULL
!= ParentWindow
)
1576 IntReleaseWindowObject(ParentWindow
);
1578 DPRINT("NtUserCreateWindowEx(): NCCREATE message failed.\n");
1582 /* Calculate the non-client size. */
1583 MaxPos
.x
= WindowObject
->WindowRect
.left
;
1584 MaxPos
.y
= WindowObject
->WindowRect
.top
;
1585 DPRINT("NtUserCreateWindowEx(): About to get non-client size.\n");
1586 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1587 Result
= WinPosGetNonClientSize(WindowObject
->Self
,
1588 &WindowObject
->WindowRect
,
1589 &WindowObject
->ClientRect
);
1590 NtGdiOffsetRect(&WindowObject
->WindowRect
,
1591 MaxPos
.x
- WindowObject
->WindowRect
.left
,
1592 MaxPos
.y
- WindowObject
->WindowRect
.top
);
1594 if (NULL
!= ParentWindow
)
1596 /* link the window into the parent's child list */
1597 if ((dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
1599 PWINDOW_OBJECT PrevSibling
;
1600 IntLockRelatives(ParentWindow
);
1601 if((PrevSibling
= ParentWindow
->LastChild
))
1602 IntReferenceWindowObject(PrevSibling
);
1603 IntUnLockRelatives(ParentWindow
);
1604 /* link window as bottom sibling */
1605 IntLinkWindow(WindowObject
, ParentWindow
, PrevSibling
/*prev sibling*/);
1607 IntReleaseWindowObject(PrevSibling
);
1611 /* link window as top sibling */
1612 IntLinkWindow(WindowObject
, ParentWindow
, NULL
/*prev sibling*/);
1616 /* Send the WM_CREATE message. */
1617 DPRINT("NtUserCreateWindowEx(): about to send CREATE message.\n");
1618 Result
= IntSendMessage(WindowObject
->Self
, WM_CREATE
, 0, (LPARAM
) &Cs
);
1619 if (Result
== (LRESULT
)-1)
1621 /* FIXME: Cleanup. */
1622 if (NULL
!= ParentWindow
)
1624 IntReleaseWindowObject(ParentWindow
);
1626 DPRINT("NtUserCreateWindowEx(): send CREATE message failed.\n");
1630 /* Send move and size messages. */
1631 if (!(WindowObject
->Flags
& WINDOWOBJECT_NEED_SIZE
))
1635 DPRINT("NtUserCreateWindow(): About to send WM_SIZE\n");
1637 if ((WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
) < 0 ||
1638 (WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
) < 0)
1639 DPRINT("Sending bogus WM_SIZE\n");
1641 lParam
= MAKE_LONG(WindowObject
->ClientRect
.right
-
1642 WindowObject
->ClientRect
.left
,
1643 WindowObject
->ClientRect
.bottom
-
1644 WindowObject
->ClientRect
.top
);
1645 IntSendMessage(WindowObject
->Self
, WM_SIZE
, SIZE_RESTORED
,
1648 DPRINT("NtUserCreateWindow(): About to send WM_MOVE\n");
1650 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1652 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
- ParentWindow
->ClientRect
.left
,
1653 WindowObject
->ClientRect
.top
- ParentWindow
->ClientRect
.top
);
1657 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
,
1658 WindowObject
->ClientRect
.top
);
1660 IntSendMessage(WindowObject
->Self
, WM_MOVE
, 0, lParam
);
1663 /* Show or maybe minimize or maximize the window. */
1664 if (WindowObject
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1669 SwFlag
= (WindowObject
->Style
& WS_MINIMIZE
) ? SW_MINIMIZE
:
1671 WinPosMinMaximize(WindowObject
, SwFlag
, &NewPos
);
1673 ((WindowObject
->Style
& WS_CHILD
) || NtUserGetActiveWindow()) ?
1674 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
:
1675 SWP_NOZORDER
| SWP_FRAMECHANGED
;
1676 DPRINT("NtUserCreateWindow(): About to minimize/maximize\n");
1677 DPRINT("%d,%d %dx%d\n", NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
);
1678 WinPosSetWindowPos(WindowObject
->Self
, 0, NewPos
.left
, NewPos
.top
,
1679 NewPos
.right
, NewPos
.bottom
, SwFlag
);
1682 /* Notify the parent window of a new child. */
1683 if ((WindowObject
->Style
& WS_CHILD
) &&
1684 (!(WindowObject
->ExStyle
& WS_EX_NOPARENTNOTIFY
)) && ParentWindow
)
1686 DPRINT("NtUserCreateWindow(): About to notify parent\n");
1687 IntSendMessage(ParentWindow
->Self
,
1689 MAKEWPARAM(WM_CREATE
, WindowObject
->IDMenu
),
1690 (LPARAM
)WindowObject
->Self
);
1693 if (NULL
!= ParentWindow
)
1695 IntReleaseWindowObject(ParentWindow
);
1698 if (dwStyle
& WS_VISIBLE
)
1700 DPRINT("NtUserCreateWindow(): About to show window\n");
1701 WinPosShowWindow(WindowObject
->Self
, dwShowMode
);
1704 DPRINT("NtUserCreateWindow(): = %X\n", Handle
);
1705 DPRINT("WindowObject->SystemMenu = 0x%x\n", WindowObject
->SystemMenu
);
1706 return((HWND
)Handle
);
1714 NtUserDeferWindowPos(HDWP WinPosInfo
,
1716 HWND WndInsertAfter
,
1733 NtUserDestroyWindow(HWND Wnd
)
1735 PWINDOW_OBJECT Window
;
1738 Window
= IntGetWindowObject(Wnd
);
1744 /* Check for owner thread and desktop window */
1745 if ((Window
->OwnerThread
!= PsGetCurrentThread()) || IntIsDesktopWindow(Window
))
1747 IntReleaseWindowObject(Window
);
1748 SetLastWin32Error(ERROR_ACCESS_DENIED
);
1752 /* Look whether the focus is within the tree of windows we will
1755 if (!WinPosShowWindow(Wnd
, SW_HIDE
))
1757 if (NtUserGetActiveWindow() == Wnd
)
1759 WinPosActivateOtherWindow(Window
);
1762 IntLockMessageQueue(Window
->MessageQueue
);
1763 if (Window
->MessageQueue
->ActiveWindow
== Window
->Self
)
1764 Window
->MessageQueue
->ActiveWindow
= NULL
;
1765 if (Window
->MessageQueue
->FocusWindow
== Window
->Self
)
1766 Window
->MessageQueue
->FocusWindow
= NULL
;
1767 if (Window
->MessageQueue
->CaptureWindow
== Window
->Self
)
1768 Window
->MessageQueue
->CaptureWindow
= NULL
;
1769 IntUnLockMessageQueue(Window
->MessageQueue
);
1773 if (HOOK_CallHooks(WH_CBT
, HCBT_DESTROYWND
, (WPARAM
) hwnd
, 0, TRUE
))
1779 isChild
= (0 != (Window
->Style
& WS_CHILD
));
1784 if (! USER_IsExitingThread(GetCurrentThreadId()))
1786 send_parent_notify(hwnd
, WM_DESTROY
);
1789 else if (NULL
!= GetWindow(Wnd
, GW_OWNER
))
1791 HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
1792 /* FIXME: clean up palette - see "Internals" p.352 */
1795 if (! IsWindow(Wnd
))
1801 if (!IntIsWindow(Wnd
))
1806 /* Recursively destroy owned windows */
1811 BOOL GotOne
= FALSE
;
1814 PWINDOW_OBJECT Child
, Desktop
;
1816 Desktop
= IntGetWindowObject(IntGetDesktopWindow());
1817 Children
= IntWinListChildren(Desktop
);
1818 IntReleaseWindowObject(Desktop
);
1821 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
1823 Child
= IntGetWindowObject(*ChildHandle
);
1828 if(Child
->Self
== Wnd
)
1830 IntReleaseWindowObject(Child
);
1833 IntLockRelatives(Child
);
1834 if (Child
->Parent
!= Window
->Self
)
1836 IntUnLockRelatives(Child
);
1837 IntReleaseWindowObject(Child
);
1840 IntUnLockRelatives(Child
);
1841 if (IntWndBelongsToThread(Child
, PsGetWin32Thread()))
1843 IntReleaseWindowObject(Child
);
1844 NtUserDestroyWindow(*ChildHandle
);
1848 IntLockRelatives(Child
);
1849 if (Child
->Owner
!= NULL
)
1851 Child
->Owner
= NULL
;
1853 IntUnLockRelatives(Child
);
1854 IntReleaseWindowObject(Child
);
1856 ExFreePool(Children
);
1865 if (!IntIsWindow(Wnd
))
1867 IntReleaseWindowObject(Window
);
1871 /* Unlink now so we won't bother with the children later on */
1872 IntUnlinkWindow(Window
);
1874 /* Destroy the window storage */
1875 IntDestroyWindow(Window
, PsGetWin32Process(), PsGetWin32Thread(), TRUE
);
1877 IntReleaseWindowObject(Window
);
1887 NtUserDrawMenuBarTemp(
1894 /* we'll use this function just for caching the menu bar */
1904 NtUserEndDeferWindowPosEx(DWORD Unknown0
,
1917 NtUserFillWindow(DWORD Unknown0
,
1930 * Searches a window's children for a window with the specified
1933 * hwndParent = The window whose childs are to be searched.
1936 * hwndChildAfter = Search starts after this child window.
1937 * NULL = start from beginning
1939 * ucClassName = Class name to search for
1940 * Reguired parameter.
1942 * ucWindowName = Window name
1943 * ->Buffer == NULL = don't care
1946 * The HWND of the window if it was found, otherwise NULL
1949 * Should use MmCopyFromCaller, we don't want an access violation in here
1956 NtUserFindWindowEx(HWND hwndParent
,
1957 HWND hwndChildAfter
,
1958 PUNICODE_STRING ucClassName
,
1959 PUNICODE_STRING ucWindowName
)
1963 PWINDOW_OBJECT ParentWindow
, WndChildAfter
, WndChild
;
1964 PWNDCLASS_OBJECT classObject
;
1966 // Get a pointer to the class
1967 status
= ClassReferenceClassByNameOrAtom(&classObject
, ucClassName
->Buffer
);
1968 if (!NT_SUCCESS(status
))
1973 // If hwndParent==NULL use the desktop window instead
1975 hwndParent
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
1978 ParentWindow
= IntGetWindowObject(hwndParent
);
1982 ObmDereferenceObject(classObject
);
1986 IntLockRelatives(ParentWindow
);
1990 if (!(WndChildAfter
= IntGetWindowObject(hwndChildAfter
)))
1992 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1996 /* must be a direct child (not a decendant child)*/
1997 IntLockRelatives(WndChildAfter
);
1998 if (WndChildAfter
->Parent
!= ParentWindow
->Self
)
2000 IntUnLockRelatives(WndChildAfter
);
2001 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2004 IntUnLockRelatives(WndChildAfter
);
2006 WndChild
= WndChildAfter
->NextSibling
;
2010 WndChild
= ParentWindow
->FirstChild
;
2015 if (classObject
== WndChild
->Class
&& (ucWindowName
->Buffer
==NULL
||
2016 RtlCompareUnicodeString (ucWindowName
, &WndChild
->WindowName
, TRUE
) == 0))
2018 windowHandle
= WndChild
->Self
;
2020 IntUnLockRelatives(ParentWindow
);
2021 IntReleaseWindowObject(ParentWindow
);
2022 ObmDereferenceObject (classObject
);
2024 return windowHandle
;
2027 WndChild
= WndChild
->NextSibling
;
2030 IntUnLockRelatives(ParentWindow
);
2032 IntReleaseWindowObject(ParentWindow
);
2033 ObmDereferenceObject (classObject
);
2043 NtUserFlashWindowEx(DWORD Unknown0
)
2055 NtUserGetAncestor(HWND hWnd
, UINT Type
)
2057 PWINDOW_OBJECT Wnd
, WndAncestor
, Parent
;
2060 if (hWnd
== IntGetDesktopWindow())
2065 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2067 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2074 WndAncestor
= IntGetParentObject(Wnd
);
2081 while (0 != (WndAncestor
->Style
& WS_CHILD
))
2083 Parent
= IntGetParentObject(WndAncestor
);
2084 if (WndAncestor
!= Wnd
)
2086 IntReleaseWindowObject(WndAncestor
);
2088 WndAncestor
= Parent
;
2095 IntReleaseWindowObject(Parent
);
2097 if(!(Parent
= IntGetParentObject(WndAncestor
)) ||
2098 !IntIsDesktopWindow(WndAncestor
))
2102 WndAncestor
= Parent
;
2109 IntReferenceWindowObject(WndAncestor
);
2114 Parent
= IntGetParent(WndAncestor
);
2115 IntReleaseWindowObject(Old
);
2120 WndAncestor
= Parent
;
2125 IntReleaseWindowObject(Wnd
);
2129 IntReleaseWindowObject(Wnd
);
2136 hWndAncestor
= WndAncestor
->Self
;
2137 if(WndAncestor
!= Wnd
)
2138 IntReleaseWindowObject(WndAncestor
);
2140 return hWndAncestor
;
2145 * Returns client window rectangle relative to the upper-left corner of client area.
2147 * \param hWnd window handle.
2148 * \param Rect pointer to the buffer where the coordinates are returned.
2155 NtUserGetClientRect(HWND hWnd
, LPRECT Rect
)
2157 PWINDOW_OBJECT WindowObject
;
2160 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
2162 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2166 IntGetClientRect(WindowObject
, &SafeRect
);
2167 IntReleaseWindowObject(WindowObject
);
2169 if(!NT_SUCCESS(MmCopyToCaller(Rect
, &SafeRect
, sizeof(RECT
))))
2181 NtUserGetDesktopWindow()
2183 return IntGetDesktopWindow();
2191 NtUserGetInternalWindowPos(DWORD Unknown0
,
2205 NtUserGetLastActivePopup(HWND hWnd
)
2208 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2209 * not changed anywhere.
2210 * -- Filip, 01/nov/2003
2216 IntAcquireWinLockShared();
2218 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2220 IntReleaseWinLock();
2221 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2225 hWndLastPopup
= Wnd
->hWndLastPopup
;
2227 IntReleaseWinLock();
2229 return hWndLastPopup
;
2238 * The NtUserGetParent function retrieves a handle to the specified window's
2242 * Note that, despite its name, this function can return an owner window
2243 * instead of a parent window.
2250 NtUserGetParent(HWND hWnd
)
2252 PWINDOW_OBJECT Wnd
, WndParent
;
2253 HWND hWndParent
= NULL
;
2255 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2257 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2261 WndParent
= IntGetParent(Wnd
);
2264 hWndParent
= WndParent
->Self
;
2265 IntReleaseWindowObject(WndParent
);
2268 IntReleaseWindowObject(Wnd
);
2276 * The NtUserSetParent function changes the parent window of the specified
2280 * The new parent window and the child window must belong to the same
2281 * application. If the window identified by the hWndChild parameter is
2282 * visible, the system performs the appropriate redrawing and repainting.
2283 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2284 * or WS_POPUP window styles of the window whose parent is being changed.
2291 NtUserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2293 PWINDOW_OBJECT Wnd
= NULL
, WndParent
= NULL
, WndOldParent
;
2294 HWND hWndOldParent
= NULL
;
2296 if (IntIsBroadcastHwnd(hWndChild
) || IntIsBroadcastHwnd(hWndNewParent
))
2298 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2302 if (hWndChild
== IntGetDesktopWindow())
2304 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2310 if (!(WndParent
= IntGetWindowObject(hWndNewParent
)))
2312 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2318 if (!(WndParent
= IntGetWindowObject(IntGetDesktopWindow())))
2320 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2325 if (!(Wnd
= IntGetWindowObject(hWndChild
)))
2327 IntReleaseWindowObject(WndParent
);
2328 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2332 WndOldParent
= IntSetParent(Wnd
, WndParent
);
2336 hWndOldParent
= WndOldParent
->Self
;
2337 IntReleaseWindowObject(WndOldParent
);
2340 IntReleaseWindowObject(Wnd
);
2341 IntReleaseWindowObject(WndParent
);
2343 return hWndOldParent
;
2347 * NtUserGetShellWindow
2349 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
2356 NtUserGetShellWindow()
2358 PWINSTATION_OBJECT WinStaObject
;
2361 NTSTATUS Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
2366 if (!NT_SUCCESS(Status
))
2368 SetLastNtError(Status
);
2372 Ret
= (HWND
)WinStaObject
->ShellWindow
;
2374 ObDereferenceObject(WinStaObject
);
2379 * NtUserSetShellWindowEx
2381 * This is undocumented function to set global shell window. The global
2382 * shell window has special handling of window position.
2389 NtUserSetShellWindowEx(HWND hwndShell
, HWND hwndListView
)
2391 PWINSTATION_OBJECT WinStaObject
;
2393 NTSTATUS Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
2398 if (!NT_SUCCESS(Status
))
2400 SetLastNtError(Status
);
2405 * Test if we are permitted to change the shell window.
2407 if (WinStaObject
->ShellWindow
)
2409 ObDereferenceObject(WinStaObject
);
2414 * Move shell window into background.
2416 if (hwndListView
&& hwndListView
!= hwndShell
)
2419 * Disabled for now to get Explorer working.
2420 * -- Filip, 01/nov/2003
2423 WinPosSetWindowPos(hwndListView
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2426 if (NtUserGetWindowLong(hwndListView
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2428 ObDereferenceObject(WinStaObject
);
2433 if (NtUserGetWindowLong(hwndShell
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2435 ObDereferenceObject(WinStaObject
);
2439 WinPosSetWindowPos(hwndShell
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2441 WinStaObject
->ShellWindow
= hwndShell
;
2442 WinStaObject
->ShellListView
= hwndListView
;
2444 ObDereferenceObject(WinStaObject
);
2449 * NtUserGetSystemMenu
2451 * The NtUserGetSystemMenu function allows the application to access the
2452 * window menu (also known as the system menu or the control menu) for
2453 * copying and modifying.
2457 * Handle to the window that will own a copy of the window menu.
2459 * Specifies the action to be taken. If this parameter is FALSE,
2460 * NtUserGetSystemMenu returns a handle to the copy of the window menu
2461 * currently in use. The copy is initially identical to the window menu
2462 * but it can be modified.
2463 * If this parameter is TRUE, GetSystemMenu resets the window menu back
2464 * to the default state. The previous window menu, if any, is destroyed.
2467 * If the bRevert parameter is FALSE, the return value is a handle to a
2468 * copy of the window menu. If the bRevert parameter is TRUE, the return
2476 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
2479 PWINDOW_OBJECT WindowObject
;
2480 PMENU_OBJECT MenuObject
;
2482 WindowObject
= IntGetWindowObject((HWND
)hWnd
);
2483 if (WindowObject
== NULL
)
2485 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2489 MenuObject
= IntGetSystemMenu(WindowObject
, bRevert
, FALSE
);
2492 Result
= MenuObject
->MenuInfo
.Self
;
2493 IntReleaseMenuObject(MenuObject
);
2496 IntReleaseWindowObject(WindowObject
);
2501 * NtUserSetSystemMenu
2508 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
2510 BOOL Result
= FALSE
;
2511 PWINDOW_OBJECT WindowObject
;
2512 PMENU_OBJECT MenuObject
;
2514 WindowObject
= IntGetWindowObject(hWnd
);
2517 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2524 * Assign new menu handle.
2526 MenuObject
= IntGetMenuObject(hMenu
);
2529 IntReleaseWindowObject(WindowObject
);
2530 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
2534 Result
= IntSetSystemMenu(WindowObject
, MenuObject
);
2536 IntReleaseMenuObject(MenuObject
);
2539 IntReleaseWindowObject(WindowObject
);
2547 * The NtUserGetWindow function retrieves a handle to a window that has the
2548 * specified relationship (Z order or owner) to the specified window.
2555 NtUserGetWindow(HWND hWnd
, UINT Relationship
)
2557 PWINDOW_OBJECT WindowObject
, Parent
;
2558 HWND hWndResult
= NULL
;
2560 if (!(WindowObject
= IntGetWindowObject(hWnd
)))
2562 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2566 IntLockRelatives(WindowObject
);
2567 switch (Relationship
)
2570 if((Parent
= IntGetParentObject(WindowObject
)))
2572 IntLockRelatives(Parent
);
2573 if (Parent
->FirstChild
)
2574 hWndResult
= Parent
->FirstChild
->Self
;
2575 IntUnLockRelatives(Parent
);
2576 IntReleaseWindowObject(Parent
);
2581 if((Parent
= IntGetParentObject(WindowObject
)))
2583 IntLockRelatives(Parent
);
2584 if (Parent
->LastChild
)
2585 hWndResult
= Parent
->LastChild
->Self
;
2586 IntUnLockRelatives(Parent
);
2587 IntReleaseWindowObject(Parent
);
2592 if (WindowObject
->NextSibling
)
2593 hWndResult
= WindowObject
->NextSibling
->Self
;
2597 if (WindowObject
->PrevSibling
)
2598 hWndResult
= WindowObject
->PrevSibling
->Self
;
2602 if((Parent
= IntGetWindowObject(WindowObject
->Owner
)))
2604 hWndResult
= Parent
->Self
;
2605 IntReleaseWindowObject(Parent
);
2609 if (WindowObject
->FirstChild
)
2610 hWndResult
= WindowObject
->FirstChild
->Self
;
2613 IntUnLockRelatives(WindowObject
);
2615 IntReleaseWindowObject(WindowObject
);
2623 * The NtUserGetWindowDC function retrieves the device context (DC) for the
2624 * entire window, including title bar, menus, and scroll bars. A window device
2625 * context permits painting anywhere in a window, because the origin of the
2626 * device context is the upper-left corner of the window instead of the client
2634 NtUserGetWindowDC(HWND hWnd
)
2636 return (DWORD
)NtUserGetDCEx(hWnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
2640 * NtUserGetWindowLong
2642 * The NtUserGetWindowLong function retrieves information about the specified
2643 * window. The function also retrieves the 32-bit (long) value at the
2644 * specified offset into the extra window memory.
2651 NtUserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
2653 PWINDOW_OBJECT WindowObject
, Parent
;
2656 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
2658 WindowObject
= IntGetWindowObject(hWnd
);
2659 if (WindowObject
== NULL
)
2661 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2666 * Only allow CSRSS to mess with the desktop window
2668 if (hWnd
== IntGetDesktopWindow()
2669 && WindowObject
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
2671 SetLastWin32Error(STATUS_ACCESS_DENIED
);
2675 if ((INT
)Index
>= 0)
2677 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
2679 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2682 Result
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
2689 Result
= WindowObject
->ExStyle
;
2693 Result
= WindowObject
->Style
;
2698 Result
= (LONG
) WindowObject
->WndProcA
;
2700 Result
= (LONG
) WindowObject
->WndProcW
;
2704 Result
= (LONG
) WindowObject
->Instance
;
2707 case GWL_HWNDPARENT
:
2708 IntLockRelatives(WindowObject
);
2709 Parent
= IntGetWindowObject(WindowObject
->Parent
);
2710 IntUnLockRelatives(WindowObject
);
2713 if (Parent
&& Parent
->Self
== IntGetDesktopWindow())
2714 Result
= (LONG
) NtUserGetWindow(WindowObject
->Self
, GW_OWNER
);
2716 Result
= (LONG
) Parent
->Self
;
2717 IntReleaseWindowObject(Parent
);
2722 Result
= (LONG
) WindowObject
->IDMenu
;
2726 Result
= WindowObject
->UserData
;
2730 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index
);
2731 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2737 IntReleaseWindowObject(WindowObject
);
2743 * NtUserSetWindowLong
2745 * The NtUserSetWindowLong function changes an attribute of the specified
2746 * window. The function also sets the 32-bit (long) value at the specified
2747 * offset into the extra window memory.
2754 NtUserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
2756 PWINDOW_OBJECT WindowObject
, Parent
;
2757 PW32PROCESS Process
;
2758 PWINSTATION_OBJECT WindowStation
;
2762 if (hWnd
== IntGetDesktopWindow())
2764 SetLastWin32Error(STATUS_ACCESS_DENIED
);
2768 WindowObject
= IntGetWindowObject(hWnd
);
2769 if (WindowObject
== NULL
)
2771 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2775 if ((INT
)Index
>= 0)
2777 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
2779 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2780 IntReleaseWindowObject(WindowObject
);
2783 OldValue
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
2784 *((LONG
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
2791 OldValue
= (LONG
) WindowObject
->ExStyle
;
2792 Style
.styleOld
= OldValue
;
2793 Style
.styleNew
= NewValue
;
2796 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
2798 Process
= WindowObject
->OwnerThread
->ThreadsProcess
->Win32Process
;
2799 WindowStation
= Process
->WindowStation
;
2802 if (hWnd
== WindowStation
->ShellWindow
|| hWnd
== WindowStation
->ShellListView
)
2803 Style
.styleNew
&= ~WS_EX_TOPMOST
;
2806 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_EXSTYLE
, (LPARAM
) &Style
);
2807 WindowObject
->ExStyle
= (DWORD
)Style
.styleNew
;
2808 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_EXSTYLE
, (LPARAM
) &Style
);
2812 OldValue
= (LONG
) WindowObject
->Style
;
2813 Style
.styleOld
= OldValue
;
2814 Style
.styleNew
= NewValue
;
2815 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_STYLE
, (LPARAM
) &Style
);
2816 WindowObject
->Style
= (DWORD
)Style
.styleNew
;
2817 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_STYLE
, (LPARAM
) &Style
);
2821 /* FIXME: should check if window belongs to current process */
2824 OldValue
= (LONG
) WindowObject
->WndProcA
;
2825 WindowObject
->WndProcA
= (WNDPROC
) NewValue
;
2826 WindowObject
->WndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,FALSE
);
2827 WindowObject
->Unicode
= FALSE
;
2831 OldValue
= (LONG
) WindowObject
->WndProcW
;
2832 WindowObject
->WndProcW
= (WNDPROC
) NewValue
;
2833 WindowObject
->WndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,TRUE
);
2834 WindowObject
->Unicode
= TRUE
;
2839 OldValue
= (LONG
) WindowObject
->Instance
;
2840 WindowObject
->Instance
= (HINSTANCE
) NewValue
;
2843 case GWL_HWNDPARENT
:
2844 Parent
= IntGetParentObject(WindowObject
);
2845 if (Parent
&& (Parent
->Self
== IntGetDesktopWindow()))
2846 OldValue
= (LONG
) IntSetOwner(WindowObject
->Self
, (HWND
) NewValue
);
2848 OldValue
= (LONG
) NtUserSetParent(WindowObject
->Self
, (HWND
) NewValue
);
2850 IntReleaseWindowObject(Parent
);
2854 OldValue
= (LONG
) WindowObject
->IDMenu
;
2855 WindowObject
->IDMenu
= (UINT
) NewValue
;
2859 OldValue
= WindowObject
->UserData
;
2860 WindowObject
->UserData
= NewValue
;
2864 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index
);
2865 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2871 IntReleaseWindowObject(WindowObject
);
2877 * NtUserSetWindowWord
2879 * Legacy function similar to NtUserSetWindowLong.
2886 NtUserSetWindowWord(HWND hWnd
, INT Index
, WORD NewValue
)
2888 PWINDOW_OBJECT WindowObject
;
2895 case GWL_HWNDPARENT
:
2896 return NtUserSetWindowLong(hWnd
, Index
, (UINT
)NewValue
, TRUE
);
2900 SetLastWin32Error(ERROR_INVALID_INDEX
);
2905 WindowObject
= IntGetWindowObject(hWnd
);
2906 if (WindowObject
== NULL
)
2908 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2912 if (Index
> WindowObject
->ExtraDataSize
- sizeof(WORD
))
2914 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2915 IntReleaseWindowObject(WindowObject
);
2919 OldValue
= *((WORD
*)(WindowObject
->ExtraData
+ Index
));
2920 *((WORD
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
2922 IntReleaseWindowObject(WindowObject
);
2931 NtUserGetWindowPlacement(HWND hWnd
,
2932 WINDOWPLACEMENT
*lpwndpl
)
2934 PWINDOW_OBJECT WindowObject
;
2935 PINTERNALPOS InternalPos
;
2937 WINDOWPLACEMENT Safepl
;
2940 WindowObject
= IntGetWindowObject(hWnd
);
2941 if (WindowObject
== NULL
)
2943 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2947 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
2948 if(!NT_SUCCESS(Status
))
2950 SetLastNtError(Status
);
2951 IntReleaseWindowObject(WindowObject
);
2954 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
2956 IntReleaseWindowObject(WindowObject
);
2961 Safepl
.showCmd
= ((WindowObject
->Flags
& WINDOWOBJECT_RESTOREMAX
) ? SW_MAXIMIZE
: SW_SHOWNORMAL
);
2963 Size
.x
= WindowObject
->WindowRect
.left
;
2964 Size
.y
= WindowObject
->WindowRect
.top
;
2965 InternalPos
= WinPosInitInternalPos(WindowObject
, &Size
,
2966 &WindowObject
->WindowRect
);
2969 Safepl
.rcNormalPosition
= InternalPos
->NormalRect
;
2970 Safepl
.ptMinPosition
= InternalPos
->IconPos
;
2971 Safepl
.ptMaxPosition
= InternalPos
->MaxPos
;
2975 IntReleaseWindowObject(WindowObject
);
2979 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
2980 if(!NT_SUCCESS(Status
))
2982 SetLastNtError(Status
);
2983 IntReleaseWindowObject(WindowObject
);
2987 IntReleaseWindowObject(WindowObject
);
2993 * Return the dimension of the window in the screen coordinates.
2994 * \param hWnd window handle.
2995 * \param Rect pointer to the buffer where the coordinates are returned.
3001 NtUserGetWindowRect(HWND hWnd
, LPRECT Rect
)
3006 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3008 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3011 Status
= MmCopyToCaller(Rect
, &Wnd
->WindowRect
, sizeof(RECT
));
3012 if (!NT_SUCCESS(Status
))
3014 IntReleaseWindowObject(Wnd
);
3015 SetLastNtError(Status
);
3019 IntReleaseWindowObject(Wnd
);
3028 NtUserGetWindowThreadProcessId(HWND hWnd
, LPDWORD UnsafePid
)
3033 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3035 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3039 tid
= (DWORD
)IntGetWndThreadId(Wnd
);
3040 pid
= (DWORD
)IntGetWndProcessId(Wnd
);
3042 if (UnsafePid
) MmCopyToCaller(UnsafePid
, &pid
, sizeof(DWORD
));
3052 NtUserLockWindowUpdate(DWORD Unknown0
)
3072 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3073 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3074 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3078 QueryWindow based on KJK::Hyperion and James Tabor.
3080 0 = QWUniqueProcessId
3081 1 = QWUniqueThreadId
3082 4 = QWIsHung Implements IsHungAppWindow found
3085 9 = QWKillWindow When I called this with hWnd ==
3086 DesktopWindow, it shutdown the system
3093 NtUserQueryWindow(HWND hWnd
, DWORD Index
)
3095 PWINDOW_OBJECT Window
= IntGetWindowObject(hWnd
);
3100 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3107 Result
= (DWORD
)IntGetWndProcessId(Window
);
3111 Result
= (DWORD
)IntGetWndThreadId(Window
);
3115 Result
= (DWORD
)NULL
;
3119 IntReleaseWindowObject(Window
);
3129 NtUserRealChildWindowFromPoint(DWORD Unknown0
,
3143 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe
)
3146 PLIST_ENTRY Current
;
3147 PREGISTERED_MESSAGE NewMsg
, RegMsg
;
3148 UINT Msg
= REGISTERED_MESSAGE_MIN
;
3149 UNICODE_STRING MessageName
;
3152 Status
= MmCopyFromCaller(&MessageName
, MessageNameUnsafe
, sizeof(UNICODE_STRING
));
3153 if (! NT_SUCCESS(Status
))
3155 SetLastNtError(Status
);
3159 NewMsg
= ExAllocatePoolWithTag(PagedPool
,
3160 sizeof(REGISTERED_MESSAGE
) +
3165 SetLastNtError(STATUS_NO_MEMORY
);
3169 Status
= MmCopyFromCaller(NewMsg
->MessageName
, MessageName
.Buffer
, MessageName
.Length
);
3170 if (! NT_SUCCESS(Status
))
3173 SetLastNtError(Status
);
3176 NewMsg
->MessageName
[MessageName
.Length
/ sizeof(WCHAR
)] = L
'\0';
3177 if (wcslen(NewMsg
->MessageName
) != MessageName
.Length
/ sizeof(WCHAR
))
3180 SetLastNtError(STATUS_INVALID_PARAMETER
);
3184 Current
= RegisteredMessageListHead
.Flink
;
3185 while (Current
!= &RegisteredMessageListHead
)
3187 RegMsg
= CONTAINING_RECORD(Current
, REGISTERED_MESSAGE
, ListEntry
);
3188 if (0 == wcscmp(NewMsg
->MessageName
, RegMsg
->MessageName
))
3194 Current
= Current
->Flink
;
3197 if (REGISTERED_MESSAGE_MAX
< Msg
)
3200 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
3204 InsertTailList(&RegisteredMessageListHead
, &(NewMsg
->ListEntry
));
3210 * - There's no need to call MmSafe*, because it should be done in kernel.
3211 * - The passed UNICODE_STRING is expected to be NULL-terminated.
3213 return (UINT
)IntAddAtom(MessageNameUnsafe
->Buffer
);
3222 NtUserSetImeOwnerWindow(DWORD Unknown0
,
3235 NtUserSetInternalWindowPos(DWORD Unknown0
,
3251 NtUserSetLayeredWindowAttributes(DWORD Unknown0
,
3266 NtUserSetLogonNotifyWindow(DWORD Unknown0
)
3283 PWINDOW_OBJECT WindowObject
;
3286 WindowObject
= IntGetWindowObject((HWND
) Wnd
);
3287 if (NULL
== WindowObject
)
3289 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3293 if (! IntSetMenu(WindowObject
, Menu
, &Changed
))
3295 IntReleaseWindowObject(WindowObject
);
3299 IntReleaseWindowObject(WindowObject
);
3301 if (Changed
&& Repaint
)
3303 WinPosSetWindowPos(Wnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
3304 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
3315 NtUserSetWindowFNID(DWORD Unknown0
,
3329 NtUserSetWindowPlacement(HWND hWnd
,
3330 WINDOWPLACEMENT
*lpwndpl
)
3332 PWINDOW_OBJECT WindowObject
;
3333 WINDOWPLACEMENT Safepl
;
3336 WindowObject
= IntGetWindowObject(hWnd
);
3337 if (WindowObject
== NULL
)
3339 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3342 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3343 if(!NT_SUCCESS(Status
))
3345 SetLastNtError(Status
);
3346 IntReleaseWindowObject(WindowObject
);
3349 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3351 IntReleaseWindowObject(WindowObject
);
3355 if ((WindowObject
->Style
& (WS_MAXIMIZE
| WS_MINIMIZE
)) == 0)
3357 WinPosSetWindowPos(WindowObject
->Self
, NULL
,
3358 Safepl
.rcNormalPosition
.left
, Safepl
.rcNormalPosition
.top
,
3359 Safepl
.rcNormalPosition
.right
- Safepl
.rcNormalPosition
.left
,
3360 Safepl
.rcNormalPosition
.bottom
- Safepl
.rcNormalPosition
.top
,
3361 SWP_NOZORDER
| SWP_NOACTIVATE
);
3364 /* FIXME - change window status */
3365 WinPosShowWindow(WindowObject
->Self
, Safepl
.showCmd
);
3367 if (WindowObject
->InternalPos
== NULL
)
3368 WindowObject
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
3369 WindowObject
->InternalPos
->NormalRect
= Safepl
.rcNormalPosition
;
3370 WindowObject
->InternalPos
->IconPos
= Safepl
.ptMinPosition
;
3371 WindowObject
->InternalPos
->MaxPos
= Safepl
.ptMaxPosition
;
3373 IntReleaseWindowObject(WindowObject
);
3384 HWND hWndInsertAfter
,
3391 return WinPosSetWindowPos(hWnd
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3399 NtUserSetWindowRgn(DWORD Unknown0
,
3413 NtUserShowWindow(HWND hWnd
,
3416 return WinPosShowWindow(hWnd
, nCmdShow
);
3424 NtUserShowWindowAsync(DWORD Unknown0
,
3437 NtUserUpdateLayeredWindow(DWORD Unknown0
,
3457 NtUserValidateRect(HWND hWnd
, const RECT
* Rect
)
3459 return (VOID
)NtUserRedrawWindow(hWnd
, Rect
, 0, RDW_VALIDATE
| RDW_NOCHILDREN
);
3467 NtUserWindowFromPoint(LONG X
, LONG Y
)
3471 PWINDOW_OBJECT DesktopWindow
, Window
= NULL
;
3473 if ((DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow())))
3480 Hit
= WinPosWindowFromPoint(DesktopWindow
, TRUE
, &pt
, &Window
);
3485 IntReleaseWindowObject(Window
);
3486 IntReleaseWindowObject(DesktopWindow
);
3490 IntReleaseWindowObject(DesktopWindow
);
3500 * Undocumented function that is called from DefWindowProc to set
3503 * FIXME: Call this from user32.dll!
3510 NtUserDefSetText(HWND WindowHandle
, PANSI_STRING Text
)
3512 PWINDOW_OBJECT WindowObject
;
3513 UNICODE_STRING NewWindowName
;
3514 BOOL Result
= FALSE
;
3516 WindowObject
= IntGetWindowObject(WindowHandle
);
3519 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3523 if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&NewWindowName
, Text
, TRUE
)))
3525 RtlFreeUnicodeString(&WindowObject
->WindowName
);
3526 WindowObject
->WindowName
.Buffer
= NewWindowName
.Buffer
;
3527 WindowObject
->WindowName
.Length
= NewWindowName
.Length
;
3528 WindowObject
->WindowName
.MaximumLength
= NewWindowName
.MaximumLength
;
3532 IntReleaseWindowObject(WindowObject
);
3538 * NtUserInternalGetWindowText
3540 * FIXME: Call this from user32.dll!
3547 NtUserInternalGetWindowText(HWND WindowHandle
, LPWSTR Text
, INT MaxCount
)
3549 PWINDOW_OBJECT WindowObject
;
3552 WindowObject
= IntGetWindowObject(WindowHandle
);
3555 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3559 Result
= WindowObject
->WindowName
.Length
/ sizeof(WCHAR
);
3562 /* FIXME: Shouldn't it be always NULL terminated? */
3563 wcsncpy(Text
, WindowObject
->WindowName
.Buffer
, MaxCount
);
3564 if (MaxCount
< Result
)
3570 IntReleaseWindowObject(WindowObject
);
3576 NtUserDereferenceWndProcHandle(WNDPROC wpHandle
, WndProcHandle
*Data
)
3578 WndProcHandle Entry
;
3579 if (((DWORD
)wpHandle
& 0xFFFF0000) == 0xFFFF0000)
3581 Entry
= WndProcHandlesArray
[(DWORD
)wpHandle
& 0x0000FFFF];
3582 Data
->WindowProc
= Entry
.WindowProc
;
3583 Data
->IsUnicode
= Entry
.IsUnicode
;
3584 Data
->ProcessID
= Entry
.ProcessID
;
3593 IntAddWndProcHandle(WNDPROC WindowProc
, BOOL IsUnicode
)
3598 WndProcHandle
*OldArray
;
3601 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
3603 if (WndProcHandlesArray
[i
].WindowProc
== NULL
)
3611 OldArray
= WndProcHandlesArray
;
3612 OldArraySize
= WndProcHandlesArraySize
;
3613 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,(OldArraySize
+ WPH_SIZE
) * sizeof(WndProcHandle
), TAG_WINPROCLST
);
3614 WndProcHandlesArraySize
= OldArraySize
+ WPH_SIZE
;
3615 RtlCopyMemory(WndProcHandlesArray
,OldArray
,OldArraySize
* sizeof(WndProcHandle
));
3616 ExFreePool(OldArray
);
3617 FreeSpot
= OldArraySize
+ 1;
3619 WndProcHandlesArray
[FreeSpot
].WindowProc
= WindowProc
;
3620 WndProcHandlesArray
[FreeSpot
].IsUnicode
= IsUnicode
;
3621 WndProcHandlesArray
[FreeSpot
].ProcessID
= PsGetCurrentProcessId();
3622 return FreeSpot
+ 0xFFFF0000;
3626 IntRemoveWndProcHandle(WNDPROC Handle
)
3629 position
= (DWORD
)Handle
& 0x0000FFFF;
3630 if (position
> WndProcHandlesArraySize
)
3634 WndProcHandlesArray
[position
].WindowProc
= NULL
;
3635 WndProcHandlesArray
[position
].IsUnicode
= FALSE
;
3636 WndProcHandlesArray
[position
].ProcessID
= NULL
;
3641 IntRemoveProcessWndProcHandles(HANDLE ProcessID
)
3644 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
3646 if (WndProcHandlesArray
[i
].ProcessID
== ProcessID
)
3648 WndProcHandlesArray
[i
].WindowProc
= NULL
;
3649 WndProcHandlesArray
[i
].IsUnicode
= FALSE
;
3650 WndProcHandlesArray
[i
].ProcessID
= NULL
;