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.190 2004/02/22 23:40:58 gvg 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 * Check if window is a broadcast.
106 * TRUE if window is broadcast, FALSE otherwise.
110 IntIsBroadcastHwnd(HWND hWnd
)
112 return (hWnd
== HWND_BROADCAST
|| hWnd
== HWND_TOPMOST
);
118 * Check if window is a desktop. Desktop windows has no parent.
121 * TRUE if window is desktop, FALSE otherwise.
125 IntIsDesktopWindow(PWINDOW_OBJECT Wnd
)
127 return Wnd
->Parent
== NULL
;
133 * The function determines whether the specified window handle identifies
134 * an existing window.
138 * Handle to the window to test.
141 * If the window handle identifies an existing window, the return value
142 * is TRUE. If the window handle does not identify an existing window,
143 * the return value is FALSE.
147 IntIsWindow(HWND hWnd
)
149 PWINDOW_OBJECT Window
;
151 if (!(Window
= IntGetWindowObject(hWnd
)))
154 IntReleaseWindowObject(Window
);
160 * IntGetProcessWindowObject
162 * Get window object from handle of specified process.
165 PWINDOW_OBJECT FASTCALL
166 IntGetProcessWindowObject(PW32PROCESS ProcessData
, HWND hWnd
)
168 PWINDOW_OBJECT WindowObject
;
171 Status
= ObmReferenceObjectByHandle(ProcessData
->WindowStation
->HandleTable
,
172 hWnd
, otWindow
, (PVOID
*)&WindowObject
);
173 if (!NT_SUCCESS(Status
))
183 * Get window object from handle of current process.
186 PWINDOW_OBJECT FASTCALL
187 IntGetWindowObject(HWND hWnd
)
189 return IntGetProcessWindowObject(PsGetWin32Process(), hWnd
);
193 * IntReleaseWindowObject
195 * Release window object returned by IntGetWindowObject or
196 * IntGetProcessWindowObject.
200 IntReleaseWindowObject(PWINDOW_OBJECT Window
)
202 ObmDereferenceObject(Window
);
208 * Compile a list of all child window handles from given window.
211 * This function is similar to Wine WIN_ListChildren. The caller
212 * must free the returned list with ExFreePool.
216 IntWinListChildren(PWINDOW_OBJECT Window
)
218 PWINDOW_OBJECT Child
;
220 UINT Index
, NumChildren
= 0;
222 ExAcquireFastMutexUnsafe(&Window
->ChildrenListLock
);
224 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
227 if (NumChildren
!= 0)
229 List
= ExAllocatePoolWithTag(PagedPool
, (NumChildren
+ 1) * sizeof(HWND
), TAG_WINLIST
);
232 for (Child
= Window
->FirstChild
, Index
= 0;
234 Child
= Child
->NextSibling
, ++Index
)
235 List
[Index
] = Child
->Self
;
240 DPRINT1("Failed to allocate memory for children array\n");
244 ExReleaseFastMutexUnsafe(&Window
->ChildrenListLock
);
246 return (NumChildren
> 0) ? List
: NULL
;
249 /***********************************************************************
252 static void IntSendDestroyMsg(HWND Wnd
)
257 if (GetGUIThreadInfo(GetCurrentThreadId(), &info
))
259 if (Wnd
== info
.hwndCaret
)
267 * Send the WM_DESTROY to the window.
269 IntSendMessage(Wnd
, WM_DESTROY
, 0, 0);
272 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
273 * make sure that the window still exists when we come back.
281 if (!(pWndArray
= WIN_ListChildren( hwnd
))) return;
283 /* start from the end (FIXME: is this needed?) */
284 for (i
= 0; pWndArray
[i
]; i
++) ;
288 if (IsWindow( pWndArray
[i
] )) WIN_SendDestroyMsg( pWndArray
[i
] );
290 HeapFree(GetProcessHeap(), 0, pWndArray
);
294 DPRINT("destroyed itself while in WM_DESTROY!\n");
299 /***********************************************************************
302 * Destroy storage associated to a window. "Internals" p.358
304 static LRESULT
IntDestroyWindow(PWINDOW_OBJECT Window
,
305 PW32PROCESS ProcessData
,
306 PW32THREAD ThreadData
,
307 BOOLEAN SendMessages
)
311 PWINDOW_OBJECT Child
;
314 if (! IntWndBelongsToThread(Window
, ThreadData
))
321 /* Send destroy messages */
322 IntSendDestroyMsg(Window
->Self
);
325 /* free child windows */
326 Children
= IntWinListChildren(Window
);
329 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
331 Child
= IntGetProcessWindowObject(ProcessData
, *ChildHandle
);
334 if(IntWndBelongsToThread(Child
, ThreadData
))
336 IntDestroyWindow(Child
, ProcessData
, ThreadData
, SendMessages
);
340 IntSendDestroyMsg(Child
->Self
);
341 IntDestroyWindow(Child
, ProcessData
, Child
->OwnerThread
->Win32Thread
, FALSE
);
343 IntReleaseWindowObject(Child
);
346 ExFreePool(Children
);
352 * Clear the update region to make sure no WM_PAINT messages will be
353 * generated for this window while processing the WM_NCDESTROY.
355 IntRedrawWindow(Window
, NULL
, 0,
356 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
|
357 RDW_NOINTERNALPAINT
| RDW_NOCHILDREN
);
360 * Send the WM_NCDESTROY to the window being destroyed.
362 IntSendMessage(Window
->Self
, WM_NCDESTROY
, 0, 0);
365 /* reset shell window handles */
366 if(ProcessData
->WindowStation
)
368 if (Window
->Self
== ProcessData
->WindowStation
->ShellWindow
)
369 ProcessData
->WindowStation
->ShellWindow
= NULL
;
371 if (Window
->Self
== ProcessData
->WindowStation
->ShellListView
)
372 ProcessData
->WindowStation
->ShellListView
= NULL
;
375 /* Unregister hot keys */
376 UnregisterWindowHotKeys (Window
);
378 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
381 WinPosCheckInternalPos(Window
->Self
);
382 if (Window
->Self
== GetCapture())
387 /* free resources associated with the window */
388 TIMER_RemoveWindowTimers(Window
->Self
);
391 if (!(Window
->Style
& WS_CHILD
) && Window
->IDMenu
392 && (Menu
= IntGetMenuObject((HMENU
)Window
->IDMenu
)))
394 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
396 IntReleaseMenuObject(Menu
);
399 if(Window
->SystemMenu
400 && (Menu
= IntGetMenuObject(Window
->SystemMenu
)))
402 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
403 Window
->SystemMenu
= (HMENU
)0;
404 IntReleaseMenuObject(Menu
);
407 DceFreeWindowDCE(Window
); /* Always do this to catch orphaned DCs */
409 WINPROC_FreeProc(Window
->winproc
, WIN_PROC_WINDOW
);
410 CLASS_RemoveWindow(Window
->Class
);
415 PWINDOW_OBJECT Parent
= Window
->Parent
;
416 ExAcquireFastMutexUnsafe(&Parent
->ChildrenListLock
);
417 IntUnlinkWindow(Window
);
418 ExReleaseFastMutexUnsafe(&Parent
->ChildrenListLock
);
421 ExAcquireFastMutexUnsafe (&ThreadData
->WindowListLock
);
422 RemoveEntryList(&Window
->ThreadListEntry
);
423 ExReleaseFastMutexUnsafe (&ThreadData
->WindowListLock
);
425 IntDestroyScrollBar(Window
, SB_VERT
);
426 IntDestroyScrollBar(Window
, SB_HORZ
);
428 ObmDereferenceObject(Window
->Class
);
429 Window
->Class
= NULL
;
430 ObmCloseHandle(ProcessData
->WindowStation
->HandleTable
, Window
->Self
);
437 PWINDOW_OBJECT WindowObject
,
441 PMENU_OBJECT OldMenuObject
, NewMenuObject
;
443 *Changed
= (WindowObject
->IDMenu
!= (UINT
) Menu
);
449 if (0 != WindowObject
->IDMenu
)
451 OldMenuObject
= IntGetMenuObject((HMENU
) WindowObject
->IDMenu
);
452 ASSERT(NULL
== OldMenuObject
|| OldMenuObject
->MenuInfo
.Wnd
== WindowObject
->Self
);
456 OldMenuObject
= NULL
;
461 NewMenuObject
= IntGetMenuObject(Menu
);
462 if (NULL
== NewMenuObject
)
464 if (NULL
!= OldMenuObject
)
466 IntReleaseMenuObject(OldMenuObject
);
468 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
471 if (NULL
!= NewMenuObject
->MenuInfo
.Wnd
)
473 /* Can't use the same menu for two windows */
474 if (NULL
!= OldMenuObject
)
476 IntReleaseMenuObject(OldMenuObject
);
478 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
484 WindowObject
->IDMenu
= (UINT
) Menu
;
485 if (NULL
!= NewMenuObject
)
487 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
488 IntReleaseMenuObject(NewMenuObject
);
490 if (NULL
!= OldMenuObject
)
492 OldMenuObject
->MenuInfo
.Wnd
= NULL
;
493 IntReleaseMenuObject(OldMenuObject
);
500 /* INTERNAL ******************************************************************/
504 DestroyThreadWindows(struct _ETHREAD
*Thread
)
506 PLIST_ENTRY LastHead
;
507 PW32PROCESS Win32Process
;
508 PW32THREAD Win32Thread
;
509 PWINDOW_OBJECT Window
;
511 Win32Thread
= Thread
->Win32Thread
;
512 Win32Process
= Thread
->ThreadsProcess
->Win32Process
;
513 ExAcquireFastMutexUnsafe(&Win32Thread
->WindowListLock
);
515 while (Win32Thread
->WindowListHead
.Flink
!= &(Win32Thread
->WindowListHead
) &&
516 Win32Thread
->WindowListHead
.Flink
!= LastHead
)
518 LastHead
= Win32Thread
->WindowListHead
.Flink
;
519 Window
= CONTAINING_RECORD(Win32Thread
->WindowListHead
.Flink
, WINDOW_OBJECT
, ThreadListEntry
);
520 ExReleaseFastMutexUnsafe(&Win32Thread
->WindowListLock
);
521 WinPosShowWindow(Window
->Self
, SW_HIDE
);
522 IntDestroyWindow(Window
, Win32Process
, Win32Thread
, FALSE
);
523 ExAcquireFastMutexUnsafe(&Win32Thread
->WindowListLock
);
525 if (Win32Thread
->WindowListHead
.Flink
== LastHead
)
527 /* Window at head of list was not removed, should never happen, infinite loop */
530 ExReleaseFastMutexUnsafe(&Win32Thread
->WindowListLock
);
536 * Returns client window rectangle relative to the upper-left corner of client area.
538 * \note Does not check the validity of the parameters
541 IntGetClientRect(PWINDOW_OBJECT WindowObject
, PRECT Rect
)
543 ASSERT( WindowObject
);
546 Rect
->left
= Rect
->top
= 0;
547 Rect
->right
= WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
;
549 WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
;
555 IntGetFocusWindow(VOID
)
557 PUSER_MESSAGE_QUEUE Queue
;
558 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
563 Queue
= (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
568 return(Queue
->FocusWindow
);
572 PWINDOW_OBJECT FASTCALL
573 IntGetParent(PWINDOW_OBJECT Wnd
)
575 if (Wnd
->Style
& WS_POPUP
)
579 else if (Wnd
->Style
& WS_CHILD
)
589 PMENU_OBJECT FASTCALL
590 IntGetSystemMenu(PWINDOW_OBJECT WindowObject
, BOOL bRevert
, BOOL RetMenu
)
592 PMENU_OBJECT MenuObject
, NewMenuObject
, SysMenuObject
, ret
= NULL
;
593 PW32PROCESS W32Process
;
594 HMENU NewMenu
, SysMenu
;
595 ROSMENUITEMINFO ItemInfo
;
599 W32Process
= PsGetWin32Process();
601 if(!W32Process
->WindowStation
)
604 if(WindowObject
->SystemMenu
)
606 MenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
609 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
610 WindowObject
->SystemMenu
= (HMENU
)0;
611 IntReleaseMenuObject(MenuObject
);
615 if(W32Process
->WindowStation
->SystemMenuTemplate
)
617 /* clone system menu */
618 MenuObject
= IntGetMenuObject(W32Process
->WindowStation
->SystemMenuTemplate
);
622 NewMenuObject
= IntCloneMenu(MenuObject
);
625 WindowObject
->SystemMenu
= NewMenuObject
->MenuInfo
.Self
;
626 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
627 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
629 //IntReleaseMenuObject(NewMenuObject);
631 IntReleaseMenuObject(MenuObject
);
635 SysMenu
= NtUserCreateMenu(FALSE
);
640 SysMenuObject
= IntGetMenuObject(SysMenu
);
641 if (NULL
== SysMenuObject
)
643 NtUserDestroyMenu(SysMenu
);
646 SysMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
647 SysMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
648 NewMenu
= IntLoadSysMenuTemplate();
651 IntReleaseMenuObject(SysMenuObject
);
652 NtUserDestroyMenu(SysMenu
);
655 MenuObject
= IntGetMenuObject(NewMenu
);
658 IntReleaseMenuObject(SysMenuObject
);
659 NtUserDestroyMenu(SysMenu
);
663 NewMenuObject
= IntCloneMenu(MenuObject
);
666 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
| MF_POPUP
;
667 IntReleaseMenuObject(NewMenuObject
);
668 NtUserSetMenuDefaultItem(NewMenuObject
->MenuInfo
.Self
, SC_CLOSE
, FALSE
);
670 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
671 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
672 ItemInfo
.fType
= MF_POPUP
;
673 ItemInfo
.fState
= MFS_ENABLED
;
674 ItemInfo
.dwTypeData
= NULL
;
676 ItemInfo
.hSubMenu
= NewMenuObject
->MenuInfo
.Self
;
677 IntInsertMenuItem(SysMenuObject
, (UINT
) -1, TRUE
, &ItemInfo
);
679 WindowObject
->SystemMenu
= SysMenuObject
->MenuInfo
.Self
;
683 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
684 IntReleaseMenuObject(MenuObject
);
693 if(WindowObject
->SystemMenu
)
694 return IntGetMenuObject((HMENU
)WindowObject
->SystemMenu
);
703 IntGetWindowThreadProcessId(PWINDOW_OBJECT Wnd
, PDWORD pid
)
705 if (pid
) *pid
= (DWORD
) Wnd
->OwnerThread
->ThreadsProcess
->UniqueProcessId
;
706 return (DWORD
) Wnd
->OwnerThread
->Cid
.UniqueThread
;
710 IntIsChildWindow(HWND Parent
, HWND Child
)
712 PWINDOW_OBJECT BaseWindow
= IntGetWindowObject(Child
);
713 PWINDOW_OBJECT Window
= BaseWindow
;
714 while (Window
!= NULL
&& Window
->Style
& WS_CHILD
)
716 if (Window
->Self
== Parent
)
718 IntReleaseWindowObject(BaseWindow
);
721 Window
= Window
->Parent
;
723 IntReleaseWindowObject(BaseWindow
);
728 IntIsWindowVisible(HWND Wnd
)
730 PWINDOW_OBJECT BaseWindow
= IntGetWindowObject(Wnd
);
731 PWINDOW_OBJECT Window
= BaseWindow
;
732 BOOLEAN Result
= FALSE
;
733 while (Window
!= NULL
&& Window
->Style
& WS_CHILD
)
735 if (!(Window
->Style
& WS_VISIBLE
))
737 IntReleaseWindowObject(BaseWindow
);
740 Window
= Window
->Parent
;
742 if (Window
!= NULL
&& Window
->Style
& WS_VISIBLE
)
746 IntReleaseWindowObject(BaseWindow
);
751 /* link the window into siblings and parent. children are kept in place. */
755 PWINDOW_OBJECT WndParent
,
756 PWINDOW_OBJECT WndPrevSibling
/* set to NULL if top sibling */
759 Wnd
->Parent
= WndParent
;
761 if ((Wnd
->PrevSibling
= WndPrevSibling
))
763 /* link after WndPrevSibling */
764 if ((Wnd
->NextSibling
= WndPrevSibling
->NextSibling
)) Wnd
->NextSibling
->PrevSibling
= Wnd
;
765 else if (Wnd
->Parent
->LastChild
== WndPrevSibling
) Wnd
->Parent
->LastChild
= Wnd
;
766 Wnd
->PrevSibling
->NextSibling
= Wnd
;
771 if ((Wnd
->NextSibling
= WndParent
->FirstChild
)) Wnd
->NextSibling
->PrevSibling
= Wnd
;
772 else Wnd
->Parent
->LastChild
= Wnd
;
773 WndParent
->FirstChild
= Wnd
;
779 IntSetOwner(HWND hWnd
, HWND hWndNewOwner
)
781 PWINDOW_OBJECT Wnd
, WndOldOwner
;
784 Wnd
= IntGetWindowObject(hWnd
);
785 WndOldOwner
= Wnd
->Owner
;
788 ret
= WndOldOwner
->Self
;
789 IntReleaseWindowObject(WndOldOwner
);
795 Wnd
->Owner
= IntGetWindowObject(hWndNewOwner
);
796 IntReleaseWindowObject(Wnd
);
800 PWINDOW_OBJECT FASTCALL
801 IntSetParent(PWINDOW_OBJECT Wnd
, PWINDOW_OBJECT WndNewParent
)
803 PWINDOW_OBJECT WndOldParent
;
804 HWND hWnd
, hWndNewParent
, hWndOldParent
;
809 hWndNewParent
= WndNewParent
->Self
;
812 * Windows hides the window first, then shows it again
813 * including the WM_SHOWWINDOW messages and all
815 WasVisible
= WinPosShowWindow(hWnd
, SW_HIDE
);
817 /* Validate that window and parent still exist */
818 if (!IntIsWindow(hWnd
) || !IntIsWindow(hWndNewParent
))
821 /* Window must belong to current process */
822 if (Wnd
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
825 WndOldParent
= Wnd
->Parent
;
826 hWndOldParent
= WndOldParent
->Self
;
828 if (WndNewParent
!= WndOldParent
)
830 ExAcquireFastMutexUnsafe(&WndOldParent
->ChildrenListLock
);
831 IntUnlinkWindow(Wnd
);
832 ExReleaseFastMutexUnsafe(&WndOldParent
->ChildrenListLock
);
833 ExAcquireFastMutexUnsafe(&WndNewParent
->ChildrenListLock
);
834 IntLinkWindow(Wnd
, WndNewParent
, NULL
/*prev sibling*/);
835 ExReleaseFastMutexUnsafe(&WndNewParent
->ChildrenListLock
);
837 if (WndNewParent
->Self
!= IntGetDesktopWindow()) /* a child window */
839 if (!(Wnd
->Style
& WS_CHILD
))
841 //if ( Wnd->Menu ) DestroyMenu ( Wnd->menu );
842 IntSetMenu(Wnd
, NULL
, &MenuChanged
);
848 * SetParent additionally needs to make hwnd the topmost window
849 * in the x-order and send the expected WM_WINDOWPOSCHANGING and
850 * WM_WINDOWPOSCHANGED notification messages.
852 WinPosSetWindowPos(hWnd
, HWND_TOPMOST
, 0, 0, 0, 0,
853 SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
| (WasVisible
? SWP_SHOWWINDOW
: 0));
856 * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
857 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
861 * Validate that the old parent still exist, since it migth have been
862 * destroyed during the last callbacks to user-mode
864 return !IntIsWindow(hWndOldParent
) ? NULL
: WndOldParent
;
868 IntSetSystemMenu(PWINDOW_OBJECT WindowObject
, PMENU_OBJECT MenuObject
)
870 PMENU_OBJECT OldMenuObject
;
871 if(WindowObject
->SystemMenu
)
873 OldMenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
876 OldMenuObject
->MenuInfo
.Flags
&= ~ MF_SYSMENU
;
877 IntReleaseMenuObject(OldMenuObject
);
883 /* FIXME check window style, propably return FALSE ? */
884 WindowObject
->SystemMenu
= MenuObject
->MenuInfo
.Self
;
885 MenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
888 WindowObject
->SystemMenu
= (HMENU
)0;
894 /* unlink the window from siblings and parent. children are kept in place. */
896 IntUnlinkWindow(PWINDOW_OBJECT Wnd
)
898 PWINDOW_OBJECT WndParent
= Wnd
->Parent
;
900 if (Wnd
->NextSibling
) Wnd
->NextSibling
->PrevSibling
= Wnd
->PrevSibling
;
901 else if (WndParent
->LastChild
== Wnd
) WndParent
->LastChild
= Wnd
->PrevSibling
;
903 if (Wnd
->PrevSibling
) Wnd
->PrevSibling
->NextSibling
= Wnd
->NextSibling
;
904 else if (WndParent
->FirstChild
== Wnd
) WndParent
->FirstChild
= Wnd
->NextSibling
;
905 //else if (parent->first_unlinked == win) parent->first_unlinked = Wnd->NextSibling;
910 IntWndBelongsToThread(PWINDOW_OBJECT Window
, PW32THREAD ThreadData
)
912 if (Window
->OwnerThread
&& Window
->OwnerThread
->Win32Thread
)
914 return (Window
->OwnerThread
->Win32Thread
== ThreadData
);
921 /* FUNCTIONS *****************************************************************/
927 NtUserAlterWindowStyle(DWORD Unknown0
,
938 * As best as I can figure, this function is used by EnumWindows,
939 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
941 * It's supposed to build a list of HWNDs to return to the caller.
942 * We can figure out what kind of list by what parameters are
961 /* FIXME handle bChildren */
964 PWINDOW_OBJECT WindowObject
= NULL
;
965 PWINDOW_OBJECT Child
;
967 WindowObject
= IntGetWindowObject ( hwndParent
);
970 DPRINT("Bad window handle 0x%x\n", hwndParent
);
971 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
975 ExAcquireFastMutex ( &WindowObject
->ChildrenListLock
);
976 Child
= WindowObject
->FirstChild
;
979 if ( pWnd
&& dwCount
< nBufSize
)
980 pWnd
[dwCount
] = Child
->Self
;
982 Child
= Child
->NextSibling
;
984 ExReleaseFastMutex ( &WindowObject
->ChildrenListLock
);
985 IntReleaseWindowObject ( WindowObject
);
987 else if ( dwThreadId
)
990 struct _ETHREAD
* Thread
;
991 struct _EPROCESS
* ThreadsProcess
;
992 struct _W32PROCESS
* Win32Process
;
993 struct _WINSTATION_OBJECT
* WindowStation
;
994 PUSER_HANDLE_TABLE HandleTable
;
996 PUSER_HANDLE_BLOCK Block
= NULL
;
999 Status
= PsLookupThreadByThreadId ( (PVOID
)dwThreadId
, &Thread
);
1000 if ( !NT_SUCCESS(Status
) || !Thread
)
1002 DPRINT("Bad ThreadId 0x%x\n", dwThreadId
);
1003 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1006 ThreadsProcess
= Thread
->ThreadsProcess
;
1007 ASSERT(ThreadsProcess
);
1008 Win32Process
= ThreadsProcess
->Win32Process
;
1009 ASSERT(Win32Process
);
1010 WindowStation
= Win32Process
->WindowStation
;
1011 ASSERT(WindowStation
);
1012 HandleTable
= (PUSER_HANDLE_TABLE
)(WindowStation
->HandleTable
);
1013 ASSERT(HandleTable
);
1015 ObDereferenceObject(Thread
);
1017 ExAcquireFastMutex(&HandleTable
->ListLock
);
1019 Current
= HandleTable
->ListHead
.Flink
;
1020 while ( Current
!= &HandleTable
->ListHead
)
1022 Block
= CONTAINING_RECORD(Current
, USER_HANDLE_BLOCK
, ListEntry
);
1023 for ( i
= 0; i
< HANDLE_BLOCK_ENTRIES
; i
++ )
1025 PVOID ObjectBody
= Block
->Handles
[i
].ObjectBody
;
1028 if ( pWnd
&& dwCount
< nBufSize
)
1031 (HWND
)ObmReferenceObjectByPointer ( ObjectBody
, otWindow
);
1036 Current
= Current
->Flink
;
1039 ExReleaseFastMutex(&HandleTable
->ListLock
);
1043 PDESKTOP_OBJECT DesktopObject
= NULL
;
1045 PWINDOW_OBJECT Child
, WndDesktop
;
1049 DesktopObject
= IntGetDesktopObject ( hDesktop
);
1052 DesktopObject
= IntGetActiveDesktop();
1055 DPRINT("Bad desktop handle 0x%x\n", hDesktop
);
1056 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1060 KeAcquireSpinLock ( &DesktopObject
->Lock
, &OldIrql
);
1062 WndDesktop
= IntGetWindowObject(DesktopObject
->DesktopWindow
);
1063 Child
= (WndDesktop
? WndDesktop
->FirstChild
: NULL
);
1066 if ( pWnd
&& dwCount
< nBufSize
)
1067 pWnd
[dwCount
] = Child
->Self
;
1069 Child
= Child
->NextSibling
;
1071 KeReleaseSpinLock ( &DesktopObject
->Lock
, OldIrql
);
1082 NtUserChildWindowFromPointEx(HWND hwndParent
,
1087 PWINDOW_OBJECT pParent
, pCurrent
, pLast
;
1090 BOOL bFirstRun
= TRUE
;
1094 pParent
= IntGetWindowObject(hwndParent
);
1097 ExAcquireFastMutexUnsafe (&pParent
->ChildrenListLock
);
1099 pLast
= IntGetWindowObject(pParent
->LastChild
->Self
);
1100 pCurrent
= IntGetWindowObject(pParent
->FirstChild
->Self
);
1106 pCurrent
= IntGetWindowObject(pCurrent
->NextSibling
->Self
);
1114 rc
.left
= pCurrent
->WindowRect
.left
- pCurrent
->Parent
->ClientRect
.left
;
1115 rc
.top
= pCurrent
->WindowRect
.top
- pCurrent
->Parent
->ClientRect
.top
;
1116 rc
.right
= rc
.left
+ (pCurrent
->WindowRect
.right
- pCurrent
->WindowRect
.left
);
1117 rc
.bottom
= rc
.top
+ (pCurrent
->WindowRect
.bottom
- pCurrent
->WindowRect
.top
);
1118 DbgPrint("Rect: %i,%i,%i,%i\n",rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
1119 if (POINT_IN_RECT(p
,rc
)) /* Found a match */
1121 if ( (uiFlags
& CWP_SKIPDISABLED
) && (pCurrent
->Style
& WS_DISABLED
) )
1123 if( (uiFlags
& CWP_SKIPTRANSPARENT
) && (pCurrent
->ExStyle
& WS_EX_TRANSPARENT
) )
1125 if( (uiFlags
& CWP_SKIPINVISIBLE
) && !(pCurrent
->Style
& WS_VISIBLE
) )
1128 ExReleaseFastMutexUnsafe(&pParent
->ChildrenListLock
);
1129 return pCurrent
->Self
;
1132 while(pCurrent
!= pLast
);
1134 ExReleaseFastMutexUnsafe(&pParent
->ChildrenListLock
);
1137 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1148 NtUserCreateWindowEx(DWORD dwExStyle
,
1149 PUNICODE_STRING lpClassName
,
1150 PUNICODE_STRING lpWindowName
,
1158 HINSTANCE hInstance
,
1161 BOOL bUnicodeWindow
)
1163 PWINSTATION_OBJECT WinStaObject
;
1164 PWNDCLASS_OBJECT ClassObject
;
1165 PWINDOW_OBJECT WindowObject
;
1166 PWINDOW_OBJECT ParentWindow
;
1167 HWND ParentWindowHandle
;
1168 HWND OwnerWindowHandle
;
1169 PMENU_OBJECT SystemMenu
;
1170 UNICODE_STRING WindowName
;
1174 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1179 CBT_CREATEWNDW CbtCreate
;
1183 DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1185 if (! RtlCreateUnicodeString(&WindowName
,
1186 NULL
== lpWindowName
->Buffer
?
1187 L
"" : lpWindowName
->Buffer
))
1189 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1193 ParentWindowHandle
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
1194 OwnerWindowHandle
= NULL
;
1196 if (hWndParent
== HWND_MESSAGE
)
1199 * native ole32.OleInitialize uses HWND_MESSAGE to create the
1200 * message window (style: WS_POPUP|WS_DISABLED)
1204 else if (hWndParent
)
1206 if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1207 ParentWindowHandle
= hWndParent
;
1209 OwnerWindowHandle
= NtUserGetAncestor(hWndParent
, GA_ROOT
);
1211 else if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1213 RtlFreeUnicodeString(&WindowName
);
1214 return (HWND
)0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1217 if (NULL
!= ParentWindowHandle
)
1219 ParentWindow
= IntGetWindowObject(ParentWindowHandle
);
1223 ParentWindow
= NULL
;
1226 /* FIXME: parent must belong to the current process */
1228 /* Check the class. */
1229 Status
= ClassReferenceClassByNameOrAtom(&ClassObject
, lpClassName
->Buffer
);
1230 if (!NT_SUCCESS(Status
))
1232 RtlFreeUnicodeString(&WindowName
);
1233 if (NULL
!= ParentWindow
)
1235 IntReleaseWindowObject(ParentWindow
);
1240 /* Check the window station. */
1241 DPRINT("IoGetCurrentProcess() %X\n", IoGetCurrentProcess());
1242 DPRINT("PROCESS_WINDOW_STATION %X\n", PROCESS_WINDOW_STATION());
1243 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
1247 if (!NT_SUCCESS(Status
))
1249 ObmDereferenceObject(ClassObject
);
1250 RtlFreeUnicodeString(&WindowName
);
1251 if (NULL
!= ParentWindow
)
1253 IntReleaseWindowObject(ParentWindow
);
1255 DPRINT("Validation of window station handle (0x%X) failed\n",
1256 PROCESS_WINDOW_STATION());
1260 /* Create the window object. */
1261 WindowObject
= (PWINDOW_OBJECT
)
1262 ObmCreateObject(PsGetWin32Process()->WindowStation
->HandleTable
, &Handle
,
1263 otWindow
, sizeof(WINDOW_OBJECT
) + ClassObject
->cbWndExtra
1266 DPRINT("Created object with handle %X\n", Handle
);
1269 ObDereferenceObject(WinStaObject
);
1270 ObmDereferenceObject(ClassObject
);
1271 RtlFreeUnicodeString(&WindowName
);
1272 if (NULL
!= ParentWindow
)
1274 IntReleaseWindowObject(ParentWindow
);
1276 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1279 ObDereferenceObject(WinStaObject
);
1281 if (NULL
== PsGetWin32Thread()->Desktop
->DesktopWindow
)
1283 /* If there is no desktop window yet, we must be creating it */
1284 PsGetWin32Thread()->Desktop
->DesktopWindow
= Handle
;
1288 * Fill out the structure describing it.
1290 WindowObject
->Class
= ClassObject
;
1291 WindowObject
->ExStyle
= dwExStyle
;
1292 WindowObject
->Style
= dwStyle
& ~WS_VISIBLE
;
1293 DPRINT("1: Style is now %d\n", WindowObject
->Style
);
1295 WindowObject
->SystemMenu
= (HMENU
)0;
1296 WindowObject
->ContextHelpId
= 0;
1297 WindowObject
->IDMenu
= 0;
1298 WindowObject
->Instance
= hInstance
;
1299 WindowObject
->Self
= Handle
;
1300 if (0 != (dwStyle
& WS_CHILD
))
1302 WindowObject
->IDMenu
= (UINT
) hMenu
;
1306 IntSetMenu(WindowObject
, hMenu
, &MenuChanged
);
1308 WindowObject
->MessageQueue
= PsGetWin32Thread()->MessageQueue
;
1309 WindowObject
->Parent
= ParentWindow
;
1310 WindowObject
->Owner
= IntGetWindowObject(OwnerWindowHandle
);
1311 WindowObject
->UserData
= 0;
1312 if ((((DWORD
)ClassObject
->lpfnWndProcA
& 0xFFFF0000) != 0xFFFF0000)
1313 && (((DWORD
)ClassObject
->lpfnWndProcW
& 0xFFFF0000) != 0xFFFF0000))
1315 WindowObject
->Unicode
= bUnicodeWindow
;
1319 WindowObject
->Unicode
= ClassObject
->Unicode
;
1321 WindowObject
->WndProcA
= ClassObject
->lpfnWndProcA
;
1322 WindowObject
->WndProcW
= ClassObject
->lpfnWndProcW
;
1323 WindowObject
->OwnerThread
= PsGetCurrentThread();
1324 WindowObject
->FirstChild
= NULL
;
1325 WindowObject
->LastChild
= NULL
;
1326 WindowObject
->PrevSibling
= NULL
;
1327 WindowObject
->NextSibling
= NULL
;
1329 /* extra window data */
1330 if (ClassObject
->cbWndExtra
!= 0)
1332 WindowObject
->ExtraData
= (PCHAR
)(WindowObject
+ 1);
1333 WindowObject
->ExtraDataSize
= ClassObject
->cbWndExtra
;
1334 RtlZeroMemory(WindowObject
->ExtraData
, WindowObject
->ExtraDataSize
);
1338 WindowObject
->ExtraData
= NULL
;
1339 WindowObject
->ExtraDataSize
= 0;
1342 InitializeListHead(&WindowObject
->PropListHead
);
1343 ExInitializeFastMutex(&WindowObject
->PropListLock
);
1344 ExInitializeFastMutex(&WindowObject
->ChildrenListLock
);
1345 ExInitializeFastMutex(&WindowObject
->UpdateLock
);
1347 RtlInitUnicodeString(&WindowObject
->WindowName
, WindowName
.Buffer
);
1349 /* Correct the window style. */
1350 if (!(dwStyle
& WS_CHILD
))
1352 WindowObject
->Style
|= WS_CLIPSIBLINGS
;
1353 DPRINT("3: Style is now %d\n", WindowObject
->Style
);
1354 if (!(dwStyle
& WS_POPUP
))
1356 WindowObject
->Style
|= WS_CAPTION
;
1357 WindowObject
->Flags
|= WINDOWOBJECT_NEED_SIZE
;
1358 DPRINT("4: Style is now %d\n", WindowObject
->Style
);
1359 /* FIXME: Note the window needs a size. */
1363 /* create system menu */
1364 if((WindowObject
->Style
& WS_SYSMENU
) && (WindowObject
->Style
& WS_CAPTION
))
1366 SystemMenu
= IntGetSystemMenu(WindowObject
, TRUE
, TRUE
);
1369 WindowObject
->SystemMenu
= SystemMenu
->MenuInfo
.Self
;
1370 IntReleaseMenuObject(SystemMenu
);
1374 /* Insert the window into the thread's window list. */
1375 ExAcquireFastMutexUnsafe (&PsGetWin32Thread()->WindowListLock
);
1376 InsertTailList (&PsGetWin32Thread()->WindowListHead
,
1377 &WindowObject
->ThreadListEntry
);
1378 ExReleaseFastMutexUnsafe (&PsGetWin32Thread()->WindowListLock
);
1380 /* Allocate a DCE for this window. */
1381 if (dwStyle
& CS_OWNDC
)
1383 WindowObject
->Dce
= DceAllocDCE(WindowObject
->Self
, DCE_WINDOW_DC
);
1385 /* FIXME: Handle "CS_CLASSDC" */
1387 /* Initialize the window dimensions. */
1388 WindowObject
->WindowRect
.left
= x
;
1389 WindowObject
->WindowRect
.top
= y
;
1390 WindowObject
->WindowRect
.right
= x
+ nWidth
;
1391 WindowObject
->WindowRect
.bottom
= y
+ nHeight
;
1392 if (0 != (WindowObject
->Style
& WS_CHILD
))
1394 NtGdiOffsetRect(&(WindowObject
->WindowRect
), WindowObject
->Parent
->ClientRect
.left
,
1395 WindowObject
->Parent
->ClientRect
.top
);
1397 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1399 Cs
.lpCreateParams
= lpParam
;
1400 Cs
.hInstance
= hInstance
;
1402 Cs
.hwndParent
= ParentWindowHandle
;
1408 Cs
.lpszName
= lpWindowName
->Buffer
;
1409 Cs
.lpszClass
= lpClassName
->Buffer
;
1410 Cs
.dwExStyle
= dwExStyle
;
1411 CbtCreate
.lpcs
= &Cs
;
1412 CbtCreate
.hwndInsertAfter
= HWND_TOP
;
1413 if (HOOK_CallHooks(WH_CBT
, HCBT_CREATEWND
, (WPARAM
) Handle
, (LPARAM
) &CbtCreate
))
1415 if (NULL
!= ParentWindow
)
1417 IntReleaseWindowObject(ParentWindow
);
1419 DPRINT1("CBT-hook returned !0\n");
1424 * Get the size and position of the window.
1426 if ((dwStyle
& WS_THICKFRAME
) || !(dwStyle
& (WS_POPUP
| WS_CHILD
)))
1428 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1430 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1431 WinPosGetMinMaxInfo(WindowObject
, &MaxSize
, &MaxPos
, &MinTrack
,
1433 if (MaxSize
.x
< nWidth
) nWidth
= MaxSize
.x
;
1434 if (MaxSize
.y
< nHeight
) nHeight
= MaxSize
.y
;
1435 if (nWidth
< MinTrack
.x
) nWidth
= MinTrack
.x
;
1436 if (nHeight
< MinTrack
.y
) nHeight
= MinTrack
.y
;
1437 if (nWidth
< 0) nWidth
= 0;
1438 if (nHeight
< 0) nHeight
= 0;
1441 WindowObject
->WindowRect
.left
= x
;
1442 WindowObject
->WindowRect
.top
= y
;
1443 WindowObject
->WindowRect
.right
= x
+ nWidth
;
1444 WindowObject
->WindowRect
.bottom
= y
+ nHeight
;
1445 if (0 != (WindowObject
->Style
& WS_CHILD
))
1447 NtGdiOffsetRect(&(WindowObject
->WindowRect
), WindowObject
->Parent
->ClientRect
.left
,
1448 WindowObject
->Parent
->ClientRect
.top
);
1450 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1452 /* FIXME: Initialize the window menu. */
1454 /* Initialize the window's scrollbars */
1455 if (dwStyle
& WS_VSCROLL
)
1457 WindowObject
->Style
&= ~WS_VSCROLL
;
1458 NtUserShowScrollBar(WindowObject
->Self
, SB_VERT
, TRUE
);
1460 if (dwStyle
& WS_HSCROLL
)
1462 WindowObject
->Style
&= ~WS_HSCROLL
;
1463 NtUserShowScrollBar(WindowObject
->Self
, SB_HORZ
, TRUE
);
1466 /* Send a NCCREATE message. */
1472 DPRINT("[win32k.window] NtUserCreateWindowEx style %d, exstyle %d, parent %d\n", Cs
.style
, Cs
.dwExStyle
, Cs
.hwndParent
);
1473 DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1474 DPRINT("NtUserCreateWindowEx(): About to send NCCREATE message.\n");
1475 Result
= IntSendMessage(WindowObject
->Self
, WM_NCCREATE
, 0, (LPARAM
) &Cs
);
1478 /* FIXME: Cleanup. */
1479 if (NULL
!= ParentWindow
)
1481 IntReleaseWindowObject(ParentWindow
);
1483 DPRINT("NtUserCreateWindowEx(): NCCREATE message failed.\n");
1487 /* Calculate the non-client size. */
1488 MaxPos
.x
= WindowObject
->WindowRect
.left
;
1489 MaxPos
.y
= WindowObject
->WindowRect
.top
;
1490 DPRINT("NtUserCreateWindowEx(): About to get non-client size.\n");
1491 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1492 Result
= WinPosGetNonClientSize(WindowObject
->Self
,
1493 &WindowObject
->WindowRect
,
1494 &WindowObject
->ClientRect
);
1495 NtGdiOffsetRect(&WindowObject
->WindowRect
,
1496 MaxPos
.x
- WindowObject
->WindowRect
.left
,
1497 MaxPos
.y
- WindowObject
->WindowRect
.top
);
1499 if (NULL
!= ParentWindow
)
1501 /* link the window into the parent's child list */
1502 ExAcquireFastMutexUnsafe(&ParentWindow
->ChildrenListLock
);
1503 if ((dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
1505 /* link window as bottom sibling */
1506 IntLinkWindow(WindowObject
, ParentWindow
, ParentWindow
->LastChild
/*prev sibling*/);
1510 /* link window as top sibling */
1511 IntLinkWindow(WindowObject
, ParentWindow
, NULL
/*prev sibling*/);
1513 ExReleaseFastMutexUnsafe(&ParentWindow
->ChildrenListLock
);
1516 /* Send the WM_CREATE message. */
1517 DPRINT("NtUserCreateWindowEx(): about to send CREATE message.\n");
1518 Result
= IntSendMessage(WindowObject
->Self
, WM_CREATE
, 0, (LPARAM
) &Cs
);
1519 if (Result
== (LRESULT
)-1)
1521 /* FIXME: Cleanup. */
1522 if (NULL
!= ParentWindow
)
1524 IntReleaseWindowObject(ParentWindow
);
1526 DPRINT("NtUserCreateWindowEx(): send CREATE message failed.\n");
1530 /* Send move and size messages. */
1531 if (!(WindowObject
->Flags
& WINDOWOBJECT_NEED_SIZE
))
1535 DPRINT("NtUserCreateWindow(): About to send WM_SIZE\n");
1537 if ((WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
) < 0 ||
1538 (WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
) < 0)
1539 DPRINT("Sending bogus WM_SIZE\n");
1541 lParam
= MAKE_LONG(WindowObject
->ClientRect
.right
-
1542 WindowObject
->ClientRect
.left
,
1543 WindowObject
->ClientRect
.bottom
-
1544 WindowObject
->ClientRect
.top
);
1545 IntSendMessage(WindowObject
->Self
, WM_SIZE
, SIZE_RESTORED
,
1548 DPRINT("NtUserCreateWindow(): About to send WM_MOVE\n");
1550 if (0 != (WindowObject
->Style
& WS_CHILD
))
1552 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
- WindowObject
->Parent
->ClientRect
.left
,
1553 WindowObject
->ClientRect
.top
- WindowObject
->Parent
->ClientRect
.top
);
1557 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
,
1558 WindowObject
->ClientRect
.top
);
1560 IntSendMessage(WindowObject
->Self
, WM_MOVE
, 0, lParam
);
1563 /* Show or maybe minimize or maximize the window. */
1564 if (WindowObject
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1569 SwFlag
= (WindowObject
->Style
& WS_MINIMIZE
) ? SW_MINIMIZE
:
1571 WinPosMinMaximize(WindowObject
, SwFlag
, &NewPos
);
1573 ((WindowObject
->Style
& WS_CHILD
) || NtUserGetActiveWindow()) ?
1574 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
:
1575 SWP_NOZORDER
| SWP_FRAMECHANGED
;
1576 DPRINT("NtUserCreateWindow(): About to minimize/maximize\n");
1577 DPRINT("%d,%d %dx%d\n", NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
);
1578 WinPosSetWindowPos(WindowObject
->Self
, 0, NewPos
.left
, NewPos
.top
,
1579 NewPos
.right
, NewPos
.bottom
, SwFlag
);
1582 /* Notify the parent window of a new child. */
1583 if ((WindowObject
->Style
& WS_CHILD
) &&
1584 (!(WindowObject
->ExStyle
& WS_EX_NOPARENTNOTIFY
)))
1586 DPRINT("NtUserCreateWindow(): About to notify parent\n");
1587 IntSendMessage(WindowObject
->Parent
->Self
,
1589 MAKEWPARAM(WM_CREATE
, WindowObject
->IDMenu
),
1590 (LPARAM
)WindowObject
->Self
);
1593 if (dwStyle
& WS_VISIBLE
)
1595 DPRINT("NtUserCreateWindow(): About to show window\n");
1596 WinPosShowWindow(WindowObject
->Self
, dwShowMode
);
1599 DPRINT("NtUserCreateWindow(): = %X\n", Handle
);
1600 DPRINT("WindowObject->SystemMenu = 0x%x\n", WindowObject
->SystemMenu
);
1601 return((HWND
)Handle
);
1609 NtUserDeferWindowPos(HDWP WinPosInfo
,
1611 HWND WndInsertAfter
,
1628 NtUserDestroyWindow(HWND Wnd
)
1630 PWINDOW_OBJECT Window
, Parent
;
1633 Window
= IntGetWindowObject(Wnd
);
1639 /* Check for owner thread and desktop window */
1640 if ((Window
->OwnerThread
!= PsGetCurrentThread()) || IntIsDesktopWindow(Window
))
1642 IntReleaseWindowObject(Window
);
1643 SetLastWin32Error(ERROR_ACCESS_DENIED
);
1647 /* Look whether the focus is within the tree of windows we will
1650 if (!WinPosShowWindow(Wnd
, SW_HIDE
))
1652 if (NtUserGetActiveWindow() == Wnd
)
1654 WinPosActivateOtherWindow(Window
);
1657 ExAcquireFastMutex(&Window
->MessageQueue
->Lock
);
1658 if (Window
->MessageQueue
->ActiveWindow
== Window
->Self
)
1659 Window
->MessageQueue
->ActiveWindow
= NULL
;
1660 if (Window
->MessageQueue
->FocusWindow
== Window
->Self
)
1661 Window
->MessageQueue
->FocusWindow
= NULL
;
1662 if (Window
->MessageQueue
->CaptureWindow
== Window
->Self
)
1663 Window
->MessageQueue
->CaptureWindow
= NULL
;
1664 ExReleaseFastMutex(&Window
->MessageQueue
->Lock
);
1668 if (HOOK_CallHooks(WH_CBT
, HCBT_DESTROYWND
, (WPARAM
) hwnd
, 0, TRUE
))
1674 isChild
= (0 != (Window
->Style
& WS_CHILD
));
1679 if (! USER_IsExitingThread(GetCurrentThreadId()))
1681 send_parent_notify(hwnd
, WM_DESTROY
);
1684 else if (NULL
!= GetWindow(Wnd
, GW_OWNER
))
1686 HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
1687 /* FIXME: clean up palette - see "Internals" p.352 */
1690 if (! IsWindow(Wnd
))
1696 if (!IntIsWindow(Wnd
))
1701 /* Recursively destroy owned windows */
1706 BOOL GotOne
= FALSE
;
1709 PWINDOW_OBJECT Child
, Desktop
;
1711 Desktop
= IntGetWindowObject(IntGetDesktopWindow());
1712 Children
= IntWinListChildren(Desktop
);
1713 IntReleaseWindowObject(Desktop
);
1716 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
1718 Child
= IntGetWindowObject(*ChildHandle
);
1723 if (Child
->Parent
!= Window
)
1725 IntReleaseWindowObject(Child
);
1728 if (IntWndBelongsToThread(Child
, PsGetWin32Thread()))
1730 IntReleaseWindowObject(Child
);
1731 NtUserDestroyWindow(*ChildHandle
);
1735 if (Child
->Owner
!= NULL
)
1737 IntReleaseWindowObject(Child
->Owner
);
1738 Child
->Owner
= NULL
;
1740 IntReleaseWindowObject(Child
);
1742 ExFreePool(Children
);
1751 if (!IntIsWindow(Wnd
))
1756 /* Unlink now so we won't bother with the children later on */
1757 Parent
= Window
->Parent
;
1758 ExAcquireFastMutexUnsafe(&Parent
->ChildrenListLock
);
1759 IntUnlinkWindow(Window
);
1760 Window
->Parent
= NULL
;
1761 ExReleaseFastMutexUnsafe(&Parent
->ChildrenListLock
);
1763 /* Destroy the window storage */
1764 IntDestroyWindow(Window
, PsGetWin32Process(), PsGetWin32Thread(), TRUE
);
1766 IntReleaseWindowObject(Window
);
1776 NtUserDrawMenuBarTemp(
1783 /* we'll use this function just for caching the menu bar */
1793 NtUserEndDeferWindowPosEx(DWORD Unknown0
,
1806 NtUserFillWindow(DWORD Unknown0
,
1819 * Searches a window's children for a window with the specified
1822 * hwndParent = The window whose childs are to be searched.
1825 * hwndChildAfter = Search starts after this child window.
1826 * NULL = start from beginning
1828 * ucClassName = Class name to search for
1829 * Reguired parameter.
1831 * ucWindowName = Window name
1832 * ->Buffer == NULL = don't care
1835 * The HWND of the window if it was found, otherwise NULL
1838 * Should use MmCopyFromCaller, we don't want an access violation in here
1845 NtUserFindWindowEx(HWND hwndParent
,
1846 HWND hwndChildAfter
,
1847 PUNICODE_STRING ucClassName
,
1848 PUNICODE_STRING ucWindowName
)
1852 PWINDOW_OBJECT ParentWindow
, WndChildAfter
, WndChild
;
1853 PWNDCLASS_OBJECT classObject
;
1855 // Get a pointer to the class
1856 status
= ClassReferenceClassByNameOrAtom(&classObject
, ucClassName
->Buffer
);
1857 if (!NT_SUCCESS(status
))
1862 // If hwndParent==NULL use the desktop window instead
1864 hwndParent
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
1867 ParentWindow
= IntGetWindowObject(hwndParent
);
1871 ObmDereferenceObject(classObject
);
1875 ExAcquireFastMutexUnsafe (&ParentWindow
->ChildrenListLock
);
1879 if (!(WndChildAfter
= IntGetWindowObject(hwndChildAfter
)))
1881 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1885 /* must be a direct child (not a decendant child)*/
1886 if (WndChildAfter
->Parent
!= ParentWindow
)
1888 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1892 WndChild
= WndChildAfter
->NextSibling
;
1896 WndChild
= ParentWindow
->FirstChild
;
1901 if (classObject
== WndChild
->Class
&& (ucWindowName
->Buffer
==NULL
||
1902 RtlCompareUnicodeString (ucWindowName
, &WndChild
->WindowName
, TRUE
) == 0))
1904 windowHandle
= WndChild
->Self
;
1906 ExReleaseFastMutexUnsafe (&ParentWindow
->ChildrenListLock
);
1907 IntReleaseWindowObject(ParentWindow
);
1908 ObmDereferenceObject (classObject
);
1910 return windowHandle
;
1913 WndChild
= WndChild
->NextSibling
;
1916 ExReleaseFastMutexUnsafe (&ParentWindow
->ChildrenListLock
);
1918 IntReleaseWindowObject(ParentWindow
);
1919 ObmDereferenceObject (classObject
);
1929 NtUserFlashWindowEx(DWORD Unknown0
)
1941 NtUserGetAncestor(HWND hWnd
, UINT Type
)
1943 PWINDOW_OBJECT Wnd
, WndAncestor
;
1944 HWND hWndAncestor
= NULL
;
1946 if (hWnd
== IntGetDesktopWindow())
1951 IntAcquireWinLockShared();
1953 if (!(Wnd
= IntGetWindowObject(hWnd
)))
1955 IntReleaseWinLock();
1956 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1963 WndAncestor
= Wnd
->Parent
;
1968 while (!IntIsDesktopWindow(WndAncestor
->Parent
))
1969 WndAncestor
= WndAncestor
->Parent
;
1976 PWINDOW_OBJECT Parent
= IntGetParent(WndAncestor
);
1978 WndAncestor
= Parent
;
1988 hWndAncestor
= WndAncestor
->Self
;
1991 IntReleaseWindowObject(Wnd
);
1992 IntReleaseWinLock();
1994 return hWndAncestor
;
1999 * Returns client window rectangle relative to the upper-left corner of client area.
2001 * \param hWnd window handle.
2002 * \param Rect pointer to the buffer where the coordinates are returned.
2009 NtUserGetClientRect(HWND hWnd
, LPRECT Rect
)
2011 PWINDOW_OBJECT WindowObject
;
2014 IntAcquireWinLockShared();
2015 if (!(WindowObject
= IntGetWindowObject(hWnd
)))
2017 IntReleaseWinLock();
2018 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2022 IntGetClientRect(WindowObject
, &SafeRect
);
2023 IntReleaseWinLock();
2025 if (! NT_SUCCESS(MmCopyToCaller(Rect
, &SafeRect
, sizeof(RECT
))))
2038 NtUserGetDesktopWindow()
2040 return IntGetDesktopWindow();
2048 NtUserGetInternalWindowPos(DWORD Unknown0
,
2062 NtUserGetLastActivePopup(HWND hWnd
)
2065 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2066 * not changed anywhere.
2067 * -- Filip, 01/nov/2003
2073 IntAcquireWinLockShared();
2075 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2077 IntReleaseWinLock();
2078 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2082 hWndLastPopup
= Wnd
->hWndLastPopup
;
2084 IntReleaseWinLock();
2086 return hWndLastPopup
;
2095 * The NtUserGetParent function retrieves a handle to the specified window's
2099 * Note that, despite its name, this function can return an owner window
2100 * instead of a parent window.
2107 NtUserGetParent(HWND hWnd
)
2109 PWINDOW_OBJECT Wnd
, WndParent
;
2110 HWND hWndParent
= NULL
;
2112 IntAcquireWinLockShared();
2114 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2116 IntReleaseWinLock();
2117 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2121 WndParent
= IntGetParent(Wnd
);
2124 hWndParent
= WndParent
->Self
;
2127 IntReleaseWindowObject(Wnd
);
2128 IntReleaseWinLock();
2136 * The NtUserSetParent function changes the parent window of the specified
2140 * The new parent window and the child window must belong to the same
2141 * application. If the window identified by the hWndChild parameter is
2142 * visible, the system performs the appropriate redrawing and repainting.
2143 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2144 * or WS_POPUP window styles of the window whose parent is being changed.
2151 NtUserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2153 PWINDOW_OBJECT Wnd
= NULL
, WndParent
= NULL
, WndOldParent
;
2154 HWND hWndOldParent
= NULL
;
2156 if (IntIsBroadcastHwnd(hWndChild
) || IntIsBroadcastHwnd(hWndNewParent
))
2158 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2162 if (hWndChild
== IntGetDesktopWindow())
2164 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2168 IntAcquireWinLockExclusive();
2171 if (!(WndParent
= IntGetWindowObject(hWndNewParent
)))
2173 IntReleaseWinLock();
2174 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2180 if (!(WndParent
= IntGetWindowObject(IntGetDesktopWindow())))
2182 IntReleaseWinLock();
2183 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2188 if (!(Wnd
= IntGetWindowObject(hWndChild
)))
2190 IntReleaseWinLock();
2191 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2195 WndOldParent
= IntSetParent(Wnd
, WndParent
);
2199 hWndOldParent
= WndOldParent
->Self
;
2202 IntReleaseWindowObject(Wnd
);
2203 IntReleaseWindowObject(WndParent
);
2204 IntReleaseWinLock();
2206 return hWndOldParent
;
2210 * NtUserGetShellWindow
2212 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
2219 NtUserGetShellWindow()
2221 PWINSTATION_OBJECT WinStaObject
;
2224 NTSTATUS Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
2229 if (!NT_SUCCESS(Status
))
2231 SetLastNtError(Status
);
2235 Ret
= (HWND
)WinStaObject
->ShellWindow
;
2237 ObDereferenceObject(WinStaObject
);
2242 * NtUserSetShellWindowEx
2244 * This is undocumented function to set global shell window. The global
2245 * shell window has special handling of window position.
2252 NtUserSetShellWindowEx(HWND hwndShell
, HWND hwndListView
)
2254 PWINSTATION_OBJECT WinStaObject
;
2256 NTSTATUS Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
2261 if (!NT_SUCCESS(Status
))
2263 SetLastNtError(Status
);
2268 * Test if we are permitted to change the shell window.
2270 if (WinStaObject
->ShellWindow
)
2272 ObDereferenceObject(WinStaObject
);
2277 * Move shell window into background.
2279 if (hwndListView
&& hwndListView
!= hwndShell
)
2282 * Disabled for now to get Explorer working.
2283 * -- Filip, 01/nov/2003
2286 WinPosSetWindowPos(hwndListView
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2289 if (NtUserGetWindowLong(hwndListView
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2291 ObDereferenceObject(WinStaObject
);
2296 if (NtUserGetWindowLong(hwndShell
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2298 ObDereferenceObject(WinStaObject
);
2302 WinPosSetWindowPos(hwndShell
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2304 WinStaObject
->ShellWindow
= hwndShell
;
2305 WinStaObject
->ShellListView
= hwndListView
;
2307 ObDereferenceObject(WinStaObject
);
2312 * NtUserGetSystemMenu
2314 * The NtUserGetSystemMenu function allows the application to access the
2315 * window menu (also known as the system menu or the control menu) for
2316 * copying and modifying.
2320 * Handle to the window that will own a copy of the window menu.
2322 * Specifies the action to be taken. If this parameter is FALSE,
2323 * NtUserGetSystemMenu returns a handle to the copy of the window menu
2324 * currently in use. The copy is initially identical to the window menu
2325 * but it can be modified.
2326 * If this parameter is TRUE, GetSystemMenu resets the window menu back
2327 * to the default state. The previous window menu, if any, is destroyed.
2330 * If the bRevert parameter is FALSE, the return value is a handle to a
2331 * copy of the window menu. If the bRevert parameter is TRUE, the return
2339 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
2342 PWINDOW_OBJECT WindowObject
;
2343 PMENU_OBJECT MenuObject
;
2345 WindowObject
= IntGetWindowObject((HWND
)hWnd
);
2346 if (WindowObject
== NULL
)
2348 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2352 MenuObject
= IntGetSystemMenu(WindowObject
, bRevert
, FALSE
);
2355 Result
= MenuObject
->MenuInfo
.Self
;
2356 IntReleaseMenuObject(MenuObject
);
2359 IntReleaseWindowObject(WindowObject
);
2364 * NtUserSetSystemMenu
2371 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
2373 BOOL Result
= FALSE
;
2374 PWINDOW_OBJECT WindowObject
;
2375 PMENU_OBJECT MenuObject
;
2377 WindowObject
= IntGetWindowObject(hWnd
);
2380 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2387 * Assign new menu handle.
2389 MenuObject
= IntGetMenuObject(hMenu
);
2392 IntReleaseWindowObject(WindowObject
);
2393 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
2397 Result
= IntSetSystemMenu(WindowObject
, MenuObject
);
2399 IntReleaseMenuObject(MenuObject
);
2402 IntReleaseWindowObject(WindowObject
);
2410 * The NtUserGetWindow function retrieves a handle to a window that has the
2411 * specified relationship (Z order or owner) to the specified window.
2418 NtUserGetWindow(HWND hWnd
, UINT Relationship
)
2420 PWINDOW_OBJECT WindowObject
;
2421 HWND hWndResult
= NULL
;
2423 IntAcquireWinLockShared();
2425 if (!(WindowObject
= IntGetWindowObject(hWnd
)))
2427 IntReleaseWinLock();
2428 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2432 switch (Relationship
)
2435 if (WindowObject
->Parent
&& WindowObject
->Parent
->FirstChild
)
2436 hWndResult
= WindowObject
->Parent
->FirstChild
->Self
;
2440 if (WindowObject
->Parent
&& WindowObject
->Parent
->LastChild
)
2441 hWndResult
= WindowObject
->Parent
->LastChild
->Self
;
2445 if (WindowObject
->NextSibling
)
2446 hWndResult
= WindowObject
->NextSibling
->Self
;
2450 if (WindowObject
->PrevSibling
)
2451 hWndResult
= WindowObject
->PrevSibling
->Self
;
2455 if (WindowObject
->Owner
)
2456 hWndResult
= WindowObject
->Owner
->Self
;
2459 if (WindowObject
->FirstChild
)
2460 hWndResult
= WindowObject
->FirstChild
->Self
;
2464 IntReleaseWindowObject(WindowObject
);
2465 IntReleaseWinLock();
2473 * The NtUserGetWindowDC function retrieves the device context (DC) for the
2474 * entire window, including title bar, menus, and scroll bars. A window device
2475 * context permits painting anywhere in a window, because the origin of the
2476 * device context is the upper-left corner of the window instead of the client
2484 NtUserGetWindowDC(HWND hWnd
)
2486 return (DWORD
)NtUserGetDCEx(hWnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
2490 * NtUserGetWindowLong
2492 * The NtUserGetWindowLong function retrieves information about the specified
2493 * window. The function also retrieves the 32-bit (long) value at the
2494 * specified offset into the extra window memory.
2501 NtUserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
2503 PWINDOW_OBJECT WindowObject
;
2506 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
2508 WindowObject
= IntGetWindowObject(hWnd
);
2509 if (WindowObject
== NULL
)
2511 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2516 * Only allow CSRSS to mess with the desktop window
2518 if (hWnd
== IntGetDesktopWindow()
2519 && WindowObject
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
2521 SetLastWin32Error(STATUS_ACCESS_DENIED
);
2525 if ((INT
)Index
>= 0)
2527 if (Index
> WindowObject
->ExtraDataSize
- sizeof(LONG
))
2529 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2532 Result
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
2539 Result
= WindowObject
->ExStyle
;
2543 Result
= WindowObject
->Style
;
2548 Result
= (LONG
) WindowObject
->WndProcA
;
2550 Result
= (LONG
) WindowObject
->WndProcW
;
2554 Result
= (LONG
) WindowObject
->Instance
;
2557 case GWL_HWNDPARENT
:
2558 if (WindowObject
->Parent
->Self
== IntGetDesktopWindow())
2559 Result
= (LONG
) NtUserGetWindow(WindowObject
->Self
, GW_OWNER
);
2561 Result
= (LONG
) NtUserGetAncestor(WindowObject
->Self
, GA_PARENT
);
2565 Result
= (LONG
) WindowObject
->IDMenu
;
2569 Result
= WindowObject
->UserData
;
2573 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index
);
2574 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2580 IntReleaseWindowObject(WindowObject
);
2586 * NtUserSetWindowLong
2588 * The NtUserSetWindowLong function changes an attribute of the specified
2589 * window. The function also sets the 32-bit (long) value at the specified
2590 * offset into the extra window memory.
2597 NtUserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
2599 PWINDOW_OBJECT WindowObject
;
2600 PW32PROCESS Process
;
2601 PWINSTATION_OBJECT WindowStation
;
2605 if (hWnd
== IntGetDesktopWindow())
2607 SetLastWin32Error(STATUS_ACCESS_DENIED
);
2611 WindowObject
= IntGetWindowObject(hWnd
);
2612 if (WindowObject
== NULL
)
2614 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2618 if ((INT
)Index
>= 0)
2620 if (Index
> WindowObject
->ExtraDataSize
- sizeof(LONG
))
2622 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2623 IntReleaseWindowObject(WindowObject
);
2626 OldValue
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
2627 *((LONG
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
2634 OldValue
= (LONG
) WindowObject
->ExStyle
;
2635 Style
.styleOld
= OldValue
;
2636 Style
.styleNew
= NewValue
;
2639 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
2641 Process
= WindowObject
->OwnerThread
->ThreadsProcess
->Win32Process
;
2642 WindowStation
= Process
->WindowStation
;
2645 if (hWnd
== WindowStation
->ShellWindow
|| hWnd
== WindowStation
->ShellListView
)
2646 Style
.styleNew
&= ~WS_EX_TOPMOST
;
2649 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_EXSTYLE
, (LPARAM
) &Style
);
2650 WindowObject
->ExStyle
= (DWORD
)Style
.styleNew
;
2651 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_EXSTYLE
, (LPARAM
) &Style
);
2655 OldValue
= (LONG
) WindowObject
->Style
;
2656 Style
.styleOld
= OldValue
;
2657 Style
.styleNew
= NewValue
;
2658 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_STYLE
, (LPARAM
) &Style
);
2659 WindowObject
->Style
= (DWORD
)Style
.styleNew
;
2660 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_STYLE
, (LPARAM
) &Style
);
2664 /* FIXME: should check if window belongs to current process */
2667 OldValue
= (LONG
) WindowObject
->WndProcA
;
2668 WindowObject
->WndProcA
= (WNDPROC
) NewValue
;
2669 WindowObject
->WndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,FALSE
);
2670 WindowObject
->Unicode
= FALSE
;
2674 OldValue
= (LONG
) WindowObject
->WndProcW
;
2675 WindowObject
->WndProcW
= (WNDPROC
) NewValue
;
2676 WindowObject
->WndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,TRUE
);
2677 WindowObject
->Unicode
= TRUE
;
2682 OldValue
= (LONG
) WindowObject
->Instance
;
2683 WindowObject
->Instance
= (HINSTANCE
) NewValue
;
2686 case GWL_HWNDPARENT
:
2687 if (WindowObject
->Parent
->Self
== IntGetDesktopWindow())
2688 OldValue
= (LONG
) IntSetOwner(WindowObject
->Self
, (HWND
) NewValue
);
2690 OldValue
= (LONG
) NtUserSetParent(WindowObject
->Self
, (HWND
) NewValue
);
2694 OldValue
= (LONG
) WindowObject
->IDMenu
;
2695 WindowObject
->IDMenu
= (UINT
) NewValue
;
2699 OldValue
= WindowObject
->UserData
;
2700 WindowObject
->UserData
= NewValue
;
2704 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index
);
2705 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2711 IntReleaseWindowObject(WindowObject
);
2717 * NtUserSetWindowWord
2719 * Legacy function similar to NtUserSetWindowLong.
2726 NtUserSetWindowWord(HWND hWnd
, INT Index
, WORD NewValue
)
2728 PWINDOW_OBJECT WindowObject
;
2735 case GWL_HWNDPARENT
:
2736 return NtUserSetWindowLong(hWnd
, Index
, (UINT
)NewValue
, TRUE
);
2740 SetLastWin32Error(ERROR_INVALID_INDEX
);
2745 WindowObject
= IntGetWindowObject(hWnd
);
2746 if (WindowObject
== NULL
)
2748 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2752 if (Index
> WindowObject
->ExtraDataSize
- sizeof(WORD
))
2754 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2755 IntReleaseWindowObject(WindowObject
);
2759 OldValue
= *((WORD
*)(WindowObject
->ExtraData
+ Index
));
2760 *((WORD
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
2762 IntReleaseWindowObject(WindowObject
);
2771 NtUserGetWindowPlacement(HWND hWnd
,
2772 WINDOWPLACEMENT
*lpwndpl
)
2774 PWINDOW_OBJECT WindowObject
;
2775 PINTERNALPOS InternalPos
;
2777 WINDOWPLACEMENT Safepl
;
2780 WindowObject
= IntGetWindowObject(hWnd
);
2781 if (WindowObject
== NULL
)
2783 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2787 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
2788 if(!NT_SUCCESS(Status
))
2790 SetLastNtError(Status
);
2791 IntReleaseWindowObject(WindowObject
);
2794 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
2796 IntReleaseWindowObject(WindowObject
);
2801 Safepl
.showCmd
= ((WindowObject
->Flags
& WINDOWOBJECT_RESTOREMAX
) ? SW_MAXIMIZE
: SW_SHOWNORMAL
);
2803 Size
.x
= WindowObject
->WindowRect
.left
;
2804 Size
.y
= WindowObject
->WindowRect
.top
;
2805 InternalPos
= WinPosInitInternalPos(WindowObject
, Size
,
2806 &WindowObject
->WindowRect
);
2809 Safepl
.rcNormalPosition
= InternalPos
->NormalRect
;
2810 Safepl
.ptMinPosition
= InternalPos
->IconPos
;
2811 Safepl
.ptMaxPosition
= InternalPos
->MaxPos
;
2815 IntReleaseWindowObject(WindowObject
);
2819 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
2820 if(!NT_SUCCESS(Status
))
2822 SetLastNtError(Status
);
2823 IntReleaseWindowObject(WindowObject
);
2827 IntReleaseWindowObject(WindowObject
);
2833 * Return the dimension of the window in the screen coordinates.
2834 * \param hWnd window handle.
2835 * \param Rect pointer to the buffer where the coordinates are returned.
2841 NtUserGetWindowRect(HWND hWnd
, LPRECT Rect
)
2846 IntAcquireWinLockShared();
2847 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2849 IntReleaseWinLock();
2850 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2854 SafeRect
= Wnd
->WindowRect
;
2855 IntReleaseWinLock();
2857 if (! NT_SUCCESS(MmCopyToCaller(Rect
, &SafeRect
, sizeof(RECT
))))
2870 NtUserGetWindowThreadProcessId(HWND hWnd
, LPDWORD UnsafePid
)
2875 IntAcquireWinLockShared();
2877 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2879 IntReleaseWinLock();
2880 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2884 tid
= IntGetWindowThreadProcessId(Wnd
, &pid
);
2885 IntReleaseWinLock();
2887 if (UnsafePid
) MmCopyToCaller(UnsafePid
, &pid
, sizeof(DWORD
));
2897 NtUserLockWindowUpdate(DWORD Unknown0
)
2917 UINT flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
2920 flags
|= SWP_NOREDRAW
;
2921 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
, flags
);
2925 QueryWindow based on KJK::Hyperion and James Tabor.
2927 0 = QWUniqueProcessId
2928 1 = QWUniqueThreadId
2929 4 = QWIsHung Implements IsHungAppWindow found
2932 9 = QWKillWindow When I called this with hWnd ==
2933 DesktopWindow, it shutdown the system
2940 NtUserQueryWindow(HWND hWnd
, DWORD Index
)
2942 PWINDOW_OBJECT Window
= IntGetWindowObject(hWnd
);
2947 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2954 Result
= (DWORD
)Window
->OwnerThread
->ThreadsProcess
->UniqueProcessId
;
2958 Result
= (DWORD
)Window
->OwnerThread
->Cid
.UniqueThread
;
2962 Result
= (DWORD
)NULL
;
2966 IntReleaseWindowObject(Window
);
2976 NtUserRealChildWindowFromPoint(DWORD Unknown0
,
2990 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe
)
2993 PLIST_ENTRY Current
;
2994 PREGISTERED_MESSAGE NewMsg
, RegMsg
;
2995 UINT Msg
= REGISTERED_MESSAGE_MIN
;
2996 UNICODE_STRING MessageName
;
2999 Status
= MmCopyFromCaller(&MessageName
, MessageNameUnsafe
, sizeof(UNICODE_STRING
));
3000 if (! NT_SUCCESS(Status
))
3002 SetLastNtError(Status
);
3006 NewMsg
= ExAllocatePoolWithTag(PagedPool
,
3007 sizeof(REGISTERED_MESSAGE
) +
3012 SetLastNtError(STATUS_NO_MEMORY
);
3016 Status
= MmCopyFromCaller(NewMsg
->MessageName
, MessageName
.Buffer
, MessageName
.Length
);
3017 if (! NT_SUCCESS(Status
))
3020 SetLastNtError(Status
);
3023 NewMsg
->MessageName
[MessageName
.Length
/ sizeof(WCHAR
)] = L
'\0';
3024 if (wcslen(NewMsg
->MessageName
) != MessageName
.Length
/ sizeof(WCHAR
))
3027 SetLastNtError(STATUS_INVALID_PARAMETER
);
3031 Current
= RegisteredMessageListHead
.Flink
;
3032 while (Current
!= &RegisteredMessageListHead
)
3034 RegMsg
= CONTAINING_RECORD(Current
, REGISTERED_MESSAGE
, ListEntry
);
3035 if (0 == wcscmp(NewMsg
->MessageName
, RegMsg
->MessageName
))
3041 Current
= Current
->Flink
;
3044 if (REGISTERED_MESSAGE_MAX
< Msg
)
3047 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
3051 InsertTailList(&RegisteredMessageListHead
, &(NewMsg
->ListEntry
));
3057 * - There's no need to call MmSafe*, because it should be done in kernel.
3058 * - The passed UNICODE_STRING is expected to be NULL-terminated.
3060 return (UINT
)IntAddAtom(MessageNameUnsafe
->Buffer
);
3069 NtUserSetImeOwnerWindow(DWORD Unknown0
,
3082 NtUserSetInternalWindowPos(DWORD Unknown0
,
3098 NtUserSetLayeredWindowAttributes(DWORD Unknown0
,
3113 NtUserSetLogonNotifyWindow(DWORD Unknown0
)
3130 PWINDOW_OBJECT WindowObject
;
3133 WindowObject
= IntGetWindowObject((HWND
) Wnd
);
3134 if (NULL
== WindowObject
)
3136 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3140 if (! IntSetMenu(WindowObject
, Menu
, &Changed
))
3142 IntReleaseWindowObject(WindowObject
);
3146 IntReleaseWindowObject(WindowObject
);
3148 if (Changed
&& Repaint
)
3150 WinPosSetWindowPos(Wnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
3151 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
3162 NtUserSetWindowFNID(DWORD Unknown0
,
3176 NtUserSetWindowPlacement(HWND hWnd
,
3177 WINDOWPLACEMENT
*lpwndpl
)
3179 PWINDOW_OBJECT WindowObject
;
3180 WINDOWPLACEMENT Safepl
;
3183 WindowObject
= IntGetWindowObject(hWnd
);
3184 if (WindowObject
== NULL
)
3186 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3189 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3190 if(!NT_SUCCESS(Status
))
3192 SetLastNtError(Status
);
3193 IntReleaseWindowObject(WindowObject
);
3196 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3198 IntReleaseWindowObject(WindowObject
);
3202 if ((WindowObject
->Style
& (WS_MAXIMIZE
| WS_MINIMIZE
)) == 0)
3204 WinPosSetWindowPos(WindowObject
->Self
, NULL
,
3205 Safepl
.rcNormalPosition
.left
, Safepl
.rcNormalPosition
.top
,
3206 Safepl
.rcNormalPosition
.right
- Safepl
.rcNormalPosition
.left
,
3207 Safepl
.rcNormalPosition
.bottom
- Safepl
.rcNormalPosition
.top
,
3208 SWP_NOZORDER
| SWP_NOACTIVATE
);
3211 /* FIXME - change window status */
3212 WinPosShowWindow(WindowObject
->Self
, Safepl
.showCmd
);
3214 if (WindowObject
->InternalPos
== NULL
)
3215 WindowObject
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
3216 WindowObject
->InternalPos
->NormalRect
= Safepl
.rcNormalPosition
;
3217 WindowObject
->InternalPos
->IconPos
= Safepl
.ptMinPosition
;
3218 WindowObject
->InternalPos
->MaxPos
= Safepl
.ptMaxPosition
;
3220 IntReleaseWindowObject(WindowObject
);
3231 HWND hWndInsertAfter
,
3238 return WinPosSetWindowPos(hWnd
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3246 NtUserSetWindowRgn(DWORD Unknown0
,
3260 NtUserShowWindow(HWND hWnd
,
3263 return WinPosShowWindow(hWnd
, nCmdShow
);
3271 NtUserShowWindowAsync(DWORD Unknown0
,
3284 NtUserUpdateLayeredWindow(DWORD Unknown0
,
3304 NtUserValidateRect(HWND hWnd
, const RECT
* Rect
)
3306 return (VOID
)NtUserRedrawWindow(hWnd
, Rect
, 0, RDW_VALIDATE
| RDW_NOCHILDREN
);
3309 static BOOL
IsStaticClass(PWINDOW_OBJECT Window
)
3313 ASSERT(0 != Window
->Class
);
3314 ASSERT(0 != Window
->Class
->Atom
);
3316 DbgPrint("FIXME: Update IsStatic to really check if a window is a static\n");
3318 if (0 == wcscmp((LPWSTR)Window->Class->lpszClassName, L"Static"))
3324 static BOOL
IsDisabled(PWINDOW_OBJECT Window
)
3327 ASSERT(0 != Window
);
3329 rc
= (Window
->Style
& WS_DISABLED
);
3334 static PWINDOW_OBJECT
RestrictiveSearchChildWindows(PWINDOW_OBJECT Window
, POINT p
)
3336 PWINDOW_OBJECT ChildWindow
= 0;
3337 PWINDOW_OBJECT rc
= Window
;
3338 ASSERT(0 != Window
);
3341 **Aquire a mutex to the Child list.
3343 ExAcquireFastMutexUnsafe(&Window
->ChildrenListLock
);
3346 **Now Find the first non-static window.
3348 ChildWindow
= Window
->FirstChild
;
3350 while (0 != ChildWindow
)
3353 **Test Restrictions on the window.
3355 if (!IsStaticClass(ChildWindow
) &&
3356 !IsDisabled(ChildWindow
) &&
3357 IntIsWindowVisible(ChildWindow
->Self
))
3360 **Now find the deepest child window
3362 if (POINT_IN_RECT(p
, ChildWindow
->WindowRect
))
3364 rc
= RestrictiveSearchChildWindows(ChildWindow
, p
);
3368 ChildWindow
= ChildWindow
->NextSibling
;
3374 ExReleaseFastMutexUnsafe(&Window
->ChildrenListLock
);
3380 * NtUserWindowFromPoint
3383 * The return value is a handle to the window that contains the point.
3384 * If no window exists at the given point, the return value is NULL.
3385 * If the point is over a static text control, the return value is a handle
3386 * to the window under the static text control.
3389 * The WindowFromPoint function does not retrieve a handle to a hidden or
3390 * disabled window, even if the point is within the window. An application
3391 * should use the ChildWindowFromPoint function for a nonrestrictive search.
3401 NtUserWindowFromPoint(LONG X
, LONG Y
)
3404 PWINDOW_OBJECT DesktopWindow
= 0;
3405 PWINDOW_OBJECT TopWindow
= 0;
3406 PWINDOW_OBJECT ChildWindow
= 0;
3409 DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow());
3414 if (DesktopWindow
!= NULL
)
3417 * Aquire the mutex to the child window list. (All the topmost windows)
3419 ExAcquireFastMutexUnsafe(&DesktopWindow
->ChildrenListLock
);
3422 * Spin through the windows looking for the window that contains the
3423 * point. The child windows are in Z-order.
3425 TopWindow
= DesktopWindow
->FirstChild
;
3426 while (TopWindow
!= NULL
)
3428 if (POINT_IN_RECT(pt
, TopWindow
->WindowRect
))
3432 TopWindow
= TopWindow
->NextSibling
;
3436 * Search for the child window that contains the point.
3438 if (TopWindow
!= NULL
)
3440 ChildWindow
= RestrictiveSearchChildWindows(TopWindow
, pt
);
3441 if (ChildWindow
!= NULL
)
3443 hWnd
= ChildWindow
->Self
;
3450 ExReleaseFastMutexUnsafe(&DesktopWindow
->ChildrenListLock
);
3453 IntReleaseWindowObject(DesktopWindow
);
3462 * Undocumented function that is called from DefWindowProc to set
3465 * FIXME: Call this from user32.dll!
3472 NtUserDefSetText(HWND WindowHandle
, PANSI_STRING Text
)
3474 PWINDOW_OBJECT WindowObject
;
3475 UNICODE_STRING NewWindowName
;
3476 BOOL Result
= FALSE
;
3478 WindowObject
= IntGetWindowObject(WindowHandle
);
3481 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3485 if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&NewWindowName
, Text
, TRUE
)))
3487 RtlFreeUnicodeString(&WindowObject
->WindowName
);
3488 WindowObject
->WindowName
.Buffer
= NewWindowName
.Buffer
;
3489 WindowObject
->WindowName
.Length
= NewWindowName
.Length
;
3490 WindowObject
->WindowName
.MaximumLength
= NewWindowName
.MaximumLength
;
3494 IntReleaseWindowObject(WindowObject
);
3500 * NtUserInternalGetWindowText
3502 * FIXME: Call this from user32.dll!
3509 NtUserInternalGetWindowText(HWND WindowHandle
, LPWSTR Text
, INT MaxCount
)
3511 PWINDOW_OBJECT WindowObject
;
3514 WindowObject
= IntGetWindowObject(WindowHandle
);
3517 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3521 Result
= WindowObject
->WindowName
.Length
/ sizeof(WCHAR
);
3524 /* FIXME: Shouldn't it be always NULL terminated? */
3525 wcsncpy(Text
, WindowObject
->WindowName
.Buffer
, MaxCount
);
3526 if (MaxCount
< Result
)
3532 IntReleaseWindowObject(WindowObject
);
3538 NtUserDereferenceWndProcHandle(WNDPROC wpHandle
, WndProcHandle
*Data
)
3540 WndProcHandle Entry
;
3541 if (((DWORD
)wpHandle
& 0xFFFF0000) == 0xFFFF0000)
3543 Entry
= WndProcHandlesArray
[(DWORD
)wpHandle
& 0x0000FFFF];
3544 Data
->WindowProc
= Entry
.WindowProc
;
3545 Data
->IsUnicode
= Entry
.IsUnicode
;
3546 Data
->ProcessID
= Entry
.ProcessID
;
3555 IntAddWndProcHandle(WNDPROC WindowProc
, BOOL IsUnicode
)
3560 WndProcHandle
*OldArray
;
3563 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
3565 if (WndProcHandlesArray
[i
].WindowProc
== NULL
)
3573 OldArray
= WndProcHandlesArray
;
3574 OldArraySize
= WndProcHandlesArraySize
;
3575 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,(OldArraySize
+ WPH_SIZE
) * sizeof(WndProcHandle
), TAG_WINPROCLST
);
3576 WndProcHandlesArraySize
= OldArraySize
+ WPH_SIZE
;
3577 RtlCopyMemory(WndProcHandlesArray
,OldArray
,OldArraySize
* sizeof(WndProcHandle
));
3578 ExFreePool(OldArray
);
3579 FreeSpot
= OldArraySize
+ 1;
3581 WndProcHandlesArray
[FreeSpot
].WindowProc
= WindowProc
;
3582 WndProcHandlesArray
[FreeSpot
].IsUnicode
= IsUnicode
;
3583 WndProcHandlesArray
[FreeSpot
].ProcessID
= PsGetCurrentProcessId();
3584 return FreeSpot
+ 0xFFFF0000;
3588 IntRemoveWndProcHandle(WNDPROC Handle
)
3591 position
= (DWORD
)Handle
& 0x0000FFFF;
3592 if (position
> WndProcHandlesArraySize
)
3596 WndProcHandlesArray
[position
].WindowProc
= NULL
;
3597 WndProcHandlesArray
[position
].IsUnicode
= FALSE
;
3598 WndProcHandlesArray
[position
].ProcessID
= NULL
;
3603 IntRemoveProcessWndProcHandles(HANDLE ProcessID
)
3606 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
3608 if (WndProcHandlesArray
[i
].ProcessID
== ProcessID
)
3610 WndProcHandlesArray
[i
].WindowProc
= NULL
;
3611 WndProcHandlesArray
[i
].IsUnicode
= FALSE
;
3612 WndProcHandlesArray
[i
].ProcessID
= NULL
;