2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
23 * FILE: subsys/win32k/ntuser/window.c
24 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * 06-06-2001 CSH Created
29 /* INCLUDES ******************************************************************/
36 static WndProcHandle
*WndProcHandlesArray
= 0;
37 static WORD WndProcHandlesArraySize
= 0;
38 #define WPH_SIZE 0x40 /* the size to add to the WndProcHandle array each time */
40 /* dialog resources appear to pass this in 16 bits, handle them properly */
41 #define CW_USEDEFAULT16 (0x8000)
43 #define POINT_IN_RECT(p, r) (((r.bottom >= p.y) && (r.top <= p.y))&&((r.left <= p.x )&&( r.right >= p.x )))
45 /* PRIVATE FUNCTIONS **********************************************************/
50 * Initialize windowing implementation.
56 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,WPH_SIZE
* sizeof(WndProcHandle
), TAG_WINPROCLST
);
57 WndProcHandlesArraySize
= WPH_SIZE
;
58 return STATUS_SUCCESS
;
64 * Cleanup windowing implementation.
68 CleanupWindowImpl(VOID
)
70 ExFreePool(WndProcHandlesArray
);
71 WndProcHandlesArray
= 0;
72 WndProcHandlesArraySize
= 0;
73 return STATUS_SUCCESS
;
76 /* HELPER FUNCTIONS ***********************************************************/
78 VOID FASTCALL
IntReleaseWindowObject(PWINDOW_OBJECT Window
)
82 ASSERT(USER_BODY_TO_HEADER(Window
)->RefCount
>= 1);
84 USER_BODY_TO_HEADER(Window
)->RefCount
--;
86 if (USER_BODY_TO_HEADER(Window
)->RefCount
== 0 && USER_BODY_TO_HEADER(Window
)->destroyed
)
92 PWINDOW_OBJECT FASTCALL
IntGetWindowObject(HWND hWnd
)
94 PWINDOW_OBJECT Window
= UserGetWindowObject(hWnd
);
97 ASSERT(USER_BODY_TO_HEADER(Window
)->RefCount
>= 0);
99 USER_BODY_TO_HEADER(Window
)->RefCount
++;
105 PWINDOW_OBJECT FASTCALL
UserGetWindowObject(HWND hWnd
)
107 PWINDOW_OBJECT Window
= (PWINDOW_OBJECT
)UserGetObject(&gHandleTable
, hWnd
, otWindow
);
110 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
114 ASSERT(USER_BODY_TO_HEADER(Window
)->RefCount
>= 0);
122 * The function determines whether the specified window handle identifies
123 * an existing window.
127 * Handle to the window to test.
130 * If the window handle identifies an existing window, the return value
131 * is TRUE. If the window handle does not identify an existing window,
132 * the return value is FALSE.
136 IntIsWindow(HWND hWnd
)
138 PWINDOW_OBJECT Window
;
140 if (!(Window
= IntGetWindowObject(hWnd
)))
143 IntReleaseWindowObject(Window
);
150 PWINDOW_OBJECT FASTCALL
151 IntGetParent(PWINDOW_OBJECT Wnd
)
155 if (Wnd
->Style
& WS_POPUP
)
158 return IntGetWindowObject(hWnd
);
160 else if (Wnd
->Style
& WS_CHILD
)
166 IntReferenceWindowObject(par
);
168 //return IntGetWindowObject(hWnd);
174 PWINDOW_OBJECT FASTCALL
175 IntGetOwner(PWINDOW_OBJECT Wnd
)
181 return IntGetWindowObject(hWnd
);
184 PWINDOW_OBJECT FASTCALL
185 IntGetParentObject(PWINDOW_OBJECT Wnd
)
191 IntReferenceWindowObject(par
);
198 * Compile a list of all child window handles from given window.
201 * This function is similar to Wine WIN_ListChildren. The caller
202 * must free the returned list with ExFreePool.
206 IntWinListChildren(PWINDOW_OBJECT Window
)
208 PWINDOW_OBJECT Child
;
210 UINT Index
, NumChildren
= 0;
212 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
215 List
= ExAllocatePoolWithTag(PagedPool
, (NumChildren
+ 1) * sizeof(HWND
), TAG_WINLIST
);
218 DPRINT1("Failed to allocate memory for children array\n");
219 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
222 for (Child
= Window
->FirstChild
, Index
= 0;
224 Child
= Child
->NextSibling
, ++Index
)
225 List
[Index
] = Child
->hSelf
;
231 /***********************************************************************
234 static void IntSendDestroyMsg(HWND Wnd
)
237 PWINDOW_OBJECT Window
, Owner
, Parent
;
242 if (GetGUIThreadInfo(GetCurrentThreadId(), &info
))
244 if (Wnd
== info
.hwndCaret
)
251 Window
= IntGetWindowObject(Wnd
);
254 Owner
= IntGetOwner(Window
);
257 Parent
= IntGetParent(Window
);
259 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
) Wnd
);
261 IntReleaseWindowObject(Parent
);
265 IntReleaseWindowObject(Owner
);
268 IntReleaseWindowObject(Window
);
271 /* The window could already be destroyed here */
274 * Send the WM_DESTROY to the window.
277 co_IntSendMessage(Wnd
, WM_DESTROY
, 0, 0);
280 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
281 * make sure that the window still exists when we come back.
290 if (!(pWndArray
= WIN_ListChildren( hwnd
)))
293 /* start from the end (FIXME: is this needed?) */
294 for (i
= 0; pWndArray
[i
]; i
++)
299 if (IsWindow( pWndArray
[i
] ))
300 WIN_SendDestroyMsg( pWndArray
[i
] );
302 HeapFree(GetProcessHeap(), 0, pWndArray
);
306 DPRINT("destroyed itself while in WM_DESTROY!\n");
311 /***********************************************************************
314 * Destroy storage associated to a window. "Internals" p.358
316 static LRESULT
co_IntDestroyWindow(PWINDOW_OBJECT Window
,
317 PW32PROCESS ProcessData
,
318 PW32THREAD ThreadData
,
319 BOOLEAN SendMessages
)
323 PWINDOW_OBJECT Child
;
325 BOOLEAN BelongsToThreadData
;
329 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
331 DPRINT("Tried to call IntDestroyWindow() twice\n");
334 Window
->Status
|= WINDOWSTATUS_DESTROYING
;
335 Window
->Flags
&= ~WS_VISIBLE
;
336 /* remove the window already at this point from the thread window list so we
337 don't get into trouble when destroying the thread windows while we're still
338 in IntDestroyWindow() */
339 RemoveEntryList(&Window
->ThreadListEntry
);
341 BelongsToThreadData
= IntWndBelongsToThread(Window
, ThreadData
);
343 IntDeRegisterShellHookWindow(Window
->hSelf
);
347 /* Send destroy messages */
348 IntSendDestroyMsg(Window
->hSelf
);
351 /* free child windows */
352 Children
= IntWinListChildren(Window
);
355 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
357 if ((Child
= IntGetWindowObject(*ChildHandle
)))
359 if(!IntWndBelongsToThread(Child
, ThreadData
))
361 /* send WM_DESTROY messages to windows not belonging to the same thread */
362 IntSendDestroyMsg(Child
->hSelf
);
365 co_IntDestroyWindow(Child
, ProcessData
, ThreadData
, SendMessages
);
366 IntReleaseWindowObject(Child
);
369 ExFreePool(Children
);
375 * Clear the update region to make sure no WM_PAINT messages will be
376 * generated for this window while processing the WM_NCDESTROY.
378 co_UserRedrawWindow(Window
, NULL
, 0,
379 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
|
380 RDW_NOINTERNALPAINT
| RDW_NOCHILDREN
);
381 if(BelongsToThreadData
)
382 co_IntSendMessage(Window
->hSelf
, WM_NCDESTROY
, 0, 0);
384 MsqRemoveTimersWindow(ThreadData
->MessageQueue
, Window
->hSelf
);
386 /* flush the message queue */
387 MsqRemoveWindowMessagesFromQueue(Window
);
389 /* from now on no messages can be sent to this window anymore */
390 Window
->Status
|= WINDOWSTATUS_DESTROYED
;
391 /* don't remove the WINDOWSTATUS_DESTROYING bit */
393 /* reset shell window handles */
394 if(ThreadData
->Desktop
)
396 if (Window
->hSelf
== ThreadData
->Desktop
->WindowStation
->ShellWindow
)
397 ThreadData
->Desktop
->WindowStation
->ShellWindow
= NULL
;
399 if (Window
->hSelf
== ThreadData
->Desktop
->WindowStation
->ShellListView
)
400 ThreadData
->Desktop
->WindowStation
->ShellListView
= NULL
;
403 /* Unregister hot keys */
404 UnregisterWindowHotKeys (Window
);
406 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
410 WinPosCheckInternalPos(Window
->hSelf
);
411 if (Window
->hSelf
== GetCapture())
416 /* free resources associated with the window */
417 TIMER_RemoveWindowTimers(Window
->hSelf
);
420 if (!(Window
->Style
& WS_CHILD
) && Window
->IDMenu
421 && (Menu
= IntGetMenuObject((HMENU
)Window
->IDMenu
)))
423 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
425 IntReleaseMenuObject(Menu
);
428 if(Window
->SystemMenu
429 && (Menu
= IntGetMenuObject(Window
->SystemMenu
)))
431 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
432 Window
->SystemMenu
= (HMENU
)0;
433 IntReleaseMenuObject(Menu
);
436 DceFreeWindowDCE(Window
); /* Always do this to catch orphaned DCs */
439 WINPROC_FreeProc(Window
->winproc
, WIN_PROC_WINDOW
);
440 CLASS_RemoveWindow(Window
->Class
);
443 IntUnlinkWindow(Window
);
445 IntReferenceWindowObject(Window
);
446 ObmDeleteObject(Window
->hSelf
, otWindow
);
448 IntDestroyScrollBars(Window
);
450 /* remove the window from the class object */
451 RemoveEntryList(&Window
->ClassListEntry
);
453 /* dereference the class */
454 ClassDereferenceObject(Window
->Class
);
455 Window
->Class
= NULL
;
457 if(Window
->WindowRegion
)
459 NtGdiDeleteObject(Window
->WindowRegion
);
462 RtlFreeUnicodeString(&Window
->WindowName
);
464 IntReleaseWindowObject(Window
);
470 IntGetWindowBorderMeasures(PWINDOW_OBJECT Window
, UINT
*cx
, UINT
*cy
)
472 if(HAS_DLGFRAME(Window
->Style
, Window
->ExStyle
) && !(Window
->Style
& WS_MINIMIZE
))
474 *cx
= UserGetSystemMetrics(SM_CXDLGFRAME
);
475 *cy
= UserGetSystemMetrics(SM_CYDLGFRAME
);
479 if(HAS_THICKFRAME(Window
->Style
, Window
->ExStyle
)&& !(Window
->Style
& WS_MINIMIZE
))
481 *cx
= UserGetSystemMetrics(SM_CXFRAME
);
482 *cy
= UserGetSystemMetrics(SM_CYFRAME
);
484 else if(HAS_THINFRAME(Window
->Style
, Window
->ExStyle
))
486 *cx
= UserGetSystemMetrics(SM_CXBORDER
);
487 *cy
= UserGetSystemMetrics(SM_CYBORDER
);
497 IntGetWindowInfo(PWINDOW_OBJECT Window
, PWINDOWINFO pwi
)
499 pwi
->cbSize
= sizeof(WINDOWINFO
);
500 pwi
->rcWindow
= Window
->WindowRect
;
501 pwi
->rcClient
= Window
->ClientRect
;
502 pwi
->dwStyle
= Window
->Style
;
503 pwi
->dwExStyle
= Window
->ExStyle
;
504 pwi
->dwWindowStatus
= (UserGetForegroundWindow() == Window
->hSelf
); /* WS_ACTIVECAPTION */
505 IntGetWindowBorderMeasures(Window
, &pwi
->cxWindowBorders
, &pwi
->cyWindowBorders
);
506 pwi
->atomWindowType
= (Window
->Class
? Window
->Class
->Atom
: 0);
507 pwi
->wCreatorVersion
= 0x400; /* FIXME - return a real version number */
513 PWINDOW_OBJECT Window
,
517 PMENU_OBJECT OldMenu
, NewMenu
= NULL
;
519 if ((Window
->Style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
521 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
525 *Changed
= (Window
->IDMenu
!= (UINT
) Menu
);
533 OldMenu
= IntGetMenuObject((HMENU
) Window
->IDMenu
);
534 ASSERT(NULL
== OldMenu
|| OldMenu
->MenuInfo
.Wnd
== Window
->hSelf
);
543 NewMenu
= IntGetMenuObject(Menu
);
548 IntReleaseMenuObject(OldMenu
);
550 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
553 if (NULL
!= NewMenu
->MenuInfo
.Wnd
)
555 /* Can't use the same menu for two windows */
558 IntReleaseMenuObject(OldMenu
);
560 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
566 Window
->IDMenu
= (UINT
) Menu
;
569 NewMenu
->MenuInfo
.Wnd
= Window
->hSelf
;
570 IntReleaseMenuObject(NewMenu
);
574 OldMenu
->MenuInfo
.Wnd
= NULL
;
575 IntReleaseMenuObject(OldMenu
);
582 /* INTERNAL ******************************************************************/
586 co_DestroyThreadWindows(struct _ETHREAD
*Thread
)
589 PW32PROCESS Win32Process
;
590 PW32THREAD Win32Thread
;
591 PWINDOW_OBJECT
*List
, *pWnd
;
594 Win32Thread
= Thread
->Tcb
.Win32Thread
;
595 Win32Process
= (PW32PROCESS
)Thread
->ThreadsProcess
->Win32Process
;
597 Current
= Win32Thread
->WindowListHead
.Flink
;
598 while (Current
!= &(Win32Thread
->WindowListHead
))
601 Current
= Current
->Flink
;
606 List
= ExAllocatePool(PagedPool
, (Cnt
+ 1) * sizeof(PWINDOW_OBJECT
));
609 DPRINT("Not enough memory to allocate window handle list\n");
613 Current
= Win32Thread
->WindowListHead
.Flink
;
614 while (Current
!= &(Win32Thread
->WindowListHead
))
616 *pWnd
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
617 IntReferenceWindowObject(*pWnd
);
619 Current
= Current
->Flink
;
623 for(pWnd
= List
; *pWnd
; pWnd
++)
625 co_UserDestroyWindow(*pWnd
);
626 IntReleaseWindowObject(*pWnd
);
637 * Returns client window rectangle relative to the upper-left corner of client area.
639 * \note Does not check the validity of the parameters
642 IntGetClientRect(PWINDOW_OBJECT Window
, PRECT Rect
)
647 Rect
->left
= Rect
->top
= 0;
648 Rect
->right
= Window
->ClientRect
.right
- Window
->ClientRect
.left
;
649 Rect
->bottom
= Window
->ClientRect
.bottom
- Window
->ClientRect
.top
;
655 IntGetFocusWindow(VOID
)
657 PUSER_MESSAGE_QUEUE Queue
;
658 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
663 Queue
= (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
668 return(Queue
->FocusWindow
);
672 PMENU_OBJECT FASTCALL
673 IntGetSystemMenu(PWINDOW_OBJECT Window
, BOOL bRevert
, BOOL RetMenu
)
675 PMENU_OBJECT Menu
, NewMenu
= NULL
, SysMenu
= NULL
, ret
= NULL
;
676 PW32THREAD W32Thread
;
677 HMENU hNewMenu
, hSysMenu
;
678 ROSMENUITEMINFO ItemInfo
;
682 W32Thread
= PsGetWin32Thread();
684 if(!W32Thread
->Desktop
)
687 if(Window
->SystemMenu
)
689 Menu
= IntGetMenuObject(Window
->SystemMenu
);
692 IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
693 Window
->SystemMenu
= (HMENU
)0;
694 IntReleaseMenuObject(Menu
);
698 if(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
)
700 /* clone system menu */
701 Menu
= IntGetMenuObject(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
);
705 NewMenu
= IntCloneMenu(Menu
);
708 Window
->SystemMenu
= NewMenu
->MenuInfo
.Self
;
709 NewMenu
->MenuInfo
.Flags
|= MF_SYSMENU
;
710 NewMenu
->MenuInfo
.Wnd
= Window
->hSelf
;
712 //IntReleaseMenuObject(NewMenuObject);
714 IntReleaseMenuObject(Menu
);
718 hSysMenu
= UserCreateMenu(FALSE
);
723 SysMenu
= IntGetMenuObject(hSysMenu
);
726 UserDestroyMenu(hSysMenu
);
729 SysMenu
->MenuInfo
.Flags
|= MF_SYSMENU
;
730 SysMenu
->MenuInfo
.Wnd
= Window
->hSelf
;
731 hNewMenu
= co_IntLoadSysMenuTemplate();
734 IntReleaseMenuObject(SysMenu
);
735 UserDestroyMenu(hSysMenu
);
738 Menu
= IntGetMenuObject(hNewMenu
);
741 IntReleaseMenuObject(SysMenu
);
742 UserDestroyMenu(hSysMenu
);
746 NewMenu
= IntCloneMenu(Menu
);
749 NewMenu
->MenuInfo
.Flags
|= MF_SYSMENU
| MF_POPUP
;
750 IntReleaseMenuObject(NewMenu
);
751 UserSetMenuDefaultItem(NewMenu
, SC_CLOSE
, FALSE
);
753 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
754 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
755 ItemInfo
.fType
= MF_POPUP
;
756 ItemInfo
.fState
= MFS_ENABLED
;
757 ItemInfo
.dwTypeData
= NULL
;
759 ItemInfo
.hSubMenu
= NewMenu
->MenuInfo
.Self
;
760 IntInsertMenuItem(SysMenu
, (UINT
) -1, TRUE
, &ItemInfo
);
762 Window
->SystemMenu
= SysMenu
->MenuInfo
.Self
;
766 IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
767 IntReleaseMenuObject(Menu
);
776 if(Window
->SystemMenu
)
777 return IntGetMenuObject((HMENU
)Window
->SystemMenu
);
785 IntIsChildWindow(HWND Parent
, HWND Child
)
787 PWINDOW_OBJECT BaseWindow
, Window
;
789 if(!(BaseWindow
= UserGetWindowObject(Child
)))
797 if (Window
->hSelf
== Parent
)
801 if(!(Window
->Style
& WS_CHILD
))
806 Window
= Window
->Parent
;
813 IntIsWindowVisible(HWND hWnd
)
815 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
817 if(!(BaseWindow
= IntGetWindowObject(hWnd
)))
825 if(!(Window
->Style
& WS_CHILD
))
829 if(!(Window
->Style
& WS_VISIBLE
))
831 if(Window
!= BaseWindow
)
832 IntReleaseWindowObject(Window
);
833 IntReleaseWindowObject(BaseWindow
);
837 Window
= IntGetParentObject(Window
);
838 if(Old
!= BaseWindow
)
839 IntReleaseWindowObject(Old
);
844 if(Window
->Style
& WS_VISIBLE
)
846 if(Window
!= BaseWindow
)
847 IntReleaseWindowObject(Window
);
848 IntReleaseWindowObject(BaseWindow
);
851 if(Window
!= BaseWindow
)
852 IntReleaseWindowObject(Window
);
854 IntReleaseWindowObject(BaseWindow
);
859 /* link the window into siblings and parent. children are kept in place. */
863 PWINDOW_OBJECT WndParent
,
864 PWINDOW_OBJECT WndPrevSibling
/* set to NULL if top sibling */
867 PWINDOW_OBJECT Parent
;
869 Wnd
->Parent
= WndParent
;
870 if ((Wnd
->PrevSibling
= WndPrevSibling
))
872 /* link after WndPrevSibling */
873 if ((Wnd
->NextSibling
= WndPrevSibling
->NextSibling
))
874 Wnd
->NextSibling
->PrevSibling
= Wnd
;
875 else if ((Parent
= Wnd
->Parent
))
877 if(Parent
->LastChild
== WndPrevSibling
)
878 Parent
->LastChild
= Wnd
;
880 Wnd
->PrevSibling
->NextSibling
= Wnd
;
885 Parent
= Wnd
->Parent
;
886 if ((Wnd
->NextSibling
= WndParent
->FirstChild
))
887 Wnd
->NextSibling
->PrevSibling
= Wnd
;
890 Parent
->LastChild
= Wnd
;
891 Parent
->FirstChild
= Wnd
;
896 Parent
->FirstChild
= Wnd
;
903 IntSetOwner(HWND hWnd
, HWND hWndNewOwner
)
905 PWINDOW_OBJECT Wnd
, WndOldOwner
, WndNewOwner
;
908 Wnd
= IntGetWindowObject(hWnd
);
912 WndOldOwner
= IntGetWindowObject(Wnd
->hOwner
);
915 ret
= WndOldOwner
->hSelf
;
916 IntReleaseWindowObject(WndOldOwner
);
923 if((WndNewOwner
= IntGetWindowObject(hWndNewOwner
)))
925 Wnd
->hOwner
= hWndNewOwner
;
926 IntReleaseWindowObject(WndNewOwner
);
931 IntReleaseWindowObject(Wnd
);
935 PWINDOW_OBJECT FASTCALL
936 co_IntSetParent(PWINDOW_OBJECT Wnd
, PWINDOW_OBJECT WndNewParent
)
938 PWINDOW_OBJECT WndOldParent
, Sibling
, InsertAfter
;
939 HWND hWnd
, hWndNewParent
, hWndOldParent
;
944 ASSERT(WndNewParent
);
946 ASSERT_REFS_CO(WndNewParent
);
949 hWndNewParent
= WndNewParent
->hSelf
;
952 * Windows hides the window first, then shows it again
953 * including the WM_SHOWWINDOW messages and all
955 WasVisible
= co_WinPosShowWindow(Wnd
, SW_HIDE
);
957 /* Validate that window and parent still exist */
958 if (!IntIsWindow(hWnd
) || !IntIsWindow(hWndNewParent
))
961 /* Window must belong to current process */
962 if (Wnd
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
965 WndOldParent
= IntGetParentObject(Wnd
);
966 hWndOldParent
= (WndOldParent
? WndOldParent
->hSelf
: NULL
);
968 if (WndNewParent
!= WndOldParent
)
970 IntUnlinkWindow(Wnd
);
972 if (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
))
974 /* Not a TOPMOST window, put after TOPMOSTs of new parent */
975 Sibling
= WndNewParent
->FirstChild
;
976 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
978 InsertAfter
= Sibling
;
979 Sibling
= Sibling
->NextSibling
;
982 if (NULL
== InsertAfter
)
984 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
988 IntReferenceWindowObject(InsertAfter
);
989 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
990 IntReleaseWindowObject(InsertAfter
);
993 if (WndNewParent
->hSelf
!= IntGetDesktopWindow()) /* a child window */
995 if (!(Wnd
->Style
& WS_CHILD
))
997 //if ( Wnd->Menu ) DestroyMenu ( Wnd->menu );
998 IntSetMenu(Wnd
, NULL
, &MenuChanged
);
1004 * SetParent additionally needs to make hwnd the top window
1005 * in the z-order and send the expected WM_WINDOWPOSCHANGING and
1006 * WM_WINDOWPOSCHANGED notification messages.
1008 co_WinPosSetWindowPos(Wnd
, (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOP
: HWND_TOPMOST
),
1009 0, 0, 0, 0, SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
1010 | (WasVisible
? SWP_SHOWWINDOW
: 0));
1013 * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
1014 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
1018 * Validate that the old parent still exist, since it migth have been
1019 * destroyed during the last callbacks to user-mode
1023 if(!IntIsWindow(WndOldParent
->hSelf
))
1025 IntReleaseWindowObject(WndOldParent
);
1029 /* don't dereference the window object here, it must be done by the caller
1030 of IntSetParent() */
1031 return WndOldParent
;
1037 IntSetSystemMenu(PWINDOW_OBJECT Window
, PMENU_OBJECT Menu
)
1039 PMENU_OBJECT OldMenu
;
1040 if(Window
->SystemMenu
)
1042 OldMenu
= IntGetMenuObject(Window
->SystemMenu
);
1045 OldMenu
->MenuInfo
.Flags
&= ~ MF_SYSMENU
;
1046 IntReleaseMenuObject(OldMenu
);
1052 /* FIXME check window style, propably return FALSE ? */
1053 Window
->SystemMenu
= Menu
->MenuInfo
.Self
;
1054 Menu
->MenuInfo
.Flags
|= MF_SYSMENU
;
1057 Window
->SystemMenu
= (HMENU
)0;
1063 /* unlink the window from siblings and parent. children are kept in place. */
1065 IntUnlinkWindow(PWINDOW_OBJECT Wnd
)
1067 PWINDOW_OBJECT WndParent
= Wnd
->Parent
;
1069 if (Wnd
->NextSibling
)
1070 Wnd
->NextSibling
->PrevSibling
= Wnd
->PrevSibling
;
1071 else if (WndParent
&& WndParent
->LastChild
== Wnd
)
1072 WndParent
->LastChild
= Wnd
->PrevSibling
;
1074 if (Wnd
->PrevSibling
)
1075 Wnd
->PrevSibling
->NextSibling
= Wnd
->NextSibling
;
1076 else if (WndParent
&& WndParent
->FirstChild
== Wnd
)
1077 WndParent
->FirstChild
= Wnd
->NextSibling
;
1079 Wnd
->PrevSibling
= Wnd
->NextSibling
= Wnd
->Parent
= NULL
;
1085 PWINDOW_OBJECT Window
, Child
;
1087 if(!(Window
= IntGetWindowObject(IntGetDesktopWindow())))
1089 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1093 for(Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
1095 if(Child
->hOwner
&& Child
->Style
& WS_VISIBLE
)
1098 * The desktop has a popup window if one of them has
1099 * an owner window and is visible
1101 IntReleaseWindowObject(Window
);
1106 IntReleaseWindowObject(Window
);
1111 IntIsWindowInDestroy(PWINDOW_OBJECT Window
)
1113 return ((Window
->Status
& WINDOWSTATUS_DESTROYING
) == WINDOWSTATUS_DESTROYING
);
1116 /* FUNCTIONS *****************************************************************/
1122 NtUserAlterWindowStyle(DWORD Unknown0
,
1133 * As best as I can figure, this function is used by EnumWindows,
1134 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
1136 * It's supposed to build a list of HWNDs to return to the caller.
1137 * We can figure out what kind of list by what parameters are
1145 NtUserBuildHwndList(
1157 /* FIXME handle bChildren */
1161 PWINDOW_OBJECT Window
, Child
;
1162 if(!(Window
= IntGetWindowObject(hwndParent
)))
1164 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1168 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1170 if(dwCount
++ < nBufSize
&& pWnd
)
1172 Status
= MmCopyToCaller(pWnd
++, &Child
->hSelf
, sizeof(HWND
));
1173 if(!NT_SUCCESS(Status
))
1175 SetLastNtError(Status
);
1181 IntReleaseWindowObject(Window
);
1186 PW32THREAD W32Thread
;
1187 PLIST_ENTRY Current
;
1188 PWINDOW_OBJECT Window
;
1190 Status
= PsLookupThreadByThreadId((HANDLE
)dwThreadId
, &Thread
);
1191 if(!NT_SUCCESS(Status
))
1193 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1196 if(!(W32Thread
= Thread
->Tcb
.Win32Thread
))
1198 ObDereferenceObject(Thread
);
1199 DPRINT("Thread is not a GUI Thread!\n");
1200 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1204 Current
= W32Thread
->WindowListHead
.Flink
;
1205 while(Current
!= &(W32Thread
->WindowListHead
))
1207 Window
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
1210 if(dwCount
< nBufSize
&& pWnd
)
1212 Status
= MmCopyToCaller(pWnd
++, &Window
->hSelf
, sizeof(HWND
));
1213 if(!NT_SUCCESS(Status
))
1215 SetLastNtError(Status
);
1220 Current
= Current
->Flink
;
1223 ObDereferenceObject(Thread
);
1227 PDESKTOP_OBJECT Desktop
;
1228 PWINDOW_OBJECT Window
, Child
;
1230 if(hDesktop
== NULL
&& !(Desktop
= IntGetActiveDesktop()))
1232 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1238 Status
= IntValidateDesktopHandle(hDesktop
,
1242 if(!NT_SUCCESS(Status
))
1244 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1248 if(!(Window
= IntGetWindowObject(Desktop
->DesktopWindow
)))
1251 ObDereferenceObject(Desktop
);
1252 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1256 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1258 if(dwCount
++ < nBufSize
&& pWnd
)
1260 Status
= MmCopyToCaller(pWnd
++, &Child
->hSelf
, sizeof(HWND
));
1261 if(!NT_SUCCESS(Status
))
1263 SetLastNtError(Status
);
1269 IntReleaseWindowObject(Window
);
1271 ObDereferenceObject(Desktop
);
1282 NtUserChildWindowFromPointEx(HWND hwndParent
,
1287 PWINDOW_OBJECT Parent
;
1292 if(!(Parent
= IntGetWindowObject(hwndParent
)))
1294 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1301 if(Parent
->hSelf
!= IntGetDesktopWindow())
1303 Pt
.x
+= Parent
->ClientRect
.left
;
1304 Pt
.y
+= Parent
->ClientRect
.top
;
1307 if(!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
))
1309 IntReleaseWindowObject(Parent
);
1313 Ret
= Parent
->hSelf
;
1314 if((List
= IntWinListChildren(Parent
)))
1316 for(phWnd
= List
; *phWnd
; phWnd
++)
1318 PWINDOW_OBJECT Child
;
1319 if((Child
= IntGetWindowObject(*phWnd
)))
1321 if(!(Child
->Style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
))
1323 IntReleaseWindowObject(Child
);
1326 if((Child
->Style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
))
1328 IntReleaseWindowObject(Child
);
1331 if((Child
->ExStyle
& WS_EX_TRANSPARENT
) && (uiFlags
& CWP_SKIPTRANSPARENT
))
1333 IntReleaseWindowObject(Child
);
1336 if(IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
1339 IntReleaseWindowObject(Child
);
1342 IntReleaseWindowObject(Child
);
1348 IntReleaseWindowObject(Parent
);
1354 * calculates the default position of a window
1357 IntCalcDefPosSize(PWINDOW_OBJECT Parent
, PWINDOW_OBJECT Window
, RECT
*rc
, BOOL IncPos
)
1364 IntGdiIntersectRect(rc
, rc
, &Parent
->ClientRect
);
1368 Pos
.x
= Parent
->TiledCounter
* (UserGetSystemMetrics(SM_CXSIZE
) + UserGetSystemMetrics(SM_CXFRAME
));
1369 Pos
.y
= Parent
->TiledCounter
* (UserGetSystemMetrics(SM_CYSIZE
) + UserGetSystemMetrics(SM_CYFRAME
));
1370 if(Pos
.x
> ((rc
->right
- rc
->left
) / 4) ||
1371 Pos
.y
> ((rc
->bottom
- rc
->top
) / 4))
1373 /* reset counter and position */
1376 Parent
->TiledCounter
= 0;
1378 Parent
->TiledCounter
++;
1389 Sz
.cx
= EngMulDiv(rc
->right
- rc
->left
, 3, 4);
1390 Sz
.cy
= EngMulDiv(rc
->bottom
- rc
->top
, 3, 4);
1394 rc
->right
= rc
->left
+ Sz
.cx
;
1395 rc
->bottom
= rc
->top
+ Sz
.cy
;
1404 co_IntCreateWindowEx(DWORD dwExStyle
,
1405 PUNICODE_STRING ClassName
,
1406 PUNICODE_STRING WindowName
,
1414 HINSTANCE hInstance
,
1417 BOOL bUnicodeWindow
)
1419 PWINSTATION_OBJECT WinSta
;
1420 PWNDCLASS_OBJECT Class
;
1421 PWINDOW_OBJECT Window
= NULL
;
1422 PWINDOW_OBJECT ParentWindow
= NULL
, OwnerWindow
;
1423 HWND ParentWindowHandle
;
1424 HWND OwnerWindowHandle
;
1425 PMENU_OBJECT SystemMenu
;
1431 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1438 CBT_CREATEWNDW CbtCreate
;
1442 DECLARE_RETURN(HWND
);
1445 ParentWindowHandle
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
1446 OwnerWindowHandle
= NULL
;
1448 if (hWndParent
== HWND_MESSAGE
)
1451 * native ole32.OleInitialize uses HWND_MESSAGE to create the
1452 * message window (style: WS_POPUP|WS_DISABLED)
1454 DPRINT1("FIXME - Parent is HWND_MESSAGE\n");
1456 else if (hWndParent
)
1458 if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1459 ParentWindowHandle
= hWndParent
;
1461 OwnerWindowHandle
= UserGetAncestor(hWndParent
, GA_ROOT
);
1463 else if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1465 RETURN( (HWND
)0); /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1468 if (NULL
!= ParentWindowHandle
)
1470 ParentWindow
= UserGetWindowObject(ParentWindowHandle
);
1473 UserRefObjectCo(ParentWindow
);
1477 ParentWindow
= NULL
;
1480 /* FIXME: parent must belong to the current process */
1482 /* Check the class. */
1483 ClassFound
= ClassReferenceClassByNameOrAtom(&Class
, ClassName
->Buffer
, hInstance
);
1486 if (IS_ATOM(ClassName
->Buffer
))
1488 DPRINT1("Class 0x%x not found\n", (DWORD_PTR
) ClassName
->Buffer
);
1492 DPRINT1("Class %wZ not found\n", ClassName
);
1495 SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS
);
1499 /* Check the window station. */
1500 if (PsGetWin32Thread()->Desktop
== NULL
)
1502 ClassDereferenceObject(Class
);
1504 DPRINT("Thread is not attached to a desktop! Cannot create window!\n");
1507 WinSta
= PsGetWin32Thread()->Desktop
->WindowStation
;
1508 ObReferenceObjectByPointer(WinSta
, KernelMode
, ExWindowStationObjectType
, 0);
1510 /* Create the window object. */
1511 Window
= (PWINDOW_OBJECT
)
1512 ObmCreateObject(&gHandleTable
, &Handle
,
1513 otWindow
, sizeof(WINDOW_OBJECT
) + Class
->cbWndExtra
1516 DPRINT("Created object with handle %X\n", Handle
);
1519 ObDereferenceObject(WinSta
);
1520 ClassDereferenceObject(Class
);
1521 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1525 UserRefObjectCo(Window
);
1528 ObDereferenceObject(WinSta
);
1530 if (NULL
== PsGetWin32Thread()->Desktop
->DesktopWindow
)
1532 /* If there is no desktop window yet, we must be creating it */
1533 PsGetWin32Thread()->Desktop
->DesktopWindow
= Handle
;
1537 * Fill out the structure describing it.
1539 Window
->Class
= Class
;
1541 InsertTailList(&Class
->ClassWindowsListHead
, &Window
->ClassListEntry
);
1543 Window
->ExStyle
= dwExStyle
;
1544 Window
->Style
= dwStyle
& ~WS_VISIBLE
;
1545 DPRINT("1: Style is now %lx\n", Window
->Style
);
1547 Window
->SystemMenu
= (HMENU
)0;
1548 Window
->ContextHelpId
= 0;
1550 Window
->Instance
= hInstance
;
1551 Window
->hSelf
= Handle
;
1552 if (0 != (dwStyle
& WS_CHILD
))
1554 Window
->IDMenu
= (UINT
) hMenu
;
1558 IntSetMenu(Window
, hMenu
, &MenuChanged
);
1560 Window
->MessageQueue
= PsGetWin32Thread()->MessageQueue
;
1561 IntReferenceMessageQueue(Window
->MessageQueue
);
1562 Window
->Parent
= ParentWindow
;
1563 if((OwnerWindow
= IntGetWindowObject(OwnerWindowHandle
)))
1565 Window
->hOwner
= OwnerWindowHandle
;
1566 IntReleaseWindowObject(OwnerWindow
);
1571 Window
->hOwner
= NULL
;
1574 Window
->UserData
= 0;
1575 if ((((DWORD
)Class
->lpfnWndProcA
& 0xFFFF0000) != 0xFFFF0000)
1576 && (((DWORD
)Class
->lpfnWndProcW
& 0xFFFF0000) != 0xFFFF0000))
1578 Window
->Unicode
= bUnicodeWindow
;
1582 Window
->Unicode
= Class
->Unicode
;
1584 Window
->WndProcA
= Class
->lpfnWndProcA
;
1585 Window
->WndProcW
= Class
->lpfnWndProcW
;
1586 Window
->OwnerThread
= PsGetCurrentThread();
1587 Window
->FirstChild
= NULL
;
1588 Window
->LastChild
= NULL
;
1589 Window
->PrevSibling
= NULL
;
1590 Window
->NextSibling
= NULL
;
1592 /* extra window data */
1593 if (Class
->cbWndExtra
!= 0)
1595 Window
->ExtraData
= (PCHAR
)(Window
+ 1);
1596 Window
->ExtraDataSize
= Class
->cbWndExtra
;
1597 RtlZeroMemory(Window
->ExtraData
, Window
->ExtraDataSize
);
1601 Window
->ExtraData
= NULL
;
1602 Window
->ExtraDataSize
= 0;
1605 InitializeListHead(&Window
->PropListHead
);
1606 InitializeListHead(&Window
->WndObjListHead
);
1608 if (NULL
!= WindowName
->Buffer
)
1610 Window
->WindowName
.MaximumLength
= WindowName
->MaximumLength
;
1611 Window
->WindowName
.Length
= WindowName
->Length
;
1612 Window
->WindowName
.Buffer
= ExAllocatePoolWithTag(PagedPool
, WindowName
->MaximumLength
,
1614 if (NULL
== Window
->WindowName
.Buffer
)
1616 ClassDereferenceObject(Class
);
1617 DPRINT1("Failed to allocate mem for window name\n");
1618 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1621 RtlCopyMemory(Window
->WindowName
.Buffer
, WindowName
->Buffer
, WindowName
->MaximumLength
);
1625 RtlInitUnicodeString(&Window
->WindowName
, NULL
);
1630 * This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1631 * tested for WS_POPUP
1633 if ((dwExStyle
& WS_EX_DLGMODALFRAME
) ||
1634 ((!(dwExStyle
& WS_EX_STATICEDGE
)) &&
1635 (dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
))))
1636 dwExStyle
|= WS_EX_WINDOWEDGE
;
1638 dwExStyle
&= ~WS_EX_WINDOWEDGE
;
1640 /* Correct the window style. */
1641 if (!(dwStyle
& WS_CHILD
))
1643 Window
->Style
|= WS_CLIPSIBLINGS
;
1644 DPRINT("3: Style is now %lx\n", Window
->Style
);
1645 if (!(dwStyle
& WS_POPUP
))
1647 Window
->Style
|= WS_CAPTION
;
1648 Window
->Flags
|= WINDOWOBJECT_NEED_SIZE
;
1649 DPRINT("4: Style is now %lx\n", Window
->Style
);
1653 /* create system menu */
1654 if((Window
->Style
& WS_SYSMENU
) &&
1655 (Window
->Style
& WS_CAPTION
) == WS_CAPTION
)
1657 SystemMenu
= IntGetSystemMenu(Window
, TRUE
, TRUE
);
1660 Window
->SystemMenu
= SystemMenu
->MenuInfo
.Self
;
1661 IntReleaseMenuObject(SystemMenu
);
1665 /* Insert the window into the thread's window list. */
1666 InsertTailList (&PsGetWin32Thread()->WindowListHead
, &Window
->ThreadListEntry
);
1668 /* Allocate a DCE for this window. */
1669 if (dwStyle
& CS_OWNDC
)
1671 Window
->Dce
= DceAllocDCE(Window
->hSelf
, DCE_WINDOW_DC
);
1673 /* FIXME: Handle "CS_CLASSDC" */
1681 Cs
.lpCreateParams
= lpParam
;
1682 Cs
.hInstance
= hInstance
;
1684 Cs
.hwndParent
= ParentWindowHandle
;
1690 Cs
.lpszName
= (LPCWSTR
) WindowName
;
1691 Cs
.lpszClass
= (LPCWSTR
) ClassName
;
1692 Cs
.dwExStyle
= dwExStyle
;
1693 CbtCreate
.lpcs
= &Cs
;
1694 CbtCreate
.hwndInsertAfter
= HWND_TOP
;
1695 if (co_HOOK_CallHooks(WH_CBT
, HCBT_CREATEWND
, (WPARAM
) Handle
, (LPARAM
) &CbtCreate
))
1698 /* FIXME - Delete window object and remove it from the thread windows list */
1699 /* FIXME - delete allocated DCE */
1701 ClassDereferenceObject(Class
);
1702 DPRINT1("CBT-hook returned !0\n");
1703 RETURN( (HWND
) NULL
);
1711 /* default positioning for overlapped windows */
1712 if(!(Window
->Style
& (WS_POPUP
| WS_CHILD
)))
1715 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
1716 BOOL CalculatedDefPosSize
= FALSE
;
1718 IntGetDesktopWorkArea(Window
->OwnerThread
->Tcb
.Win32Thread
->Desktop
, &WorkArea
);
1721 ProcessParams
= PsGetCurrentProcess()->Peb
->ProcessParameters
;
1723 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1725 CalculatedDefPosSize
= IntCalcDefPosSize(ParentWindow
, Window
, &rc
, TRUE
);
1727 if(ProcessParams
->WindowFlags
& STARTF_USEPOSITION
)
1729 ProcessParams
->WindowFlags
&= ~STARTF_USEPOSITION
;
1730 Pos
.x
= WorkArea
.left
+ ProcessParams
->StartingX
;
1731 Pos
.y
= WorkArea
.top
+ ProcessParams
->StartingY
;
1739 /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
1740 y is something else */
1741 if(y
!= CW_USEDEFAULT
&& y
!= CW_USEDEFAULT16
)
1746 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1748 if(!CalculatedDefPosSize
)
1750 IntCalcDefPosSize(ParentWindow
, Window
, &rc
, FALSE
);
1752 if(ProcessParams
->WindowFlags
& STARTF_USESIZE
)
1754 ProcessParams
->WindowFlags
&= ~STARTF_USESIZE
;
1755 Size
.cx
= ProcessParams
->CountX
;
1756 Size
.cy
= ProcessParams
->CountY
;
1760 Size
.cx
= rc
.right
- rc
.left
;
1761 Size
.cy
= rc
.bottom
- rc
.top
;
1764 /* move the window if necessary */
1766 Pos
.x
= max(rc
.left
, 0);
1768 Pos
.y
= max(rc
.top
, 0);
1773 /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
1774 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1779 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1786 /* Initialize the window dimensions. */
1787 Window
->WindowRect
.left
= Pos
.x
;
1788 Window
->WindowRect
.top
= Pos
.y
;
1789 Window
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1790 Window
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1791 if (0 != (Window
->Style
& WS_CHILD
) && ParentWindow
)
1793 IntGdiOffsetRect(&(Window
->WindowRect
), ParentWindow
->ClientRect
.left
,
1794 ParentWindow
->ClientRect
.top
);
1796 Window
->ClientRect
= Window
->WindowRect
;
1799 * Get the size and position of the window.
1801 if ((dwStyle
& WS_THICKFRAME
) || !(dwStyle
& (WS_POPUP
| WS_CHILD
)))
1803 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1805 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1806 co_WinPosGetMinMaxInfo(Window
, &MaxSize
, &MaxPos
, &MinTrack
,
1808 if (MaxSize
.x
< nWidth
)
1810 if (MaxSize
.y
< nHeight
)
1811 nHeight
= MaxSize
.y
;
1812 if (nWidth
< MinTrack
.x
)
1813 nWidth
= MinTrack
.x
;
1814 if (nHeight
< MinTrack
.y
)
1815 nHeight
= MinTrack
.y
;
1822 Window
->WindowRect
.left
= Pos
.x
;
1823 Window
->WindowRect
.top
= Pos
.y
;
1824 Window
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1825 Window
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1826 if (0 != (Window
->Style
& WS_CHILD
) && ParentWindow
)
1828 IntGdiOffsetRect(&(Window
->WindowRect
), ParentWindow
->ClientRect
.left
,
1829 ParentWindow
->ClientRect
.top
);
1831 Window
->ClientRect
= Window
->WindowRect
;
1833 /* FIXME: Initialize the window menu. */
1835 /* Send a NCCREATE message. */
1841 DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d\n", Cs
.style
, Cs
.dwExStyle
, Cs
.hwndParent
);
1842 DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1843 DPRINT("IntCreateWindowEx(): About to send NCCREATE message.\n");
1844 Result
= co_IntSendMessage(Window
->hSelf
, WM_NCCREATE
, 0, (LPARAM
) &Cs
);
1847 /* FIXME: Cleanup. */
1848 DPRINT("IntCreateWindowEx(): NCCREATE message failed.\n");
1852 /* Calculate the non-client size. */
1853 MaxPos
.x
= Window
->WindowRect
.left
;
1854 MaxPos
.y
= Window
->WindowRect
.top
;
1855 DPRINT("IntCreateWindowEx(): About to get non-client size.\n");
1856 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1857 Result
= co_WinPosGetNonClientSize(Window
->hSelf
,
1858 &Window
->WindowRect
,
1859 &Window
->ClientRect
);
1860 IntGdiOffsetRect(&Window
->WindowRect
,
1861 MaxPos
.x
- Window
->WindowRect
.left
,
1862 MaxPos
.y
- Window
->WindowRect
.top
);
1864 if (NULL
!= ParentWindow
)
1866 /* link the window into the parent's child list */
1867 if ((dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
1869 PWINDOW_OBJECT PrevSibling
;
1870 if((PrevSibling
= ParentWindow
->LastChild
))
1871 IntReferenceWindowObject(PrevSibling
);
1872 /* link window as bottom sibling */
1873 IntLinkWindow(Window
, ParentWindow
, PrevSibling
/*prev sibling*/);
1875 IntReleaseWindowObject(PrevSibling
);
1879 /* link window as top sibling (but after topmost siblings) */
1880 PWINDOW_OBJECT InsertAfter
, Sibling
;
1881 if (0 == (dwExStyle
& WS_EX_TOPMOST
))
1884 Sibling
= ParentWindow
->FirstChild
;
1885 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
1887 InsertAfter
= Sibling
;
1888 Sibling
= Sibling
->NextSibling
;
1895 if (NULL
!= InsertAfter
)
1897 IntReferenceWindowObject(InsertAfter
);
1899 IntLinkWindow(Window
, ParentWindow
, InsertAfter
/* prev sibling */);
1900 if (NULL
!= InsertAfter
)
1902 IntReleaseWindowObject(InsertAfter
);
1907 /* Send the WM_CREATE message. */
1908 DPRINT("IntCreateWindowEx(): about to send CREATE message.\n");
1909 Result
= co_IntSendMessage(Window
->hSelf
, WM_CREATE
, 0, (LPARAM
) &Cs
);
1910 if (Result
== (LRESULT
)-1)
1912 /* FIXME: Cleanup. */
1913 ClassDereferenceObject(Class
);
1914 DPRINT("IntCreateWindowEx(): send CREATE message failed.\n");
1918 /* Send move and size messages. */
1919 if (!(Window
->Flags
& WINDOWOBJECT_NEED_SIZE
))
1923 DPRINT("IntCreateWindow(): About to send WM_SIZE\n");
1925 if ((Window
->ClientRect
.right
- Window
->ClientRect
.left
) < 0 ||
1926 (Window
->ClientRect
.bottom
- Window
->ClientRect
.top
) < 0)
1928 DPRINT("Sending bogus WM_SIZE\n");
1931 lParam
= MAKE_LONG(Window
->ClientRect
.right
-
1932 Window
->ClientRect
.left
,
1933 Window
->ClientRect
.bottom
-
1934 Window
->ClientRect
.top
);
1935 co_IntSendMessage(Window
->hSelf
, WM_SIZE
, SIZE_RESTORED
,
1938 DPRINT("IntCreateWindow(): About to send WM_MOVE\n");
1940 if (0 != (Window
->Style
& WS_CHILD
) && ParentWindow
)
1942 lParam
= MAKE_LONG(Window
->ClientRect
.left
- ParentWindow
->ClientRect
.left
,
1943 Window
->ClientRect
.top
- ParentWindow
->ClientRect
.top
);
1947 lParam
= MAKE_LONG(Window
->ClientRect
.left
,
1948 Window
->ClientRect
.top
);
1950 co_IntSendMessage(Window
->hSelf
, WM_MOVE
, 0, lParam
);
1952 /* Call WNDOBJ change procs */
1953 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
1956 /* Show or maybe minimize or maximize the window. */
1957 if (Window
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1962 SwFlag
= (Window
->Style
& WS_MINIMIZE
) ? SW_MINIMIZE
:
1964 co_WinPosMinMaximize(Window
, SwFlag
, &NewPos
);
1966 ((Window
->Style
& WS_CHILD
) || UserGetActiveWindow()) ?
1967 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
:
1968 SWP_NOZORDER
| SWP_FRAMECHANGED
;
1969 DPRINT("IntCreateWindow(): About to minimize/maximize\n");
1970 DPRINT("%d,%d %dx%d\n", NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
);
1971 co_WinPosSetWindowPos(Window
, 0, NewPos
.left
, NewPos
.top
,
1972 NewPos
.right
, NewPos
.bottom
, SwFlag
);
1975 /* Notify the parent window of a new child. */
1976 if ((Window
->Style
& WS_CHILD
) &&
1977 (!(Window
->ExStyle
& WS_EX_NOPARENTNOTIFY
)) && ParentWindow
)
1979 DPRINT("IntCreateWindow(): About to notify parent\n");
1980 co_IntSendMessage(ParentWindow
->hSelf
,
1982 MAKEWPARAM(WM_CREATE
, Window
->IDMenu
),
1983 (LPARAM
)Window
->hSelf
);
1986 if ((!hWndParent
) && (!HasOwner
))
1988 DPRINT("Sending CREATED notify\n");
1989 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Handle
);
1993 DPRINT("Not sending CREATED notify, %x %d\n", ParentWindow
, HasOwner
);
1996 /* Initialize and show the window's scrollbars */
1997 if (Window
->Style
& WS_VSCROLL
)
1999 co_UserShowScrollBar(Window
, SB_VERT
, TRUE
);
2001 if (Window
->Style
& WS_HSCROLL
)
2003 co_UserShowScrollBar(Window
, SB_HORZ
, TRUE
);
2006 if (dwStyle
& WS_VISIBLE
)
2008 DPRINT("IntCreateWindow(): About to show window\n");
2009 co_WinPosShowWindow(Window
, dwShowMode
);
2012 DPRINT("IntCreateWindow(): = %X\n", Handle
);
2013 DPRINT("WindowObject->SystemMenu = 0x%x\n", Window
->SystemMenu
);
2014 RETURN((HWND
)Handle
);
2018 UserDerefObjectCo(Window
);
2020 UserDerefObjectCo(ParentWindow
);
2026 NtUserCreateWindowEx(DWORD dwExStyle
,
2027 PUNICODE_STRING UnsafeClassName
,
2028 PUNICODE_STRING UnsafeWindowName
,
2036 HINSTANCE hInstance
,
2039 BOOL bUnicodeWindow
)
2042 UNICODE_STRING WindowName
;
2043 UNICODE_STRING ClassName
;
2045 DECLARE_RETURN(HWND
);
2047 DPRINT("Enter NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
2048 UserEnterExclusive();
2050 /* Get the class name (string or atom) */
2051 Status
= MmCopyFromCaller(&ClassName
, UnsafeClassName
, sizeof(UNICODE_STRING
));
2052 if (! NT_SUCCESS(Status
))
2054 SetLastNtError(Status
);
2057 if (! IS_ATOM(ClassName
.Buffer
))
2059 Status
= IntSafeCopyUnicodeStringTerminateNULL(&ClassName
, UnsafeClassName
);
2060 if (! NT_SUCCESS(Status
))
2062 SetLastNtError(Status
);
2067 /* safely copy the window name */
2068 if (NULL
!= UnsafeWindowName
)
2070 Status
= IntSafeCopyUnicodeString(&WindowName
, UnsafeWindowName
);
2071 if (! NT_SUCCESS(Status
))
2073 if (! IS_ATOM(ClassName
.Buffer
))
2075 RtlFreeUnicodeString(&ClassName
);
2077 SetLastNtError(Status
);
2083 RtlInitUnicodeString(&WindowName
, NULL
);
2086 NewWindow
= co_IntCreateWindowEx(dwExStyle
, &ClassName
, &WindowName
, dwStyle
, x
, y
, nWidth
, nHeight
,
2087 hWndParent
, hMenu
, hInstance
, lpParam
, dwShowMode
, bUnicodeWindow
);
2089 RtlFreeUnicodeString(&WindowName
);
2090 if (! IS_ATOM(ClassName
.Buffer
))
2092 RtlFreeUnicodeString(&ClassName
);
2098 DPRINT("Leave NtUserCreateWindowEx, ret=%i\n",_ret_
);
2107 NtUserDeferWindowPos(HDWP WinPosInfo
,
2109 HWND WndInsertAfter
,
2122 BOOLEAN FASTCALL
co_UserDestroyWindow(PWINDOW_OBJECT Window
)
2126 ASSERT_REFS_CO(Window
);
2133 /* Check for owner thread and desktop window */
2134 if ((Window
->OwnerThread
!= PsGetCurrentThread()) || IntIsDesktopWindow(Window
))
2136 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2140 /* Look whether the focus is within the tree of windows we will
2143 if (!co_WinPosShowWindow(Window
, SW_HIDE
))
2145 if (UserGetActiveWindow() == Window
->hSelf
)
2147 co_WinPosActivateOtherWindow(Window
);
2151 if (Window
->MessageQueue
->ActiveWindow
== Window
->hSelf
)
2152 Window
->MessageQueue
->ActiveWindow
= NULL
;
2153 if (Window
->MessageQueue
->FocusWindow
== Window
->hSelf
)
2154 Window
->MessageQueue
->FocusWindow
= NULL
;
2155 if (Window
->MessageQueue
->CaptureWindow
== Window
->hSelf
)
2156 Window
->MessageQueue
->CaptureWindow
= NULL
;
2158 IntDereferenceMessageQueue(Window
->MessageQueue
);
2162 if (co_HOOK_CallHooks(WH_CBT
, HCBT_DESTROYWND
, (WPARAM
) hwnd
, 0, TRUE
))
2168 IntEngWindowChanged(Window
, WOC_DELETE
);
2169 isChild
= (0 != (Window
->Style
& WS_CHILD
));
2175 if (! USER_IsExitingThread(GetCurrentThreadId()))
2177 send_parent_notify(hwnd
, WM_DESTROY
);
2180 else if (NULL
!= GetWindow(Wnd
, GW_OWNER
))
2182 co_HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
2183 /* FIXME: clean up palette - see "Internals" p.352 */
2187 if (!IntIsWindow(Window
->hSelf
))
2192 /* Recursively destroy owned windows */
2197 BOOL GotOne
= FALSE
;
2200 PWINDOW_OBJECT Child
, Desktop
;
2202 Desktop
= IntGetWindowObject(IntGetDesktopWindow());
2203 Children
= IntWinListChildren(Desktop
);
2204 IntReleaseWindowObject(Desktop
);
2207 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
2209 Child
= IntGetWindowObject(*ChildHandle
);
2212 if (Child
->hOwner
!= Window
->hSelf
)
2214 IntReleaseWindowObject(Child
);
2218 if (IntWndBelongsToThread(Child
, PsGetWin32Thread()))
2220 co_UserDestroyWindow(Child
);
2221 IntReleaseWindowObject(Child
);
2226 if (Child
->hOwner
!= NULL
)
2228 Child
->hOwner
= NULL
;
2231 IntReleaseWindowObject(Child
);
2233 ExFreePool(Children
);
2242 if (!IntIsWindow(Window
->hSelf
))
2247 /* Destroy the window storage */
2248 co_IntDestroyWindow(Window
, PsGetWin32Process(), PsGetWin32Thread(), TRUE
);
2260 NtUserDestroyWindow(HWND Wnd
)
2262 PWINDOW_OBJECT Window
;
2263 DECLARE_RETURN(BOOLEAN
);
2265 DPRINT("Enter NtUserDestroyWindow\n");
2266 UserEnterExclusive();
2268 Window
= IntGetWindowObject(Wnd
);
2274 RETURN(co_UserDestroyWindow(Window
));
2277 DPRINT("Leave NtUserDestroyWindow, ret=%i\n",_ret_
);
2289 NtUserDrawMenuBarTemp(
2296 /* we'll use this function just for caching the menu bar */
2306 NtUserEndDeferWindowPosEx(DWORD Unknown0
,
2319 NtUserFillWindow(DWORD Unknown0
,
2331 IntFindWindow(PWINDOW_OBJECT Parent
,
2332 PWINDOW_OBJECT ChildAfter
,
2334 PUNICODE_STRING WindowName
)
2336 BOOL CheckWindowName
;
2342 CheckWindowName
= (WindowName
&& (WindowName
->Length
> 0));
2344 if((List
= IntWinListChildren(Parent
)))
2349 /* skip handles before and including ChildAfter */
2350 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->hSelf
))
2354 /* search children */
2357 PWINDOW_OBJECT Child
;
2358 if(!(Child
= IntGetWindowObject(*(phWnd
++))))
2363 /* Do not send WM_GETTEXT messages in the kernel mode version!
2364 The user mode version however calls GetWindowText() which will
2365 send WM_GETTEXT messages to windows belonging to its processes */
2366 if((!CheckWindowName
|| !RtlCompareUnicodeString(WindowName
, &(Child
->WindowName
), FALSE
)) &&
2367 (!ClassAtom
|| Child
->Class
->Atom
== ClassAtom
))
2370 IntReleaseWindowObject(Child
);
2374 IntReleaseWindowObject(Child
);
2384 * Searches a window's children for a window with the specified
2387 * hwndParent = The window whose childs are to be searched.
2389 * HWND_MESSAGE = message-only windows
2391 * hwndChildAfter = Search starts after this child window.
2392 * NULL = start from beginning
2394 * ucClassName = Class name to search for
2395 * Reguired parameter.
2397 * ucWindowName = Window name
2398 * ->Buffer == NULL = don't care
2401 * The HWND of the window if it was found, otherwise NULL
2407 NtUserFindWindowEx(HWND hwndParent
,
2408 HWND hwndChildAfter
,
2409 PUNICODE_STRING ucClassName
,
2410 PUNICODE_STRING ucWindowName
)
2412 PWINDOW_OBJECT Parent
, ChildAfter
;
2413 UNICODE_STRING ClassName
, WindowName
;
2415 HWND Desktop
, Ret
= NULL
;
2417 DECLARE_RETURN(HWND
);
2419 DPRINT("Enter NtUserFindWindowEx\n");
2422 Desktop
= IntGetCurrentThreadDesktopWindow();
2424 if(hwndParent
== NULL
)
2425 hwndParent
= Desktop
;
2427 else if(hwndParent == HWND_MESSAGE)
2429 hwndParent = IntGetMessageWindow();
2433 if(!(Parent
= IntGetWindowObject(hwndParent
)))
2435 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2440 if(hwndChildAfter
&& !(ChildAfter
= IntGetWindowObject(hwndChildAfter
)))
2442 IntReleaseWindowObject(Parent
);
2443 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2447 /* copy the window name */
2448 Status
= IntSafeCopyUnicodeString(&WindowName
, ucWindowName
);
2449 if(!NT_SUCCESS(Status
))
2451 SetLastNtError(Status
);
2455 /* safely copy the class name */
2456 Status
= MmCopyFromCaller(&ClassName
, ucClassName
, sizeof(UNICODE_STRING
));
2457 if(!NT_SUCCESS(Status
))
2459 SetLastNtError(Status
);
2462 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2465 /* safely copy the class name string (NULL terminated because class-lookup
2467 buf
= ExAllocatePoolWithTag(PagedPool
, ClassName
.Length
+ sizeof(WCHAR
), TAG_STRING
);
2470 SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES
);
2473 Status
= MmCopyFromCaller(buf
, ClassName
.Buffer
, ClassName
.Length
);
2474 if(!NT_SUCCESS(Status
))
2477 SetLastNtError(Status
);
2480 ClassName
.Buffer
= buf
;
2481 /* make sure the string is null-terminated */
2482 buf
+= ClassName
.Length
/ sizeof(WCHAR
);
2486 /* find the class object */
2487 if(ClassName
.Buffer
)
2489 PWINSTATION_OBJECT WinStaObject
;
2491 if (PsGetWin32Thread()->Desktop
== NULL
)
2493 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2497 WinStaObject
= PsGetWin32Thread()->Desktop
->WindowStation
;
2499 Status
= RtlLookupAtomInAtomTable(
2500 WinStaObject
->AtomTable
,
2504 if (!NT_SUCCESS(Status
))
2506 DPRINT1("Failed to lookup class atom!\n");
2507 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST
);
2512 if(Parent
->hSelf
== Desktop
)
2515 PWINDOW_OBJECT TopLevelWindow
;
2516 BOOLEAN CheckWindowName
;
2517 BOOLEAN CheckClassName
;
2518 BOOLEAN WindowMatches
;
2519 BOOLEAN ClassMatches
;
2521 /* windows searches through all top-level windows if the parent is the desktop
2524 if((List
= IntWinListChildren(Parent
)))
2530 /* skip handles before and including ChildAfter */
2531 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->hSelf
))
2535 CheckWindowName
= WindowName
.Length
> 0;
2536 CheckClassName
= ClassName
.Buffer
!= NULL
;
2538 /* search children */
2541 if(!(TopLevelWindow
= IntGetWindowObject(*(phWnd
++))))
2546 /* Do not send WM_GETTEXT messages in the kernel mode version!
2547 The user mode version however calls GetWindowText() which will
2548 send WM_GETTEXT messages to windows belonging to its processes */
2549 WindowMatches
= !CheckWindowName
|| !RtlCompareUnicodeString(
2550 &WindowName
, &TopLevelWindow
->WindowName
, FALSE
);
2551 ClassMatches
= !CheckClassName
||
2552 ClassAtom
== TopLevelWindow
->Class
->Atom
;
2554 if (WindowMatches
&& ClassMatches
)
2556 Ret
= TopLevelWindow
->hSelf
;
2557 IntReleaseWindowObject(TopLevelWindow
);
2561 if (IntFindWindow(TopLevelWindow
, NULL
, ClassAtom
, &WindowName
))
2563 /* window returns the handle of the top-level window, in case it found
2565 Ret
= TopLevelWindow
->hSelf
;
2566 IntReleaseWindowObject(TopLevelWindow
);
2570 IntReleaseWindowObject(TopLevelWindow
);
2576 Ret
= IntFindWindow(Parent
, ChildAfter
, ClassAtom
, &WindowName
);
2580 if(Ret
== NULL
&& hwndParent
== NULL
&& hwndChildAfter
== NULL
)
2582 /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
2583 search the message-only windows. Should this also be done if
2584 Parent is the desktop window??? */
2585 PWINDOW_OBJECT MsgWindows
;
2587 if((MsgWindows
= IntGetWindowObject(IntGetMessageWindow())))
2589 Ret
= IntFindWindow(MsgWindows
, ChildAfter
, ClassAtom
, &WindowName
);
2590 IntReleaseWindowObject(MsgWindows
);
2596 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2597 ExFreePool(ClassName
.Buffer
);
2600 RtlFreeUnicodeString(&WindowName
);
2604 IntReleaseWindowObject(ChildAfter
);
2605 IntReleaseWindowObject(Parent
);
2610 DPRINT("Leave NtUserFindWindowEx, ret %i\n",_ret_
);
2620 NtUserFlashWindowEx(DWORD Unknown0
)
2631 HWND FASTCALL
UserGetAncestor(HWND hWnd
, UINT Type
)
2633 PWINDOW_OBJECT Wnd
, WndAncestor
, Parent
;
2636 if (hWnd
== IntGetDesktopWindow())
2641 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2643 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2651 WndAncestor
= IntGetParentObject(Wnd
);
2664 if(!(Parent
= IntGetParentObject(WndAncestor
)))
2668 if(IntIsDesktopWindow(Parent
))
2670 IntReleaseWindowObject(Parent
);
2674 IntReleaseWindowObject(tmp
);
2675 WndAncestor
= Parent
;
2683 IntReferenceWindowObject(WndAncestor
);
2688 Parent
= IntGetParent(WndAncestor
);
2689 IntReleaseWindowObject(Old
);
2694 WndAncestor
= Parent
;
2701 IntReleaseWindowObject(Wnd
);
2706 hWndAncestor
= (WndAncestor
? WndAncestor
->hSelf
: NULL
);
2707 IntReleaseWindowObject(Wnd
);
2709 if(WndAncestor
&& (WndAncestor
!= Wnd
))
2710 IntReleaseWindowObject(WndAncestor
);
2712 return hWndAncestor
;
2721 NtUserGetAncestor(HWND hWnd
, UINT Type
)
2723 DECLARE_RETURN(HWND
);
2725 DPRINT("Enter NtUserGetAncestor\n");
2726 UserEnterExclusive();
2728 RETURN(UserGetAncestor(hWnd
, Type
));
2731 DPRINT("Leave NtUserGetAncestor, ret=%i\n",_ret_
);
2737 * Returns client window rectangle relative to the upper-left corner of client area.
2739 * \param hWnd window handle.
2740 * \param Rect pointer to the buffer where the coordinates are returned.
2747 NtUserGetClientRect(HWND hWnd
, LPRECT Rect
)
2749 PWINDOW_OBJECT Window
;
2751 DECLARE_RETURN(BOOL
);
2753 DPRINT("Enter NtUserGetClientRect\n");
2756 if(!(Window
= IntGetWindowObject(hWnd
)))
2758 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2762 IntGetClientRect(Window
, &SafeRect
);
2763 IntReleaseWindowObject(Window
);
2765 if(!NT_SUCCESS(MmCopyToCaller(Rect
, &SafeRect
, sizeof(RECT
))))
2772 DPRINT("Leave NtUserGetClientRect, ret=%i\n",_ret_
);
2782 NtUserGetDesktopWindow()
2784 DECLARE_RETURN(HWND
);
2786 DPRINT("Enter NtUserGetDesktopWindow\n");
2789 RETURN( IntGetDesktopWindow());
2792 DPRINT("Leave NtUserGetDesktopWindow, ret=%i\n",_ret_
);
2802 NtUserGetInternalWindowPos(DWORD Unknown0
,
2816 NtUserGetLastActivePopup(HWND hWnd
)
2819 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2820 * not changed anywhere.
2821 * -- Filip, 01/nov/2003
2827 IntAcquireWinLockShared();
2829 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2831 IntReleaseWinLock();
2832 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2836 hWndLastPopup
= Wnd
->hWndLastPopup
;
2838 IntReleaseWinLock();
2840 return hWndLastPopup
;
2850 * The NtUserGetParent function retrieves a handle to the specified window's
2854 * Note that, despite its name, this function can return an owner window
2855 * instead of a parent window.
2862 NtUserGetParent(HWND hWnd
)
2864 PWINDOW_OBJECT Wnd
, WndParent
;
2865 HWND hWndParent
= NULL
;
2866 DECLARE_RETURN(HWND
);
2868 DPRINT("Enter NtUserGetParent\n");
2869 UserEnterExclusive();
2871 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2873 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2877 WndParent
= IntGetParent(Wnd
);
2880 hWndParent
= WndParent
->hSelf
;
2881 IntReleaseWindowObject(WndParent
);
2884 IntReleaseWindowObject(Wnd
);
2886 RETURN( hWndParent
);
2889 DPRINT("Leave NtUserGetParent, ret=%i\n",_ret_
);
2898 co_UserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2900 PWINDOW_OBJECT Wnd
= NULL
, WndParent
= NULL
, WndOldParent
;
2901 HWND hWndOldParent
= NULL
;
2903 if (IntIsBroadcastHwnd(hWndChild
) || IntIsBroadcastHwnd(hWndNewParent
))
2905 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2909 if (hWndChild
== IntGetDesktopWindow())
2911 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2917 if (!(WndParent
= IntGetWindowObject(hWndNewParent
)))
2919 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2925 if (!(WndParent
= IntGetWindowObject(IntGetDesktopWindow())))
2927 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2932 if (!(Wnd
= IntGetWindowObject(hWndChild
)))
2934 IntReleaseWindowObject(WndParent
);
2935 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2939 WndOldParent
= co_IntSetParent(Wnd
, WndParent
);
2943 hWndOldParent
= WndOldParent
->hSelf
;
2944 IntReleaseWindowObject(WndOldParent
);
2947 IntReleaseWindowObject(Wnd
);
2948 IntReleaseWindowObject(WndParent
);
2950 return( hWndOldParent
);
2958 * The NtUserSetParent function changes the parent window of the specified
2962 * The new parent window and the child window must belong to the same
2963 * application. If the window identified by the hWndChild parameter is
2964 * visible, the system performs the appropriate redrawing and repainting.
2965 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2966 * or WS_POPUP window styles of the window whose parent is being changed.
2973 NtUserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2975 DECLARE_RETURN(HWND
);
2977 DPRINT("Enter NtUserSetParent\n");
2978 UserEnterExclusive();
2980 RETURN( co_UserSetParent(hWndChild
, hWndNewParent
));
2983 DPRINT("Leave NtUserSetParent, ret=%i\n",_ret_
);
2991 HWND FASTCALL
UserGetShellWindow()
2993 PWINSTATION_OBJECT WinStaObject
;
2996 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
3001 if (!NT_SUCCESS(Status
))
3003 SetLastNtError(Status
);
3007 Ret
= (HWND
)WinStaObject
->ShellWindow
;
3009 ObDereferenceObject(WinStaObject
);
3015 * NtUserGetShellWindow
3017 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
3024 NtUserGetShellWindow()
3026 DECLARE_RETURN(HWND
);
3028 DPRINT("Enter NtUserGetShellWindow\n");
3031 RETURN( UserGetShellWindow() );
3034 DPRINT("Leave NtUserGetShellWindow, ret=%i\n",_ret_
);
3040 * NtUserSetShellWindowEx
3042 * This is undocumented function to set global shell window. The global
3043 * shell window has special handling of window position.
3050 NtUserSetShellWindowEx(HWND hwndShell
, HWND hwndListView
)
3052 PWINSTATION_OBJECT WinStaObject
;
3053 PWINDOW_OBJECT WndShell
;
3054 DECLARE_RETURN(BOOL
);
3056 DPRINT("Enter NtUserSetShellWindowEx\n");
3057 UserEnterExclusive();
3059 if (!(WndShell
= UserGetWindowObject(hwndShell
)))
3064 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
3069 if (!NT_SUCCESS(Status
))
3071 SetLastNtError(Status
);
3076 * Test if we are permitted to change the shell window.
3078 if (WinStaObject
->ShellWindow
)
3080 ObDereferenceObject(WinStaObject
);
3085 * Move shell window into background.
3087 if (hwndListView
&& hwndListView
!= hwndShell
)
3090 * Disabled for now to get Explorer working.
3091 * -- Filip, 01/nov/2003
3094 co_WinPosSetWindowPos(hwndListView
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
3097 if (UserGetWindowLong(hwndListView
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
3099 ObDereferenceObject(WinStaObject
);
3104 if (UserGetWindowLong(hwndShell
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
3106 ObDereferenceObject(WinStaObject
);
3110 UserRefObjectCo(WndShell
);
3111 co_WinPosSetWindowPos(WndShell
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
3113 WinStaObject
->ShellWindow
= hwndShell
;
3114 WinStaObject
->ShellListView
= hwndListView
;
3116 UserDerefObjectCo(WndShell
);
3118 ObDereferenceObject(WinStaObject
);
3122 DPRINT("Leave NtUserSetShellWindowEx, ret=%i\n",_ret_
);
3128 * NtUserGetSystemMenu
3130 * The NtUserGetSystemMenu function allows the application to access the
3131 * window menu (also known as the system menu or the control menu) for
3132 * copying and modifying.
3136 * Handle to the window that will own a copy of the window menu.
3138 * Specifies the action to be taken. If this parameter is FALSE,
3139 * NtUserGetSystemMenu returns a handle to the copy of the window menu
3140 * currently in use. The copy is initially identical to the window menu
3141 * but it can be modified.
3142 * If this parameter is TRUE, GetSystemMenu resets the window menu back
3143 * to the default state. The previous window menu, if any, is destroyed.
3146 * If the bRevert parameter is FALSE, the return value is a handle to a
3147 * copy of the window menu. If the bRevert parameter is TRUE, the return
3155 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
3157 PWINDOW_OBJECT Window
;
3159 DECLARE_RETURN(HMENU
);
3161 DPRINT("Enter NtUserGetSystemMenu\n");
3164 if (!(Window
= UserGetWindowObject(hWnd
)))
3169 if (!(Menu
= IntGetSystemMenu(Window
, bRevert
, FALSE
)))
3174 RETURN(Menu
->MenuInfo
.Self
);
3177 DPRINT("Leave NtUserGetSystemMenu, ret=%i\n",_ret_
);
3183 * NtUserSetSystemMenu
3190 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
3192 BOOL Result
= FALSE
;
3193 PWINDOW_OBJECT Window
;
3195 DECLARE_RETURN(BOOL
);
3197 DPRINT("Enter NtUserSetSystemMenu\n");
3198 UserEnterExclusive();
3200 if (!(Window
= IntGetWindowObject(hWnd
)))
3202 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3209 * Assign new menu handle.
3211 Menu
= IntGetMenuObject(hMenu
);
3214 IntReleaseWindowObject(Window
);
3215 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
3219 Result
= IntSetSystemMenu(Window
, Menu
);
3221 IntReleaseMenuObject(Menu
);
3224 IntReleaseWindowObject(Window
);
3229 DPRINT("Leave NtUserSetSystemMenu, ret=%i\n",_ret_
);
3238 UserGetWindow(HWND hWnd
, UINT Relationship
)
3240 PWINDOW_OBJECT Parent
, Window
;
3241 HWND hWndResult
= NULL
;
3243 if (!(Window
= UserGetWindowObject(hWnd
)))
3246 switch (Relationship
)
3249 if((Parent
= Window
->Parent
))
3251 if (Parent
->FirstChild
)
3252 hWndResult
= Parent
->FirstChild
->hSelf
;
3257 if((Parent
= Window
->Parent
))
3259 if (Parent
->LastChild
)
3260 hWndResult
= Parent
->LastChild
->hSelf
;
3265 if (Window
->NextSibling
)
3266 hWndResult
= Window
->NextSibling
->hSelf
;
3270 if (Window
->PrevSibling
)
3271 hWndResult
= Window
->PrevSibling
->hSelf
;
3275 if((Parent
= IntGetWindowObject(Window
->hOwner
)))
3277 hWndResult
= Parent
->hSelf
;
3278 IntReleaseWindowObject(Parent
);
3282 if (Window
->FirstChild
)
3283 hWndResult
= Window
->FirstChild
->hSelf
;
3295 * The NtUserGetWindow function retrieves a handle to a window that has the
3296 * specified relationship (Z order or owner) to the specified window.
3303 NtUserGetWindow(HWND hWnd
, UINT Relationship
)
3305 DECLARE_RETURN(HWND
);
3307 DPRINT("Enter NtUserGetWindow\n");
3310 RETURN(UserGetWindow(hWnd
, Relationship
));
3313 DPRINT("Leave NtUserGetWindow, ret=%i\n",_ret_
);
3322 * NtUserGetWindowLong
3324 * The NtUserGetWindowLong function retrieves information about the specified
3325 * window. The function also retrieves the 32-bit (long) value at the
3326 * specified offset into the extra window memory.
3333 UserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3335 PWINDOW_OBJECT Window
, Parent
;
3338 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3340 if (!(Window
= IntGetWindowObject(hWnd
)))
3342 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3347 * WndProc is only available to the owner process
3349 if (GWL_WNDPROC
== Index
3350 && Window
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
3352 SetLastWin32Error(ERROR_ACCESS_DENIED
);
3356 if ((INT
)Index
>= 0)
3358 if ((Index
+ sizeof(LONG
)) > Window
->ExtraDataSize
)
3360 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3363 Result
= *((LONG
*)(Window
->ExtraData
+ Index
));
3370 Result
= Window
->ExStyle
;
3374 Result
= Window
->Style
;
3379 Result
= (LONG
) Window
->WndProcA
;
3381 Result
= (LONG
) Window
->WndProcW
;
3385 Result
= (LONG
) Window
->Instance
;
3388 case GWL_HWNDPARENT
:
3389 Parent
= Window
->Parent
;
3392 if (Parent
&& Parent
->hSelf
== IntGetDesktopWindow())
3393 Result
= (LONG
) UserGetWindow(Window
->hSelf
, GW_OWNER
);
3395 Result
= (LONG
) Parent
->hSelf
;
3400 Result
= (LONG
) Window
->IDMenu
;
3404 Result
= Window
->UserData
;
3408 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index
);
3409 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3415 IntReleaseWindowObject(Window
);
3424 * NtUserGetWindowLong
3426 * The NtUserGetWindowLong function retrieves information about the specified
3427 * window. The function also retrieves the 32-bit (long) value at the
3428 * specified offset into the extra window memory.
3435 NtUserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3437 DECLARE_RETURN(LONG
);
3439 DPRINT("Enter NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3440 UserEnterExclusive();
3442 RETURN(UserGetWindowLong(hWnd
, Index
, Ansi
));
3445 DPRINT("Leave NtUserGetWindowLong, ret=%i\n",_ret_
);
3454 co_UserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3456 PWINDOW_OBJECT Window
, Parent
;
3457 PWINSTATION_OBJECT WindowStation
;
3461 if (hWnd
== IntGetDesktopWindow())
3463 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3467 if (!(Window
= IntGetWindowObject(hWnd
)))
3469 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3473 if ((INT
)Index
>= 0)
3475 if ((Index
+ sizeof(LONG
)) > Window
->ExtraDataSize
)
3477 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3478 IntReleaseWindowObject(Window
);
3481 OldValue
= *((LONG
*)(Window
->ExtraData
+ Index
));
3482 *((LONG
*)(Window
->ExtraData
+ Index
)) = NewValue
;
3489 OldValue
= (LONG
) Window
->ExStyle
;
3490 Style
.styleOld
= OldValue
;
3491 Style
.styleNew
= NewValue
;
3494 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3496 WindowStation
= Window
->OwnerThread
->Tcb
.Win32Thread
->Desktop
->WindowStation
;
3499 if (hWnd
== WindowStation
->ShellWindow
|| hWnd
== WindowStation
->ShellListView
)
3500 Style
.styleNew
&= ~WS_EX_TOPMOST
;
3503 co_IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3504 Window
->ExStyle
= (DWORD
)Style
.styleNew
;
3505 co_IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3509 OldValue
= (LONG
) Window
->Style
;
3510 Style
.styleOld
= OldValue
;
3511 Style
.styleNew
= NewValue
;
3512 co_IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_STYLE
, (LPARAM
) &Style
);
3513 Window
->Style
= (DWORD
)Style
.styleNew
;
3514 co_IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_STYLE
, (LPARAM
) &Style
);
3518 /* FIXME: should check if window belongs to current process */
3521 OldValue
= (LONG
) Window
->WndProcA
;
3522 Window
->WndProcA
= (WNDPROC
) NewValue
;
3523 Window
->WndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,FALSE
);
3524 Window
->Unicode
= FALSE
;
3528 OldValue
= (LONG
) Window
->WndProcW
;
3529 Window
->WndProcW
= (WNDPROC
) NewValue
;
3530 Window
->WndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,TRUE
);
3531 Window
->Unicode
= TRUE
;
3536 OldValue
= (LONG
) Window
->Instance
;
3537 Window
->Instance
= (HINSTANCE
) NewValue
;
3540 case GWL_HWNDPARENT
:
3541 Parent
= IntGetParentObject(Window
);
3542 if (Parent
&& (Parent
->hSelf
== IntGetDesktopWindow()))
3543 OldValue
= (LONG
) IntSetOwner(Window
->hSelf
, (HWND
) NewValue
);
3545 OldValue
= (LONG
) co_UserSetParent(Window
->hSelf
, (HWND
) NewValue
);
3547 IntReleaseWindowObject(Parent
);
3551 OldValue
= (LONG
) Window
->IDMenu
;
3552 Window
->IDMenu
= (UINT
) NewValue
;
3556 OldValue
= Window
->UserData
;
3557 Window
->UserData
= NewValue
;
3561 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index
);
3562 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3568 IntReleaseWindowObject(Window
);
3576 * NtUserSetWindowLong
3578 * The NtUserSetWindowLong function changes an attribute of the specified
3579 * window. The function also sets the 32-bit (long) value at the specified
3580 * offset into the extra window memory.
3587 NtUserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3589 DECLARE_RETURN(LONG
);
3591 DPRINT("Enter NtUserSetWindowLong\n");
3592 UserEnterExclusive();
3594 RETURN( co_UserSetWindowLong(hWnd
, Index
, NewValue
, Ansi
));
3597 DPRINT("Leave NtUserSetWindowLong, ret=%i\n",_ret_
);
3603 * NtUserSetWindowWord
3605 * Legacy function similar to NtUserSetWindowLong.
3612 NtUserSetWindowWord(HWND hWnd
, INT Index
, WORD NewValue
)
3614 PWINDOW_OBJECT Window
;
3616 DECLARE_RETURN(WORD
);
3618 DPRINT("Enter NtUserSetWindowWord\n");
3619 UserEnterExclusive();
3625 case GWL_HWNDPARENT
:
3626 RETURN( co_UserSetWindowLong(hWnd
, Index
, (UINT
)NewValue
, TRUE
));
3630 SetLastWin32Error(ERROR_INVALID_INDEX
);
3635 if (!(Window
= IntGetWindowObject(hWnd
)))
3637 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3641 if (Index
> Window
->ExtraDataSize
- sizeof(WORD
))
3643 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3644 IntReleaseWindowObject(Window
);
3648 OldValue
= *((WORD
*)(Window
->ExtraData
+ Index
));
3649 *((WORD
*)(Window
->ExtraData
+ Index
)) = NewValue
;
3651 IntReleaseWindowObject(Window
);
3656 DPRINT("Leave NtUserSetWindowWord, ret=%i\n",_ret_
);
3665 NtUserGetWindowPlacement(HWND hWnd
,
3666 WINDOWPLACEMENT
*lpwndpl
)
3668 PWINDOW_OBJECT Window
;
3669 PINTERNALPOS InternalPos
;
3671 WINDOWPLACEMENT Safepl
;
3673 DECLARE_RETURN(BOOL
);
3675 DPRINT("Enter NtUserGetWindowPlacement\n");
3678 if (!(Window
= IntGetWindowObject(hWnd
)))
3680 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3684 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3685 if(!NT_SUCCESS(Status
))
3687 SetLastNtError(Status
);
3688 IntReleaseWindowObject(Window
);
3691 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3693 IntReleaseWindowObject(Window
);
3698 Safepl
.showCmd
= ((Window
->Flags
& WINDOWOBJECT_RESTOREMAX
) ? SW_MAXIMIZE
: SW_SHOWNORMAL
);
3700 Size
.x
= Window
->WindowRect
.left
;
3701 Size
.y
= Window
->WindowRect
.top
;
3702 InternalPos
= WinPosInitInternalPos(Window
, &Size
,
3703 &Window
->WindowRect
);
3706 Safepl
.rcNormalPosition
= InternalPos
->NormalRect
;
3707 Safepl
.ptMinPosition
= InternalPos
->IconPos
;
3708 Safepl
.ptMaxPosition
= InternalPos
->MaxPos
;
3712 IntReleaseWindowObject(Window
);
3716 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3717 if(!NT_SUCCESS(Status
))
3719 SetLastNtError(Status
);
3720 IntReleaseWindowObject(Window
);
3724 IntReleaseWindowObject(Window
);
3728 DPRINT("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
3735 * Return the dimension of the window in the screen coordinates.
3736 * \param hWnd window handle.
3737 * \param Rect pointer to the buffer where the coordinates are returned.
3743 NtUserGetWindowRect(HWND hWnd
, LPRECT Rect
)
3747 DECLARE_RETURN(BOOL
);
3749 DPRINT("Enter NtUserGetWindowRect\n");
3752 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3754 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3757 Status
= MmCopyToCaller(Rect
, &Wnd
->WindowRect
, sizeof(RECT
));
3758 if (!NT_SUCCESS(Status
))
3760 IntReleaseWindowObject(Wnd
);
3761 SetLastNtError(Status
);
3765 IntReleaseWindowObject(Wnd
);
3769 DPRINT("Leave NtUserGetWindowRect, ret=%i\n",_ret_
);
3779 NtUserGetWindowThreadProcessId(HWND hWnd
, LPDWORD UnsafePid
)
3783 DECLARE_RETURN(DWORD
);
3785 DPRINT("Enter NtUserGetWindowThreadProcessId\n");
3788 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3790 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3794 tid
= (DWORD
)IntGetWndThreadId(Wnd
);
3795 pid
= (DWORD
)IntGetWndProcessId(Wnd
);
3798 MmCopyToCaller(UnsafePid
, &pid
, sizeof(DWORD
));
3803 DPRINT("Leave NtUserGetWindowThreadProcessId, ret=%i\n",_ret_
);
3813 NtUserLockWindowUpdate(DWORD Unknown0
)
3833 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3834 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3835 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3839 QueryWindow based on KJK::Hyperion and James Tabor.
3841 0 = QWUniqueProcessId
3842 1 = QWUniqueThreadId
3843 4 = QWIsHung Implements IsHungAppWindow found
3846 9 = QWKillWindow When I called this with hWnd ==
3847 DesktopWindow, it shutdown the system
3854 NtUserQueryWindow(HWND hWnd
, DWORD Index
)
3856 PWINDOW_OBJECT Window
= IntGetWindowObject(hWnd
);
3858 DECLARE_RETURN(UINT
);
3860 DPRINT("Enter NtUserQueryWindow\n");
3865 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3871 case QUERY_WINDOW_UNIQUE_PROCESS_ID
:
3872 Result
= (DWORD
)IntGetWndProcessId(Window
);
3875 case QUERY_WINDOW_UNIQUE_THREAD_ID
:
3876 Result
= (DWORD
)IntGetWndThreadId(Window
);
3879 case QUERY_WINDOW_ISHUNG
:
3880 Result
= (DWORD
)MsqIsHung(Window
->MessageQueue
);
3884 Result
= (DWORD
)NULL
;
3888 IntReleaseWindowObject(Window
);
3894 DPRINT("Leave NtUserQueryWindow, ret=%i\n",_ret_
);
3904 NtUserRealChildWindowFromPoint(DWORD Unknown0
,
3918 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe
)
3920 UNICODE_STRING SafeMessageName
;
3923 DECLARE_RETURN(UINT
);
3925 DPRINT("Enter NtUserRegisterWindowMessage\n");
3926 UserEnterExclusive();
3928 if(MessageNameUnsafe
== NULL
)
3930 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3934 Status
= IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName
, MessageNameUnsafe
);
3935 if(!NT_SUCCESS(Status
))
3937 SetLastNtError(Status
);
3941 Ret
= (UINT
)IntAddAtom(SafeMessageName
.Buffer
);
3943 RtlFreeUnicodeString(&SafeMessageName
);
3947 DPRINT("Leave NtUserRegisterWindowMessage, ret=%i\n",_ret_
);
3957 NtUserSetImeOwnerWindow(DWORD Unknown0
,
3970 NtUserSetInternalWindowPos(DWORD Unknown0
,
3986 NtUserSetLayeredWindowAttributes(DWORD Unknown0
,
4001 NtUserSetLogonNotifyWindow(DWORD Unknown0
)
4018 PWINDOW_OBJECT Window
;
4020 DECLARE_RETURN(BOOL
);
4022 DPRINT("Enter NtUserSetMenu\n");
4023 UserEnterExclusive();
4025 if (!(Window
= UserGetWindowObject(hWnd
)))
4030 if (! IntSetMenu(Window
, Menu
, &Changed
))
4035 if (Changed
&& Repaint
)
4037 UserRefObjectCo(Window
);
4038 co_WinPosSetWindowPos(Window
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
4039 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
4041 UserDerefObjectCo(Window
);
4047 DPRINT("Leave NtUserSetMenu, ret=%i\n",_ret_
);
4057 NtUserSetWindowFNID(DWORD Unknown0
,
4071 NtUserSetWindowPlacement(HWND hWnd
,
4072 WINDOWPLACEMENT
*lpwndpl
)
4074 PWINDOW_OBJECT Window
;
4075 WINDOWPLACEMENT Safepl
;
4077 DECLARE_RETURN(BOOL
);
4079 DPRINT("Enter NtUserSetWindowPlacement\n");
4080 UserEnterExclusive();
4082 if (!(Window
= IntGetWindowObject(hWnd
)))
4084 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4087 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
4088 if(!NT_SUCCESS(Status
))
4090 SetLastNtError(Status
);
4091 IntReleaseWindowObject(Window
);
4094 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
4096 IntReleaseWindowObject(Window
);
4100 if ((Window
->Style
& (WS_MAXIMIZE
| WS_MINIMIZE
)) == 0)
4102 co_WinPosSetWindowPos(Window
, NULL
,
4103 Safepl
.rcNormalPosition
.left
, Safepl
.rcNormalPosition
.top
,
4104 Safepl
.rcNormalPosition
.right
- Safepl
.rcNormalPosition
.left
,
4105 Safepl
.rcNormalPosition
.bottom
- Safepl
.rcNormalPosition
.top
,
4106 SWP_NOZORDER
| SWP_NOACTIVATE
);
4109 /* FIXME - change window status */
4110 co_WinPosShowWindow(Window
, Safepl
.showCmd
);
4112 if (Window
->InternalPos
== NULL
)
4113 Window
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
4114 Window
->InternalPos
->NormalRect
= Safepl
.rcNormalPosition
;
4115 Window
->InternalPos
->IconPos
= Safepl
.ptMinPosition
;
4116 Window
->InternalPos
->MaxPos
= Safepl
.ptMaxPosition
;
4118 IntReleaseWindowObject(Window
);
4122 DPRINT("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
4134 HWND hWndInsertAfter
,
4141 DECLARE_RETURN(BOOL
);
4142 PWINDOW_OBJECT Window
;
4145 DPRINT("Enter NtUserSetWindowPos\n");
4146 UserEnterExclusive();
4148 if (!(Window
= UserGetWindowObject(hWnd
)))
4153 UserRefObjectCo(Window
);
4154 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
4155 UserDerefObjectCo(Window
);
4160 DPRINT("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
4167 IntGetWindowRgn(HWND hWnd
, HRGN hRgn
)
4170 PWINDOW_OBJECT Window
;
4174 if(!(Window
= IntGetWindowObject(hWnd
)))
4176 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4181 IntReleaseWindowObject(Window
);
4185 /* Create a new window region using the window rectangle */
4186 VisRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->WindowRect
);
4187 NtGdiOffsetRgn(VisRgn
, -Window
->WindowRect
.left
, -Window
->WindowRect
.top
);
4188 /* if there's a region assigned to the window, combine them both */
4189 if(Window
->WindowRegion
&& !(Window
->Style
& WS_MINIMIZE
))
4190 NtGdiCombineRgn(VisRgn
, VisRgn
, Window
->WindowRegion
, RGN_AND
);
4191 /* Copy the region into hRgn */
4192 NtGdiCombineRgn(hRgn
, VisRgn
, NULL
, RGN_COPY
);
4194 if((pRgn
= RGNDATA_LockRgn(hRgn
)))
4196 Ret
= pRgn
->rdh
.iType
;
4197 RGNDATA_UnlockRgn(pRgn
);
4202 NtGdiDeleteObject(VisRgn
);
4204 IntReleaseWindowObject(Window
);
4209 IntGetWindowRgnBox(HWND hWnd
, RECT
*Rect
)
4212 PWINDOW_OBJECT Window
;
4216 if(!(Window
= IntGetWindowObject(hWnd
)))
4218 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4223 IntReleaseWindowObject(Window
);
4227 /* Create a new window region using the window rectangle */
4228 VisRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->WindowRect
);
4229 NtGdiOffsetRgn(VisRgn
, -Window
->WindowRect
.left
, -Window
->WindowRect
.top
);
4230 /* if there's a region assigned to the window, combine them both */
4231 if(Window
->WindowRegion
&& !(Window
->Style
& WS_MINIMIZE
))
4232 NtGdiCombineRgn(VisRgn
, VisRgn
, Window
->WindowRegion
, RGN_AND
);
4234 if((pRgn
= RGNDATA_LockRgn(VisRgn
)))
4236 Ret
= pRgn
->rdh
.iType
;
4237 *Rect
= pRgn
->rdh
.rcBound
;
4238 RGNDATA_UnlockRgn(pRgn
);
4243 NtGdiDeleteObject(VisRgn
);
4245 IntReleaseWindowObject(Window
);
4259 PWINDOW_OBJECT Window
;
4260 DECLARE_RETURN(INT
);
4262 DPRINT("Enter NtUserSetWindowRgn\n");
4263 UserEnterExclusive();
4265 if (!(Window
= IntGetWindowObject(hWnd
)))
4267 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4271 /* FIXME - Verify if hRgn is a valid handle!!!!
4272 Propably make this operation thread-safe, but maybe it's not necessary */
4274 if(Window
->WindowRegion
)
4276 /* Delete no longer needed region handle */
4277 NtGdiDeleteObject(Window
->WindowRegion
);
4279 Window
->WindowRegion
= hRgn
;
4281 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
4285 co_UserRedrawWindow(Window
, NULL
, NULL
, RDW_INVALIDATE
);
4288 IntReleaseWindowObject(Window
);
4292 DPRINT("Leave NtUserSystemParametersInfo, ret=%i\n",_ret_
);
4302 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
4304 PWINDOW_OBJECT Window
;
4306 DECLARE_RETURN(BOOL
);
4308 DPRINT("Enter NtUserShowWindow\n");
4309 UserEnterExclusive();
4311 if (!(Window
= UserGetWindowObject(hWnd
)))
4316 UserRefObjectCo(Window
);
4317 ret
= co_WinPosShowWindow(Window
, nCmdShow
);
4318 UserDerefObjectCo(Window
);
4323 DPRINT("Leave NtUserShowWindow, ret=%i\n",_ret_
);
4333 NtUserShowWindowAsync(DWORD Unknown0
,
4346 NtUserUpdateLayeredWindow(DWORD Unknown0
,
4366 NtUserValidateRect(HWND hWnd
, const RECT
* Rect
)
4368 return (VOID
)NtUserRedrawWindow(hWnd
, Rect
, 0, RDW_VALIDATE
| RDW_NOCHILDREN
);
4376 NtUserWindowFromPoint(LONG X
, LONG Y
)
4380 PWINDOW_OBJECT DesktopWindow
, Window
= NULL
;
4381 DECLARE_RETURN(HWND
);
4383 DPRINT("Enter NtUserWindowFromPoint\n");
4384 UserEnterExclusive();
4386 if ((DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow())))
4393 Hit
= co_WinPosWindowFromPoint(DesktopWindow
, PsGetWin32Thread()->MessageQueue
, &pt
, &Window
);
4397 Ret
= Window
->hSelf
;
4398 IntReleaseWindowObject(Window
);
4399 IntReleaseWindowObject(DesktopWindow
);
4403 IntReleaseWindowObject(DesktopWindow
);
4409 DPRINT("Leave NtUserWindowFromPoint, ret=%i\n",_ret_
);
4419 * Undocumented function that is called from DefWindowProc to set
4427 NtUserDefSetText(HWND hWnd
, PUNICODE_STRING WindowText
)
4429 PWINDOW_OBJECT Window
, Parent
, Owner
;
4430 UNICODE_STRING SafeText
;
4432 DECLARE_RETURN(INT
);
4434 DPRINT("Enter NtUserDefSetText\n");
4435 UserEnterExclusive();
4437 if(!(Window
= IntGetWindowObject(hWnd
)))
4439 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4445 Status
= IntSafeCopyUnicodeString(&SafeText
, WindowText
);
4446 if(!NT_SUCCESS(Status
))
4448 SetLastNtError(Status
);
4449 IntReleaseWindowObject(Window
);
4455 RtlInitUnicodeString(&SafeText
, NULL
);
4458 /* FIXME - do this thread-safe! otherwise one could crash here! */
4459 RtlFreeUnicodeString(&Window
->WindowName
);
4461 Window
->WindowName
= SafeText
;
4463 /* Send shell notifications */
4465 Owner
= IntGetOwner(Window
);
4466 Parent
= IntGetParent(Window
);
4468 if ((!Owner
) && (!Parent
))
4470 co_IntShellHookNotify(HSHELL_REDRAW
, (LPARAM
) hWnd
);
4475 IntReleaseWindowObject(Owner
);
4480 IntReleaseWindowObject(Parent
);
4483 IntReleaseWindowObject(Window
);
4487 DPRINT("Leave NtUserDefSetText, ret=%i\n",_ret_
);
4493 * NtUserInternalGetWindowText
4500 NtUserInternalGetWindowText(HWND hWnd
, LPWSTR lpString
, INT nMaxCount
)
4502 PWINDOW_OBJECT Window
;
4505 DECLARE_RETURN(INT
);
4507 DPRINT("Enter NtUserInternalGetWindowText\n");
4510 if(lpString
&& (nMaxCount
<= 1))
4512 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
4516 if(!(Window
= IntGetWindowObject(hWnd
)))
4518 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4522 /* FIXME - do this thread-safe! otherwise one could crash here! */
4523 Result
= Window
->WindowName
.Length
/ sizeof(WCHAR
);
4526 const WCHAR Terminator
= L
'\0';
4528 WCHAR
*Buffer
= (WCHAR
*)lpString
;
4530 Copy
= min(nMaxCount
- 1, Result
);
4533 Status
= MmCopyToCaller(Buffer
, Window
->WindowName
.Buffer
, Copy
* sizeof(WCHAR
));
4534 if(!NT_SUCCESS(Status
))
4536 SetLastNtError(Status
);
4537 IntReleaseWindowObject(Window
);
4543 Status
= MmCopyToCaller(Buffer
, &Terminator
, sizeof(WCHAR
));
4544 if(!NT_SUCCESS(Status
))
4546 SetLastNtError(Status
);
4547 IntReleaseWindowObject(Window
);
4554 IntReleaseWindowObject(Window
);
4558 DPRINT("Leave NtUserInternalGetWindowText, ret=%i\n",_ret_
);
4564 NtUserDereferenceWndProcHandle(WNDPROC wpHandle
, WndProcHandle
*Data
)
4566 DECLARE_RETURN(DWORD
);
4568 DPRINT("Enter NtUserDereferenceWndProcHandle\n");
4571 WndProcHandle Entry
;
4572 if (((DWORD
)wpHandle
& 0xFFFF0000) == 0xFFFF0000)
4574 Entry
= WndProcHandlesArray
[(DWORD
)wpHandle
& 0x0000FFFF];
4575 Data
->WindowProc
= Entry
.WindowProc
;
4576 Data
->IsUnicode
= Entry
.IsUnicode
;
4577 Data
->ProcessID
= Entry
.ProcessID
;
4587 DPRINT("Leave NtUserDereferenceWndProcHandle, ret=%i\n",_ret_
);
4593 IntAddWndProcHandle(WNDPROC WindowProc
, BOOL IsUnicode
)
4598 WndProcHandle
*OldArray
;
4601 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4603 if (WndProcHandlesArray
[i
].WindowProc
== NULL
)
4611 OldArray
= WndProcHandlesArray
;
4612 OldArraySize
= WndProcHandlesArraySize
;
4613 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,(OldArraySize
+ WPH_SIZE
) * sizeof(WndProcHandle
), TAG_WINPROCLST
);
4614 WndProcHandlesArraySize
= OldArraySize
+ WPH_SIZE
;
4615 RtlCopyMemory(WndProcHandlesArray
,OldArray
,OldArraySize
* sizeof(WndProcHandle
));
4616 ExFreePool(OldArray
);
4617 FreeSpot
= OldArraySize
+ 1;
4619 WndProcHandlesArray
[FreeSpot
].WindowProc
= WindowProc
;
4620 WndProcHandlesArray
[FreeSpot
].IsUnicode
= IsUnicode
;
4621 WndProcHandlesArray
[FreeSpot
].ProcessID
= PsGetCurrentProcessId();
4622 return FreeSpot
+ 0xFFFF0000;
4626 IntRemoveWndProcHandle(WNDPROC Handle
)
4629 position
= (DWORD
)Handle
& 0x0000FFFF;
4630 if (position
> WndProcHandlesArraySize
)
4634 WndProcHandlesArray
[position
].WindowProc
= NULL
;
4635 WndProcHandlesArray
[position
].IsUnicode
= FALSE
;
4636 WndProcHandlesArray
[position
].ProcessID
= NULL
;
4641 IntRemoveProcessWndProcHandles(HANDLE ProcessID
)
4644 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4646 if (WndProcHandlesArray
[i
].ProcessID
== ProcessID
)
4648 WndProcHandlesArray
[i
].WindowProc
= NULL
;
4649 WndProcHandlesArray
[i
].IsUnicode
= FALSE
;
4650 WndProcHandlesArray
[i
].ProcessID
= NULL
;
4656 #define WIN_NEEDS_SHOW_OWNEDPOPUP (0x00000040)
4660 IntShowOwnedPopups( HWND owner
, BOOL fShow
)
4663 PWINDOW_OBJECT Window
, pWnd
;
4666 if(!(Window
= IntGetWindowObject(owner
)))
4668 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4672 win_array
= IntWinListChildren( Window
);
4673 IntReleaseWindowObject(Window
);
4678 while (win_array
[count
])
4680 while (--count
>= 0)
4682 if (UserGetWindow( win_array
[count
], GW_OWNER
) != owner
)
4684 if (!(pWnd
= IntGetWindowObject( win_array
[count
] )))
4686 // if (pWnd == WND_OTHER_PROCESS) continue;
4690 if (pWnd
->Flags
& WIN_NEEDS_SHOW_OWNEDPOPUP
)
4692 IntReleaseWindowObject( pWnd
);
4693 /* In Windows, ShowOwnedPopups(TRUE) generates
4694 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
4695 * regardless of the state of the owner
4697 co_IntSendMessage(win_array
[count
], WM_SHOWWINDOW
, SW_SHOWNORMAL
, SW_PARENTOPENING
);
4703 if (pWnd
->Style
& WS_VISIBLE
)
4705 IntReleaseWindowObject( pWnd
);
4706 /* In Windows, ShowOwnedPopups(FALSE) generates
4707 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
4708 * regardless of the state of the owner
4710 co_IntSendMessage(win_array
[count
], WM_SHOWWINDOW
, SW_HIDE
, SW_PARENTCLOSING
);
4714 IntReleaseWindowObject( pWnd
);
4716 ExFreePool( win_array
);