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.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
24 * FILE: subsys/win32k/ntuser/window.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
27 * 06-06-2001 CSH Created
29 /* INCLUDES ******************************************************************/
32 static WndProcHandle
*WndProcHandlesArray
= 0;
33 static WORD WndProcHandlesArraySize
= 0;
34 #define WPH_SIZE 0x40 /* the size to add to the WndProcHandle array each time */
36 /* dialog resources appear to pass this in 16 bits, handle them properly */
37 #define CW_USEDEFAULT16 (0x8000)
39 #define POINT_IN_RECT(p, r) (((r.bottom >= p.y) && (r.top <= p.y))&&((r.left <= p.x )&&( r.right >= p.x )))
41 /* PRIVATE FUNCTIONS **********************************************************/
46 * Initialize windowing implementation.
52 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,WPH_SIZE
* sizeof(WndProcHandle
), TAG_WINPROCLST
);
53 WndProcHandlesArraySize
= WPH_SIZE
;
54 return STATUS_SUCCESS
;
60 * Cleanup windowing implementation.
64 CleanupWindowImpl(VOID
)
66 ExFreePool(WndProcHandlesArray
);
67 WndProcHandlesArray
= 0;
68 WndProcHandlesArraySize
= 0;
69 return STATUS_SUCCESS
;
72 /* HELPER FUNCTIONS ***********************************************************/
77 * The function determines whether the specified window handle identifies
82 * Handle to the window to test.
85 * If the window handle identifies an existing window, the return value
86 * is TRUE. If the window handle does not identify an existing window,
87 * the return value is FALSE.
91 IntIsWindow(HWND hWnd
)
93 PWINDOW_OBJECT Window
;
95 if (!(Window
= IntGetWindowObject(hWnd
)))
98 IntReleaseWindowObject(Window
);
103 * IntGetProcessWindowObject
105 * Get window object from handle of specified process.
108 PWINDOW_OBJECT FASTCALL
109 IntGetProcessWindowObject(PW32THREAD Thread
, HWND hWnd
)
111 PWINDOW_OBJECT WindowObject
;
114 if(Thread
->Desktop
!= NULL
)
116 Status
= ObmReferenceObjectByHandle(Thread
->Desktop
->WindowStation
->HandleTable
,
117 hWnd
, otWindow
, (PVOID
*)&WindowObject
);
118 if (NT_SUCCESS(Status
))
127 PWINDOW_OBJECT FASTCALL
128 IntGetParent(PWINDOW_OBJECT Wnd
)
132 if (Wnd
->Style
& WS_POPUP
)
134 IntLockRelatives(Wnd
);
136 IntUnLockRelatives(Wnd
);
137 return IntGetWindowObject(hWnd
);
139 else if (Wnd
->Style
& WS_CHILD
)
141 IntLockRelatives(Wnd
);
143 IntUnLockRelatives(Wnd
);
144 return IntGetWindowObject(hWnd
);
151 PWINDOW_OBJECT FASTCALL
152 IntGetParentObject(PWINDOW_OBJECT Wnd
)
156 IntLockRelatives(Wnd
);
157 hParent
= Wnd
->Parent
;
158 IntUnLockRelatives(Wnd
);
159 return IntGetWindowObject(hParent
);
165 * Compile a list of all child window handles from given window.
168 * This function is similar to Wine WIN_ListChildren. The caller
169 * must free the returned list with ExFreePool.
173 IntWinListChildren(PWINDOW_OBJECT Window
)
175 PWINDOW_OBJECT Child
;
177 UINT Index
, NumChildren
= 0;
179 IntLockRelatives(Window
);
181 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
184 List
= ExAllocatePoolWithTag(PagedPool
, (NumChildren
+ 1) * sizeof(HWND
), TAG_WINLIST
);
187 DPRINT1("Failed to allocate memory for children array\n");
188 IntUnLockRelatives(Window
);
189 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
192 for (Child
= Window
->FirstChild
, Index
= 0;
194 Child
= Child
->NextSibling
, ++Index
)
195 List
[Index
] = Child
->Self
;
198 IntUnLockRelatives(Window
);
203 /***********************************************************************
206 static void IntSendDestroyMsg(HWND Wnd
)
211 if (GetGUIThreadInfo(GetCurrentThreadId(), &info
))
213 if (Wnd
== info
.hwndCaret
)
221 * Send the WM_DESTROY to the window.
223 IntSendMessage(Wnd
, WM_DESTROY
, 0, 0);
226 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
227 * make sure that the window still exists when we come back.
235 if (!(pWndArray
= WIN_ListChildren( hwnd
))) return;
237 /* start from the end (FIXME: is this needed?) */
238 for (i
= 0; pWndArray
[i
]; i
++) ;
242 if (IsWindow( pWndArray
[i
] )) WIN_SendDestroyMsg( pWndArray
[i
] );
244 HeapFree(GetProcessHeap(), 0, pWndArray
);
248 DPRINT("destroyed itself while in WM_DESTROY!\n");
253 /***********************************************************************
256 * Destroy storage associated to a window. "Internals" p.358
258 static LRESULT
IntDestroyWindow(PWINDOW_OBJECT Window
,
259 PW32PROCESS ProcessData
,
260 PW32THREAD ThreadData
,
261 BOOLEAN SendMessages
)
265 PWINDOW_OBJECT Child
;
267 BOOLEAN BelongsToThreadData
;
271 IntLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
272 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
274 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
275 DPRINT("Tried to call IntDestroyWindow() twice\n");
278 Window
->Status
|= WINDOWSTATUS_DESTROYING
;
279 Window
->Flags
&= ~WS_VISIBLE
;
280 /* remove the window already at this point from the thread window list so we
281 don't get into trouble when destroying the thread windows while we're still
282 in IntDestroyWindow() */
283 RemoveEntryList(&Window
->ThreadListEntry
);
284 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
286 BelongsToThreadData
= IntWndBelongsToThread(Window
, ThreadData
);
290 /* Send destroy messages */
291 IntSendDestroyMsg(Window
->Self
);
294 /* free child windows */
295 Children
= IntWinListChildren(Window
);
298 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
300 if ((Child
= IntGetWindowObject(*ChildHandle
)))
302 if(!IntWndBelongsToThread(Child
, ThreadData
))
304 /* send WM_DESTROY messages to windows not belonging to the same thread */
305 IntSendDestroyMsg(Child
->Self
);
308 IntDestroyWindow(Child
, ProcessData
, ThreadData
, SendMessages
);
309 IntReleaseWindowObject(Child
);
312 ExFreePool(Children
);
318 * Clear the update region to make sure no WM_PAINT messages will be
319 * generated for this window while processing the WM_NCDESTROY.
321 IntRedrawWindow(Window
, NULL
, 0,
322 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
|
323 RDW_NOINTERNALPAINT
| RDW_NOCHILDREN
);
324 if(BelongsToThreadData
)
325 IntSendMessage(Window
->Self
, WM_NCDESTROY
, 0, 0);
327 MsqRemoveTimersWindow(ThreadData
->MessageQueue
, Window
->Self
);
329 /* flush the message queue */
330 MsqRemoveWindowMessagesFromQueue(Window
);
332 /* from now on no messages can be sent to this window anymore */
333 IntLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
334 Window
->Status
|= WINDOWSTATUS_DESTROYED
;
335 /* don't remove the WINDOWSTATUS_DESTROYING bit */
336 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
338 /* reset shell window handles */
339 if(ThreadData
->Desktop
)
341 if (Window
->Self
== ThreadData
->Desktop
->WindowStation
->ShellWindow
)
342 ThreadData
->Desktop
->WindowStation
->ShellWindow
= NULL
;
344 if (Window
->Self
== ThreadData
->Desktop
->WindowStation
->ShellListView
)
345 ThreadData
->Desktop
->WindowStation
->ShellListView
= NULL
;
348 /* Unregister hot keys */
349 UnregisterWindowHotKeys (Window
);
351 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
354 WinPosCheckInternalPos(Window
->Self
);
355 if (Window
->Self
== GetCapture())
360 /* free resources associated with the window */
361 TIMER_RemoveWindowTimers(Window
->Self
);
364 if (!(Window
->Style
& WS_CHILD
) && Window
->IDMenu
365 && (Menu
= IntGetMenuObject((HMENU
)Window
->IDMenu
)))
367 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
369 IntReleaseMenuObject(Menu
);
372 if(Window
->SystemMenu
373 && (Menu
= IntGetMenuObject(Window
->SystemMenu
)))
375 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
376 Window
->SystemMenu
= (HMENU
)0;
377 IntReleaseMenuObject(Menu
);
380 DceFreeWindowDCE(Window
); /* Always do this to catch orphaned DCs */
382 WINPROC_FreeProc(Window
->winproc
, WIN_PROC_WINDOW
);
383 CLASS_RemoveWindow(Window
->Class
);
386 IntUnlinkWindow(Window
);
388 IntReferenceWindowObject(Window
);
389 ObmCloseHandle(ThreadData
->Desktop
->WindowStation
->HandleTable
, Window
->Self
);
391 IntDestroyScrollBars(Window
);
393 /* remove the window from the class object */
394 IntLockClassWindows(Window
->Class
);
395 RemoveEntryList(&Window
->ClassListEntry
);
396 IntUnLockClassWindows(Window
->Class
);
398 /* dereference the class */
399 ClassDereferenceObject(Window
->Class
);
400 Window
->Class
= NULL
;
402 if(Window
->WindowRegion
)
404 NtGdiDeleteObject(Window
->WindowRegion
);
407 RtlFreeUnicodeString(&Window
->WindowName
);
409 IntReleaseWindowObject(Window
);
415 IntGetWindowBorderMeasures(PWINDOW_OBJECT WindowObject
, UINT
*cx
, UINT
*cy
)
417 if(HAS_DLGFRAME(WindowObject
->Style
, WindowObject
->ExStyle
) && !(WindowObject
->Style
& WS_MINIMIZE
))
419 *cx
= NtUserGetSystemMetrics(SM_CXDLGFRAME
);
420 *cy
= NtUserGetSystemMetrics(SM_CYDLGFRAME
);
424 if(HAS_THICKFRAME(WindowObject
->Style
, WindowObject
->ExStyle
)&& !(WindowObject
->Style
& WS_MINIMIZE
))
426 *cx
= NtUserGetSystemMetrics(SM_CXFRAME
);
427 *cy
= NtUserGetSystemMetrics(SM_CYFRAME
);
429 else if(HAS_THINFRAME(WindowObject
->Style
, WindowObject
->ExStyle
))
431 *cx
= NtUserGetSystemMetrics(SM_CXBORDER
);
432 *cy
= NtUserGetSystemMetrics(SM_CYBORDER
);
442 IntGetWindowInfo(PWINDOW_OBJECT WindowObject
, PWINDOWINFO pwi
)
444 pwi
->cbSize
= sizeof(WINDOWINFO
);
445 pwi
->rcWindow
= WindowObject
->WindowRect
;
446 pwi
->rcClient
= WindowObject
->ClientRect
;
447 pwi
->dwStyle
= WindowObject
->Style
;
448 pwi
->dwExStyle
= WindowObject
->ExStyle
;
449 pwi
->dwWindowStatus
= (NtUserGetForegroundWindow() == WindowObject
->Self
); /* WS_ACTIVECAPTION */
450 IntGetWindowBorderMeasures(WindowObject
, &pwi
->cxWindowBorders
, &pwi
->cyWindowBorders
);
451 pwi
->atomWindowType
= (WindowObject
->Class
? WindowObject
->Class
->Atom
: 0);
452 pwi
->wCreatorVersion
= 0x400; /* FIXME - return a real version number */
458 PWINDOW_OBJECT WindowObject
,
462 PMENU_OBJECT OldMenuObject
, NewMenuObject
= NULL
;
464 *Changed
= (WindowObject
->IDMenu
!= (UINT
) Menu
);
470 if (0 != WindowObject
->IDMenu
)
472 OldMenuObject
= IntGetMenuObject((HMENU
) WindowObject
->IDMenu
);
473 ASSERT(NULL
== OldMenuObject
|| OldMenuObject
->MenuInfo
.Wnd
== WindowObject
->Self
);
477 OldMenuObject
= NULL
;
482 NewMenuObject
= IntGetMenuObject(Menu
);
483 if (NULL
== NewMenuObject
)
485 if (NULL
!= OldMenuObject
)
487 IntReleaseMenuObject(OldMenuObject
);
489 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
492 if (NULL
!= NewMenuObject
->MenuInfo
.Wnd
)
494 /* Can't use the same menu for two windows */
495 if (NULL
!= OldMenuObject
)
497 IntReleaseMenuObject(OldMenuObject
);
499 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
505 WindowObject
->IDMenu
= (UINT
) Menu
;
506 if (NULL
!= NewMenuObject
)
508 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
509 IntReleaseMenuObject(NewMenuObject
);
511 if (NULL
!= OldMenuObject
)
513 OldMenuObject
->MenuInfo
.Wnd
= NULL
;
514 IntReleaseMenuObject(OldMenuObject
);
521 /* INTERNAL ******************************************************************/
525 DestroyThreadWindows(struct _ETHREAD
*Thread
)
528 PW32PROCESS Win32Process
;
529 PW32THREAD Win32Thread
;
530 PWINDOW_OBJECT
*List
, *pWnd
;
533 Win32Thread
= Thread
->Tcb
.Win32Thread
;
534 Win32Process
= Thread
->ThreadsProcess
->Win32Process
;
536 IntLockThreadWindows(Win32Thread
);
537 Current
= Win32Thread
->WindowListHead
.Flink
;
538 while (Current
!= &(Win32Thread
->WindowListHead
))
541 Current
= Current
->Flink
;
546 List
= ExAllocatePool(PagedPool
, (Cnt
+ 1) * sizeof(PWINDOW_OBJECT
));
549 DPRINT("Not enough memory to allocate window handle list\n");
550 IntUnLockThreadWindows(Win32Thread
);
554 Current
= Win32Thread
->WindowListHead
.Flink
;
555 while (Current
!= &(Win32Thread
->WindowListHead
))
557 *pWnd
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
558 IntReferenceWindowObject(*pWnd
);
560 Current
= Current
->Flink
;
562 IntUnLockThreadWindows(Win32Thread
);
565 for(pWnd
= List
; *pWnd
; pWnd
++)
567 NtUserDestroyWindow((*pWnd
)->Self
);
568 IntReleaseWindowObject(*pWnd
);
574 IntUnLockThreadWindows(Win32Thread
);
580 * Returns client window rectangle relative to the upper-left corner of client area.
582 * \note Does not check the validity of the parameters
585 IntGetClientRect(PWINDOW_OBJECT WindowObject
, PRECT Rect
)
587 ASSERT( WindowObject
);
590 Rect
->left
= Rect
->top
= 0;
591 Rect
->right
= WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
;
592 Rect
->bottom
= WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
;
598 IntGetFocusWindow(VOID
)
600 PUSER_MESSAGE_QUEUE Queue
;
601 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
606 Queue
= (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
611 return(Queue
->FocusWindow
);
615 PMENU_OBJECT FASTCALL
616 IntGetSystemMenu(PWINDOW_OBJECT WindowObject
, BOOL bRevert
, BOOL RetMenu
)
618 PMENU_OBJECT MenuObject
, NewMenuObject
, SysMenuObject
, ret
= NULL
;
619 PW32THREAD W32Thread
;
620 HMENU NewMenu
, SysMenu
;
621 ROSMENUITEMINFO ItemInfo
;
625 W32Thread
= PsGetWin32Thread();
627 if(!W32Thread
->Desktop
)
630 if(WindowObject
->SystemMenu
)
632 MenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
635 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
636 WindowObject
->SystemMenu
= (HMENU
)0;
637 IntReleaseMenuObject(MenuObject
);
641 if(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
)
643 /* clone system menu */
644 MenuObject
= IntGetMenuObject(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
);
648 NewMenuObject
= IntCloneMenu(MenuObject
);
651 WindowObject
->SystemMenu
= NewMenuObject
->MenuInfo
.Self
;
652 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
653 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
655 //IntReleaseMenuObject(NewMenuObject);
657 IntReleaseMenuObject(MenuObject
);
661 SysMenu
= NtUserCreateMenu(FALSE
);
666 SysMenuObject
= IntGetMenuObject(SysMenu
);
667 if (NULL
== SysMenuObject
)
669 NtUserDestroyMenu(SysMenu
);
672 SysMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
673 SysMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
674 NewMenu
= IntLoadSysMenuTemplate();
677 IntReleaseMenuObject(SysMenuObject
);
678 NtUserDestroyMenu(SysMenu
);
681 MenuObject
= IntGetMenuObject(NewMenu
);
684 IntReleaseMenuObject(SysMenuObject
);
685 NtUserDestroyMenu(SysMenu
);
689 NewMenuObject
= IntCloneMenu(MenuObject
);
692 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
| MF_POPUP
;
693 IntReleaseMenuObject(NewMenuObject
);
694 NtUserSetMenuDefaultItem(NewMenuObject
->MenuInfo
.Self
, SC_CLOSE
, FALSE
);
696 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
697 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
698 ItemInfo
.fType
= MF_POPUP
;
699 ItemInfo
.fState
= MFS_ENABLED
;
700 ItemInfo
.dwTypeData
= NULL
;
702 ItemInfo
.hSubMenu
= NewMenuObject
->MenuInfo
.Self
;
703 IntInsertMenuItem(SysMenuObject
, (UINT
) -1, TRUE
, &ItemInfo
);
705 WindowObject
->SystemMenu
= SysMenuObject
->MenuInfo
.Self
;
709 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
710 IntReleaseMenuObject(MenuObject
);
719 if(WindowObject
->SystemMenu
)
720 return IntGetMenuObject((HMENU
)WindowObject
->SystemMenu
);
728 IntIsChildWindow(HWND Parent
, HWND Child
)
730 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
732 if(!(BaseWindow
= IntGetWindowObject(Child
)))
740 if (Window
->Self
== Parent
)
742 if(Window
!= BaseWindow
)
743 IntReleaseWindowObject(Window
);
744 IntReleaseWindowObject(BaseWindow
);
747 if(!(Window
->Style
& WS_CHILD
))
749 if(Window
!= BaseWindow
)
750 IntReleaseWindowObject(Window
);
754 Window
= IntGetParentObject(Window
);
755 if(Old
!= BaseWindow
)
756 IntReleaseWindowObject(Old
);
759 IntReleaseWindowObject(BaseWindow
);
764 IntIsWindowVisible(HWND hWnd
)
766 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
768 if(!(BaseWindow
= IntGetWindowObject(hWnd
)))
776 if(!(Window
->Style
& WS_CHILD
))
780 if(!(Window
->Style
& WS_VISIBLE
))
782 if(Window
!= BaseWindow
)
783 IntReleaseWindowObject(Window
);
784 IntReleaseWindowObject(BaseWindow
);
788 Window
= IntGetParentObject(Window
);
789 if(Old
!= BaseWindow
)
790 IntReleaseWindowObject(Old
);
795 if(Window
->Style
& WS_VISIBLE
)
797 if(Window
!= BaseWindow
)
798 IntReleaseWindowObject(Window
);
799 IntReleaseWindowObject(BaseWindow
);
802 if(Window
!= BaseWindow
)
803 IntReleaseWindowObject(Window
);
805 IntReleaseWindowObject(BaseWindow
);
810 /* link the window into siblings and parent. children are kept in place. */
814 PWINDOW_OBJECT WndParent
,
815 PWINDOW_OBJECT WndPrevSibling
/* set to NULL if top sibling */
818 PWINDOW_OBJECT Parent
;
820 IntLockRelatives(Wnd
);
821 Wnd
->Parent
= WndParent
->Self
;
822 if ((Wnd
->PrevSibling
= WndPrevSibling
))
824 /* link after WndPrevSibling */
825 if ((Wnd
->NextSibling
= WndPrevSibling
->NextSibling
))
826 Wnd
->NextSibling
->PrevSibling
= Wnd
;
827 else if ((Parent
= IntGetWindowObject(Wnd
->Parent
)))
829 IntLockRelatives(Parent
);
830 if(Parent
->LastChild
== WndPrevSibling
)
831 Parent
->LastChild
= Wnd
;
832 IntUnLockRelatives(Parent
);
833 IntReleaseWindowObject(Parent
);
835 Wnd
->PrevSibling
->NextSibling
= Wnd
;
840 Parent
= IntGetWindowObject(Wnd
->Parent
);
841 if ((Wnd
->NextSibling
= WndParent
->FirstChild
))
842 Wnd
->NextSibling
->PrevSibling
= Wnd
;
845 IntLockRelatives(Parent
);
846 Parent
->LastChild
= Wnd
;
847 Parent
->FirstChild
= Wnd
;
848 IntUnLockRelatives(Parent
);
849 IntReleaseWindowObject(Parent
);
850 IntUnLockRelatives(Wnd
);
855 IntLockRelatives(Parent
);
856 Parent
->FirstChild
= Wnd
;
857 IntUnLockRelatives(Parent
);
858 IntReleaseWindowObject(Parent
);
861 IntUnLockRelatives(Wnd
);
865 IntSetOwner(HWND hWnd
, HWND hWndNewOwner
)
867 PWINDOW_OBJECT Wnd
, WndOldOwner
, WndNewOwner
;
870 Wnd
= IntGetWindowObject(hWnd
);
874 IntLockRelatives(Wnd
);
875 WndOldOwner
= IntGetWindowObject(Wnd
->Owner
);
878 ret
= WndOldOwner
->Self
;
879 IntReleaseWindowObject(WndOldOwner
);
886 if((WndNewOwner
= IntGetWindowObject(hWndNewOwner
)))
888 Wnd
->Owner
= hWndNewOwner
;
889 IntReleaseWindowObject(WndNewOwner
);
894 IntUnLockRelatives(Wnd
);
895 IntReleaseWindowObject(Wnd
);
899 PWINDOW_OBJECT FASTCALL
900 IntSetParent(PWINDOW_OBJECT Wnd
, PWINDOW_OBJECT WndNewParent
)
902 PWINDOW_OBJECT WndOldParent
, Sibling
, InsertAfter
;
903 HWND hWnd
, hWndNewParent
, hWndOldParent
;
908 ASSERT(WndNewParent
);
911 hWndNewParent
= WndNewParent
->Self
;
914 * Windows hides the window first, then shows it again
915 * including the WM_SHOWWINDOW messages and all
917 WasVisible
= WinPosShowWindow(hWnd
, SW_HIDE
);
919 /* Validate that window and parent still exist */
920 if (!IntIsWindow(hWnd
) || !IntIsWindow(hWndNewParent
))
923 /* Window must belong to current process */
924 if (Wnd
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
927 WndOldParent
= IntGetParentObject(Wnd
);
928 hWndOldParent
= (WndOldParent
? WndOldParent
->Self
: NULL
);
930 if (WndNewParent
!= WndOldParent
)
932 IntUnlinkWindow(Wnd
);
934 if (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
))
936 /* Not a TOPMOST window, put after TOPMOSTs of new parent */
937 IntLockRelatives(WndNewParent
);
938 Sibling
= WndNewParent
->FirstChild
;
939 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
941 InsertAfter
= Sibling
;
942 Sibling
= Sibling
->NextSibling
;
944 IntUnLockRelatives(WndNewParent
);
946 if (NULL
== InsertAfter
)
948 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
952 IntReferenceWindowObject(InsertAfter
);
953 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
954 IntReleaseWindowObject(InsertAfter
);
957 if (WndNewParent
->Self
!= IntGetDesktopWindow()) /* a child window */
959 if (!(Wnd
->Style
& WS_CHILD
))
961 //if ( Wnd->Menu ) DestroyMenu ( Wnd->menu );
962 IntSetMenu(Wnd
, NULL
, &MenuChanged
);
968 * SetParent additionally needs to make hwnd the top window
969 * in the z-order and send the expected WM_WINDOWPOSCHANGING and
970 * WM_WINDOWPOSCHANGED notification messages.
972 WinPosSetWindowPos(hWnd
, (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOP
: HWND_TOPMOST
),
973 0, 0, 0, 0, SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
974 | (WasVisible
? SWP_SHOWWINDOW
: 0));
977 * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
978 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
982 * Validate that the old parent still exist, since it migth have been
983 * destroyed during the last callbacks to user-mode
987 if(!IntIsWindow(WndOldParent
->Self
))
989 IntReleaseWindowObject(WndOldParent
);
993 /* don't dereference the window object here, it must be done by the caller
1001 IntSetSystemMenu(PWINDOW_OBJECT WindowObject
, PMENU_OBJECT MenuObject
)
1003 PMENU_OBJECT OldMenuObject
;
1004 if(WindowObject
->SystemMenu
)
1006 OldMenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
1009 OldMenuObject
->MenuInfo
.Flags
&= ~ MF_SYSMENU
;
1010 IntReleaseMenuObject(OldMenuObject
);
1016 /* FIXME check window style, propably return FALSE ? */
1017 WindowObject
->SystemMenu
= MenuObject
->MenuInfo
.Self
;
1018 MenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
1021 WindowObject
->SystemMenu
= (HMENU
)0;
1027 /* unlink the window from siblings and parent. children are kept in place. */
1029 IntUnlinkWindow(PWINDOW_OBJECT Wnd
)
1031 PWINDOW_OBJECT WndParent
;
1033 IntLockRelatives(Wnd
);
1034 if((WndParent
= IntGetWindowObject(Wnd
->Parent
)))
1036 IntLockRelatives(WndParent
);
1039 if (Wnd
->NextSibling
) Wnd
->NextSibling
->PrevSibling
= Wnd
->PrevSibling
;
1040 else if (WndParent
&& WndParent
->LastChild
== Wnd
) WndParent
->LastChild
= Wnd
->PrevSibling
;
1042 if (Wnd
->PrevSibling
) Wnd
->PrevSibling
->NextSibling
= Wnd
->NextSibling
;
1043 else if (WndParent
&& WndParent
->FirstChild
== Wnd
) WndParent
->FirstChild
= Wnd
->NextSibling
;
1047 IntUnLockRelatives(WndParent
);
1048 IntReleaseWindowObject(WndParent
);
1050 Wnd
->PrevSibling
= Wnd
->NextSibling
= Wnd
->Parent
= NULL
;
1051 IntUnLockRelatives(Wnd
);
1057 PWINDOW_OBJECT Window
, Child
;
1059 if(!(Window
= IntGetWindowObject(IntGetDesktopWindow())))
1061 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1065 IntLockRelatives(Window
);
1066 for(Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
1068 if(Child
->Owner
&& Child
->Style
& WS_VISIBLE
)
1071 * The desktop has a popup window if one of them has
1072 * an owner window and is visible
1074 IntUnLockRelatives(Window
);
1075 IntReleaseWindowObject(Window
);
1079 IntUnLockRelatives(Window
);
1080 IntReleaseWindowObject(Window
);
1085 IntIsWindowInDestroy(PWINDOW_OBJECT Window
)
1087 return ((Window
->Status
& WINDOWSTATUS_DESTROYING
) == WINDOWSTATUS_DESTROYING
);
1090 /* FUNCTIONS *****************************************************************/
1096 NtUserAlterWindowStyle(DWORD Unknown0
,
1107 * As best as I can figure, this function is used by EnumWindows,
1108 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
1110 * It's supposed to build a list of HWNDs to return to the caller.
1111 * We can figure out what kind of list by what parameters are
1119 NtUserBuildHwndList(
1131 /* FIXME handle bChildren */
1135 PWINDOW_OBJECT Window
, Child
;
1136 if(!(Window
= IntGetWindowObject(hwndParent
)))
1138 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1142 IntLockRelatives(Window
);
1143 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1145 if(dwCount
++ < nBufSize
&& pWnd
)
1147 Status
= MmCopyToCaller(pWnd
++, &Child
->Self
, sizeof(HWND
));
1148 if(!NT_SUCCESS(Status
))
1150 SetLastNtError(Status
);
1155 IntUnLockRelatives(Window
);
1157 IntReleaseWindowObject(Window
);
1162 PW32THREAD W32Thread
;
1163 PLIST_ENTRY Current
;
1164 PWINDOW_OBJECT Window
;
1166 Status
= PsLookupThreadByThreadId((HANDLE
)dwThreadId
, &Thread
);
1167 if(!NT_SUCCESS(Status
))
1169 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1172 if(!(W32Thread
= Thread
->Tcb
.Win32Thread
))
1174 ObDereferenceObject(Thread
);
1175 DPRINT("Thread is not a GUI Thread!\n");
1176 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1180 IntLockThreadWindows(W32Thread
);
1181 Current
= W32Thread
->WindowListHead
.Flink
;
1182 while(Current
!= &(W32Thread
->WindowListHead
))
1184 Window
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
1187 if(dwCount
< nBufSize
&& pWnd
)
1189 Status
= MmCopyToCaller(pWnd
++, &Window
->Self
, sizeof(HWND
));
1190 if(!NT_SUCCESS(Status
))
1192 SetLastNtError(Status
);
1197 Current
= Current
->Flink
;
1199 IntUnLockThreadWindows(W32Thread
);
1201 ObDereferenceObject(Thread
);
1205 PDESKTOP_OBJECT Desktop
;
1206 PWINDOW_OBJECT Window
, Child
;
1208 if(hDesktop
== NULL
&& !(Desktop
= IntGetActiveDesktop()))
1210 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1216 Status
= IntValidateDesktopHandle(hDesktop
,
1220 if(!NT_SUCCESS(Status
))
1222 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1226 if(!(Window
= IntGetWindowObject(Desktop
->DesktopWindow
)))
1229 ObDereferenceObject(Desktop
);
1230 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1234 IntLockRelatives(Window
);
1235 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1237 if(dwCount
++ < nBufSize
&& pWnd
)
1239 Status
= MmCopyToCaller(pWnd
++, &Child
->Self
, sizeof(HWND
));
1240 if(!NT_SUCCESS(Status
))
1242 SetLastNtError(Status
);
1247 IntUnLockRelatives(Window
);
1249 IntReleaseWindowObject(Window
);
1251 ObDereferenceObject(Desktop
);
1262 NtUserChildWindowFromPointEx(HWND hwndParent
,
1267 PWINDOW_OBJECT Parent
;
1272 if(!(Parent
= IntGetWindowObject(hwndParent
)))
1274 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1281 if(Parent
->Self
!= IntGetDesktopWindow())
1283 Pt
.x
+= Parent
->ClientRect
.left
;
1284 Pt
.y
+= Parent
->ClientRect
.top
;
1287 if(!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
))
1289 IntReleaseWindowObject(Parent
);
1294 if((List
= IntWinListChildren(Parent
)))
1296 for(phWnd
= List
; *phWnd
; phWnd
++)
1298 PWINDOW_OBJECT Child
;
1299 if((Child
= IntGetWindowObject(*phWnd
)))
1301 if(!(Child
->Style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
))
1303 IntReleaseWindowObject(Child
);
1306 if((Child
->Style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
))
1308 IntReleaseWindowObject(Child
);
1311 if((Child
->ExStyle
& WS_EX_TRANSPARENT
) && (uiFlags
& CWP_SKIPTRANSPARENT
))
1313 IntReleaseWindowObject(Child
);
1316 if(IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
1319 IntReleaseWindowObject(Child
);
1322 IntReleaseWindowObject(Child
);
1328 IntReleaseWindowObject(Parent
);
1334 * calculates the default position of a window
1337 IntCalcDefPosSize(PWINDOW_OBJECT Parent
, PWINDOW_OBJECT WindowObject
, RECT
*rc
, BOOL IncPos
)
1344 IntGdiIntersectRect(rc
, rc
, &Parent
->ClientRect
);
1348 Pos
.x
= Parent
->TiledCounter
* (NtUserGetSystemMetrics(SM_CXSIZE
) + NtUserGetSystemMetrics(SM_CXFRAME
));
1349 Pos
.y
= Parent
->TiledCounter
* (NtUserGetSystemMetrics(SM_CYSIZE
) + NtUserGetSystemMetrics(SM_CYFRAME
));
1350 if(Pos
.x
> ((rc
->right
- rc
->left
) / 4) ||
1351 Pos
.y
> ((rc
->bottom
- rc
->top
) / 4))
1353 /* reset counter and position */
1356 Parent
->TiledCounter
= 0;
1358 Parent
->TiledCounter
++;
1369 Sz
.cx
= EngMulDiv(rc
->right
- rc
->left
, 3, 4);
1370 Sz
.cy
= EngMulDiv(rc
->bottom
- rc
->top
, 3, 4);
1374 rc
->right
= rc
->left
+ Sz
.cx
;
1375 rc
->bottom
= rc
->top
+ Sz
.cy
;
1384 IntCreateWindowEx(DWORD dwExStyle
,
1385 PUNICODE_STRING ClassName
,
1386 PUNICODE_STRING WindowName
,
1394 HINSTANCE hInstance
,
1397 BOOL bUnicodeWindow
)
1399 PWINSTATION_OBJECT WinStaObject
;
1400 PWNDCLASS_OBJECT ClassObject
;
1401 PWINDOW_OBJECT WindowObject
;
1402 PWINDOW_OBJECT ParentWindow
, OwnerWindow
;
1403 HWND ParentWindowHandle
;
1404 HWND OwnerWindowHandle
;
1405 PMENU_OBJECT SystemMenu
;
1410 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1415 CBT_CREATEWNDW CbtCreate
;
1420 ParentWindowHandle
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
1421 OwnerWindowHandle
= NULL
;
1423 if (hWndParent
== HWND_MESSAGE
)
1426 * native ole32.OleInitialize uses HWND_MESSAGE to create the
1427 * message window (style: WS_POPUP|WS_DISABLED)
1429 DPRINT1("FIXME - Parent is HWND_MESSAGE\n");
1431 else if (hWndParent
)
1433 if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1434 ParentWindowHandle
= hWndParent
;
1436 OwnerWindowHandle
= NtUserGetAncestor(hWndParent
, GA_ROOT
);
1438 else if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1440 return (HWND
)0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1443 if (NULL
!= ParentWindowHandle
)
1445 ParentWindow
= IntGetWindowObject(ParentWindowHandle
);
1449 ParentWindow
= NULL
;
1452 /* FIXME: parent must belong to the current process */
1454 /* Check the class. */
1455 ClassFound
= ClassReferenceClassByNameOrAtom(&ClassObject
, ClassName
->Buffer
, hInstance
);
1458 if (IS_ATOM(ClassName
->Buffer
))
1460 DPRINT1("Class 0x%x not found\n", (DWORD_PTR
) ClassName
->Buffer
);
1464 DPRINT1("Class %wZ not found\n", ClassName
);
1466 if (NULL
!= ParentWindow
)
1468 IntReleaseWindowObject(ParentWindow
);
1470 SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS
);
1474 /* Check the window station. */
1475 if (PsGetWin32Thread()->Desktop
== NULL
)
1477 ClassDereferenceObject(ClassObject
);
1478 if (NULL
!= ParentWindow
)
1480 IntReleaseWindowObject(ParentWindow
);
1482 DPRINT("Thread is not attached to a desktop! Cannot create window!\n");
1485 WinStaObject
= PsGetWin32Thread()->Desktop
->WindowStation
;
1486 ObReferenceObjectByPointer(WinStaObject
, KernelMode
, ExWindowStationObjectType
, 0);
1488 /* Create the window object. */
1489 WindowObject
= (PWINDOW_OBJECT
)
1490 ObmCreateObject(PsGetWin32Thread()->Desktop
->WindowStation
->HandleTable
, &Handle
,
1491 otWindow
, sizeof(WINDOW_OBJECT
) + ClassObject
->cbWndExtra
1494 DPRINT("Created object with handle %X\n", Handle
);
1497 ObDereferenceObject(WinStaObject
);
1498 ClassDereferenceObject(ClassObject
);
1499 if (NULL
!= ParentWindow
)
1501 IntReleaseWindowObject(ParentWindow
);
1503 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1506 ObDereferenceObject(WinStaObject
);
1508 if (NULL
== PsGetWin32Thread()->Desktop
->DesktopWindow
)
1510 /* If there is no desktop window yet, we must be creating it */
1511 PsGetWin32Thread()->Desktop
->DesktopWindow
= Handle
;
1515 * Fill out the structure describing it.
1517 WindowObject
->Class
= ClassObject
;
1518 IntLockClassWindows(ClassObject
);
1519 InsertTailList(&ClassObject
->ClassWindowsListHead
, &WindowObject
->ClassListEntry
);
1520 IntUnLockClassWindows(ClassObject
);
1522 WindowObject
->ExStyle
= dwExStyle
;
1523 WindowObject
->Style
= dwStyle
& ~WS_VISIBLE
;
1524 DPRINT("1: Style is now %lx\n", WindowObject
->Style
);
1526 WindowObject
->SystemMenu
= (HMENU
)0;
1527 WindowObject
->ContextHelpId
= 0;
1528 WindowObject
->IDMenu
= 0;
1529 WindowObject
->Instance
= hInstance
;
1530 WindowObject
->Self
= Handle
;
1531 if (0 != (dwStyle
& WS_CHILD
))
1533 WindowObject
->IDMenu
= (UINT
) hMenu
;
1537 IntSetMenu(WindowObject
, hMenu
, &MenuChanged
);
1539 WindowObject
->MessageQueue
= PsGetWin32Thread()->MessageQueue
;
1540 WindowObject
->Parent
= (ParentWindow
? ParentWindow
->Self
: NULL
);
1541 if((OwnerWindow
= IntGetWindowObject(OwnerWindowHandle
)))
1543 WindowObject
->Owner
= OwnerWindowHandle
;
1544 IntReleaseWindowObject(OwnerWindow
);
1547 WindowObject
->Owner
= NULL
;
1548 WindowObject
->UserData
= 0;
1549 if ((((DWORD
)ClassObject
->lpfnWndProcA
& 0xFFFF0000) != 0xFFFF0000)
1550 && (((DWORD
)ClassObject
->lpfnWndProcW
& 0xFFFF0000) != 0xFFFF0000))
1552 WindowObject
->Unicode
= bUnicodeWindow
;
1556 WindowObject
->Unicode
= ClassObject
->Unicode
;
1558 WindowObject
->WndProcA
= ClassObject
->lpfnWndProcA
;
1559 WindowObject
->WndProcW
= ClassObject
->lpfnWndProcW
;
1560 WindowObject
->OwnerThread
= PsGetCurrentThread();
1561 WindowObject
->FirstChild
= NULL
;
1562 WindowObject
->LastChild
= NULL
;
1563 WindowObject
->PrevSibling
= NULL
;
1564 WindowObject
->NextSibling
= NULL
;
1566 /* extra window data */
1567 if (ClassObject
->cbWndExtra
!= 0)
1569 WindowObject
->ExtraData
= (PCHAR
)(WindowObject
+ 1);
1570 WindowObject
->ExtraDataSize
= ClassObject
->cbWndExtra
;
1571 RtlZeroMemory(WindowObject
->ExtraData
, WindowObject
->ExtraDataSize
);
1575 WindowObject
->ExtraData
= NULL
;
1576 WindowObject
->ExtraDataSize
= 0;
1579 InitializeListHead(&WindowObject
->PropListHead
);
1580 ExInitializeFastMutex(&WindowObject
->PropListLock
);
1581 ExInitializeFastMutex(&WindowObject
->RelativesLock
);
1582 ExInitializeFastMutex(&WindowObject
->UpdateLock
);
1584 if (NULL
!= WindowName
->Buffer
)
1586 WindowObject
->WindowName
.MaximumLength
= WindowName
->MaximumLength
;
1587 WindowObject
->WindowName
.Length
= WindowName
->Length
;
1588 WindowObject
->WindowName
.Buffer
= ExAllocatePoolWithTag(PagedPool
, WindowName
->MaximumLength
,
1590 if (NULL
== WindowObject
->WindowName
.Buffer
)
1592 ClassDereferenceObject(ClassObject
);
1593 DPRINT1("Failed to allocate mem for window name\n");
1594 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1597 RtlCopyMemory(WindowObject
->WindowName
.Buffer
, WindowName
->Buffer
, WindowName
->MaximumLength
);
1601 RtlInitUnicodeString(&WindowObject
->WindowName
, NULL
);
1606 * This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1607 * tested for WS_POPUP
1609 if ((dwExStyle
& WS_EX_DLGMODALFRAME
) ||
1610 ((!(dwExStyle
& WS_EX_STATICEDGE
)) &&
1611 (dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
))))
1612 dwExStyle
|= WS_EX_WINDOWEDGE
;
1614 dwExStyle
&= ~WS_EX_WINDOWEDGE
;
1616 /* Correct the window style. */
1617 if (!(dwStyle
& WS_CHILD
))
1619 WindowObject
->Style
|= WS_CLIPSIBLINGS
;
1620 DPRINT("3: Style is now %lx\n", WindowObject
->Style
);
1621 if (!(dwStyle
& WS_POPUP
))
1623 WindowObject
->Style
|= WS_CAPTION
;
1624 WindowObject
->Flags
|= WINDOWOBJECT_NEED_SIZE
;
1625 DPRINT("4: Style is now %lx\n", WindowObject
->Style
);
1629 /* create system menu */
1630 if((WindowObject
->Style
& WS_SYSMENU
) &&
1631 (WindowObject
->Style
& WS_CAPTION
) == WS_CAPTION
)
1633 SystemMenu
= IntGetSystemMenu(WindowObject
, TRUE
, TRUE
);
1636 WindowObject
->SystemMenu
= SystemMenu
->MenuInfo
.Self
;
1637 IntReleaseMenuObject(SystemMenu
);
1641 /* Insert the window into the thread's window list. */
1642 IntLockThreadWindows(PsGetWin32Thread());
1643 InsertTailList (&PsGetWin32Thread()->WindowListHead
,
1644 &WindowObject
->ThreadListEntry
);
1645 IntUnLockThreadWindows(PsGetWin32Thread());
1647 /* Allocate a DCE for this window. */
1648 if (dwStyle
& CS_OWNDC
)
1650 WindowObject
->Dce
= DceAllocDCE(WindowObject
->Self
, DCE_WINDOW_DC
);
1652 /* FIXME: Handle "CS_CLASSDC" */
1660 Cs
.lpCreateParams
= lpParam
;
1661 Cs
.hInstance
= hInstance
;
1663 Cs
.hwndParent
= ParentWindowHandle
;
1669 Cs
.lpszName
= (LPCWSTR
) WindowName
;
1670 Cs
.lpszClass
= (LPCWSTR
) ClassName
;
1671 Cs
.dwExStyle
= dwExStyle
;
1672 CbtCreate
.lpcs
= &Cs
;
1673 CbtCreate
.hwndInsertAfter
= HWND_TOP
;
1674 if (HOOK_CallHooks(WH_CBT
, HCBT_CREATEWND
, (WPARAM
) Handle
, (LPARAM
) &CbtCreate
))
1676 if (NULL
!= ParentWindow
)
1678 IntReleaseWindowObject(ParentWindow
);
1681 /* FIXME - Delete window object and remove it from the thread windows list */
1682 /* FIXME - delete allocated DCE */
1684 ClassDereferenceObject(ClassObject
);
1685 DPRINT1("CBT-hook returned !0\n");
1694 /* default positioning for overlapped windows */
1695 if(!(WindowObject
->Style
& (WS_POPUP
| WS_CHILD
)))
1698 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
1699 BOOL CalculatedDefPosSize
= FALSE
;
1701 IntGetDesktopWorkArea(WindowObject
->OwnerThread
->Tcb
.Win32Thread
->Desktop
, &WorkArea
);
1704 ProcessParams
= PsGetCurrentProcess()->Peb
->ProcessParameters
;
1706 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1708 CalculatedDefPosSize
= IntCalcDefPosSize(ParentWindow
, WindowObject
, &rc
, TRUE
);
1710 if(ProcessParams
->dwFlags
& STARTF_USEPOSITION
)
1712 ProcessParams
->dwFlags
&= ~STARTF_USEPOSITION
;
1713 Pos
.x
= WorkArea
.left
+ ProcessParams
->dwX
;
1714 Pos
.y
= WorkArea
.top
+ ProcessParams
->dwY
;
1722 /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
1723 y is something else */
1724 if(y
!= CW_USEDEFAULT
&& y
!= CW_USEDEFAULT16
)
1729 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1731 if(!CalculatedDefPosSize
)
1733 IntCalcDefPosSize(ParentWindow
, WindowObject
, &rc
, FALSE
);
1735 if(ProcessParams
->dwFlags
& STARTF_USESIZE
)
1737 ProcessParams
->dwFlags
&= ~STARTF_USESIZE
;
1738 Size
.cx
= ProcessParams
->dwXSize
;
1739 Size
.cy
= ProcessParams
->dwYSize
;
1743 Size
.cx
= rc
.right
- rc
.left
;
1744 Size
.cy
= rc
.bottom
- rc
.top
;
1747 /* move the window if necessary */
1749 Pos
.x
= max(rc
.left
, 0);
1751 Pos
.y
= max(rc
.top
, 0);
1756 /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
1757 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1762 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1769 /* Initialize the window dimensions. */
1770 WindowObject
->WindowRect
.left
= Pos
.x
;
1771 WindowObject
->WindowRect
.top
= Pos
.y
;
1772 WindowObject
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1773 WindowObject
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1774 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1776 IntGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1777 ParentWindow
->ClientRect
.top
);
1779 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1782 * Get the size and position of the window.
1784 if ((dwStyle
& WS_THICKFRAME
) || !(dwStyle
& (WS_POPUP
| WS_CHILD
)))
1786 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1788 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1789 WinPosGetMinMaxInfo(WindowObject
, &MaxSize
, &MaxPos
, &MinTrack
,
1791 if (MaxSize
.x
< nWidth
) nWidth
= MaxSize
.x
;
1792 if (MaxSize
.y
< nHeight
) nHeight
= MaxSize
.y
;
1793 if (nWidth
< MinTrack
.x
) nWidth
= MinTrack
.x
;
1794 if (nHeight
< MinTrack
.y
) nHeight
= MinTrack
.y
;
1795 if (nWidth
< 0) nWidth
= 0;
1796 if (nHeight
< 0) nHeight
= 0;
1799 WindowObject
->WindowRect
.left
= Pos
.x
;
1800 WindowObject
->WindowRect
.top
= Pos
.y
;
1801 WindowObject
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1802 WindowObject
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1803 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1805 IntGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1806 ParentWindow
->ClientRect
.top
);
1808 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1810 /* FIXME: Initialize the window menu. */
1812 /* Send a NCCREATE message. */
1818 DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d\n", Cs
.style
, Cs
.dwExStyle
, Cs
.hwndParent
);
1819 DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1820 DPRINT("IntCreateWindowEx(): About to send NCCREATE message.\n");
1821 Result
= IntSendMessage(WindowObject
->Self
, WM_NCCREATE
, 0, (LPARAM
) &Cs
);
1824 /* FIXME: Cleanup. */
1825 if (NULL
!= ParentWindow
)
1827 IntReleaseWindowObject(ParentWindow
);
1829 DPRINT("IntCreateWindowEx(): NCCREATE message failed.\n");
1833 /* Calculate the non-client size. */
1834 MaxPos
.x
= WindowObject
->WindowRect
.left
;
1835 MaxPos
.y
= WindowObject
->WindowRect
.top
;
1836 DPRINT("IntCreateWindowEx(): About to get non-client size.\n");
1837 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1838 Result
= WinPosGetNonClientSize(WindowObject
->Self
,
1839 &WindowObject
->WindowRect
,
1840 &WindowObject
->ClientRect
);
1841 IntGdiOffsetRect(&WindowObject
->WindowRect
,
1842 MaxPos
.x
- WindowObject
->WindowRect
.left
,
1843 MaxPos
.y
- WindowObject
->WindowRect
.top
);
1845 if (NULL
!= ParentWindow
)
1847 /* link the window into the parent's child list */
1848 if ((dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
1850 PWINDOW_OBJECT PrevSibling
;
1851 IntLockRelatives(ParentWindow
);
1852 if((PrevSibling
= ParentWindow
->LastChild
))
1853 IntReferenceWindowObject(PrevSibling
);
1854 IntUnLockRelatives(ParentWindow
);
1855 /* link window as bottom sibling */
1856 IntLinkWindow(WindowObject
, ParentWindow
, PrevSibling
/*prev sibling*/);
1858 IntReleaseWindowObject(PrevSibling
);
1862 /* link window as top sibling (but after topmost siblings) */
1863 PWINDOW_OBJECT InsertAfter
, Sibling
;
1864 if (0 == (dwExStyle
& WS_EX_TOPMOST
))
1866 IntLockRelatives(ParentWindow
);
1868 Sibling
= ParentWindow
->FirstChild
;
1869 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
1871 InsertAfter
= Sibling
;
1872 Sibling
= Sibling
->NextSibling
;
1874 IntUnLockRelatives(ParentWindow
);
1880 if (NULL
!= InsertAfter
)
1882 IntReferenceWindowObject(InsertAfter
);
1884 IntLinkWindow(WindowObject
, ParentWindow
, InsertAfter
/* prev sibling */);
1885 if (NULL
!= InsertAfter
)
1887 IntReleaseWindowObject(InsertAfter
);
1892 /* Send the WM_CREATE message. */
1893 DPRINT("IntCreateWindowEx(): about to send CREATE message.\n");
1894 Result
= IntSendMessage(WindowObject
->Self
, WM_CREATE
, 0, (LPARAM
) &Cs
);
1895 if (Result
== (LRESULT
)-1)
1897 /* FIXME: Cleanup. */
1898 if (NULL
!= ParentWindow
)
1900 IntReleaseWindowObject(ParentWindow
);
1902 ClassDereferenceObject(ClassObject
);
1903 DPRINT("IntCreateWindowEx(): send CREATE message failed.\n");
1907 /* Send move and size messages. */
1908 if (!(WindowObject
->Flags
& WINDOWOBJECT_NEED_SIZE
))
1912 DPRINT("IntCreateWindow(): About to send WM_SIZE\n");
1914 if ((WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
) < 0 ||
1915 (WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
) < 0)
1917 DPRINT("Sending bogus WM_SIZE\n");
1920 lParam
= MAKE_LONG(WindowObject
->ClientRect
.right
-
1921 WindowObject
->ClientRect
.left
,
1922 WindowObject
->ClientRect
.bottom
-
1923 WindowObject
->ClientRect
.top
);
1924 IntSendMessage(WindowObject
->Self
, WM_SIZE
, SIZE_RESTORED
,
1927 DPRINT("IntCreateWindow(): About to send WM_MOVE\n");
1929 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1931 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
- ParentWindow
->ClientRect
.left
,
1932 WindowObject
->ClientRect
.top
- ParentWindow
->ClientRect
.top
);
1936 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
,
1937 WindowObject
->ClientRect
.top
);
1939 IntSendMessage(WindowObject
->Self
, WM_MOVE
, 0, lParam
);
1942 /* Show or maybe minimize or maximize the window. */
1943 if (WindowObject
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1948 SwFlag
= (WindowObject
->Style
& WS_MINIMIZE
) ? SW_MINIMIZE
:
1950 WinPosMinMaximize(WindowObject
, SwFlag
, &NewPos
);
1952 ((WindowObject
->Style
& WS_CHILD
) || NtUserGetActiveWindow()) ?
1953 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
:
1954 SWP_NOZORDER
| SWP_FRAMECHANGED
;
1955 DPRINT("IntCreateWindow(): About to minimize/maximize\n");
1956 DPRINT("%d,%d %dx%d\n", NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
);
1957 WinPosSetWindowPos(WindowObject
->Self
, 0, NewPos
.left
, NewPos
.top
,
1958 NewPos
.right
, NewPos
.bottom
, SwFlag
);
1961 /* Notify the parent window of a new child. */
1962 if ((WindowObject
->Style
& WS_CHILD
) &&
1963 (!(WindowObject
->ExStyle
& WS_EX_NOPARENTNOTIFY
)) && ParentWindow
)
1965 DPRINT("IntCreateWindow(): About to notify parent\n");
1966 IntSendMessage(ParentWindow
->Self
,
1968 MAKEWPARAM(WM_CREATE
, WindowObject
->IDMenu
),
1969 (LPARAM
)WindowObject
->Self
);
1972 if (NULL
!= ParentWindow
)
1974 IntReleaseWindowObject(ParentWindow
);
1977 /* Initialize and show the window's scrollbars */
1978 if (WindowObject
->Style
& WS_VSCROLL
)
1980 NtUserShowScrollBar(WindowObject
->Self
, SB_VERT
, TRUE
);
1982 if (WindowObject
->Style
& WS_HSCROLL
)
1984 NtUserShowScrollBar(WindowObject
->Self
, SB_HORZ
, TRUE
);
1987 if (dwStyle
& WS_VISIBLE
)
1989 DPRINT("IntCreateWindow(): About to show window\n");
1990 WinPosShowWindow(WindowObject
->Self
, dwShowMode
);
1993 DPRINT("IntCreateWindow(): = %X\n", Handle
);
1994 DPRINT("WindowObject->SystemMenu = 0x%x\n", WindowObject
->SystemMenu
);
1995 return((HWND
)Handle
);
1999 NtUserCreateWindowEx(DWORD dwExStyle
,
2000 PUNICODE_STRING UnsafeClassName
,
2001 PUNICODE_STRING UnsafeWindowName
,
2009 HINSTANCE hInstance
,
2012 BOOL bUnicodeWindow
)
2015 UNICODE_STRING WindowName
;
2016 UNICODE_STRING ClassName
;
2019 DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
2021 /* Get the class name (string or atom) */
2022 Status
= MmCopyFromCaller(&ClassName
, UnsafeClassName
, sizeof(UNICODE_STRING
));
2023 if (! NT_SUCCESS(Status
))
2025 SetLastNtError(Status
);
2028 if (! IS_ATOM(ClassName
.Buffer
))
2030 Status
= IntSafeCopyUnicodeStringTerminateNULL(&ClassName
, UnsafeClassName
);
2031 if (! NT_SUCCESS(Status
))
2033 SetLastNtError(Status
);
2038 /* safely copy the window name */
2039 if (NULL
!= UnsafeWindowName
)
2041 Status
= IntSafeCopyUnicodeString(&WindowName
, UnsafeWindowName
);
2042 if (! NT_SUCCESS(Status
))
2044 if (! IS_ATOM(ClassName
.Buffer
))
2046 RtlFreeUnicodeString(&ClassName
);
2048 SetLastNtError(Status
);
2054 RtlInitUnicodeString(&WindowName
, NULL
);
2057 NewWindow
= IntCreateWindowEx(dwExStyle
, &ClassName
, &WindowName
, dwStyle
, x
, y
, nWidth
, nHeight
,
2058 hWndParent
, hMenu
, hInstance
, lpParam
, dwShowMode
, bUnicodeWindow
);
2060 RtlFreeUnicodeString(&WindowName
);
2061 if (! IS_ATOM(ClassName
.Buffer
))
2063 RtlFreeUnicodeString(&ClassName
);
2073 NtUserDeferWindowPos(HDWP WinPosInfo
,
2075 HWND WndInsertAfter
,
2092 NtUserDestroyWindow(HWND Wnd
)
2094 PWINDOW_OBJECT Window
;
2097 Window
= IntGetWindowObject(Wnd
);
2103 /* Check for owner thread and desktop window */
2104 if ((Window
->OwnerThread
!= PsGetCurrentThread()) || IntIsDesktopWindow(Window
))
2106 IntReleaseWindowObject(Window
);
2107 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2111 /* Look whether the focus is within the tree of windows we will
2114 if (!WinPosShowWindow(Wnd
, SW_HIDE
))
2116 if (NtUserGetActiveWindow() == Wnd
)
2118 WinPosActivateOtherWindow(Window
);
2121 IntLockMessageQueue(Window
->MessageQueue
);
2122 if (Window
->MessageQueue
->ActiveWindow
== Window
->Self
)
2123 Window
->MessageQueue
->ActiveWindow
= NULL
;
2124 if (Window
->MessageQueue
->FocusWindow
== Window
->Self
)
2125 Window
->MessageQueue
->FocusWindow
= NULL
;
2126 if (Window
->MessageQueue
->CaptureWindow
== Window
->Self
)
2127 Window
->MessageQueue
->CaptureWindow
= NULL
;
2128 IntUnLockMessageQueue(Window
->MessageQueue
);
2132 if (HOOK_CallHooks(WH_CBT
, HCBT_DESTROYWND
, (WPARAM
) hwnd
, 0, TRUE
))
2138 isChild
= (0 != (Window
->Style
& WS_CHILD
));
2143 if (! USER_IsExitingThread(GetCurrentThreadId()))
2145 send_parent_notify(hwnd
, WM_DESTROY
);
2148 else if (NULL
!= GetWindow(Wnd
, GW_OWNER
))
2150 HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
2151 /* FIXME: clean up palette - see "Internals" p.352 */
2155 if (!IntIsWindow(Wnd
))
2160 /* Recursively destroy owned windows */
2165 BOOL GotOne
= FALSE
;
2168 PWINDOW_OBJECT Child
, Desktop
;
2170 Desktop
= IntGetWindowObject(IntGetDesktopWindow());
2171 Children
= IntWinListChildren(Desktop
);
2172 IntReleaseWindowObject(Desktop
);
2175 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
2177 Child
= IntGetWindowObject(*ChildHandle
);
2180 IntLockRelatives(Child
);
2181 if (Child
->Owner
!= Window
->Self
)
2183 IntUnLockRelatives(Child
);
2184 IntReleaseWindowObject(Child
);
2187 IntUnLockRelatives(Child
);
2188 if (IntWndBelongsToThread(Child
, PsGetWin32Thread()))
2190 IntReleaseWindowObject(Child
);
2191 NtUserDestroyWindow(*ChildHandle
);
2195 IntLockRelatives(Child
);
2196 if (Child
->Owner
!= NULL
)
2198 Child
->Owner
= NULL
;
2200 IntUnLockRelatives(Child
);
2201 IntReleaseWindowObject(Child
);
2203 ExFreePool(Children
);
2212 if (!IntIsWindow(Wnd
))
2214 IntReleaseWindowObject(Window
);
2218 /* Destroy the window storage */
2219 IntDestroyWindow(Window
, PsGetWin32Process(), PsGetWin32Thread(), TRUE
);
2221 IntReleaseWindowObject(Window
);
2231 NtUserDrawMenuBarTemp(
2238 /* we'll use this function just for caching the menu bar */
2248 NtUserEndDeferWindowPosEx(DWORD Unknown0
,
2261 NtUserFillWindow(DWORD Unknown0
,
2273 IntFindWindow(PWINDOW_OBJECT Parent
,
2274 PWINDOW_OBJECT ChildAfter
,
2276 PUNICODE_STRING WindowName
)
2278 BOOL CheckWindowName
;
2284 CheckWindowName
= (WindowName
&& (WindowName
->Length
> 0));
2286 if((List
= IntWinListChildren(Parent
)))
2291 /* skip handles before and including ChildAfter */
2292 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->Self
));
2295 /* search children */
2298 PWINDOW_OBJECT Child
;
2299 if(!(Child
= IntGetWindowObject(*(phWnd
++))))
2304 /* Do not send WM_GETTEXT messages in the kernel mode version!
2305 The user mode version however calls GetWindowText() which will
2306 send WM_GETTEXT messages to windows belonging to its processes */
2307 if((!CheckWindowName
|| !RtlCompareUnicodeString(WindowName
, &(Child
->WindowName
), FALSE
)) &&
2308 (!ClassAtom
|| Child
->Class
->Atom
== ClassAtom
))
2311 IntReleaseWindowObject(Child
);
2315 IntReleaseWindowObject(Child
);
2325 * Searches a window's children for a window with the specified
2328 * hwndParent = The window whose childs are to be searched.
2330 * HWND_MESSAGE = message-only windows
2332 * hwndChildAfter = Search starts after this child window.
2333 * NULL = start from beginning
2335 * ucClassName = Class name to search for
2336 * Reguired parameter.
2338 * ucWindowName = Window name
2339 * ->Buffer == NULL = don't care
2342 * The HWND of the window if it was found, otherwise NULL
2348 NtUserFindWindowEx(HWND hwndParent
,
2349 HWND hwndChildAfter
,
2350 PUNICODE_STRING ucClassName
,
2351 PUNICODE_STRING ucWindowName
)
2353 PWINDOW_OBJECT Parent
, ChildAfter
;
2354 UNICODE_STRING ClassName
, WindowName
;
2356 HWND Desktop
, Ret
= NULL
;
2359 Desktop
= IntGetCurrentThreadDesktopWindow();
2361 if(hwndParent
== NULL
)
2362 hwndParent
= Desktop
;
2364 else if(hwndParent == HWND_MESSAGE)
2366 hwndParent = IntGetMessageWindow();
2370 if(!(Parent
= IntGetWindowObject(hwndParent
)))
2372 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2377 if(hwndChildAfter
&& !(ChildAfter
= IntGetWindowObject(hwndChildAfter
)))
2379 IntReleaseWindowObject(Parent
);
2380 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2384 /* copy the window name */
2385 Status
= IntSafeCopyUnicodeString(&WindowName
, ucWindowName
);
2386 if(!NT_SUCCESS(Status
))
2388 SetLastNtError(Status
);
2392 /* safely copy the class name */
2393 Status
= MmCopyFromCaller(&ClassName
, ucClassName
, sizeof(UNICODE_STRING
));
2394 if(!NT_SUCCESS(Status
))
2396 SetLastNtError(Status
);
2399 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2402 /* safely copy the class name string (NULL terminated because class-lookup
2404 buf
= ExAllocatePoolWithTag(PagedPool
, ClassName
.Length
+ sizeof(WCHAR
), TAG_STRING
);
2407 SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES
);
2410 Status
= MmCopyFromCaller(buf
, ClassName
.Buffer
, ClassName
.Length
);
2411 if(!NT_SUCCESS(Status
))
2414 SetLastNtError(Status
);
2417 ClassName
.Buffer
= buf
;
2418 /* make sure the string is null-terminated */
2419 buf
+= ClassName
.Length
/ sizeof(WCHAR
);
2423 /* find the class object */
2424 if(ClassName
.Buffer
)
2426 PWINSTATION_OBJECT WinStaObject
;
2428 if (PsGetWin32Thread()->Desktop
== NULL
)
2430 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2434 WinStaObject
= PsGetWin32Thread()->Desktop
->WindowStation
;
2436 Status
= RtlLookupAtomInAtomTable(
2437 WinStaObject
->AtomTable
,
2441 if (!NT_SUCCESS(Status
))
2443 DPRINT1("Failed to lookup class atom!\n");
2444 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST
);
2449 if(Parent
->Self
== Desktop
)
2452 PWINDOW_OBJECT TopLevelWindow
;
2453 BOOLEAN CheckWindowName
;
2454 BOOLEAN CheckClassName
;
2455 BOOLEAN WindowMatches
;
2456 BOOLEAN ClassMatches
;
2458 /* windows searches through all top-level windows if the parent is the desktop
2461 if((List
= IntWinListChildren(Parent
)))
2467 /* skip handles before and including ChildAfter */
2468 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->Self
));
2471 CheckWindowName
= WindowName
.Length
> 0;
2472 CheckClassName
= ClassName
.Buffer
!= NULL
;
2474 /* search children */
2477 if(!(TopLevelWindow
= IntGetWindowObject(*(phWnd
++))))
2482 /* Do not send WM_GETTEXT messages in the kernel mode version!
2483 The user mode version however calls GetWindowText() which will
2484 send WM_GETTEXT messages to windows belonging to its processes */
2485 WindowMatches
= !CheckWindowName
|| !RtlCompareUnicodeString(
2486 &WindowName
, &TopLevelWindow
->WindowName
, FALSE
);
2487 ClassMatches
= !CheckClassName
||
2488 ClassAtom
== TopLevelWindow
->Class
->Atom
;
2490 if (WindowMatches
&& ClassMatches
)
2492 Ret
= TopLevelWindow
->Self
;
2493 IntReleaseWindowObject(TopLevelWindow
);
2497 if (IntFindWindow(TopLevelWindow
, NULL
, ClassAtom
, &WindowName
))
2499 /* window returns the handle of the top-level window, in case it found
2501 Ret
= TopLevelWindow
->Self
;
2502 IntReleaseWindowObject(TopLevelWindow
);
2506 IntReleaseWindowObject(TopLevelWindow
);
2512 Ret
= IntFindWindow(Parent
, ChildAfter
, ClassAtom
, &WindowName
);
2515 if(Ret
== NULL
&& hwndParent
== NULL
&& hwndChildAfter
== NULL
)
2517 /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
2518 search the message-only windows. Should this also be done if
2519 Parent is the desktop window??? */
2520 PWINDOW_OBJECT MsgWindows
;
2522 if((MsgWindows
= IntGetWindowObject(IntGetMessageWindow())))
2524 Ret
= IntFindWindow(MsgWindows
, ChildAfter
, ClassAtom
, &WindowName
);
2525 IntReleaseWindowObject(MsgWindows
);
2531 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2532 ExFreePool(ClassName
.Buffer
);
2535 RtlFreeUnicodeString(&WindowName
);
2539 IntReleaseWindowObject(ChildAfter
);
2540 IntReleaseWindowObject(Parent
);
2550 NtUserFlashWindowEx(DWORD Unknown0
)
2562 NtUserGetAncestor(HWND hWnd
, UINT Type
)
2564 PWINDOW_OBJECT Wnd
, WndAncestor
, Parent
;
2567 if (hWnd
== IntGetDesktopWindow())
2572 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2574 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2582 WndAncestor
= IntGetParentObject(Wnd
);
2595 if(!(Parent
= IntGetParentObject(WndAncestor
)))
2599 if(IntIsDesktopWindow(Parent
))
2601 IntReleaseWindowObject(Parent
);
2605 IntReleaseWindowObject(tmp
);
2606 WndAncestor
= Parent
;
2614 IntReferenceWindowObject(WndAncestor
);
2619 Parent
= IntGetParent(WndAncestor
);
2620 IntReleaseWindowObject(Old
);
2625 WndAncestor
= Parent
;
2632 IntReleaseWindowObject(Wnd
);
2637 hWndAncestor
= (WndAncestor
? WndAncestor
->Self
: NULL
);
2638 IntReleaseWindowObject(Wnd
);
2640 if(WndAncestor
&& (WndAncestor
!= Wnd
))
2641 IntReleaseWindowObject(WndAncestor
);
2643 return hWndAncestor
;
2648 * Returns client window rectangle relative to the upper-left corner of client area.
2650 * \param hWnd window handle.
2651 * \param Rect pointer to the buffer where the coordinates are returned.
2658 NtUserGetClientRect(HWND hWnd
, LPRECT Rect
)
2660 PWINDOW_OBJECT WindowObject
;
2663 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
2665 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2669 IntGetClientRect(WindowObject
, &SafeRect
);
2670 IntReleaseWindowObject(WindowObject
);
2672 if(!NT_SUCCESS(MmCopyToCaller(Rect
, &SafeRect
, sizeof(RECT
))))
2684 NtUserGetDesktopWindow()
2686 return IntGetDesktopWindow();
2694 NtUserGetInternalWindowPos(DWORD Unknown0
,
2708 NtUserGetLastActivePopup(HWND hWnd
)
2711 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2712 * not changed anywhere.
2713 * -- Filip, 01/nov/2003
2719 IntAcquireWinLockShared();
2721 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2723 IntReleaseWinLock();
2724 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2728 hWndLastPopup
= Wnd
->hWndLastPopup
;
2730 IntReleaseWinLock();
2732 return hWndLastPopup
;
2741 * The NtUserGetParent function retrieves a handle to the specified window's
2745 * Note that, despite its name, this function can return an owner window
2746 * instead of a parent window.
2753 NtUserGetParent(HWND hWnd
)
2755 PWINDOW_OBJECT Wnd
, WndParent
;
2756 HWND hWndParent
= NULL
;
2758 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2760 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2764 WndParent
= IntGetParent(Wnd
);
2767 hWndParent
= WndParent
->Self
;
2768 IntReleaseWindowObject(WndParent
);
2771 IntReleaseWindowObject(Wnd
);
2779 * The NtUserSetParent function changes the parent window of the specified
2783 * The new parent window and the child window must belong to the same
2784 * application. If the window identified by the hWndChild parameter is
2785 * visible, the system performs the appropriate redrawing and repainting.
2786 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2787 * or WS_POPUP window styles of the window whose parent is being changed.
2794 NtUserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2796 PWINDOW_OBJECT Wnd
= NULL
, WndParent
= NULL
, WndOldParent
;
2797 HWND hWndOldParent
= NULL
;
2799 if (IntIsBroadcastHwnd(hWndChild
) || IntIsBroadcastHwnd(hWndNewParent
))
2801 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2805 if (hWndChild
== IntGetDesktopWindow())
2807 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2813 if (!(WndParent
= IntGetWindowObject(hWndNewParent
)))
2815 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2821 if (!(WndParent
= IntGetWindowObject(IntGetDesktopWindow())))
2823 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2828 if (!(Wnd
= IntGetWindowObject(hWndChild
)))
2830 IntReleaseWindowObject(WndParent
);
2831 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2835 WndOldParent
= IntSetParent(Wnd
, WndParent
);
2839 hWndOldParent
= WndOldParent
->Self
;
2840 IntReleaseWindowObject(WndOldParent
);
2843 IntReleaseWindowObject(Wnd
);
2844 IntReleaseWindowObject(WndParent
);
2846 return hWndOldParent
;
2850 * NtUserGetShellWindow
2852 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
2859 NtUserGetShellWindow()
2861 PWINSTATION_OBJECT WinStaObject
;
2864 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
2869 if (!NT_SUCCESS(Status
))
2871 SetLastNtError(Status
);
2875 Ret
= (HWND
)WinStaObject
->ShellWindow
;
2877 ObDereferenceObject(WinStaObject
);
2882 * NtUserSetShellWindowEx
2884 * This is undocumented function to set global shell window. The global
2885 * shell window has special handling of window position.
2892 NtUserSetShellWindowEx(HWND hwndShell
, HWND hwndListView
)
2894 PWINSTATION_OBJECT WinStaObject
;
2896 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
2901 if (!NT_SUCCESS(Status
))
2903 SetLastNtError(Status
);
2908 * Test if we are permitted to change the shell window.
2910 if (WinStaObject
->ShellWindow
)
2912 ObDereferenceObject(WinStaObject
);
2917 * Move shell window into background.
2919 if (hwndListView
&& hwndListView
!= hwndShell
)
2922 * Disabled for now to get Explorer working.
2923 * -- Filip, 01/nov/2003
2926 WinPosSetWindowPos(hwndListView
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2929 if (NtUserGetWindowLong(hwndListView
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2931 ObDereferenceObject(WinStaObject
);
2936 if (NtUserGetWindowLong(hwndShell
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2938 ObDereferenceObject(WinStaObject
);
2942 WinPosSetWindowPos(hwndShell
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2944 WinStaObject
->ShellWindow
= hwndShell
;
2945 WinStaObject
->ShellListView
= hwndListView
;
2947 ObDereferenceObject(WinStaObject
);
2952 * NtUserGetSystemMenu
2954 * The NtUserGetSystemMenu function allows the application to access the
2955 * window menu (also known as the system menu or the control menu) for
2956 * copying and modifying.
2960 * Handle to the window that will own a copy of the window menu.
2962 * Specifies the action to be taken. If this parameter is FALSE,
2963 * NtUserGetSystemMenu returns a handle to the copy of the window menu
2964 * currently in use. The copy is initially identical to the window menu
2965 * but it can be modified.
2966 * If this parameter is TRUE, GetSystemMenu resets the window menu back
2967 * to the default state. The previous window menu, if any, is destroyed.
2970 * If the bRevert parameter is FALSE, the return value is a handle to a
2971 * copy of the window menu. If the bRevert parameter is TRUE, the return
2979 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
2982 PWINDOW_OBJECT WindowObject
;
2983 PMENU_OBJECT MenuObject
;
2985 WindowObject
= IntGetWindowObject((HWND
)hWnd
);
2986 if (WindowObject
== NULL
)
2988 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2992 MenuObject
= IntGetSystemMenu(WindowObject
, bRevert
, FALSE
);
2995 Result
= MenuObject
->MenuInfo
.Self
;
2996 IntReleaseMenuObject(MenuObject
);
2999 IntReleaseWindowObject(WindowObject
);
3004 * NtUserSetSystemMenu
3011 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
3013 BOOL Result
= FALSE
;
3014 PWINDOW_OBJECT WindowObject
;
3015 PMENU_OBJECT MenuObject
;
3017 WindowObject
= IntGetWindowObject(hWnd
);
3020 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3027 * Assign new menu handle.
3029 MenuObject
= IntGetMenuObject(hMenu
);
3032 IntReleaseWindowObject(WindowObject
);
3033 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
3037 Result
= IntSetSystemMenu(WindowObject
, MenuObject
);
3039 IntReleaseMenuObject(MenuObject
);
3042 IntReleaseWindowObject(WindowObject
);
3050 * The NtUserGetWindow function retrieves a handle to a window that has the
3051 * specified relationship (Z order or owner) to the specified window.
3058 NtUserGetWindow(HWND hWnd
, UINT Relationship
)
3060 PWINDOW_OBJECT WindowObject
, Parent
;
3061 HWND hWndResult
= NULL
;
3063 if (!(WindowObject
= IntGetWindowObject(hWnd
)))
3065 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3069 switch (Relationship
)
3072 if((Parent
= IntGetParentObject(WindowObject
)))
3074 IntLockRelatives(Parent
);
3075 if (Parent
->FirstChild
)
3076 hWndResult
= Parent
->FirstChild
->Self
;
3077 IntUnLockRelatives(Parent
);
3078 IntReleaseWindowObject(Parent
);
3083 if((Parent
= IntGetParentObject(WindowObject
)))
3085 IntLockRelatives(Parent
);
3086 if (Parent
->LastChild
)
3087 hWndResult
= Parent
->LastChild
->Self
;
3088 IntUnLockRelatives(Parent
);
3089 IntReleaseWindowObject(Parent
);
3094 IntLockRelatives(WindowObject
);
3095 if (WindowObject
->NextSibling
)
3096 hWndResult
= WindowObject
->NextSibling
->Self
;
3097 IntUnLockRelatives(WindowObject
);
3101 IntLockRelatives(WindowObject
);
3102 if (WindowObject
->PrevSibling
)
3103 hWndResult
= WindowObject
->PrevSibling
->Self
;
3104 IntUnLockRelatives(WindowObject
);
3108 IntLockRelatives(WindowObject
);
3109 if((Parent
= IntGetWindowObject(WindowObject
->Owner
)))
3111 hWndResult
= Parent
->Self
;
3112 IntReleaseWindowObject(Parent
);
3114 IntUnLockRelatives(WindowObject
);
3117 IntLockRelatives(WindowObject
);
3118 if (WindowObject
->FirstChild
)
3119 hWndResult
= WindowObject
->FirstChild
->Self
;
3120 IntUnLockRelatives(WindowObject
);
3124 IntReleaseWindowObject(WindowObject
);
3130 * NtUserGetWindowLong
3132 * The NtUserGetWindowLong function retrieves information about the specified
3133 * window. The function also retrieves the 32-bit (long) value at the
3134 * specified offset into the extra window memory.
3141 NtUserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3143 PWINDOW_OBJECT WindowObject
, Parent
;
3146 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3148 WindowObject
= IntGetWindowObject(hWnd
);
3149 if (WindowObject
== NULL
)
3151 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3156 * Only allow CSRSS to mess with the desktop window
3158 if (hWnd
== IntGetDesktopWindow()
3159 && WindowObject
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
3161 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3165 if ((INT
)Index
>= 0)
3167 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
3169 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3172 Result
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
3179 Result
= WindowObject
->ExStyle
;
3183 Result
= WindowObject
->Style
;
3188 Result
= (LONG
) WindowObject
->WndProcA
;
3190 Result
= (LONG
) WindowObject
->WndProcW
;
3194 Result
= (LONG
) WindowObject
->Instance
;
3197 case GWL_HWNDPARENT
:
3198 IntLockRelatives(WindowObject
);
3199 Parent
= IntGetWindowObject(WindowObject
->Parent
);
3200 IntUnLockRelatives(WindowObject
);
3203 if (Parent
&& Parent
->Self
== IntGetDesktopWindow())
3204 Result
= (LONG
) NtUserGetWindow(WindowObject
->Self
, GW_OWNER
);
3206 Result
= (LONG
) Parent
->Self
;
3207 IntReleaseWindowObject(Parent
);
3212 Result
= (LONG
) WindowObject
->IDMenu
;
3216 Result
= WindowObject
->UserData
;
3220 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index
);
3221 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3227 IntReleaseWindowObject(WindowObject
);
3233 * NtUserSetWindowLong
3235 * The NtUserSetWindowLong function changes an attribute of the specified
3236 * window. The function also sets the 32-bit (long) value at the specified
3237 * offset into the extra window memory.
3244 NtUserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3246 PWINDOW_OBJECT WindowObject
, Parent
;
3247 PWINSTATION_OBJECT WindowStation
;
3251 if (hWnd
== IntGetDesktopWindow())
3253 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3257 WindowObject
= IntGetWindowObject(hWnd
);
3258 if (WindowObject
== NULL
)
3260 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3264 if ((INT
)Index
>= 0)
3266 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
3268 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3269 IntReleaseWindowObject(WindowObject
);
3272 OldValue
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
3273 *((LONG
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
3280 OldValue
= (LONG
) WindowObject
->ExStyle
;
3281 Style
.styleOld
= OldValue
;
3282 Style
.styleNew
= NewValue
;
3285 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3287 WindowStation
= WindowObject
->OwnerThread
->Tcb
.Win32Thread
->Desktop
->WindowStation
;
3290 if (hWnd
== WindowStation
->ShellWindow
|| hWnd
== WindowStation
->ShellListView
)
3291 Style
.styleNew
&= ~WS_EX_TOPMOST
;
3294 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3295 WindowObject
->ExStyle
= (DWORD
)Style
.styleNew
;
3296 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3300 OldValue
= (LONG
) WindowObject
->Style
;
3301 Style
.styleOld
= OldValue
;
3302 Style
.styleNew
= NewValue
;
3303 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_STYLE
, (LPARAM
) &Style
);
3304 WindowObject
->Style
= (DWORD
)Style
.styleNew
;
3305 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_STYLE
, (LPARAM
) &Style
);
3309 /* FIXME: should check if window belongs to current process */
3312 OldValue
= (LONG
) WindowObject
->WndProcA
;
3313 WindowObject
->WndProcA
= (WNDPROC
) NewValue
;
3314 WindowObject
->WndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,FALSE
);
3315 WindowObject
->Unicode
= FALSE
;
3319 OldValue
= (LONG
) WindowObject
->WndProcW
;
3320 WindowObject
->WndProcW
= (WNDPROC
) NewValue
;
3321 WindowObject
->WndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,TRUE
);
3322 WindowObject
->Unicode
= TRUE
;
3327 OldValue
= (LONG
) WindowObject
->Instance
;
3328 WindowObject
->Instance
= (HINSTANCE
) NewValue
;
3331 case GWL_HWNDPARENT
:
3332 Parent
= IntGetParentObject(WindowObject
);
3333 if (Parent
&& (Parent
->Self
== IntGetDesktopWindow()))
3334 OldValue
= (LONG
) IntSetOwner(WindowObject
->Self
, (HWND
) NewValue
);
3336 OldValue
= (LONG
) NtUserSetParent(WindowObject
->Self
, (HWND
) NewValue
);
3338 IntReleaseWindowObject(Parent
);
3342 OldValue
= (LONG
) WindowObject
->IDMenu
;
3343 WindowObject
->IDMenu
= (UINT
) NewValue
;
3347 OldValue
= WindowObject
->UserData
;
3348 WindowObject
->UserData
= NewValue
;
3352 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index
);
3353 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3359 IntReleaseWindowObject(WindowObject
);
3365 * NtUserSetWindowWord
3367 * Legacy function similar to NtUserSetWindowLong.
3374 NtUserSetWindowWord(HWND hWnd
, INT Index
, WORD NewValue
)
3376 PWINDOW_OBJECT WindowObject
;
3383 case GWL_HWNDPARENT
:
3384 return NtUserSetWindowLong(hWnd
, Index
, (UINT
)NewValue
, TRUE
);
3388 SetLastWin32Error(ERROR_INVALID_INDEX
);
3393 WindowObject
= IntGetWindowObject(hWnd
);
3394 if (WindowObject
== NULL
)
3396 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3400 if (Index
> WindowObject
->ExtraDataSize
- sizeof(WORD
))
3402 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3403 IntReleaseWindowObject(WindowObject
);
3407 OldValue
= *((WORD
*)(WindowObject
->ExtraData
+ Index
));
3408 *((WORD
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
3410 IntReleaseWindowObject(WindowObject
);
3419 NtUserGetWindowPlacement(HWND hWnd
,
3420 WINDOWPLACEMENT
*lpwndpl
)
3422 PWINDOW_OBJECT WindowObject
;
3423 PINTERNALPOS InternalPos
;
3425 WINDOWPLACEMENT Safepl
;
3428 WindowObject
= IntGetWindowObject(hWnd
);
3429 if (WindowObject
== NULL
)
3431 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3435 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3436 if(!NT_SUCCESS(Status
))
3438 SetLastNtError(Status
);
3439 IntReleaseWindowObject(WindowObject
);
3442 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3444 IntReleaseWindowObject(WindowObject
);
3449 Safepl
.showCmd
= ((WindowObject
->Flags
& WINDOWOBJECT_RESTOREMAX
) ? SW_MAXIMIZE
: SW_SHOWNORMAL
);
3451 Size
.x
= WindowObject
->WindowRect
.left
;
3452 Size
.y
= WindowObject
->WindowRect
.top
;
3453 InternalPos
= WinPosInitInternalPos(WindowObject
, &Size
,
3454 &WindowObject
->WindowRect
);
3457 Safepl
.rcNormalPosition
= InternalPos
->NormalRect
;
3458 Safepl
.ptMinPosition
= InternalPos
->IconPos
;
3459 Safepl
.ptMaxPosition
= InternalPos
->MaxPos
;
3463 IntReleaseWindowObject(WindowObject
);
3467 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3468 if(!NT_SUCCESS(Status
))
3470 SetLastNtError(Status
);
3471 IntReleaseWindowObject(WindowObject
);
3475 IntReleaseWindowObject(WindowObject
);
3481 * Return the dimension of the window in the screen coordinates.
3482 * \param hWnd window handle.
3483 * \param Rect pointer to the buffer where the coordinates are returned.
3489 NtUserGetWindowRect(HWND hWnd
, LPRECT Rect
)
3494 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3496 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3499 Status
= MmCopyToCaller(Rect
, &Wnd
->WindowRect
, sizeof(RECT
));
3500 if (!NT_SUCCESS(Status
))
3502 IntReleaseWindowObject(Wnd
);
3503 SetLastNtError(Status
);
3507 IntReleaseWindowObject(Wnd
);
3516 NtUserGetWindowThreadProcessId(HWND hWnd
, LPDWORD UnsafePid
)
3521 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3523 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3527 tid
= (DWORD
)IntGetWndThreadId(Wnd
);
3528 pid
= (DWORD
)IntGetWndProcessId(Wnd
);
3530 if (UnsafePid
) MmCopyToCaller(UnsafePid
, &pid
, sizeof(DWORD
));
3540 NtUserLockWindowUpdate(DWORD Unknown0
)
3560 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3561 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3562 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3566 QueryWindow based on KJK::Hyperion and James Tabor.
3568 0 = QWUniqueProcessId
3569 1 = QWUniqueThreadId
3570 4 = QWIsHung Implements IsHungAppWindow found
3573 9 = QWKillWindow When I called this with hWnd ==
3574 DesktopWindow, it shutdown the system
3581 NtUserQueryWindow(HWND hWnd
, DWORD Index
)
3583 PWINDOW_OBJECT Window
= IntGetWindowObject(hWnd
);
3588 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3594 case QUERY_WINDOW_UNIQUE_PROCESS_ID
:
3595 Result
= (DWORD
)IntGetWndProcessId(Window
);
3598 case QUERY_WINDOW_UNIQUE_THREAD_ID
:
3599 Result
= (DWORD
)IntGetWndThreadId(Window
);
3602 case QUERY_WINDOW_ISHUNG
:
3603 Result
= (DWORD
)MsqIsHung(Window
->MessageQueue
);
3607 Result
= (DWORD
)NULL
;
3611 IntReleaseWindowObject(Window
);
3621 NtUserRealChildWindowFromPoint(DWORD Unknown0
,
3635 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe
)
3637 UNICODE_STRING SafeMessageName
;
3641 if(MessageNameUnsafe
== NULL
)
3643 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3647 Status
= IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName
, MessageNameUnsafe
);
3648 if(!NT_SUCCESS(Status
))
3650 SetLastNtError(Status
);
3654 Ret
= (UINT
)IntAddAtom(SafeMessageName
.Buffer
);
3656 RtlFreeUnicodeString(&SafeMessageName
);
3665 NtUserSetImeOwnerWindow(DWORD Unknown0
,
3678 NtUserSetInternalWindowPos(DWORD Unknown0
,
3694 NtUserSetLayeredWindowAttributes(DWORD Unknown0
,
3709 NtUserSetLogonNotifyWindow(DWORD Unknown0
)
3726 PWINDOW_OBJECT WindowObject
;
3729 WindowObject
= IntGetWindowObject((HWND
) Wnd
);
3730 if (NULL
== WindowObject
)
3732 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3736 if (! IntSetMenu(WindowObject
, Menu
, &Changed
))
3738 IntReleaseWindowObject(WindowObject
);
3742 IntReleaseWindowObject(WindowObject
);
3744 if (Changed
&& Repaint
)
3746 WinPosSetWindowPos(Wnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
3747 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
3758 NtUserSetWindowFNID(DWORD Unknown0
,
3772 NtUserSetWindowPlacement(HWND hWnd
,
3773 WINDOWPLACEMENT
*lpwndpl
)
3775 PWINDOW_OBJECT WindowObject
;
3776 WINDOWPLACEMENT Safepl
;
3779 WindowObject
= IntGetWindowObject(hWnd
);
3780 if (WindowObject
== NULL
)
3782 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3785 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3786 if(!NT_SUCCESS(Status
))
3788 SetLastNtError(Status
);
3789 IntReleaseWindowObject(WindowObject
);
3792 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3794 IntReleaseWindowObject(WindowObject
);
3798 if ((WindowObject
->Style
& (WS_MAXIMIZE
| WS_MINIMIZE
)) == 0)
3800 WinPosSetWindowPos(WindowObject
->Self
, NULL
,
3801 Safepl
.rcNormalPosition
.left
, Safepl
.rcNormalPosition
.top
,
3802 Safepl
.rcNormalPosition
.right
- Safepl
.rcNormalPosition
.left
,
3803 Safepl
.rcNormalPosition
.bottom
- Safepl
.rcNormalPosition
.top
,
3804 SWP_NOZORDER
| SWP_NOACTIVATE
);
3807 /* FIXME - change window status */
3808 WinPosShowWindow(WindowObject
->Self
, Safepl
.showCmd
);
3810 if (WindowObject
->InternalPos
== NULL
)
3811 WindowObject
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
3812 WindowObject
->InternalPos
->NormalRect
= Safepl
.rcNormalPosition
;
3813 WindowObject
->InternalPos
->IconPos
= Safepl
.ptMinPosition
;
3814 WindowObject
->InternalPos
->MaxPos
= Safepl
.ptMaxPosition
;
3816 IntReleaseWindowObject(WindowObject
);
3827 HWND hWndInsertAfter
,
3834 return WinPosSetWindowPos(hWnd
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3839 IntGetWindowRgn(HWND hWnd
, HRGN hRgn
)
3842 PWINDOW_OBJECT WindowObject
;
3846 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
3848 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3853 IntReleaseWindowObject(WindowObject
);
3857 /* Create a new window region using the window rectangle */
3858 VisRgn
= UnsafeIntCreateRectRgnIndirect(&WindowObject
->WindowRect
);
3859 NtGdiOffsetRgn(VisRgn
, -WindowObject
->WindowRect
.left
, -WindowObject
->WindowRect
.top
);
3860 /* if there's a region assigned to the window, combine them both */
3861 if(WindowObject
->WindowRegion
&& !(WindowObject
->Style
& WS_MINIMIZE
))
3862 NtGdiCombineRgn(VisRgn
, VisRgn
, WindowObject
->WindowRegion
, RGN_AND
);
3863 /* Copy the region into hRgn */
3864 NtGdiCombineRgn(hRgn
, VisRgn
, NULL
, RGN_COPY
);
3866 if((pRgn
= RGNDATA_LockRgn(hRgn
)))
3868 Ret
= pRgn
->rdh
.iType
;
3869 RGNDATA_UnlockRgn(hRgn
);
3874 NtGdiDeleteObject(VisRgn
);
3876 IntReleaseWindowObject(WindowObject
);
3881 IntGetWindowRgnBox(HWND hWnd
, RECT
*Rect
)
3884 PWINDOW_OBJECT WindowObject
;
3888 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
3890 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3895 IntReleaseWindowObject(WindowObject
);
3899 /* Create a new window region using the window rectangle */
3900 VisRgn
= UnsafeIntCreateRectRgnIndirect(&WindowObject
->WindowRect
);
3901 NtGdiOffsetRgn(VisRgn
, -WindowObject
->WindowRect
.left
, -WindowObject
->WindowRect
.top
);
3902 /* if there's a region assigned to the window, combine them both */
3903 if(WindowObject
->WindowRegion
&& !(WindowObject
->Style
& WS_MINIMIZE
))
3904 NtGdiCombineRgn(VisRgn
, VisRgn
, WindowObject
->WindowRegion
, RGN_AND
);
3906 if((pRgn
= RGNDATA_LockRgn(VisRgn
)))
3908 Ret
= pRgn
->rdh
.iType
;
3909 *Rect
= pRgn
->rdh
.rcBound
;
3910 RGNDATA_UnlockRgn(VisRgn
);
3915 NtGdiDeleteObject(VisRgn
);
3917 IntReleaseWindowObject(WindowObject
);
3931 PWINDOW_OBJECT WindowObject
;
3933 WindowObject
= IntGetWindowObject(hWnd
);
3934 if (WindowObject
== NULL
)
3936 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3940 /* FIXME - Verify if hRgn is a valid handle!!!!
3941 Propably make this operation thread-safe, but maybe it's not necessary */
3943 if(WindowObject
->WindowRegion
)
3945 /* Delete no longer needed region handle */
3946 NtGdiDeleteObject(WindowObject
->WindowRegion
);
3948 WindowObject
->WindowRegion
= hRgn
;
3950 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
3954 IntRedrawWindow(WindowObject
, NULL
, NULL
, RDW_INVALIDATE
);
3957 IntReleaseWindowObject(WindowObject
);
3966 NtUserShowWindow(HWND hWnd
,
3969 return WinPosShowWindow(hWnd
, nCmdShow
);
3977 NtUserShowWindowAsync(DWORD Unknown0
,
3990 NtUserUpdateLayeredWindow(DWORD Unknown0
,
4010 NtUserValidateRect(HWND hWnd
, const RECT
* Rect
)
4012 return (VOID
)NtUserRedrawWindow(hWnd
, Rect
, 0, RDW_VALIDATE
| RDW_NOCHILDREN
);
4020 NtUserWindowFromPoint(LONG X
, LONG Y
)
4024 PWINDOW_OBJECT DesktopWindow
, Window
= NULL
;
4026 if ((DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow())))
4033 Hit
= WinPosWindowFromPoint(DesktopWindow
, PsGetWin32Thread()->MessageQueue
, &pt
, &Window
);
4038 IntReleaseWindowObject(Window
);
4039 IntReleaseWindowObject(DesktopWindow
);
4043 IntReleaseWindowObject(DesktopWindow
);
4053 * Undocumented function that is called from DefWindowProc to set
4061 NtUserDefSetText(HWND WindowHandle
, PUNICODE_STRING WindowText
)
4063 PWINDOW_OBJECT WindowObject
;
4064 UNICODE_STRING SafeText
;
4067 WindowObject
= IntGetWindowObject(WindowHandle
);
4070 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4076 Status
= IntSafeCopyUnicodeString(&SafeText
, WindowText
);
4077 if(!NT_SUCCESS(Status
))
4079 SetLastNtError(Status
);
4080 IntReleaseWindowObject(WindowObject
);
4086 RtlInitUnicodeString(&SafeText
, NULL
);
4089 /* FIXME - do this thread-safe! otherwise one could crash here! */
4090 RtlFreeUnicodeString(&WindowObject
->WindowName
);
4092 WindowObject
->WindowName
= SafeText
;
4094 IntReleaseWindowObject(WindowObject
);
4099 * NtUserInternalGetWindowText
4106 NtUserInternalGetWindowText(HWND hWnd
, LPWSTR lpString
, INT nMaxCount
)
4108 PWINDOW_OBJECT WindowObject
;
4112 if(lpString
&& (nMaxCount
<= 1))
4114 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
4118 WindowObject
= IntGetWindowObject(hWnd
);
4121 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4125 /* FIXME - do this thread-safe! otherwise one could crash here! */
4126 Result
= WindowObject
->WindowName
.Length
/ sizeof(WCHAR
);
4129 const WCHAR Terminator
= L
'\0';
4131 WCHAR
*Buffer
= (WCHAR
*)lpString
;
4133 Copy
= min(nMaxCount
- 1, Result
);
4136 Status
= MmCopyToCaller(Buffer
, WindowObject
->WindowName
.Buffer
, Copy
* sizeof(WCHAR
));
4137 if(!NT_SUCCESS(Status
))
4139 SetLastNtError(Status
);
4140 IntReleaseWindowObject(WindowObject
);
4146 Status
= MmCopyToCaller(Buffer
, &Terminator
, sizeof(WCHAR
));
4147 if(!NT_SUCCESS(Status
))
4149 SetLastNtError(Status
);
4150 IntReleaseWindowObject(WindowObject
);
4157 IntReleaseWindowObject(WindowObject
);
4162 NtUserDereferenceWndProcHandle(WNDPROC wpHandle
, WndProcHandle
*Data
)
4164 WndProcHandle Entry
;
4165 if (((DWORD
)wpHandle
& 0xFFFF0000) == 0xFFFF0000)
4167 Entry
= WndProcHandlesArray
[(DWORD
)wpHandle
& 0x0000FFFF];
4168 Data
->WindowProc
= Entry
.WindowProc
;
4169 Data
->IsUnicode
= Entry
.IsUnicode
;
4170 Data
->ProcessID
= Entry
.ProcessID
;
4179 IntAddWndProcHandle(WNDPROC WindowProc
, BOOL IsUnicode
)
4184 WndProcHandle
*OldArray
;
4187 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4189 if (WndProcHandlesArray
[i
].WindowProc
== NULL
)
4197 OldArray
= WndProcHandlesArray
;
4198 OldArraySize
= WndProcHandlesArraySize
;
4199 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,(OldArraySize
+ WPH_SIZE
) * sizeof(WndProcHandle
), TAG_WINPROCLST
);
4200 WndProcHandlesArraySize
= OldArraySize
+ WPH_SIZE
;
4201 RtlCopyMemory(WndProcHandlesArray
,OldArray
,OldArraySize
* sizeof(WndProcHandle
));
4202 ExFreePool(OldArray
);
4203 FreeSpot
= OldArraySize
+ 1;
4205 WndProcHandlesArray
[FreeSpot
].WindowProc
= WindowProc
;
4206 WndProcHandlesArray
[FreeSpot
].IsUnicode
= IsUnicode
;
4207 WndProcHandlesArray
[FreeSpot
].ProcessID
= PsGetCurrentProcessId();
4208 return FreeSpot
+ 0xFFFF0000;
4212 IntRemoveWndProcHandle(WNDPROC Handle
)
4215 position
= (DWORD
)Handle
& 0x0000FFFF;
4216 if (position
> WndProcHandlesArraySize
)
4220 WndProcHandlesArray
[position
].WindowProc
= NULL
;
4221 WndProcHandlesArray
[position
].IsUnicode
= FALSE
;
4222 WndProcHandlesArray
[position
].ProcessID
= NULL
;
4227 IntRemoveProcessWndProcHandles(HANDLE ProcessID
)
4230 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4232 if (WndProcHandlesArray
[i
].ProcessID
== ProcessID
)
4234 WndProcHandlesArray
[i
].WindowProc
= NULL
;
4235 WndProcHandlesArray
[i
].IsUnicode
= FALSE
;
4236 WndProcHandlesArray
[i
].ProcessID
= NULL
;