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
);
150 PWINDOW_OBJECT FASTCALL
151 IntGetOwner(PWINDOW_OBJECT Wnd
)
155 IntLockRelatives(Wnd
);
157 IntUnLockRelatives(Wnd
);
159 return IntGetWindowObject(hWnd
);
162 PWINDOW_OBJECT FASTCALL
163 IntGetParentObject(PWINDOW_OBJECT Wnd
)
167 IntLockRelatives(Wnd
);
168 hParent
= Wnd
->Parent
;
169 IntUnLockRelatives(Wnd
);
170 return IntGetWindowObject(hParent
);
176 * Compile a list of all child window handles from given window.
179 * This function is similar to Wine WIN_ListChildren. The caller
180 * must free the returned list with ExFreePool.
184 IntWinListChildren(PWINDOW_OBJECT Window
)
186 PWINDOW_OBJECT Child
;
188 UINT Index
, NumChildren
= 0;
190 IntLockRelatives(Window
);
192 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
195 List
= ExAllocatePoolWithTag(PagedPool
, (NumChildren
+ 1) * sizeof(HWND
), TAG_WINLIST
);
198 DPRINT1("Failed to allocate memory for children array\n");
199 IntUnLockRelatives(Window
);
200 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
203 for (Child
= Window
->FirstChild
, Index
= 0;
205 Child
= Child
->NextSibling
, ++Index
)
206 List
[Index
] = Child
->Self
;
209 IntUnLockRelatives(Window
);
214 /***********************************************************************
217 static void IntSendDestroyMsg(HWND Wnd
)
220 PWINDOW_OBJECT Window
, Owner
, Parent
;
224 if (GetGUIThreadInfo(GetCurrentThreadId(), &info
))
226 if (Wnd
== info
.hwndCaret
)
233 Window
= IntGetWindowObject(Wnd
);
235 Owner
= IntGetOwner(Window
);
237 Parent
= IntGetParent(Window
);
239 IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
) Wnd
);
241 IntReleaseWindowObject(Parent
);
243 IntReleaseWindowObject(Owner
);
246 IntReleaseWindowObject(Window
);
249 /* The window could already be destroyed here */
252 * Send the WM_DESTROY to the window.
255 IntSendMessage(Wnd
, WM_DESTROY
, 0, 0);
258 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
259 * make sure that the window still exists when we come back.
267 if (!(pWndArray
= WIN_ListChildren( hwnd
))) return;
269 /* start from the end (FIXME: is this needed?) */
270 for (i
= 0; pWndArray
[i
]; i
++) ;
274 if (IsWindow( pWndArray
[i
] )) WIN_SendDestroyMsg( pWndArray
[i
] );
276 HeapFree(GetProcessHeap(), 0, pWndArray
);
280 DPRINT("destroyed itself while in WM_DESTROY!\n");
285 /***********************************************************************
288 * Destroy storage associated to a window. "Internals" p.358
290 static LRESULT
IntDestroyWindow(PWINDOW_OBJECT Window
,
291 PW32PROCESS ProcessData
,
292 PW32THREAD ThreadData
,
293 BOOLEAN SendMessages
)
297 PWINDOW_OBJECT Child
;
299 BOOLEAN BelongsToThreadData
;
303 IntLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
304 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
306 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
307 DPRINT("Tried to call IntDestroyWindow() twice\n");
310 Window
->Status
|= WINDOWSTATUS_DESTROYING
;
311 Window
->Flags
&= ~WS_VISIBLE
;
312 /* remove the window already at this point from the thread window list so we
313 don't get into trouble when destroying the thread windows while we're still
314 in IntDestroyWindow() */
315 RemoveEntryList(&Window
->ThreadListEntry
);
316 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
318 BelongsToThreadData
= IntWndBelongsToThread(Window
, ThreadData
);
320 IntDeRegisterShellHookWindow(Window
->Self
);
324 /* Send destroy messages */
325 IntSendDestroyMsg(Window
->Self
);
328 /* free child windows */
329 Children
= IntWinListChildren(Window
);
332 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
334 if ((Child
= IntGetWindowObject(*ChildHandle
)))
336 if(!IntWndBelongsToThread(Child
, ThreadData
))
338 /* send WM_DESTROY messages to windows not belonging to the same thread */
339 IntSendDestroyMsg(Child
->Self
);
342 IntDestroyWindow(Child
, ProcessData
, ThreadData
, SendMessages
);
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
);
358 if(BelongsToThreadData
)
359 IntSendMessage(Window
->Self
, WM_NCDESTROY
, 0, 0);
361 MsqRemoveTimersWindow(ThreadData
->MessageQueue
, Window
->Self
);
363 /* flush the message queue */
364 MsqRemoveWindowMessagesFromQueue(Window
);
366 /* from now on no messages can be sent to this window anymore */
367 IntLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
368 Window
->Status
|= WINDOWSTATUS_DESTROYED
;
369 /* don't remove the WINDOWSTATUS_DESTROYING bit */
370 IntUnLockThreadWindows(Window
->OwnerThread
->Tcb
.Win32Thread
);
372 /* reset shell window handles */
373 if(ThreadData
->Desktop
)
375 if (Window
->Self
== ThreadData
->Desktop
->WindowStation
->ShellWindow
)
376 ThreadData
->Desktop
->WindowStation
->ShellWindow
= NULL
;
378 if (Window
->Self
== ThreadData
->Desktop
->WindowStation
->ShellListView
)
379 ThreadData
->Desktop
->WindowStation
->ShellListView
= NULL
;
382 /* Unregister hot keys */
383 UnregisterWindowHotKeys (Window
);
385 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
388 WinPosCheckInternalPos(Window
->Self
);
389 if (Window
->Self
== GetCapture())
394 /* free resources associated with the window */
395 TIMER_RemoveWindowTimers(Window
->Self
);
398 if (!(Window
->Style
& WS_CHILD
) && Window
->IDMenu
399 && (Menu
= IntGetMenuObject((HMENU
)Window
->IDMenu
)))
401 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
403 IntReleaseMenuObject(Menu
);
406 if(Window
->SystemMenu
407 && (Menu
= IntGetMenuObject(Window
->SystemMenu
)))
409 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
410 Window
->SystemMenu
= (HMENU
)0;
411 IntReleaseMenuObject(Menu
);
414 DceFreeWindowDCE(Window
); /* Always do this to catch orphaned DCs */
416 WINPROC_FreeProc(Window
->winproc
, WIN_PROC_WINDOW
);
417 CLASS_RemoveWindow(Window
->Class
);
420 IntUnlinkWindow(Window
);
422 IntReferenceWindowObject(Window
);
423 ObmCloseHandle(ThreadData
->Desktop
->WindowStation
->HandleTable
, Window
->Self
);
425 IntDestroyScrollBars(Window
);
427 /* remove the window from the class object */
428 IntLockClassWindows(Window
->Class
);
429 RemoveEntryList(&Window
->ClassListEntry
);
430 IntUnLockClassWindows(Window
->Class
);
432 /* dereference the class */
433 ClassDereferenceObject(Window
->Class
);
434 Window
->Class
= NULL
;
436 if(Window
->WindowRegion
)
438 NtGdiDeleteObject(Window
->WindowRegion
);
441 RtlFreeUnicodeString(&Window
->WindowName
);
443 IntReleaseWindowObject(Window
);
449 IntGetWindowBorderMeasures(PWINDOW_OBJECT WindowObject
, UINT
*cx
, UINT
*cy
)
451 if(HAS_DLGFRAME(WindowObject
->Style
, WindowObject
->ExStyle
) && !(WindowObject
->Style
& WS_MINIMIZE
))
453 *cx
= NtUserGetSystemMetrics(SM_CXDLGFRAME
);
454 *cy
= NtUserGetSystemMetrics(SM_CYDLGFRAME
);
458 if(HAS_THICKFRAME(WindowObject
->Style
, WindowObject
->ExStyle
)&& !(WindowObject
->Style
& WS_MINIMIZE
))
460 *cx
= NtUserGetSystemMetrics(SM_CXFRAME
);
461 *cy
= NtUserGetSystemMetrics(SM_CYFRAME
);
463 else if(HAS_THINFRAME(WindowObject
->Style
, WindowObject
->ExStyle
))
465 *cx
= NtUserGetSystemMetrics(SM_CXBORDER
);
466 *cy
= NtUserGetSystemMetrics(SM_CYBORDER
);
476 IntGetWindowInfo(PWINDOW_OBJECT WindowObject
, PWINDOWINFO pwi
)
478 pwi
->cbSize
= sizeof(WINDOWINFO
);
479 pwi
->rcWindow
= WindowObject
->WindowRect
;
480 pwi
->rcClient
= WindowObject
->ClientRect
;
481 pwi
->dwStyle
= WindowObject
->Style
;
482 pwi
->dwExStyle
= WindowObject
->ExStyle
;
483 pwi
->dwWindowStatus
= (NtUserGetForegroundWindow() == WindowObject
->Self
); /* WS_ACTIVECAPTION */
484 IntGetWindowBorderMeasures(WindowObject
, &pwi
->cxWindowBorders
, &pwi
->cyWindowBorders
);
485 pwi
->atomWindowType
= (WindowObject
->Class
? WindowObject
->Class
->Atom
: 0);
486 pwi
->wCreatorVersion
= 0x400; /* FIXME - return a real version number */
492 PWINDOW_OBJECT WindowObject
,
496 PMENU_OBJECT OldMenuObject
, NewMenuObject
= NULL
;
498 *Changed
= (WindowObject
->IDMenu
!= (UINT
) Menu
);
504 if (0 != WindowObject
->IDMenu
)
506 OldMenuObject
= IntGetMenuObject((HMENU
) WindowObject
->IDMenu
);
507 ASSERT(NULL
== OldMenuObject
|| OldMenuObject
->MenuInfo
.Wnd
== WindowObject
->Self
);
511 OldMenuObject
= NULL
;
516 NewMenuObject
= IntGetMenuObject(Menu
);
517 if (NULL
== NewMenuObject
)
519 if (NULL
!= OldMenuObject
)
521 IntReleaseMenuObject(OldMenuObject
);
523 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
526 if (NULL
!= NewMenuObject
->MenuInfo
.Wnd
)
528 /* Can't use the same menu for two windows */
529 if (NULL
!= OldMenuObject
)
531 IntReleaseMenuObject(OldMenuObject
);
533 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
539 WindowObject
->IDMenu
= (UINT
) Menu
;
540 if (NULL
!= NewMenuObject
)
542 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
543 IntReleaseMenuObject(NewMenuObject
);
545 if (NULL
!= OldMenuObject
)
547 OldMenuObject
->MenuInfo
.Wnd
= NULL
;
548 IntReleaseMenuObject(OldMenuObject
);
555 /* INTERNAL ******************************************************************/
559 DestroyThreadWindows(struct _ETHREAD
*Thread
)
562 PW32PROCESS Win32Process
;
563 PW32THREAD Win32Thread
;
564 PWINDOW_OBJECT
*List
, *pWnd
;
567 Win32Thread
= Thread
->Tcb
.Win32Thread
;
568 Win32Process
= Thread
->ThreadsProcess
->Win32Process
;
570 IntLockThreadWindows(Win32Thread
);
571 Current
= Win32Thread
->WindowListHead
.Flink
;
572 while (Current
!= &(Win32Thread
->WindowListHead
))
575 Current
= Current
->Flink
;
580 List
= ExAllocatePool(PagedPool
, (Cnt
+ 1) * sizeof(PWINDOW_OBJECT
));
583 DPRINT("Not enough memory to allocate window handle list\n");
584 IntUnLockThreadWindows(Win32Thread
);
588 Current
= Win32Thread
->WindowListHead
.Flink
;
589 while (Current
!= &(Win32Thread
->WindowListHead
))
591 *pWnd
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
592 IntReferenceWindowObject(*pWnd
);
594 Current
= Current
->Flink
;
596 IntUnLockThreadWindows(Win32Thread
);
599 for(pWnd
= List
; *pWnd
; pWnd
++)
601 NtUserDestroyWindow((*pWnd
)->Self
);
602 IntReleaseWindowObject(*pWnd
);
608 IntUnLockThreadWindows(Win32Thread
);
614 * Returns client window rectangle relative to the upper-left corner of client area.
616 * \note Does not check the validity of the parameters
619 IntGetClientRect(PWINDOW_OBJECT WindowObject
, PRECT Rect
)
621 ASSERT( WindowObject
);
624 Rect
->left
= Rect
->top
= 0;
625 Rect
->right
= WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
;
626 Rect
->bottom
= WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
;
632 IntGetFocusWindow(VOID
)
634 PUSER_MESSAGE_QUEUE Queue
;
635 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
640 Queue
= (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
645 return(Queue
->FocusWindow
);
649 PMENU_OBJECT FASTCALL
650 IntGetSystemMenu(PWINDOW_OBJECT WindowObject
, BOOL bRevert
, BOOL RetMenu
)
652 PMENU_OBJECT MenuObject
, NewMenuObject
, SysMenuObject
, ret
= NULL
;
653 PW32THREAD W32Thread
;
654 HMENU NewMenu
, SysMenu
;
655 ROSMENUITEMINFO ItemInfo
;
659 W32Thread
= PsGetWin32Thread();
661 if(!W32Thread
->Desktop
)
664 if(WindowObject
->SystemMenu
)
666 MenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
669 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
670 WindowObject
->SystemMenu
= (HMENU
)0;
671 IntReleaseMenuObject(MenuObject
);
675 if(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
)
677 /* clone system menu */
678 MenuObject
= IntGetMenuObject(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
);
682 NewMenuObject
= IntCloneMenu(MenuObject
);
685 WindowObject
->SystemMenu
= NewMenuObject
->MenuInfo
.Self
;
686 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
687 NewMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
689 //IntReleaseMenuObject(NewMenuObject);
691 IntReleaseMenuObject(MenuObject
);
695 SysMenu
= NtUserCreateMenu(FALSE
);
700 SysMenuObject
= IntGetMenuObject(SysMenu
);
701 if (NULL
== SysMenuObject
)
703 NtUserDestroyMenu(SysMenu
);
706 SysMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
707 SysMenuObject
->MenuInfo
.Wnd
= WindowObject
->Self
;
708 NewMenu
= IntLoadSysMenuTemplate();
711 IntReleaseMenuObject(SysMenuObject
);
712 NtUserDestroyMenu(SysMenu
);
715 MenuObject
= IntGetMenuObject(NewMenu
);
718 IntReleaseMenuObject(SysMenuObject
);
719 NtUserDestroyMenu(SysMenu
);
723 NewMenuObject
= IntCloneMenu(MenuObject
);
726 NewMenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
| MF_POPUP
;
727 IntReleaseMenuObject(NewMenuObject
);
728 NtUserSetMenuDefaultItem(NewMenuObject
->MenuInfo
.Self
, SC_CLOSE
, FALSE
);
730 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
731 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
732 ItemInfo
.fType
= MF_POPUP
;
733 ItemInfo
.fState
= MFS_ENABLED
;
734 ItemInfo
.dwTypeData
= NULL
;
736 ItemInfo
.hSubMenu
= NewMenuObject
->MenuInfo
.Self
;
737 IntInsertMenuItem(SysMenuObject
, (UINT
) -1, TRUE
, &ItemInfo
);
739 WindowObject
->SystemMenu
= SysMenuObject
->MenuInfo
.Self
;
743 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
744 IntReleaseMenuObject(MenuObject
);
753 if(WindowObject
->SystemMenu
)
754 return IntGetMenuObject((HMENU
)WindowObject
->SystemMenu
);
762 IntIsChildWindow(HWND Parent
, HWND Child
)
764 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
766 if(!(BaseWindow
= IntGetWindowObject(Child
)))
774 if (Window
->Self
== Parent
)
776 if(Window
!= BaseWindow
)
777 IntReleaseWindowObject(Window
);
778 IntReleaseWindowObject(BaseWindow
);
781 if(!(Window
->Style
& WS_CHILD
))
783 if(Window
!= BaseWindow
)
784 IntReleaseWindowObject(Window
);
788 Window
= IntGetParentObject(Window
);
789 if(Old
!= BaseWindow
)
790 IntReleaseWindowObject(Old
);
793 IntReleaseWindowObject(BaseWindow
);
798 IntIsWindowVisible(HWND hWnd
)
800 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
802 if(!(BaseWindow
= IntGetWindowObject(hWnd
)))
810 if(!(Window
->Style
& WS_CHILD
))
814 if(!(Window
->Style
& WS_VISIBLE
))
816 if(Window
!= BaseWindow
)
817 IntReleaseWindowObject(Window
);
818 IntReleaseWindowObject(BaseWindow
);
822 Window
= IntGetParentObject(Window
);
823 if(Old
!= BaseWindow
)
824 IntReleaseWindowObject(Old
);
829 if(Window
->Style
& WS_VISIBLE
)
831 if(Window
!= BaseWindow
)
832 IntReleaseWindowObject(Window
);
833 IntReleaseWindowObject(BaseWindow
);
836 if(Window
!= BaseWindow
)
837 IntReleaseWindowObject(Window
);
839 IntReleaseWindowObject(BaseWindow
);
844 /* link the window into siblings and parent. children are kept in place. */
848 PWINDOW_OBJECT WndParent
,
849 PWINDOW_OBJECT WndPrevSibling
/* set to NULL if top sibling */
852 PWINDOW_OBJECT Parent
;
854 IntLockRelatives(Wnd
);
855 Wnd
->Parent
= WndParent
->Self
;
856 if ((Wnd
->PrevSibling
= WndPrevSibling
))
858 /* link after WndPrevSibling */
859 if ((Wnd
->NextSibling
= WndPrevSibling
->NextSibling
))
860 Wnd
->NextSibling
->PrevSibling
= Wnd
;
861 else if ((Parent
= IntGetWindowObject(Wnd
->Parent
)))
863 IntLockRelatives(Parent
);
864 if(Parent
->LastChild
== WndPrevSibling
)
865 Parent
->LastChild
= Wnd
;
866 IntUnLockRelatives(Parent
);
867 IntReleaseWindowObject(Parent
);
869 Wnd
->PrevSibling
->NextSibling
= Wnd
;
874 Parent
= IntGetWindowObject(Wnd
->Parent
);
875 if ((Wnd
->NextSibling
= WndParent
->FirstChild
))
876 Wnd
->NextSibling
->PrevSibling
= Wnd
;
879 IntLockRelatives(Parent
);
880 Parent
->LastChild
= Wnd
;
881 Parent
->FirstChild
= Wnd
;
882 IntUnLockRelatives(Parent
);
883 IntReleaseWindowObject(Parent
);
884 IntUnLockRelatives(Wnd
);
889 IntLockRelatives(Parent
);
890 Parent
->FirstChild
= Wnd
;
891 IntUnLockRelatives(Parent
);
892 IntReleaseWindowObject(Parent
);
895 IntUnLockRelatives(Wnd
);
899 IntSetOwner(HWND hWnd
, HWND hWndNewOwner
)
901 PWINDOW_OBJECT Wnd
, WndOldOwner
, WndNewOwner
;
904 Wnd
= IntGetWindowObject(hWnd
);
908 IntLockRelatives(Wnd
);
909 WndOldOwner
= IntGetWindowObject(Wnd
->Owner
);
912 ret
= WndOldOwner
->Self
;
913 IntReleaseWindowObject(WndOldOwner
);
920 if((WndNewOwner
= IntGetWindowObject(hWndNewOwner
)))
922 Wnd
->Owner
= hWndNewOwner
;
923 IntReleaseWindowObject(WndNewOwner
);
928 IntUnLockRelatives(Wnd
);
929 IntReleaseWindowObject(Wnd
);
933 PWINDOW_OBJECT FASTCALL
934 IntSetParent(PWINDOW_OBJECT Wnd
, PWINDOW_OBJECT WndNewParent
)
936 PWINDOW_OBJECT WndOldParent
, Sibling
, InsertAfter
;
937 HWND hWnd
, hWndNewParent
, hWndOldParent
;
942 ASSERT(WndNewParent
);
945 hWndNewParent
= WndNewParent
->Self
;
948 * Windows hides the window first, then shows it again
949 * including the WM_SHOWWINDOW messages and all
951 WasVisible
= WinPosShowWindow(hWnd
, SW_HIDE
);
953 /* Validate that window and parent still exist */
954 if (!IntIsWindow(hWnd
) || !IntIsWindow(hWndNewParent
))
957 /* Window must belong to current process */
958 if (Wnd
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
961 WndOldParent
= IntGetParentObject(Wnd
);
962 hWndOldParent
= (WndOldParent
? WndOldParent
->Self
: NULL
);
964 if (WndNewParent
!= WndOldParent
)
966 IntUnlinkWindow(Wnd
);
968 if (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
))
970 /* Not a TOPMOST window, put after TOPMOSTs of new parent */
971 IntLockRelatives(WndNewParent
);
972 Sibling
= WndNewParent
->FirstChild
;
973 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
975 InsertAfter
= Sibling
;
976 Sibling
= Sibling
->NextSibling
;
978 IntUnLockRelatives(WndNewParent
);
980 if (NULL
== InsertAfter
)
982 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
986 IntReferenceWindowObject(InsertAfter
);
987 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
988 IntReleaseWindowObject(InsertAfter
);
991 if (WndNewParent
->Self
!= IntGetDesktopWindow()) /* a child window */
993 if (!(Wnd
->Style
& WS_CHILD
))
995 //if ( Wnd->Menu ) DestroyMenu ( Wnd->menu );
996 IntSetMenu(Wnd
, NULL
, &MenuChanged
);
1002 * SetParent additionally needs to make hwnd the top window
1003 * in the z-order and send the expected WM_WINDOWPOSCHANGING and
1004 * WM_WINDOWPOSCHANGED notification messages.
1006 WinPosSetWindowPos(hWnd
, (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOP
: HWND_TOPMOST
),
1007 0, 0, 0, 0, SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
1008 | (WasVisible
? SWP_SHOWWINDOW
: 0));
1011 * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
1012 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
1016 * Validate that the old parent still exist, since it migth have been
1017 * destroyed during the last callbacks to user-mode
1021 if(!IntIsWindow(WndOldParent
->Self
))
1023 IntReleaseWindowObject(WndOldParent
);
1027 /* don't dereference the window object here, it must be done by the caller
1028 of IntSetParent() */
1029 return WndOldParent
;
1035 IntSetSystemMenu(PWINDOW_OBJECT WindowObject
, PMENU_OBJECT MenuObject
)
1037 PMENU_OBJECT OldMenuObject
;
1038 if(WindowObject
->SystemMenu
)
1040 OldMenuObject
= IntGetMenuObject(WindowObject
->SystemMenu
);
1043 OldMenuObject
->MenuInfo
.Flags
&= ~ MF_SYSMENU
;
1044 IntReleaseMenuObject(OldMenuObject
);
1050 /* FIXME check window style, propably return FALSE ? */
1051 WindowObject
->SystemMenu
= MenuObject
->MenuInfo
.Self
;
1052 MenuObject
->MenuInfo
.Flags
|= MF_SYSMENU
;
1055 WindowObject
->SystemMenu
= (HMENU
)0;
1061 /* unlink the window from siblings and parent. children are kept in place. */
1063 IntUnlinkWindow(PWINDOW_OBJECT Wnd
)
1065 PWINDOW_OBJECT WndParent
;
1067 IntLockRelatives(Wnd
);
1068 if((WndParent
= IntGetWindowObject(Wnd
->Parent
)))
1070 IntLockRelatives(WndParent
);
1073 if (Wnd
->NextSibling
) Wnd
->NextSibling
->PrevSibling
= Wnd
->PrevSibling
;
1074 else if (WndParent
&& WndParent
->LastChild
== Wnd
) WndParent
->LastChild
= Wnd
->PrevSibling
;
1076 if (Wnd
->PrevSibling
) Wnd
->PrevSibling
->NextSibling
= Wnd
->NextSibling
;
1077 else if (WndParent
&& WndParent
->FirstChild
== Wnd
) WndParent
->FirstChild
= Wnd
->NextSibling
;
1081 IntUnLockRelatives(WndParent
);
1082 IntReleaseWindowObject(WndParent
);
1084 Wnd
->PrevSibling
= Wnd
->NextSibling
= Wnd
->Parent
= NULL
;
1085 IntUnLockRelatives(Wnd
);
1091 PWINDOW_OBJECT Window
, Child
;
1093 if(!(Window
= IntGetWindowObject(IntGetDesktopWindow())))
1095 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1099 IntLockRelatives(Window
);
1100 for(Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
1102 if(Child
->Owner
&& Child
->Style
& WS_VISIBLE
)
1105 * The desktop has a popup window if one of them has
1106 * an owner window and is visible
1108 IntUnLockRelatives(Window
);
1109 IntReleaseWindowObject(Window
);
1113 IntUnLockRelatives(Window
);
1114 IntReleaseWindowObject(Window
);
1119 IntIsWindowInDestroy(PWINDOW_OBJECT Window
)
1121 return ((Window
->Status
& WINDOWSTATUS_DESTROYING
) == WINDOWSTATUS_DESTROYING
);
1124 /* FUNCTIONS *****************************************************************/
1130 NtUserAlterWindowStyle(DWORD Unknown0
,
1141 * As best as I can figure, this function is used by EnumWindows,
1142 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
1144 * It's supposed to build a list of HWNDs to return to the caller.
1145 * We can figure out what kind of list by what parameters are
1153 NtUserBuildHwndList(
1165 /* FIXME handle bChildren */
1169 PWINDOW_OBJECT Window
, Child
;
1170 if(!(Window
= IntGetWindowObject(hwndParent
)))
1172 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1176 IntLockRelatives(Window
);
1177 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1179 if(dwCount
++ < nBufSize
&& pWnd
)
1181 Status
= MmCopyToCaller(pWnd
++, &Child
->Self
, sizeof(HWND
));
1182 if(!NT_SUCCESS(Status
))
1184 SetLastNtError(Status
);
1189 IntUnLockRelatives(Window
);
1191 IntReleaseWindowObject(Window
);
1196 PW32THREAD W32Thread
;
1197 PLIST_ENTRY Current
;
1198 PWINDOW_OBJECT Window
;
1200 Status
= PsLookupThreadByThreadId((HANDLE
)dwThreadId
, &Thread
);
1201 if(!NT_SUCCESS(Status
))
1203 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1206 if(!(W32Thread
= Thread
->Tcb
.Win32Thread
))
1208 ObDereferenceObject(Thread
);
1209 DPRINT("Thread is not a GUI Thread!\n");
1210 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1214 IntLockThreadWindows(W32Thread
);
1215 Current
= W32Thread
->WindowListHead
.Flink
;
1216 while(Current
!= &(W32Thread
->WindowListHead
))
1218 Window
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
1221 if(dwCount
< nBufSize
&& pWnd
)
1223 Status
= MmCopyToCaller(pWnd
++, &Window
->Self
, sizeof(HWND
));
1224 if(!NT_SUCCESS(Status
))
1226 SetLastNtError(Status
);
1231 Current
= Current
->Flink
;
1233 IntUnLockThreadWindows(W32Thread
);
1235 ObDereferenceObject(Thread
);
1239 PDESKTOP_OBJECT Desktop
;
1240 PWINDOW_OBJECT Window
, Child
;
1242 if(hDesktop
== NULL
&& !(Desktop
= IntGetActiveDesktop()))
1244 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1250 Status
= IntValidateDesktopHandle(hDesktop
,
1254 if(!NT_SUCCESS(Status
))
1256 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1260 if(!(Window
= IntGetWindowObject(Desktop
->DesktopWindow
)))
1263 ObDereferenceObject(Desktop
);
1264 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1268 IntLockRelatives(Window
);
1269 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1271 if(dwCount
++ < nBufSize
&& pWnd
)
1273 Status
= MmCopyToCaller(pWnd
++, &Child
->Self
, sizeof(HWND
));
1274 if(!NT_SUCCESS(Status
))
1276 SetLastNtError(Status
);
1281 IntUnLockRelatives(Window
);
1283 IntReleaseWindowObject(Window
);
1285 ObDereferenceObject(Desktop
);
1296 NtUserChildWindowFromPointEx(HWND hwndParent
,
1301 PWINDOW_OBJECT Parent
;
1306 if(!(Parent
= IntGetWindowObject(hwndParent
)))
1308 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1315 if(Parent
->Self
!= IntGetDesktopWindow())
1317 Pt
.x
+= Parent
->ClientRect
.left
;
1318 Pt
.y
+= Parent
->ClientRect
.top
;
1321 if(!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
))
1323 IntReleaseWindowObject(Parent
);
1328 if((List
= IntWinListChildren(Parent
)))
1330 for(phWnd
= List
; *phWnd
; phWnd
++)
1332 PWINDOW_OBJECT Child
;
1333 if((Child
= IntGetWindowObject(*phWnd
)))
1335 if(!(Child
->Style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
))
1337 IntReleaseWindowObject(Child
);
1340 if((Child
->Style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
))
1342 IntReleaseWindowObject(Child
);
1345 if((Child
->ExStyle
& WS_EX_TRANSPARENT
) && (uiFlags
& CWP_SKIPTRANSPARENT
))
1347 IntReleaseWindowObject(Child
);
1350 if(IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
1353 IntReleaseWindowObject(Child
);
1356 IntReleaseWindowObject(Child
);
1362 IntReleaseWindowObject(Parent
);
1368 * calculates the default position of a window
1371 IntCalcDefPosSize(PWINDOW_OBJECT Parent
, PWINDOW_OBJECT WindowObject
, RECT
*rc
, BOOL IncPos
)
1378 IntGdiIntersectRect(rc
, rc
, &Parent
->ClientRect
);
1382 Pos
.x
= Parent
->TiledCounter
* (NtUserGetSystemMetrics(SM_CXSIZE
) + NtUserGetSystemMetrics(SM_CXFRAME
));
1383 Pos
.y
= Parent
->TiledCounter
* (NtUserGetSystemMetrics(SM_CYSIZE
) + NtUserGetSystemMetrics(SM_CYFRAME
));
1384 if(Pos
.x
> ((rc
->right
- rc
->left
) / 4) ||
1385 Pos
.y
> ((rc
->bottom
- rc
->top
) / 4))
1387 /* reset counter and position */
1390 Parent
->TiledCounter
= 0;
1392 Parent
->TiledCounter
++;
1403 Sz
.cx
= EngMulDiv(rc
->right
- rc
->left
, 3, 4);
1404 Sz
.cy
= EngMulDiv(rc
->bottom
- rc
->top
, 3, 4);
1408 rc
->right
= rc
->left
+ Sz
.cx
;
1409 rc
->bottom
= rc
->top
+ Sz
.cy
;
1418 IntCreateWindowEx(DWORD dwExStyle
,
1419 PUNICODE_STRING ClassName
,
1420 PUNICODE_STRING WindowName
,
1428 HINSTANCE hInstance
,
1431 BOOL bUnicodeWindow
)
1433 PWINSTATION_OBJECT WinStaObject
;
1434 PWNDCLASS_OBJECT ClassObject
;
1435 PWINDOW_OBJECT WindowObject
;
1436 PWINDOW_OBJECT ParentWindow
, OwnerWindow
;
1437 HWND ParentWindowHandle
;
1438 HWND OwnerWindowHandle
;
1439 PMENU_OBJECT SystemMenu
;
1444 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1449 CBT_CREATEWNDW CbtCreate
;
1456 ParentWindowHandle
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
1457 OwnerWindowHandle
= NULL
;
1459 if (hWndParent
== HWND_MESSAGE
)
1462 * native ole32.OleInitialize uses HWND_MESSAGE to create the
1463 * message window (style: WS_POPUP|WS_DISABLED)
1465 DPRINT1("FIXME - Parent is HWND_MESSAGE\n");
1467 else if (hWndParent
)
1469 if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1470 ParentWindowHandle
= hWndParent
;
1472 OwnerWindowHandle
= NtUserGetAncestor(hWndParent
, GA_ROOT
);
1474 else if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1476 return (HWND
)0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1479 if (NULL
!= ParentWindowHandle
)
1481 ParentWindow
= IntGetWindowObject(ParentWindowHandle
);
1485 ParentWindow
= NULL
;
1488 /* FIXME: parent must belong to the current process */
1490 /* Check the class. */
1491 ClassFound
= ClassReferenceClassByNameOrAtom(&ClassObject
, ClassName
->Buffer
, hInstance
);
1494 if (IS_ATOM(ClassName
->Buffer
))
1496 DPRINT1("Class 0x%x not found\n", (DWORD_PTR
) ClassName
->Buffer
);
1500 DPRINT1("Class %wZ not found\n", ClassName
);
1502 if (NULL
!= ParentWindow
)
1504 IntReleaseWindowObject(ParentWindow
);
1506 SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS
);
1510 /* Check the window station. */
1511 if (PsGetWin32Thread()->Desktop
== NULL
)
1513 ClassDereferenceObject(ClassObject
);
1514 if (NULL
!= ParentWindow
)
1516 IntReleaseWindowObject(ParentWindow
);
1518 DPRINT("Thread is not attached to a desktop! Cannot create window!\n");
1521 WinStaObject
= PsGetWin32Thread()->Desktop
->WindowStation
;
1522 ObReferenceObjectByPointer(WinStaObject
, KernelMode
, ExWindowStationObjectType
, 0);
1524 /* Create the window object. */
1525 WindowObject
= (PWINDOW_OBJECT
)
1526 ObmCreateObject(PsGetWin32Thread()->Desktop
->WindowStation
->HandleTable
, &Handle
,
1527 otWindow
, sizeof(WINDOW_OBJECT
) + ClassObject
->cbWndExtra
1530 DPRINT("Created object with handle %X\n", Handle
);
1533 ObDereferenceObject(WinStaObject
);
1534 ClassDereferenceObject(ClassObject
);
1535 if (NULL
!= ParentWindow
)
1537 IntReleaseWindowObject(ParentWindow
);
1539 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1542 ObDereferenceObject(WinStaObject
);
1544 if (NULL
== PsGetWin32Thread()->Desktop
->DesktopWindow
)
1546 /* If there is no desktop window yet, we must be creating it */
1547 PsGetWin32Thread()->Desktop
->DesktopWindow
= Handle
;
1551 * Fill out the structure describing it.
1553 WindowObject
->Class
= ClassObject
;
1554 IntLockClassWindows(ClassObject
);
1555 InsertTailList(&ClassObject
->ClassWindowsListHead
, &WindowObject
->ClassListEntry
);
1556 IntUnLockClassWindows(ClassObject
);
1558 WindowObject
->ExStyle
= dwExStyle
;
1559 WindowObject
->Style
= dwStyle
& ~WS_VISIBLE
;
1560 DPRINT("1: Style is now %lx\n", WindowObject
->Style
);
1562 WindowObject
->SystemMenu
= (HMENU
)0;
1563 WindowObject
->ContextHelpId
= 0;
1564 WindowObject
->IDMenu
= 0;
1565 WindowObject
->Instance
= hInstance
;
1566 WindowObject
->Self
= Handle
;
1567 if (0 != (dwStyle
& WS_CHILD
))
1569 WindowObject
->IDMenu
= (UINT
) hMenu
;
1573 IntSetMenu(WindowObject
, hMenu
, &MenuChanged
);
1575 WindowObject
->MessageQueue
= PsGetWin32Thread()->MessageQueue
;
1576 WindowObject
->Parent
= (ParentWindow
? ParentWindow
->Self
: NULL
);
1577 if((OwnerWindow
= IntGetWindowObject(OwnerWindowHandle
)))
1579 WindowObject
->Owner
= OwnerWindowHandle
;
1580 IntReleaseWindowObject(OwnerWindow
);
1583 WindowObject
->Owner
= NULL
;
1586 WindowObject
->UserData
= 0;
1587 if ((((DWORD
)ClassObject
->lpfnWndProcA
& 0xFFFF0000) != 0xFFFF0000)
1588 && (((DWORD
)ClassObject
->lpfnWndProcW
& 0xFFFF0000) != 0xFFFF0000))
1590 WindowObject
->Unicode
= bUnicodeWindow
;
1594 WindowObject
->Unicode
= ClassObject
->Unicode
;
1596 WindowObject
->WndProcA
= ClassObject
->lpfnWndProcA
;
1597 WindowObject
->WndProcW
= ClassObject
->lpfnWndProcW
;
1598 WindowObject
->OwnerThread
= PsGetCurrentThread();
1599 WindowObject
->FirstChild
= NULL
;
1600 WindowObject
->LastChild
= NULL
;
1601 WindowObject
->PrevSibling
= NULL
;
1602 WindowObject
->NextSibling
= NULL
;
1604 /* extra window data */
1605 if (ClassObject
->cbWndExtra
!= 0)
1607 WindowObject
->ExtraData
= (PCHAR
)(WindowObject
+ 1);
1608 WindowObject
->ExtraDataSize
= ClassObject
->cbWndExtra
;
1609 RtlZeroMemory(WindowObject
->ExtraData
, WindowObject
->ExtraDataSize
);
1613 WindowObject
->ExtraData
= NULL
;
1614 WindowObject
->ExtraDataSize
= 0;
1617 InitializeListHead(&WindowObject
->PropListHead
);
1618 ExInitializeFastMutex(&WindowObject
->PropListLock
);
1619 ExInitializeFastMutex(&WindowObject
->RelativesLock
);
1620 ExInitializeFastMutex(&WindowObject
->UpdateLock
);
1621 InitializeListHead(&WindowObject
->WndObjListHead
);
1622 ExInitializeFastMutex(&WindowObject
->WndObjListLock
);
1624 if (NULL
!= WindowName
->Buffer
)
1626 WindowObject
->WindowName
.MaximumLength
= WindowName
->MaximumLength
;
1627 WindowObject
->WindowName
.Length
= WindowName
->Length
;
1628 WindowObject
->WindowName
.Buffer
= ExAllocatePoolWithTag(PagedPool
, WindowName
->MaximumLength
,
1630 if (NULL
== WindowObject
->WindowName
.Buffer
)
1632 ClassDereferenceObject(ClassObject
);
1633 DPRINT1("Failed to allocate mem for window name\n");
1634 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1637 RtlCopyMemory(WindowObject
->WindowName
.Buffer
, WindowName
->Buffer
, WindowName
->MaximumLength
);
1641 RtlInitUnicodeString(&WindowObject
->WindowName
, NULL
);
1646 * This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1647 * tested for WS_POPUP
1649 if ((dwExStyle
& WS_EX_DLGMODALFRAME
) ||
1650 ((!(dwExStyle
& WS_EX_STATICEDGE
)) &&
1651 (dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
))))
1652 dwExStyle
|= WS_EX_WINDOWEDGE
;
1654 dwExStyle
&= ~WS_EX_WINDOWEDGE
;
1656 /* Correct the window style. */
1657 if (!(dwStyle
& WS_CHILD
))
1659 WindowObject
->Style
|= WS_CLIPSIBLINGS
;
1660 DPRINT("3: Style is now %lx\n", WindowObject
->Style
);
1661 if (!(dwStyle
& WS_POPUP
))
1663 WindowObject
->Style
|= WS_CAPTION
;
1664 WindowObject
->Flags
|= WINDOWOBJECT_NEED_SIZE
;
1665 DPRINT("4: Style is now %lx\n", WindowObject
->Style
);
1669 /* create system menu */
1670 if((WindowObject
->Style
& WS_SYSMENU
) &&
1671 (WindowObject
->Style
& WS_CAPTION
) == WS_CAPTION
)
1673 SystemMenu
= IntGetSystemMenu(WindowObject
, TRUE
, TRUE
);
1676 WindowObject
->SystemMenu
= SystemMenu
->MenuInfo
.Self
;
1677 IntReleaseMenuObject(SystemMenu
);
1681 /* Insert the window into the thread's window list. */
1682 IntLockThreadWindows(PsGetWin32Thread());
1683 InsertTailList (&PsGetWin32Thread()->WindowListHead
,
1684 &WindowObject
->ThreadListEntry
);
1685 IntUnLockThreadWindows(PsGetWin32Thread());
1687 /* Allocate a DCE for this window. */
1688 if (dwStyle
& CS_OWNDC
)
1690 WindowObject
->Dce
= DceAllocDCE(WindowObject
->Self
, DCE_WINDOW_DC
);
1692 /* FIXME: Handle "CS_CLASSDC" */
1700 Cs
.lpCreateParams
= lpParam
;
1701 Cs
.hInstance
= hInstance
;
1703 Cs
.hwndParent
= ParentWindowHandle
;
1709 Cs
.lpszName
= (LPCWSTR
) WindowName
;
1710 Cs
.lpszClass
= (LPCWSTR
) ClassName
;
1711 Cs
.dwExStyle
= dwExStyle
;
1712 CbtCreate
.lpcs
= &Cs
;
1713 CbtCreate
.hwndInsertAfter
= HWND_TOP
;
1714 if (HOOK_CallHooks(WH_CBT
, HCBT_CREATEWND
, (WPARAM
) Handle
, (LPARAM
) &CbtCreate
))
1716 if (NULL
!= ParentWindow
)
1718 IntReleaseWindowObject(ParentWindow
);
1721 /* FIXME - Delete window object and remove it from the thread windows list */
1722 /* FIXME - delete allocated DCE */
1724 ClassDereferenceObject(ClassObject
);
1725 DPRINT1("CBT-hook returned !0\n");
1734 /* default positioning for overlapped windows */
1735 if(!(WindowObject
->Style
& (WS_POPUP
| WS_CHILD
)))
1738 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
1739 BOOL CalculatedDefPosSize
= FALSE
;
1741 IntGetDesktopWorkArea(WindowObject
->OwnerThread
->Tcb
.Win32Thread
->Desktop
, &WorkArea
);
1744 ProcessParams
= PsGetCurrentProcess()->Peb
->ProcessParameters
;
1746 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1748 CalculatedDefPosSize
= IntCalcDefPosSize(ParentWindow
, WindowObject
, &rc
, TRUE
);
1750 if(ProcessParams
->dwFlags
& STARTF_USEPOSITION
)
1752 ProcessParams
->dwFlags
&= ~STARTF_USEPOSITION
;
1753 Pos
.x
= WorkArea
.left
+ ProcessParams
->dwX
;
1754 Pos
.y
= WorkArea
.top
+ ProcessParams
->dwY
;
1762 /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
1763 y is something else */
1764 if(y
!= CW_USEDEFAULT
&& y
!= CW_USEDEFAULT16
)
1769 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1771 if(!CalculatedDefPosSize
)
1773 IntCalcDefPosSize(ParentWindow
, WindowObject
, &rc
, FALSE
);
1775 if(ProcessParams
->dwFlags
& STARTF_USESIZE
)
1777 ProcessParams
->dwFlags
&= ~STARTF_USESIZE
;
1778 Size
.cx
= ProcessParams
->dwXSize
;
1779 Size
.cy
= ProcessParams
->dwYSize
;
1783 Size
.cx
= rc
.right
- rc
.left
;
1784 Size
.cy
= rc
.bottom
- rc
.top
;
1787 /* move the window if necessary */
1789 Pos
.x
= max(rc
.left
, 0);
1791 Pos
.y
= max(rc
.top
, 0);
1796 /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
1797 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1802 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1809 /* Initialize the window dimensions. */
1810 WindowObject
->WindowRect
.left
= Pos
.x
;
1811 WindowObject
->WindowRect
.top
= Pos
.y
;
1812 WindowObject
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1813 WindowObject
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1814 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1816 IntGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1817 ParentWindow
->ClientRect
.top
);
1819 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1822 * Get the size and position of the window.
1824 if ((dwStyle
& WS_THICKFRAME
) || !(dwStyle
& (WS_POPUP
| WS_CHILD
)))
1826 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1828 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1829 WinPosGetMinMaxInfo(WindowObject
, &MaxSize
, &MaxPos
, &MinTrack
,
1831 if (MaxSize
.x
< nWidth
) nWidth
= MaxSize
.x
;
1832 if (MaxSize
.y
< nHeight
) nHeight
= MaxSize
.y
;
1833 if (nWidth
< MinTrack
.x
) nWidth
= MinTrack
.x
;
1834 if (nHeight
< MinTrack
.y
) nHeight
= MinTrack
.y
;
1835 if (nWidth
< 0) nWidth
= 0;
1836 if (nHeight
< 0) nHeight
= 0;
1839 WindowObject
->WindowRect
.left
= Pos
.x
;
1840 WindowObject
->WindowRect
.top
= Pos
.y
;
1841 WindowObject
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1842 WindowObject
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1843 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1845 IntGdiOffsetRect(&(WindowObject
->WindowRect
), ParentWindow
->ClientRect
.left
,
1846 ParentWindow
->ClientRect
.top
);
1848 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
1850 /* FIXME: Initialize the window menu. */
1852 /* Send a NCCREATE message. */
1858 DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d\n", Cs
.style
, Cs
.dwExStyle
, Cs
.hwndParent
);
1859 DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1860 DPRINT("IntCreateWindowEx(): About to send NCCREATE message.\n");
1861 Result
= IntSendMessage(WindowObject
->Self
, WM_NCCREATE
, 0, (LPARAM
) &Cs
);
1864 /* FIXME: Cleanup. */
1865 if (NULL
!= ParentWindow
)
1867 IntReleaseWindowObject(ParentWindow
);
1869 DPRINT("IntCreateWindowEx(): NCCREATE message failed.\n");
1873 /* Calculate the non-client size. */
1874 MaxPos
.x
= WindowObject
->WindowRect
.left
;
1875 MaxPos
.y
= WindowObject
->WindowRect
.top
;
1876 DPRINT("IntCreateWindowEx(): About to get non-client size.\n");
1877 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1878 Result
= WinPosGetNonClientSize(WindowObject
->Self
,
1879 &WindowObject
->WindowRect
,
1880 &WindowObject
->ClientRect
);
1881 IntGdiOffsetRect(&WindowObject
->WindowRect
,
1882 MaxPos
.x
- WindowObject
->WindowRect
.left
,
1883 MaxPos
.y
- WindowObject
->WindowRect
.top
);
1885 if (NULL
!= ParentWindow
)
1887 /* link the window into the parent's child list */
1888 if ((dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
1890 PWINDOW_OBJECT PrevSibling
;
1891 IntLockRelatives(ParentWindow
);
1892 if((PrevSibling
= ParentWindow
->LastChild
))
1893 IntReferenceWindowObject(PrevSibling
);
1894 IntUnLockRelatives(ParentWindow
);
1895 /* link window as bottom sibling */
1896 IntLinkWindow(WindowObject
, ParentWindow
, PrevSibling
/*prev sibling*/);
1898 IntReleaseWindowObject(PrevSibling
);
1902 /* link window as top sibling (but after topmost siblings) */
1903 PWINDOW_OBJECT InsertAfter
, Sibling
;
1904 if (0 == (dwExStyle
& WS_EX_TOPMOST
))
1906 IntLockRelatives(ParentWindow
);
1908 Sibling
= ParentWindow
->FirstChild
;
1909 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
1911 InsertAfter
= Sibling
;
1912 Sibling
= Sibling
->NextSibling
;
1914 IntUnLockRelatives(ParentWindow
);
1920 if (NULL
!= InsertAfter
)
1922 IntReferenceWindowObject(InsertAfter
);
1924 IntLinkWindow(WindowObject
, ParentWindow
, InsertAfter
/* prev sibling */);
1925 if (NULL
!= InsertAfter
)
1927 IntReleaseWindowObject(InsertAfter
);
1932 /* Send the WM_CREATE message. */
1933 DPRINT("IntCreateWindowEx(): about to send CREATE message.\n");
1934 Result
= IntSendMessage(WindowObject
->Self
, WM_CREATE
, 0, (LPARAM
) &Cs
);
1935 if (Result
== (LRESULT
)-1)
1937 /* FIXME: Cleanup. */
1938 if (NULL
!= ParentWindow
)
1940 IntReleaseWindowObject(ParentWindow
);
1942 ClassDereferenceObject(ClassObject
);
1943 DPRINT("IntCreateWindowEx(): send CREATE message failed.\n");
1947 /* Send move and size messages. */
1948 if (!(WindowObject
->Flags
& WINDOWOBJECT_NEED_SIZE
))
1952 DPRINT("IntCreateWindow(): About to send WM_SIZE\n");
1954 if ((WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
) < 0 ||
1955 (WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
) < 0)
1957 DPRINT("Sending bogus WM_SIZE\n");
1960 lParam
= MAKE_LONG(WindowObject
->ClientRect
.right
-
1961 WindowObject
->ClientRect
.left
,
1962 WindowObject
->ClientRect
.bottom
-
1963 WindowObject
->ClientRect
.top
);
1964 IntSendMessage(WindowObject
->Self
, WM_SIZE
, SIZE_RESTORED
,
1967 DPRINT("IntCreateWindow(): About to send WM_MOVE\n");
1969 if (0 != (WindowObject
->Style
& WS_CHILD
) && ParentWindow
)
1971 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
- ParentWindow
->ClientRect
.left
,
1972 WindowObject
->ClientRect
.top
- ParentWindow
->ClientRect
.top
);
1976 lParam
= MAKE_LONG(WindowObject
->ClientRect
.left
,
1977 WindowObject
->ClientRect
.top
);
1979 IntSendMessage(WindowObject
->Self
, WM_MOVE
, 0, lParam
);
1981 /* Call WNDOBJ change procs */
1982 IntEngWindowChanged(WindowObject
, WOC_RGN_CLIENT
);
1985 /* Show or maybe minimize or maximize the window. */
1986 if (WindowObject
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1991 SwFlag
= (WindowObject
->Style
& WS_MINIMIZE
) ? SW_MINIMIZE
:
1993 WinPosMinMaximize(WindowObject
, SwFlag
, &NewPos
);
1995 ((WindowObject
->Style
& WS_CHILD
) || NtUserGetActiveWindow()) ?
1996 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
:
1997 SWP_NOZORDER
| SWP_FRAMECHANGED
;
1998 DPRINT("IntCreateWindow(): About to minimize/maximize\n");
1999 DPRINT("%d,%d %dx%d\n", NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
);
2000 WinPosSetWindowPos(WindowObject
->Self
, 0, NewPos
.left
, NewPos
.top
,
2001 NewPos
.right
, NewPos
.bottom
, SwFlag
);
2004 /* Notify the parent window of a new child. */
2005 if ((WindowObject
->Style
& WS_CHILD
) &&
2006 (!(WindowObject
->ExStyle
& WS_EX_NOPARENTNOTIFY
)) && ParentWindow
)
2008 DPRINT("IntCreateWindow(): About to notify parent\n");
2009 IntSendMessage(ParentWindow
->Self
,
2011 MAKEWPARAM(WM_CREATE
, WindowObject
->IDMenu
),
2012 (LPARAM
)WindowObject
->Self
);
2015 if ((!hWndParent
) && (!HasOwner
)) {
2016 DPRINT("Sending CREATED notify\n");
2017 IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Handle
);
2019 DPRINT("Not sending CREATED notify, %x %d\n", ParentWindow
, HasOwner
);
2022 if (NULL
!= ParentWindow
)
2024 IntReleaseWindowObject(ParentWindow
);
2027 /* Initialize and show the window's scrollbars */
2028 if (WindowObject
->Style
& WS_VSCROLL
)
2030 NtUserShowScrollBar(WindowObject
->Self
, SB_VERT
, TRUE
);
2032 if (WindowObject
->Style
& WS_HSCROLL
)
2034 NtUserShowScrollBar(WindowObject
->Self
, SB_HORZ
, TRUE
);
2037 if (dwStyle
& WS_VISIBLE
)
2039 DPRINT("IntCreateWindow(): About to show window\n");
2040 WinPosShowWindow(WindowObject
->Self
, dwShowMode
);
2043 DPRINT("IntCreateWindow(): = %X\n", Handle
);
2044 DPRINT("WindowObject->SystemMenu = 0x%x\n", WindowObject
->SystemMenu
);
2045 return((HWND
)Handle
);
2049 NtUserCreateWindowEx(DWORD dwExStyle
,
2050 PUNICODE_STRING UnsafeClassName
,
2051 PUNICODE_STRING UnsafeWindowName
,
2059 HINSTANCE hInstance
,
2062 BOOL bUnicodeWindow
)
2065 UNICODE_STRING WindowName
;
2066 UNICODE_STRING ClassName
;
2069 DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
2071 /* Get the class name (string or atom) */
2072 Status
= MmCopyFromCaller(&ClassName
, UnsafeClassName
, sizeof(UNICODE_STRING
));
2073 if (! NT_SUCCESS(Status
))
2075 SetLastNtError(Status
);
2078 if (! IS_ATOM(ClassName
.Buffer
))
2080 Status
= IntSafeCopyUnicodeStringTerminateNULL(&ClassName
, UnsafeClassName
);
2081 if (! NT_SUCCESS(Status
))
2083 SetLastNtError(Status
);
2088 /* safely copy the window name */
2089 if (NULL
!= UnsafeWindowName
)
2091 Status
= IntSafeCopyUnicodeString(&WindowName
, UnsafeWindowName
);
2092 if (! NT_SUCCESS(Status
))
2094 if (! IS_ATOM(ClassName
.Buffer
))
2096 RtlFreeUnicodeString(&ClassName
);
2098 SetLastNtError(Status
);
2104 RtlInitUnicodeString(&WindowName
, NULL
);
2107 NewWindow
= IntCreateWindowEx(dwExStyle
, &ClassName
, &WindowName
, dwStyle
, x
, y
, nWidth
, nHeight
,
2108 hWndParent
, hMenu
, hInstance
, lpParam
, dwShowMode
, bUnicodeWindow
);
2110 RtlFreeUnicodeString(&WindowName
);
2111 if (! IS_ATOM(ClassName
.Buffer
))
2113 RtlFreeUnicodeString(&ClassName
);
2123 NtUserDeferWindowPos(HDWP WinPosInfo
,
2125 HWND WndInsertAfter
,
2142 NtUserDestroyWindow(HWND Wnd
)
2144 PWINDOW_OBJECT Window
;
2147 Window
= IntGetWindowObject(Wnd
);
2153 /* Check for owner thread and desktop window */
2154 if ((Window
->OwnerThread
!= PsGetCurrentThread()) || IntIsDesktopWindow(Window
))
2156 IntReleaseWindowObject(Window
);
2157 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2161 /* Look whether the focus is within the tree of windows we will
2164 if (!WinPosShowWindow(Wnd
, SW_HIDE
))
2166 if (NtUserGetActiveWindow() == Wnd
)
2168 WinPosActivateOtherWindow(Window
);
2171 IntLockMessageQueue(Window
->MessageQueue
);
2172 if (Window
->MessageQueue
->ActiveWindow
== Window
->Self
)
2173 Window
->MessageQueue
->ActiveWindow
= NULL
;
2174 if (Window
->MessageQueue
->FocusWindow
== Window
->Self
)
2175 Window
->MessageQueue
->FocusWindow
= NULL
;
2176 if (Window
->MessageQueue
->CaptureWindow
== Window
->Self
)
2177 Window
->MessageQueue
->CaptureWindow
= NULL
;
2178 IntUnLockMessageQueue(Window
->MessageQueue
);
2182 if (HOOK_CallHooks(WH_CBT
, HCBT_DESTROYWND
, (WPARAM
) hwnd
, 0, TRUE
))
2188 IntEngWindowChanged(Window
, WOC_DELETE
);
2189 isChild
= (0 != (Window
->Style
& WS_CHILD
));
2194 if (! USER_IsExitingThread(GetCurrentThreadId()))
2196 send_parent_notify(hwnd
, WM_DESTROY
);
2199 else if (NULL
!= GetWindow(Wnd
, GW_OWNER
))
2201 HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
2202 /* FIXME: clean up palette - see "Internals" p.352 */
2206 if (!IntIsWindow(Wnd
))
2211 /* Recursively destroy owned windows */
2216 BOOL GotOne
= FALSE
;
2219 PWINDOW_OBJECT Child
, Desktop
;
2221 Desktop
= IntGetWindowObject(IntGetDesktopWindow());
2222 Children
= IntWinListChildren(Desktop
);
2223 IntReleaseWindowObject(Desktop
);
2226 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
2228 Child
= IntGetWindowObject(*ChildHandle
);
2231 IntLockRelatives(Child
);
2232 if (Child
->Owner
!= Window
->Self
)
2234 IntUnLockRelatives(Child
);
2235 IntReleaseWindowObject(Child
);
2238 IntUnLockRelatives(Child
);
2239 if (IntWndBelongsToThread(Child
, PsGetWin32Thread()))
2241 IntReleaseWindowObject(Child
);
2242 NtUserDestroyWindow(*ChildHandle
);
2246 IntLockRelatives(Child
);
2247 if (Child
->Owner
!= NULL
)
2249 Child
->Owner
= NULL
;
2251 IntUnLockRelatives(Child
);
2252 IntReleaseWindowObject(Child
);
2254 ExFreePool(Children
);
2263 if (!IntIsWindow(Wnd
))
2265 IntReleaseWindowObject(Window
);
2269 /* Destroy the window storage */
2270 IntDestroyWindow(Window
, PsGetWin32Process(), PsGetWin32Thread(), TRUE
);
2272 IntReleaseWindowObject(Window
);
2282 NtUserDrawMenuBarTemp(
2289 /* we'll use this function just for caching the menu bar */
2299 NtUserEndDeferWindowPosEx(DWORD Unknown0
,
2312 NtUserFillWindow(DWORD Unknown0
,
2324 IntFindWindow(PWINDOW_OBJECT Parent
,
2325 PWINDOW_OBJECT ChildAfter
,
2327 PUNICODE_STRING WindowName
)
2329 BOOL CheckWindowName
;
2335 CheckWindowName
= (WindowName
&& (WindowName
->Length
> 0));
2337 if((List
= IntWinListChildren(Parent
)))
2342 /* skip handles before and including ChildAfter */
2343 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->Self
));
2346 /* search children */
2349 PWINDOW_OBJECT Child
;
2350 if(!(Child
= IntGetWindowObject(*(phWnd
++))))
2355 /* Do not send WM_GETTEXT messages in the kernel mode version!
2356 The user mode version however calls GetWindowText() which will
2357 send WM_GETTEXT messages to windows belonging to its processes */
2358 if((!CheckWindowName
|| !RtlCompareUnicodeString(WindowName
, &(Child
->WindowName
), FALSE
)) &&
2359 (!ClassAtom
|| Child
->Class
->Atom
== ClassAtom
))
2362 IntReleaseWindowObject(Child
);
2366 IntReleaseWindowObject(Child
);
2376 * Searches a window's children for a window with the specified
2379 * hwndParent = The window whose childs are to be searched.
2381 * HWND_MESSAGE = message-only windows
2383 * hwndChildAfter = Search starts after this child window.
2384 * NULL = start from beginning
2386 * ucClassName = Class name to search for
2387 * Reguired parameter.
2389 * ucWindowName = Window name
2390 * ->Buffer == NULL = don't care
2393 * The HWND of the window if it was found, otherwise NULL
2399 NtUserFindWindowEx(HWND hwndParent
,
2400 HWND hwndChildAfter
,
2401 PUNICODE_STRING ucClassName
,
2402 PUNICODE_STRING ucWindowName
)
2404 PWINDOW_OBJECT Parent
, ChildAfter
;
2405 UNICODE_STRING ClassName
, WindowName
;
2407 HWND Desktop
, Ret
= NULL
;
2410 Desktop
= IntGetCurrentThreadDesktopWindow();
2412 if(hwndParent
== NULL
)
2413 hwndParent
= Desktop
;
2415 else if(hwndParent == HWND_MESSAGE)
2417 hwndParent = IntGetMessageWindow();
2421 if(!(Parent
= IntGetWindowObject(hwndParent
)))
2423 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2428 if(hwndChildAfter
&& !(ChildAfter
= IntGetWindowObject(hwndChildAfter
)))
2430 IntReleaseWindowObject(Parent
);
2431 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2435 /* copy the window name */
2436 Status
= IntSafeCopyUnicodeString(&WindowName
, ucWindowName
);
2437 if(!NT_SUCCESS(Status
))
2439 SetLastNtError(Status
);
2443 /* safely copy the class name */
2444 Status
= MmCopyFromCaller(&ClassName
, ucClassName
, sizeof(UNICODE_STRING
));
2445 if(!NT_SUCCESS(Status
))
2447 SetLastNtError(Status
);
2450 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2453 /* safely copy the class name string (NULL terminated because class-lookup
2455 buf
= ExAllocatePoolWithTag(PagedPool
, ClassName
.Length
+ sizeof(WCHAR
), TAG_STRING
);
2458 SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES
);
2461 Status
= MmCopyFromCaller(buf
, ClassName
.Buffer
, ClassName
.Length
);
2462 if(!NT_SUCCESS(Status
))
2465 SetLastNtError(Status
);
2468 ClassName
.Buffer
= buf
;
2469 /* make sure the string is null-terminated */
2470 buf
+= ClassName
.Length
/ sizeof(WCHAR
);
2474 /* find the class object */
2475 if(ClassName
.Buffer
)
2477 PWINSTATION_OBJECT WinStaObject
;
2479 if (PsGetWin32Thread()->Desktop
== NULL
)
2481 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2485 WinStaObject
= PsGetWin32Thread()->Desktop
->WindowStation
;
2487 Status
= RtlLookupAtomInAtomTable(
2488 WinStaObject
->AtomTable
,
2492 if (!NT_SUCCESS(Status
))
2494 DPRINT1("Failed to lookup class atom!\n");
2495 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST
);
2500 if(Parent
->Self
== Desktop
)
2503 PWINDOW_OBJECT TopLevelWindow
;
2504 BOOLEAN CheckWindowName
;
2505 BOOLEAN CheckClassName
;
2506 BOOLEAN WindowMatches
;
2507 BOOLEAN ClassMatches
;
2509 /* windows searches through all top-level windows if the parent is the desktop
2512 if((List
= IntWinListChildren(Parent
)))
2518 /* skip handles before and including ChildAfter */
2519 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->Self
));
2522 CheckWindowName
= WindowName
.Length
> 0;
2523 CheckClassName
= ClassName
.Buffer
!= NULL
;
2525 /* search children */
2528 if(!(TopLevelWindow
= IntGetWindowObject(*(phWnd
++))))
2533 /* Do not send WM_GETTEXT messages in the kernel mode version!
2534 The user mode version however calls GetWindowText() which will
2535 send WM_GETTEXT messages to windows belonging to its processes */
2536 WindowMatches
= !CheckWindowName
|| !RtlCompareUnicodeString(
2537 &WindowName
, &TopLevelWindow
->WindowName
, FALSE
);
2538 ClassMatches
= !CheckClassName
||
2539 ClassAtom
== TopLevelWindow
->Class
->Atom
;
2541 if (WindowMatches
&& ClassMatches
)
2543 Ret
= TopLevelWindow
->Self
;
2544 IntReleaseWindowObject(TopLevelWindow
);
2548 if (IntFindWindow(TopLevelWindow
, NULL
, ClassAtom
, &WindowName
))
2550 /* window returns the handle of the top-level window, in case it found
2552 Ret
= TopLevelWindow
->Self
;
2553 IntReleaseWindowObject(TopLevelWindow
);
2557 IntReleaseWindowObject(TopLevelWindow
);
2563 Ret
= IntFindWindow(Parent
, ChildAfter
, ClassAtom
, &WindowName
);
2566 if(Ret
== NULL
&& hwndParent
== NULL
&& hwndChildAfter
== NULL
)
2568 /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
2569 search the message-only windows. Should this also be done if
2570 Parent is the desktop window??? */
2571 PWINDOW_OBJECT MsgWindows
;
2573 if((MsgWindows
= IntGetWindowObject(IntGetMessageWindow())))
2575 Ret
= IntFindWindow(MsgWindows
, ChildAfter
, ClassAtom
, &WindowName
);
2576 IntReleaseWindowObject(MsgWindows
);
2582 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2583 ExFreePool(ClassName
.Buffer
);
2586 RtlFreeUnicodeString(&WindowName
);
2590 IntReleaseWindowObject(ChildAfter
);
2591 IntReleaseWindowObject(Parent
);
2601 NtUserFlashWindowEx(DWORD Unknown0
)
2613 NtUserGetAncestor(HWND hWnd
, UINT Type
)
2615 PWINDOW_OBJECT Wnd
, WndAncestor
, Parent
;
2618 if (hWnd
== IntGetDesktopWindow())
2623 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2625 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2633 WndAncestor
= IntGetParentObject(Wnd
);
2646 if(!(Parent
= IntGetParentObject(WndAncestor
)))
2650 if(IntIsDesktopWindow(Parent
))
2652 IntReleaseWindowObject(Parent
);
2656 IntReleaseWindowObject(tmp
);
2657 WndAncestor
= Parent
;
2665 IntReferenceWindowObject(WndAncestor
);
2670 Parent
= IntGetParent(WndAncestor
);
2671 IntReleaseWindowObject(Old
);
2676 WndAncestor
= Parent
;
2683 IntReleaseWindowObject(Wnd
);
2688 hWndAncestor
= (WndAncestor
? WndAncestor
->Self
: NULL
);
2689 IntReleaseWindowObject(Wnd
);
2691 if(WndAncestor
&& (WndAncestor
!= Wnd
))
2692 IntReleaseWindowObject(WndAncestor
);
2694 return hWndAncestor
;
2699 * Returns client window rectangle relative to the upper-left corner of client area.
2701 * \param hWnd window handle.
2702 * \param Rect pointer to the buffer where the coordinates are returned.
2709 NtUserGetClientRect(HWND hWnd
, LPRECT Rect
)
2711 PWINDOW_OBJECT WindowObject
;
2714 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
2716 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2720 IntGetClientRect(WindowObject
, &SafeRect
);
2721 IntReleaseWindowObject(WindowObject
);
2723 if(!NT_SUCCESS(MmCopyToCaller(Rect
, &SafeRect
, sizeof(RECT
))))
2735 NtUserGetDesktopWindow()
2737 return IntGetDesktopWindow();
2745 NtUserGetInternalWindowPos(DWORD Unknown0
,
2759 NtUserGetLastActivePopup(HWND hWnd
)
2762 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2763 * not changed anywhere.
2764 * -- Filip, 01/nov/2003
2770 IntAcquireWinLockShared();
2772 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2774 IntReleaseWinLock();
2775 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2779 hWndLastPopup
= Wnd
->hWndLastPopup
;
2781 IntReleaseWinLock();
2783 return hWndLastPopup
;
2792 * The NtUserGetParent function retrieves a handle to the specified window's
2796 * Note that, despite its name, this function can return an owner window
2797 * instead of a parent window.
2804 NtUserGetParent(HWND hWnd
)
2806 PWINDOW_OBJECT Wnd
, WndParent
;
2807 HWND hWndParent
= NULL
;
2809 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2811 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2815 WndParent
= IntGetParent(Wnd
);
2818 hWndParent
= WndParent
->Self
;
2819 IntReleaseWindowObject(WndParent
);
2822 IntReleaseWindowObject(Wnd
);
2830 * The NtUserSetParent function changes the parent window of the specified
2834 * The new parent window and the child window must belong to the same
2835 * application. If the window identified by the hWndChild parameter is
2836 * visible, the system performs the appropriate redrawing and repainting.
2837 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2838 * or WS_POPUP window styles of the window whose parent is being changed.
2845 NtUserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2847 PWINDOW_OBJECT Wnd
= NULL
, WndParent
= NULL
, WndOldParent
;
2848 HWND hWndOldParent
= NULL
;
2850 if (IntIsBroadcastHwnd(hWndChild
) || IntIsBroadcastHwnd(hWndNewParent
))
2852 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2856 if (hWndChild
== IntGetDesktopWindow())
2858 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2864 if (!(WndParent
= IntGetWindowObject(hWndNewParent
)))
2866 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2872 if (!(WndParent
= IntGetWindowObject(IntGetDesktopWindow())))
2874 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2879 if (!(Wnd
= IntGetWindowObject(hWndChild
)))
2881 IntReleaseWindowObject(WndParent
);
2882 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2886 WndOldParent
= IntSetParent(Wnd
, WndParent
);
2890 hWndOldParent
= WndOldParent
->Self
;
2891 IntReleaseWindowObject(WndOldParent
);
2894 IntReleaseWindowObject(Wnd
);
2895 IntReleaseWindowObject(WndParent
);
2897 return hWndOldParent
;
2901 * NtUserGetShellWindow
2903 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
2910 NtUserGetShellWindow()
2912 PWINSTATION_OBJECT WinStaObject
;
2915 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
2920 if (!NT_SUCCESS(Status
))
2922 SetLastNtError(Status
);
2926 Ret
= (HWND
)WinStaObject
->ShellWindow
;
2928 ObDereferenceObject(WinStaObject
);
2933 * NtUserSetShellWindowEx
2935 * This is undocumented function to set global shell window. The global
2936 * shell window has special handling of window position.
2943 NtUserSetShellWindowEx(HWND hwndShell
, HWND hwndListView
)
2945 PWINSTATION_OBJECT WinStaObject
;
2947 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
2952 if (!NT_SUCCESS(Status
))
2954 SetLastNtError(Status
);
2959 * Test if we are permitted to change the shell window.
2961 if (WinStaObject
->ShellWindow
)
2963 ObDereferenceObject(WinStaObject
);
2968 * Move shell window into background.
2970 if (hwndListView
&& hwndListView
!= hwndShell
)
2973 * Disabled for now to get Explorer working.
2974 * -- Filip, 01/nov/2003
2977 WinPosSetWindowPos(hwndListView
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2980 if (NtUserGetWindowLong(hwndListView
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2982 ObDereferenceObject(WinStaObject
);
2987 if (NtUserGetWindowLong(hwndShell
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2989 ObDereferenceObject(WinStaObject
);
2993 WinPosSetWindowPos(hwndShell
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2995 WinStaObject
->ShellWindow
= hwndShell
;
2996 WinStaObject
->ShellListView
= hwndListView
;
2998 ObDereferenceObject(WinStaObject
);
3003 * NtUserGetSystemMenu
3005 * The NtUserGetSystemMenu function allows the application to access the
3006 * window menu (also known as the system menu or the control menu) for
3007 * copying and modifying.
3011 * Handle to the window that will own a copy of the window menu.
3013 * Specifies the action to be taken. If this parameter is FALSE,
3014 * NtUserGetSystemMenu returns a handle to the copy of the window menu
3015 * currently in use. The copy is initially identical to the window menu
3016 * but it can be modified.
3017 * If this parameter is TRUE, GetSystemMenu resets the window menu back
3018 * to the default state. The previous window menu, if any, is destroyed.
3021 * If the bRevert parameter is FALSE, the return value is a handle to a
3022 * copy of the window menu. If the bRevert parameter is TRUE, the return
3030 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
3033 PWINDOW_OBJECT WindowObject
;
3034 PMENU_OBJECT MenuObject
;
3036 WindowObject
= IntGetWindowObject((HWND
)hWnd
);
3037 if (WindowObject
== NULL
)
3039 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3043 MenuObject
= IntGetSystemMenu(WindowObject
, bRevert
, FALSE
);
3046 Result
= MenuObject
->MenuInfo
.Self
;
3047 IntReleaseMenuObject(MenuObject
);
3050 IntReleaseWindowObject(WindowObject
);
3055 * NtUserSetSystemMenu
3062 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
3064 BOOL Result
= FALSE
;
3065 PWINDOW_OBJECT WindowObject
;
3066 PMENU_OBJECT MenuObject
;
3068 WindowObject
= IntGetWindowObject(hWnd
);
3071 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3078 * Assign new menu handle.
3080 MenuObject
= IntGetMenuObject(hMenu
);
3083 IntReleaseWindowObject(WindowObject
);
3084 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
3088 Result
= IntSetSystemMenu(WindowObject
, MenuObject
);
3090 IntReleaseMenuObject(MenuObject
);
3093 IntReleaseWindowObject(WindowObject
);
3101 * The NtUserGetWindow function retrieves a handle to a window that has the
3102 * specified relationship (Z order or owner) to the specified window.
3109 NtUserGetWindow(HWND hWnd
, UINT Relationship
)
3111 PWINDOW_OBJECT WindowObject
, Parent
;
3112 HWND hWndResult
= NULL
;
3114 if (!(WindowObject
= IntGetWindowObject(hWnd
)))
3116 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3120 switch (Relationship
)
3123 if((Parent
= IntGetParentObject(WindowObject
)))
3125 IntLockRelatives(Parent
);
3126 if (Parent
->FirstChild
)
3127 hWndResult
= Parent
->FirstChild
->Self
;
3128 IntUnLockRelatives(Parent
);
3129 IntReleaseWindowObject(Parent
);
3134 if((Parent
= IntGetParentObject(WindowObject
)))
3136 IntLockRelatives(Parent
);
3137 if (Parent
->LastChild
)
3138 hWndResult
= Parent
->LastChild
->Self
;
3139 IntUnLockRelatives(Parent
);
3140 IntReleaseWindowObject(Parent
);
3145 IntLockRelatives(WindowObject
);
3146 if (WindowObject
->NextSibling
)
3147 hWndResult
= WindowObject
->NextSibling
->Self
;
3148 IntUnLockRelatives(WindowObject
);
3152 IntLockRelatives(WindowObject
);
3153 if (WindowObject
->PrevSibling
)
3154 hWndResult
= WindowObject
->PrevSibling
->Self
;
3155 IntUnLockRelatives(WindowObject
);
3159 IntLockRelatives(WindowObject
);
3160 if((Parent
= IntGetWindowObject(WindowObject
->Owner
)))
3162 hWndResult
= Parent
->Self
;
3163 IntReleaseWindowObject(Parent
);
3165 IntUnLockRelatives(WindowObject
);
3168 IntLockRelatives(WindowObject
);
3169 if (WindowObject
->FirstChild
)
3170 hWndResult
= WindowObject
->FirstChild
->Self
;
3171 IntUnLockRelatives(WindowObject
);
3175 IntReleaseWindowObject(WindowObject
);
3181 * NtUserGetWindowLong
3183 * The NtUserGetWindowLong function retrieves information about the specified
3184 * window. The function also retrieves the 32-bit (long) value at the
3185 * specified offset into the extra window memory.
3192 NtUserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3194 PWINDOW_OBJECT WindowObject
, Parent
;
3197 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3199 WindowObject
= IntGetWindowObject(hWnd
);
3200 if (WindowObject
== NULL
)
3202 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3207 * Only allow CSRSS to mess with the desktop window
3209 if (hWnd
== IntGetDesktopWindow()
3210 && WindowObject
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
3212 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3216 if ((INT
)Index
>= 0)
3218 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
3220 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3223 Result
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
3230 Result
= WindowObject
->ExStyle
;
3234 Result
= WindowObject
->Style
;
3239 Result
= (LONG
) WindowObject
->WndProcA
;
3241 Result
= (LONG
) WindowObject
->WndProcW
;
3245 Result
= (LONG
) WindowObject
->Instance
;
3248 case GWL_HWNDPARENT
:
3249 IntLockRelatives(WindowObject
);
3250 Parent
= IntGetWindowObject(WindowObject
->Parent
);
3251 IntUnLockRelatives(WindowObject
);
3254 if (Parent
&& Parent
->Self
== IntGetDesktopWindow())
3255 Result
= (LONG
) NtUserGetWindow(WindowObject
->Self
, GW_OWNER
);
3257 Result
= (LONG
) Parent
->Self
;
3258 IntReleaseWindowObject(Parent
);
3263 Result
= (LONG
) WindowObject
->IDMenu
;
3267 Result
= WindowObject
->UserData
;
3271 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index
);
3272 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3278 IntReleaseWindowObject(WindowObject
);
3284 * NtUserSetWindowLong
3286 * The NtUserSetWindowLong function changes an attribute of the specified
3287 * window. The function also sets the 32-bit (long) value at the specified
3288 * offset into the extra window memory.
3295 NtUserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3297 PWINDOW_OBJECT WindowObject
, Parent
;
3298 PWINSTATION_OBJECT WindowStation
;
3302 if (hWnd
== IntGetDesktopWindow())
3304 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3308 WindowObject
= IntGetWindowObject(hWnd
);
3309 if (WindowObject
== NULL
)
3311 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3315 if ((INT
)Index
>= 0)
3317 if ((Index
+ sizeof(LONG
)) > WindowObject
->ExtraDataSize
)
3319 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3320 IntReleaseWindowObject(WindowObject
);
3323 OldValue
= *((LONG
*)(WindowObject
->ExtraData
+ Index
));
3324 *((LONG
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
3331 OldValue
= (LONG
) WindowObject
->ExStyle
;
3332 Style
.styleOld
= OldValue
;
3333 Style
.styleNew
= NewValue
;
3336 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3338 WindowStation
= WindowObject
->OwnerThread
->Tcb
.Win32Thread
->Desktop
->WindowStation
;
3341 if (hWnd
== WindowStation
->ShellWindow
|| hWnd
== WindowStation
->ShellListView
)
3342 Style
.styleNew
&= ~WS_EX_TOPMOST
;
3345 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3346 WindowObject
->ExStyle
= (DWORD
)Style
.styleNew
;
3347 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3351 OldValue
= (LONG
) WindowObject
->Style
;
3352 Style
.styleOld
= OldValue
;
3353 Style
.styleNew
= NewValue
;
3354 IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_STYLE
, (LPARAM
) &Style
);
3355 WindowObject
->Style
= (DWORD
)Style
.styleNew
;
3356 IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_STYLE
, (LPARAM
) &Style
);
3360 /* FIXME: should check if window belongs to current process */
3363 OldValue
= (LONG
) WindowObject
->WndProcA
;
3364 WindowObject
->WndProcA
= (WNDPROC
) NewValue
;
3365 WindowObject
->WndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,FALSE
);
3366 WindowObject
->Unicode
= FALSE
;
3370 OldValue
= (LONG
) WindowObject
->WndProcW
;
3371 WindowObject
->WndProcW
= (WNDPROC
) NewValue
;
3372 WindowObject
->WndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,TRUE
);
3373 WindowObject
->Unicode
= TRUE
;
3378 OldValue
= (LONG
) WindowObject
->Instance
;
3379 WindowObject
->Instance
= (HINSTANCE
) NewValue
;
3382 case GWL_HWNDPARENT
:
3383 Parent
= IntGetParentObject(WindowObject
);
3384 if (Parent
&& (Parent
->Self
== IntGetDesktopWindow()))
3385 OldValue
= (LONG
) IntSetOwner(WindowObject
->Self
, (HWND
) NewValue
);
3387 OldValue
= (LONG
) NtUserSetParent(WindowObject
->Self
, (HWND
) NewValue
);
3389 IntReleaseWindowObject(Parent
);
3393 OldValue
= (LONG
) WindowObject
->IDMenu
;
3394 WindowObject
->IDMenu
= (UINT
) NewValue
;
3398 OldValue
= WindowObject
->UserData
;
3399 WindowObject
->UserData
= NewValue
;
3403 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index
);
3404 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3410 IntReleaseWindowObject(WindowObject
);
3416 * NtUserSetWindowWord
3418 * Legacy function similar to NtUserSetWindowLong.
3425 NtUserSetWindowWord(HWND hWnd
, INT Index
, WORD NewValue
)
3427 PWINDOW_OBJECT WindowObject
;
3434 case GWL_HWNDPARENT
:
3435 return NtUserSetWindowLong(hWnd
, Index
, (UINT
)NewValue
, TRUE
);
3439 SetLastWin32Error(ERROR_INVALID_INDEX
);
3444 WindowObject
= IntGetWindowObject(hWnd
);
3445 if (WindowObject
== NULL
)
3447 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3451 if (Index
> WindowObject
->ExtraDataSize
- sizeof(WORD
))
3453 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3454 IntReleaseWindowObject(WindowObject
);
3458 OldValue
= *((WORD
*)(WindowObject
->ExtraData
+ Index
));
3459 *((WORD
*)(WindowObject
->ExtraData
+ Index
)) = NewValue
;
3461 IntReleaseWindowObject(WindowObject
);
3470 NtUserGetWindowPlacement(HWND hWnd
,
3471 WINDOWPLACEMENT
*lpwndpl
)
3473 PWINDOW_OBJECT WindowObject
;
3474 PINTERNALPOS InternalPos
;
3476 WINDOWPLACEMENT Safepl
;
3479 WindowObject
= IntGetWindowObject(hWnd
);
3480 if (WindowObject
== NULL
)
3482 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3486 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3487 if(!NT_SUCCESS(Status
))
3489 SetLastNtError(Status
);
3490 IntReleaseWindowObject(WindowObject
);
3493 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3495 IntReleaseWindowObject(WindowObject
);
3500 Safepl
.showCmd
= ((WindowObject
->Flags
& WINDOWOBJECT_RESTOREMAX
) ? SW_MAXIMIZE
: SW_SHOWNORMAL
);
3502 Size
.x
= WindowObject
->WindowRect
.left
;
3503 Size
.y
= WindowObject
->WindowRect
.top
;
3504 InternalPos
= WinPosInitInternalPos(WindowObject
, &Size
,
3505 &WindowObject
->WindowRect
);
3508 Safepl
.rcNormalPosition
= InternalPos
->NormalRect
;
3509 Safepl
.ptMinPosition
= InternalPos
->IconPos
;
3510 Safepl
.ptMaxPosition
= InternalPos
->MaxPos
;
3514 IntReleaseWindowObject(WindowObject
);
3518 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3519 if(!NT_SUCCESS(Status
))
3521 SetLastNtError(Status
);
3522 IntReleaseWindowObject(WindowObject
);
3526 IntReleaseWindowObject(WindowObject
);
3532 * Return the dimension of the window in the screen coordinates.
3533 * \param hWnd window handle.
3534 * \param Rect pointer to the buffer where the coordinates are returned.
3540 NtUserGetWindowRect(HWND hWnd
, LPRECT Rect
)
3545 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3547 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3550 Status
= MmCopyToCaller(Rect
, &Wnd
->WindowRect
, sizeof(RECT
));
3551 if (!NT_SUCCESS(Status
))
3553 IntReleaseWindowObject(Wnd
);
3554 SetLastNtError(Status
);
3558 IntReleaseWindowObject(Wnd
);
3567 NtUserGetWindowThreadProcessId(HWND hWnd
, LPDWORD UnsafePid
)
3572 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3574 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3578 tid
= (DWORD
)IntGetWndThreadId(Wnd
);
3579 pid
= (DWORD
)IntGetWndProcessId(Wnd
);
3581 if (UnsafePid
) MmCopyToCaller(UnsafePid
, &pid
, sizeof(DWORD
));
3591 NtUserLockWindowUpdate(DWORD Unknown0
)
3611 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3612 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3613 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3617 QueryWindow based on KJK::Hyperion and James Tabor.
3619 0 = QWUniqueProcessId
3620 1 = QWUniqueThreadId
3621 4 = QWIsHung Implements IsHungAppWindow found
3624 9 = QWKillWindow When I called this with hWnd ==
3625 DesktopWindow, it shutdown the system
3632 NtUserQueryWindow(HWND hWnd
, DWORD Index
)
3634 PWINDOW_OBJECT Window
= IntGetWindowObject(hWnd
);
3639 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3645 case QUERY_WINDOW_UNIQUE_PROCESS_ID
:
3646 Result
= (DWORD
)IntGetWndProcessId(Window
);
3649 case QUERY_WINDOW_UNIQUE_THREAD_ID
:
3650 Result
= (DWORD
)IntGetWndThreadId(Window
);
3653 case QUERY_WINDOW_ISHUNG
:
3654 Result
= (DWORD
)MsqIsHung(Window
->MessageQueue
);
3658 Result
= (DWORD
)NULL
;
3662 IntReleaseWindowObject(Window
);
3672 NtUserRealChildWindowFromPoint(DWORD Unknown0
,
3686 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe
)
3688 UNICODE_STRING SafeMessageName
;
3692 if(MessageNameUnsafe
== NULL
)
3694 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3698 Status
= IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName
, MessageNameUnsafe
);
3699 if(!NT_SUCCESS(Status
))
3701 SetLastNtError(Status
);
3705 Ret
= (UINT
)IntAddAtom(SafeMessageName
.Buffer
);
3707 RtlFreeUnicodeString(&SafeMessageName
);
3716 NtUserSetImeOwnerWindow(DWORD Unknown0
,
3729 NtUserSetInternalWindowPos(DWORD Unknown0
,
3745 NtUserSetLayeredWindowAttributes(DWORD Unknown0
,
3760 NtUserSetLogonNotifyWindow(DWORD Unknown0
)
3777 PWINDOW_OBJECT WindowObject
;
3780 WindowObject
= IntGetWindowObject((HWND
) Wnd
);
3781 if (NULL
== WindowObject
)
3783 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3787 if (! IntSetMenu(WindowObject
, Menu
, &Changed
))
3789 IntReleaseWindowObject(WindowObject
);
3793 IntReleaseWindowObject(WindowObject
);
3795 if (Changed
&& Repaint
)
3797 WinPosSetWindowPos(Wnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
3798 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
3809 NtUserSetWindowFNID(DWORD Unknown0
,
3823 NtUserSetWindowPlacement(HWND hWnd
,
3824 WINDOWPLACEMENT
*lpwndpl
)
3826 PWINDOW_OBJECT WindowObject
;
3827 WINDOWPLACEMENT Safepl
;
3830 WindowObject
= IntGetWindowObject(hWnd
);
3831 if (WindowObject
== NULL
)
3833 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3836 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3837 if(!NT_SUCCESS(Status
))
3839 SetLastNtError(Status
);
3840 IntReleaseWindowObject(WindowObject
);
3843 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3845 IntReleaseWindowObject(WindowObject
);
3849 if ((WindowObject
->Style
& (WS_MAXIMIZE
| WS_MINIMIZE
)) == 0)
3851 WinPosSetWindowPos(WindowObject
->Self
, NULL
,
3852 Safepl
.rcNormalPosition
.left
, Safepl
.rcNormalPosition
.top
,
3853 Safepl
.rcNormalPosition
.right
- Safepl
.rcNormalPosition
.left
,
3854 Safepl
.rcNormalPosition
.bottom
- Safepl
.rcNormalPosition
.top
,
3855 SWP_NOZORDER
| SWP_NOACTIVATE
);
3858 /* FIXME - change window status */
3859 WinPosShowWindow(WindowObject
->Self
, Safepl
.showCmd
);
3861 if (WindowObject
->InternalPos
== NULL
)
3862 WindowObject
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
3863 WindowObject
->InternalPos
->NormalRect
= Safepl
.rcNormalPosition
;
3864 WindowObject
->InternalPos
->IconPos
= Safepl
.ptMinPosition
;
3865 WindowObject
->InternalPos
->MaxPos
= Safepl
.ptMaxPosition
;
3867 IntReleaseWindowObject(WindowObject
);
3878 HWND hWndInsertAfter
,
3885 return WinPosSetWindowPos(hWnd
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3890 IntGetWindowRgn(HWND hWnd
, HRGN hRgn
)
3893 PWINDOW_OBJECT WindowObject
;
3897 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
3899 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3904 IntReleaseWindowObject(WindowObject
);
3908 /* Create a new window region using the window rectangle */
3909 VisRgn
= UnsafeIntCreateRectRgnIndirect(&WindowObject
->WindowRect
);
3910 NtGdiOffsetRgn(VisRgn
, -WindowObject
->WindowRect
.left
, -WindowObject
->WindowRect
.top
);
3911 /* if there's a region assigned to the window, combine them both */
3912 if(WindowObject
->WindowRegion
&& !(WindowObject
->Style
& WS_MINIMIZE
))
3913 NtGdiCombineRgn(VisRgn
, VisRgn
, WindowObject
->WindowRegion
, RGN_AND
);
3914 /* Copy the region into hRgn */
3915 NtGdiCombineRgn(hRgn
, VisRgn
, NULL
, RGN_COPY
);
3917 if((pRgn
= RGNDATA_LockRgn(hRgn
)))
3919 Ret
= pRgn
->rdh
.iType
;
3920 RGNDATA_UnlockRgn(hRgn
);
3925 NtGdiDeleteObject(VisRgn
);
3927 IntReleaseWindowObject(WindowObject
);
3932 IntGetWindowRgnBox(HWND hWnd
, RECT
*Rect
)
3935 PWINDOW_OBJECT WindowObject
;
3939 if(!(WindowObject
= IntGetWindowObject(hWnd
)))
3941 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3946 IntReleaseWindowObject(WindowObject
);
3950 /* Create a new window region using the window rectangle */
3951 VisRgn
= UnsafeIntCreateRectRgnIndirect(&WindowObject
->WindowRect
);
3952 NtGdiOffsetRgn(VisRgn
, -WindowObject
->WindowRect
.left
, -WindowObject
->WindowRect
.top
);
3953 /* if there's a region assigned to the window, combine them both */
3954 if(WindowObject
->WindowRegion
&& !(WindowObject
->Style
& WS_MINIMIZE
))
3955 NtGdiCombineRgn(VisRgn
, VisRgn
, WindowObject
->WindowRegion
, RGN_AND
);
3957 if((pRgn
= RGNDATA_LockRgn(VisRgn
)))
3959 Ret
= pRgn
->rdh
.iType
;
3960 *Rect
= pRgn
->rdh
.rcBound
;
3961 RGNDATA_UnlockRgn(VisRgn
);
3966 NtGdiDeleteObject(VisRgn
);
3968 IntReleaseWindowObject(WindowObject
);
3982 PWINDOW_OBJECT WindowObject
;
3984 WindowObject
= IntGetWindowObject(hWnd
);
3985 if (WindowObject
== NULL
)
3987 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3991 /* FIXME - Verify if hRgn is a valid handle!!!!
3992 Propably make this operation thread-safe, but maybe it's not necessary */
3994 if(WindowObject
->WindowRegion
)
3996 /* Delete no longer needed region handle */
3997 NtGdiDeleteObject(WindowObject
->WindowRegion
);
3999 WindowObject
->WindowRegion
= hRgn
;
4001 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
4005 IntRedrawWindow(WindowObject
, NULL
, NULL
, RDW_INVALIDATE
);
4008 IntReleaseWindowObject(WindowObject
);
4017 NtUserShowWindow(HWND hWnd
,
4020 return WinPosShowWindow(hWnd
, nCmdShow
);
4028 NtUserShowWindowAsync(DWORD Unknown0
,
4041 NtUserUpdateLayeredWindow(DWORD Unknown0
,
4061 NtUserValidateRect(HWND hWnd
, const RECT
* Rect
)
4063 return (VOID
)NtUserRedrawWindow(hWnd
, Rect
, 0, RDW_VALIDATE
| RDW_NOCHILDREN
);
4071 NtUserWindowFromPoint(LONG X
, LONG Y
)
4075 PWINDOW_OBJECT DesktopWindow
, Window
= NULL
;
4077 if ((DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow())))
4084 Hit
= WinPosWindowFromPoint(DesktopWindow
, PsGetWin32Thread()->MessageQueue
, &pt
, &Window
);
4089 IntReleaseWindowObject(Window
);
4090 IntReleaseWindowObject(DesktopWindow
);
4094 IntReleaseWindowObject(DesktopWindow
);
4104 * Undocumented function that is called from DefWindowProc to set
4112 NtUserDefSetText(HWND WindowHandle
, PUNICODE_STRING WindowText
)
4114 PWINDOW_OBJECT WindowObject
, Parent
, Owner
;
4115 UNICODE_STRING SafeText
;
4118 WindowObject
= IntGetWindowObject(WindowHandle
);
4121 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4127 Status
= IntSafeCopyUnicodeString(&SafeText
, WindowText
);
4128 if(!NT_SUCCESS(Status
))
4130 SetLastNtError(Status
);
4131 IntReleaseWindowObject(WindowObject
);
4137 RtlInitUnicodeString(&SafeText
, NULL
);
4140 /* FIXME - do this thread-safe! otherwise one could crash here! */
4141 RtlFreeUnicodeString(&WindowObject
->WindowName
);
4143 WindowObject
->WindowName
= SafeText
;
4145 /* Send shell notifications */
4147 Owner
= IntGetOwner(WindowObject
);
4148 Parent
= IntGetParent(WindowObject
);
4150 if ((!Owner
) && (!Parent
))
4152 IntShellHookNotify(HSHELL_REDRAW
, (LPARAM
) WindowHandle
);
4157 IntReleaseWindowObject(Owner
);
4162 IntReleaseWindowObject(Parent
);
4165 IntReleaseWindowObject(WindowObject
);
4170 * NtUserInternalGetWindowText
4177 NtUserInternalGetWindowText(HWND hWnd
, LPWSTR lpString
, INT nMaxCount
)
4179 PWINDOW_OBJECT WindowObject
;
4183 if(lpString
&& (nMaxCount
<= 1))
4185 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
4189 WindowObject
= IntGetWindowObject(hWnd
);
4192 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4196 /* FIXME - do this thread-safe! otherwise one could crash here! */
4197 Result
= WindowObject
->WindowName
.Length
/ sizeof(WCHAR
);
4200 const WCHAR Terminator
= L
'\0';
4202 WCHAR
*Buffer
= (WCHAR
*)lpString
;
4204 Copy
= min(nMaxCount
- 1, Result
);
4207 Status
= MmCopyToCaller(Buffer
, WindowObject
->WindowName
.Buffer
, Copy
* sizeof(WCHAR
));
4208 if(!NT_SUCCESS(Status
))
4210 SetLastNtError(Status
);
4211 IntReleaseWindowObject(WindowObject
);
4217 Status
= MmCopyToCaller(Buffer
, &Terminator
, sizeof(WCHAR
));
4218 if(!NT_SUCCESS(Status
))
4220 SetLastNtError(Status
);
4221 IntReleaseWindowObject(WindowObject
);
4228 IntReleaseWindowObject(WindowObject
);
4233 NtUserDereferenceWndProcHandle(WNDPROC wpHandle
, WndProcHandle
*Data
)
4235 WndProcHandle Entry
;
4236 if (((DWORD
)wpHandle
& 0xFFFF0000) == 0xFFFF0000)
4238 Entry
= WndProcHandlesArray
[(DWORD
)wpHandle
& 0x0000FFFF];
4239 Data
->WindowProc
= Entry
.WindowProc
;
4240 Data
->IsUnicode
= Entry
.IsUnicode
;
4241 Data
->ProcessID
= Entry
.ProcessID
;
4250 IntAddWndProcHandle(WNDPROC WindowProc
, BOOL IsUnicode
)
4255 WndProcHandle
*OldArray
;
4258 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4260 if (WndProcHandlesArray
[i
].WindowProc
== NULL
)
4268 OldArray
= WndProcHandlesArray
;
4269 OldArraySize
= WndProcHandlesArraySize
;
4270 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,(OldArraySize
+ WPH_SIZE
) * sizeof(WndProcHandle
), TAG_WINPROCLST
);
4271 WndProcHandlesArraySize
= OldArraySize
+ WPH_SIZE
;
4272 RtlCopyMemory(WndProcHandlesArray
,OldArray
,OldArraySize
* sizeof(WndProcHandle
));
4273 ExFreePool(OldArray
);
4274 FreeSpot
= OldArraySize
+ 1;
4276 WndProcHandlesArray
[FreeSpot
].WindowProc
= WindowProc
;
4277 WndProcHandlesArray
[FreeSpot
].IsUnicode
= IsUnicode
;
4278 WndProcHandlesArray
[FreeSpot
].ProcessID
= PsGetCurrentProcessId();
4279 return FreeSpot
+ 0xFFFF0000;
4283 IntRemoveWndProcHandle(WNDPROC Handle
)
4286 position
= (DWORD
)Handle
& 0x0000FFFF;
4287 if (position
> WndProcHandlesArraySize
)
4291 WndProcHandlesArray
[position
].WindowProc
= NULL
;
4292 WndProcHandlesArray
[position
].IsUnicode
= FALSE
;
4293 WndProcHandlesArray
[position
].ProcessID
= NULL
;
4298 IntRemoveProcessWndProcHandles(HANDLE ProcessID
)
4301 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4303 if (WndProcHandlesArray
[i
].ProcessID
== ProcessID
)
4305 WndProcHandlesArray
[i
].WindowProc
= NULL
;
4306 WndProcHandlesArray
[i
].IsUnicode
= FALSE
;
4307 WndProcHandlesArray
[i
].ProcessID
= NULL
;