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 ***********************************************************/
81 PWINDOW_OBJECT FASTCALL
UserGetWindowObjectNoRef(HWND hWnd
)
84 PWINDOW_OBJECT w
= IntGetWindowObject(hWnd
);
85 if (w
) IntReleaseWindowObject(w
);
93 * The function determines whether the specified window handle identifies
98 * Handle to the window to test.
101 * If the window handle identifies an existing window, the return value
102 * is TRUE. If the window handle does not identify an existing window,
103 * the return value is FALSE.
107 IntIsWindow(HWND hWnd
)
109 PWINDOW_OBJECT Window
;
111 if (!(Window
= IntGetWindowObject(hWnd
)))
114 IntReleaseWindowObject(Window
);
119 * IntGetProcessWindowObject
121 * Get window object from handle of specified process.
124 PWINDOW_OBJECT FASTCALL
125 IntGetProcessWindowObject(PW32THREAD Thread
, HWND hWnd
)
127 PWINDOW_OBJECT Window
;
130 if(Thread
->Desktop
!= NULL
)
132 Status
= ObmReferenceObjectByHandle(gHandleTable
,
133 hWnd
, otWindow
, (PVOID
*)&Window
);
134 if (NT_SUCCESS(Status
))
143 PWINDOW_OBJECT FASTCALL
144 IntGetParent(PWINDOW_OBJECT Wnd
)
148 if (Wnd
->Style
& WS_POPUP
)
151 return IntGetWindowObject(hWnd
);
153 else if (Wnd
->Style
& WS_CHILD
)
158 if (par
) IntReferenceWindowObject(par
);
160 //return IntGetWindowObject(hWnd);
166 PWINDOW_OBJECT FASTCALL
167 IntGetOwner(PWINDOW_OBJECT Wnd
)
173 return IntGetWindowObject(hWnd
);
176 PWINDOW_OBJECT FASTCALL
177 IntGetParentObject(PWINDOW_OBJECT Wnd
)
182 if (par
) IntReferenceWindowObject(par
);
189 * Compile a list of all child window handles from given window.
192 * This function is similar to Wine WIN_ListChildren. The caller
193 * must free the returned list with ExFreePool.
197 IntWinListChildren(PWINDOW_OBJECT Window
)
199 PWINDOW_OBJECT Child
;
201 UINT Index
, NumChildren
= 0;
203 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
206 List
= ExAllocatePoolWithTag(PagedPool
, (NumChildren
+ 1) * sizeof(HWND
), TAG_WINLIST
);
209 DPRINT1("Failed to allocate memory for children array\n");
210 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
213 for (Child
= Window
->FirstChild
, Index
= 0;
215 Child
= Child
->NextSibling
, ++Index
)
216 List
[Index
] = Child
->hSelf
;
222 /***********************************************************************
225 static void IntSendDestroyMsg(HWND Wnd
)
228 PWINDOW_OBJECT Window
, Owner
, Parent
;
232 if (GetGUIThreadInfo(GetCurrentThreadId(), &info
))
234 if (Wnd
== info
.hwndCaret
)
241 Window
= IntGetWindowObject(Wnd
);
243 Owner
= IntGetOwner(Window
);
245 Parent
= IntGetParent(Window
);
247 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
) Wnd
);
249 IntReleaseWindowObject(Parent
);
251 IntReleaseWindowObject(Owner
);
254 IntReleaseWindowObject(Window
);
257 /* The window could already be destroyed here */
260 * Send the WM_DESTROY to the window.
263 co_IntSendMessage(Wnd
, WM_DESTROY
, 0, 0);
266 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
267 * make sure that the window still exists when we come back.
275 if (!(pWndArray
= WIN_ListChildren( hwnd
))) return;
277 /* start from the end (FIXME: is this needed?) */
278 for (i
= 0; pWndArray
[i
]; i
++) ;
282 if (IsWindow( pWndArray
[i
] )) WIN_SendDestroyMsg( pWndArray
[i
] );
284 HeapFree(GetProcessHeap(), 0, pWndArray
);
288 DPRINT("destroyed itself while in WM_DESTROY!\n");
293 /***********************************************************************
296 * Destroy storage associated to a window. "Internals" p.358
298 static LRESULT
co_IntDestroyWindow(PWINDOW_OBJECT Window
,
299 PW32PROCESS ProcessData
,
300 PW32THREAD ThreadData
,
301 BOOLEAN SendMessages
)
305 PWINDOW_OBJECT Child
;
307 BOOLEAN BelongsToThreadData
;
311 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
313 DPRINT("Tried to call IntDestroyWindow() twice\n");
316 Window
->Status
|= WINDOWSTATUS_DESTROYING
;
317 Window
->Flags
&= ~WS_VISIBLE
;
318 /* remove the window already at this point from the thread window list so we
319 don't get into trouble when destroying the thread windows while we're still
320 in IntDestroyWindow() */
321 RemoveEntryList(&Window
->ThreadListEntry
);
323 BelongsToThreadData
= IntWndBelongsToThread(Window
, ThreadData
);
325 IntDeRegisterShellHookWindow(Window
->hSelf
);
329 /* Send destroy messages */
330 IntSendDestroyMsg(Window
->hSelf
);
333 /* free child windows */
334 Children
= IntWinListChildren(Window
);
337 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
339 if ((Child
= IntGetWindowObject(*ChildHandle
)))
341 if(!IntWndBelongsToThread(Child
, ThreadData
))
343 /* send WM_DESTROY messages to windows not belonging to the same thread */
344 IntSendDestroyMsg(Child
->hSelf
);
347 co_IntDestroyWindow(Child
, ProcessData
, ThreadData
, SendMessages
);
348 IntReleaseWindowObject(Child
);
351 ExFreePool(Children
);
357 * Clear the update region to make sure no WM_PAINT messages will be
358 * generated for this window while processing the WM_NCDESTROY.
360 co_UserRedrawWindow(Window
, NULL
, 0,
361 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
|
362 RDW_NOINTERNALPAINT
| RDW_NOCHILDREN
);
363 if(BelongsToThreadData
)
364 co_IntSendMessage(Window
->hSelf
, WM_NCDESTROY
, 0, 0);
366 MsqRemoveTimersWindow(ThreadData
->MessageQueue
, Window
->hSelf
);
368 /* flush the message queue */
369 MsqRemoveWindowMessagesFromQueue(Window
);
371 /* from now on no messages can be sent to this window anymore */
372 Window
->Status
|= WINDOWSTATUS_DESTROYED
;
373 /* don't remove the WINDOWSTATUS_DESTROYING bit */
375 /* reset shell window handles */
376 if(ThreadData
->Desktop
)
378 if (Window
->hSelf
== ThreadData
->Desktop
->WindowStation
->ShellWindow
)
379 ThreadData
->Desktop
->WindowStation
->ShellWindow
= NULL
;
381 if (Window
->hSelf
== ThreadData
->Desktop
->WindowStation
->ShellListView
)
382 ThreadData
->Desktop
->WindowStation
->ShellListView
= NULL
;
385 /* Unregister hot keys */
386 UnregisterWindowHotKeys (Window
);
388 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
391 WinPosCheckInternalPos(Window
->hSelf
);
392 if (Window
->hSelf
== GetCapture())
397 /* free resources associated with the window */
398 TIMER_RemoveWindowTimers(Window
->hSelf
);
401 if (!(Window
->Style
& WS_CHILD
) && Window
->IDMenu
402 && (Menu
= IntGetMenuObject((HMENU
)Window
->IDMenu
)))
404 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
406 IntReleaseMenuObject(Menu
);
409 if(Window
->SystemMenu
410 && (Menu
= IntGetMenuObject(Window
->SystemMenu
)))
412 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
413 Window
->SystemMenu
= (HMENU
)0;
414 IntReleaseMenuObject(Menu
);
417 DceFreeWindowDCE(Window
); /* Always do this to catch orphaned DCs */
419 WINPROC_FreeProc(Window
->winproc
, WIN_PROC_WINDOW
);
420 CLASS_RemoveWindow(Window
->Class
);
423 IntUnlinkWindow(Window
);
425 IntReferenceWindowObject(Window
);
426 ObmCloseHandle(gHandleTable
, Window
->hSelf
);
428 IntDestroyScrollBars(Window
);
430 /* remove the window from the class object */
431 RemoveEntryList(&Window
->ClassListEntry
);
433 /* dereference the class */
434 ClassDereferenceObject(Window
->Class
);
435 Window
->Class
= NULL
;
437 if(Window
->WindowRegion
)
439 NtGdiDeleteObject(Window
->WindowRegion
);
442 RtlFreeUnicodeString(&Window
->WindowName
);
444 IntReleaseWindowObject(Window
);
450 IntGetWindowBorderMeasures(PWINDOW_OBJECT Window
, UINT
*cx
, UINT
*cy
)
452 if(HAS_DLGFRAME(Window
->Style
, Window
->ExStyle
) && !(Window
->Style
& WS_MINIMIZE
))
454 *cx
= UserGetSystemMetrics(SM_CXDLGFRAME
);
455 *cy
= UserGetSystemMetrics(SM_CYDLGFRAME
);
459 if(HAS_THICKFRAME(Window
->Style
, Window
->ExStyle
)&& !(Window
->Style
& WS_MINIMIZE
))
461 *cx
= UserGetSystemMetrics(SM_CXFRAME
);
462 *cy
= UserGetSystemMetrics(SM_CYFRAME
);
464 else if(HAS_THINFRAME(Window
->Style
, Window
->ExStyle
))
466 *cx
= UserGetSystemMetrics(SM_CXBORDER
);
467 *cy
= UserGetSystemMetrics(SM_CYBORDER
);
477 IntGetWindowInfo(PWINDOW_OBJECT Window
, PWINDOWINFO pwi
)
479 pwi
->cbSize
= sizeof(WINDOWINFO
);
480 pwi
->rcWindow
= Window
->WindowRect
;
481 pwi
->rcClient
= Window
->ClientRect
;
482 pwi
->dwStyle
= Window
->Style
;
483 pwi
->dwExStyle
= Window
->ExStyle
;
484 pwi
->dwWindowStatus
= (UserGetForegroundWindow() == Window
->hSelf
); /* WS_ACTIVECAPTION */
485 IntGetWindowBorderMeasures(Window
, &pwi
->cxWindowBorders
, &pwi
->cyWindowBorders
);
486 pwi
->atomWindowType
= (Window
->Class
? Window
->Class
->Atom
: 0);
487 pwi
->wCreatorVersion
= 0x400; /* FIXME - return a real version number */
493 PWINDOW_OBJECT Window
,
497 PMENU_OBJECT OldMenu
, NewMenu
= NULL
;
499 if ((Window
->Style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
501 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
505 *Changed
= (Window
->IDMenu
!= (UINT
) Menu
);
513 OldMenu
= IntGetMenuObject((HMENU
) Window
->IDMenu
);
514 ASSERT(NULL
== OldMenu
|| OldMenu
->MenuInfo
.Wnd
== Window
->hSelf
);
523 NewMenu
= IntGetMenuObject(Menu
);
528 IntReleaseMenuObject(OldMenu
);
530 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
533 if (NULL
!= NewMenu
->MenuInfo
.Wnd
)
535 /* Can't use the same menu for two windows */
538 IntReleaseMenuObject(OldMenu
);
540 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
546 Window
->IDMenu
= (UINT
) Menu
;
549 NewMenu
->MenuInfo
.Wnd
= Window
->hSelf
;
550 IntReleaseMenuObject(NewMenu
);
554 OldMenu
->MenuInfo
.Wnd
= NULL
;
555 IntReleaseMenuObject(OldMenu
);
562 /* INTERNAL ******************************************************************/
566 co_DestroyThreadWindows(struct _ETHREAD
*Thread
)
569 PW32PROCESS Win32Process
;
570 PW32THREAD Win32Thread
;
571 PWINDOW_OBJECT
*List
, *pWnd
;
574 Win32Thread
= Thread
->Tcb
.Win32Thread
;
575 Win32Process
= (PW32PROCESS
)Thread
->ThreadsProcess
->Win32Process
;
577 Current
= Win32Thread
->WindowListHead
.Flink
;
578 while (Current
!= &(Win32Thread
->WindowListHead
))
581 Current
= Current
->Flink
;
586 List
= ExAllocatePool(PagedPool
, (Cnt
+ 1) * sizeof(PWINDOW_OBJECT
));
589 DPRINT("Not enough memory to allocate window handle list\n");
593 Current
= Win32Thread
->WindowListHead
.Flink
;
594 while (Current
!= &(Win32Thread
->WindowListHead
))
596 *pWnd
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
597 IntReferenceWindowObject(*pWnd
);
599 Current
= Current
->Flink
;
603 for(pWnd
= List
; *pWnd
; pWnd
++)
605 co_UserDestroyWindow(*pWnd
);
606 IntReleaseWindowObject(*pWnd
);
617 * Returns client window rectangle relative to the upper-left corner of client area.
619 * \note Does not check the validity of the parameters
622 IntGetClientRect(PWINDOW_OBJECT Window
, PRECT Rect
)
627 Rect
->left
= Rect
->top
= 0;
628 Rect
->right
= Window
->ClientRect
.right
- Window
->ClientRect
.left
;
629 Rect
->bottom
= Window
->ClientRect
.bottom
- Window
->ClientRect
.top
;
635 IntGetFocusWindow(VOID
)
637 PUSER_MESSAGE_QUEUE Queue
;
638 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
643 Queue
= (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
648 return(Queue
->FocusWindow
);
652 PMENU_OBJECT FASTCALL
653 IntGetSystemMenu(PWINDOW_OBJECT Window
, BOOL bRevert
, BOOL RetMenu
)
655 PMENU_OBJECT Menu
, NewMenu
, SysMenu
, ret
= NULL
;
656 PW32THREAD W32Thread
;
657 HMENU hNewMenu
, hSysMenu
;
658 ROSMENUITEMINFO ItemInfo
;
662 W32Thread
= PsGetWin32Thread();
664 if(!W32Thread
->Desktop
)
667 if(Window
->SystemMenu
)
669 Menu
= IntGetMenuObject(Window
->SystemMenu
);
672 IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
673 Window
->SystemMenu
= (HMENU
)0;
674 IntReleaseMenuObject(Menu
);
678 if(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
)
680 /* clone system menu */
681 Menu
= IntGetMenuObject(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
);
685 NewMenu
= IntCloneMenu(Menu
);
688 Window
->SystemMenu
= NewMenu
->MenuInfo
.Self
;
689 NewMenu
->MenuInfo
.Flags
|= MF_SYSMENU
;
690 NewMenu
->MenuInfo
.Wnd
= Window
->hSelf
;
692 //IntReleaseMenuObject(NewMenuObject);
694 IntReleaseMenuObject(Menu
);
698 hSysMenu
= UserCreateMenu(FALSE
);
703 SysMenu
= IntGetMenuObject(hSysMenu
);
706 UserDestroyMenu(hSysMenu
);
709 SysMenu
->MenuInfo
.Flags
|= MF_SYSMENU
;
710 SysMenu
->MenuInfo
.Wnd
= Window
->hSelf
;
711 hNewMenu
= co_IntLoadSysMenuTemplate();
714 IntReleaseMenuObject(SysMenu
);
715 UserDestroyMenu(hSysMenu
);
718 Menu
= IntGetMenuObject(hNewMenu
);
721 IntReleaseMenuObject(SysMenu
);
722 UserDestroyMenu(hSysMenu
);
726 NewMenu
= IntCloneMenu(Menu
);
729 NewMenu
->MenuInfo
.Flags
|= MF_SYSMENU
| MF_POPUP
;
730 IntReleaseMenuObject(NewMenu
);
731 UserSetMenuDefaultItem(NewMenu
->MenuInfo
.Self
, SC_CLOSE
, FALSE
);
733 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
734 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
735 ItemInfo
.fType
= MF_POPUP
;
736 ItemInfo
.fState
= MFS_ENABLED
;
737 ItemInfo
.dwTypeData
= NULL
;
739 ItemInfo
.hSubMenu
= NewMenu
->MenuInfo
.Self
;
740 IntInsertMenuItem(SysMenu
, (UINT
) -1, TRUE
, &ItemInfo
);
742 Window
->SystemMenu
= SysMenu
->MenuInfo
.Self
;
746 IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
747 IntReleaseMenuObject(Menu
);
756 if(Window
->SystemMenu
)
757 return IntGetMenuObject((HMENU
)Window
->SystemMenu
);
765 IntIsChildWindow(HWND Parent
, HWND Child
)
767 PWINDOW_OBJECT BaseWindow
, Window
;
769 if(!(BaseWindow
= UserGetWindowObjectNoRef(Child
)))
777 if (Window
->hSelf
== Parent
)
781 if(!(Window
->Style
& WS_CHILD
))
786 Window
= Window
->Parent
;
793 IntIsWindowVisible(HWND hWnd
)
795 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
797 if(!(BaseWindow
= IntGetWindowObject(hWnd
)))
805 if(!(Window
->Style
& WS_CHILD
))
809 if(!(Window
->Style
& WS_VISIBLE
))
811 if(Window
!= BaseWindow
)
812 IntReleaseWindowObject(Window
);
813 IntReleaseWindowObject(BaseWindow
);
817 Window
= IntGetParentObject(Window
);
818 if(Old
!= BaseWindow
)
819 IntReleaseWindowObject(Old
);
824 if(Window
->Style
& WS_VISIBLE
)
826 if(Window
!= BaseWindow
)
827 IntReleaseWindowObject(Window
);
828 IntReleaseWindowObject(BaseWindow
);
831 if(Window
!= BaseWindow
)
832 IntReleaseWindowObject(Window
);
834 IntReleaseWindowObject(BaseWindow
);
839 /* link the window into siblings and parent. children are kept in place. */
843 PWINDOW_OBJECT WndParent
,
844 PWINDOW_OBJECT WndPrevSibling
/* set to NULL if top sibling */
847 PWINDOW_OBJECT Parent
;
849 Wnd
->Parent
= WndParent
;
850 if ((Wnd
->PrevSibling
= WndPrevSibling
))
852 /* link after WndPrevSibling */
853 if ((Wnd
->NextSibling
= WndPrevSibling
->NextSibling
))
854 Wnd
->NextSibling
->PrevSibling
= Wnd
;
855 else if ((Parent
= Wnd
->Parent
))
857 if(Parent
->LastChild
== WndPrevSibling
)
858 Parent
->LastChild
= Wnd
;
860 Wnd
->PrevSibling
->NextSibling
= Wnd
;
865 Parent
= Wnd
->Parent
;
866 if ((Wnd
->NextSibling
= WndParent
->FirstChild
))
867 Wnd
->NextSibling
->PrevSibling
= Wnd
;
870 Parent
->LastChild
= Wnd
;
871 Parent
->FirstChild
= Wnd
;
876 Parent
->FirstChild
= Wnd
;
883 IntSetOwner(HWND hWnd
, HWND hWndNewOwner
)
885 PWINDOW_OBJECT Wnd
, WndOldOwner
, WndNewOwner
;
888 Wnd
= IntGetWindowObject(hWnd
);
892 WndOldOwner
= IntGetWindowObject(Wnd
->hOwner
);
895 ret
= WndOldOwner
->hSelf
;
896 IntReleaseWindowObject(WndOldOwner
);
903 if((WndNewOwner
= IntGetWindowObject(hWndNewOwner
)))
905 Wnd
->hOwner
= hWndNewOwner
;
906 IntReleaseWindowObject(WndNewOwner
);
911 IntReleaseWindowObject(Wnd
);
915 PWINDOW_OBJECT FASTCALL
916 IntSetParent(PWINDOW_OBJECT Wnd
, PWINDOW_OBJECT WndNewParent
)
918 PWINDOW_OBJECT WndOldParent
, Sibling
, InsertAfter
;
919 HWND hWnd
, hWndNewParent
, hWndOldParent
;
924 ASSERT(WndNewParent
);
927 hWndNewParent
= WndNewParent
->hSelf
;
930 * Windows hides the window first, then shows it again
931 * including the WM_SHOWWINDOW messages and all
933 WasVisible
= co_WinPosShowWindow(hWnd
, SW_HIDE
);
935 /* Validate that window and parent still exist */
936 if (!IntIsWindow(hWnd
) || !IntIsWindow(hWndNewParent
))
939 /* Window must belong to current process */
940 if (Wnd
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
943 WndOldParent
= IntGetParentObject(Wnd
);
944 hWndOldParent
= (WndOldParent
? WndOldParent
->hSelf
: NULL
);
946 if (WndNewParent
!= WndOldParent
)
948 IntUnlinkWindow(Wnd
);
950 if (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
))
952 /* Not a TOPMOST window, put after TOPMOSTs of new parent */
953 Sibling
= WndNewParent
->FirstChild
;
954 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
956 InsertAfter
= Sibling
;
957 Sibling
= Sibling
->NextSibling
;
960 if (NULL
== InsertAfter
)
962 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
966 IntReferenceWindowObject(InsertAfter
);
967 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
968 IntReleaseWindowObject(InsertAfter
);
971 if (WndNewParent
->hSelf
!= IntGetDesktopWindow()) /* a child window */
973 if (!(Wnd
->Style
& WS_CHILD
))
975 //if ( Wnd->Menu ) DestroyMenu ( Wnd->menu );
976 IntSetMenu(Wnd
, NULL
, &MenuChanged
);
982 * SetParent additionally needs to make hwnd the top window
983 * in the z-order and send the expected WM_WINDOWPOSCHANGING and
984 * WM_WINDOWPOSCHANGED notification messages.
986 co_WinPosSetWindowPos(hWnd
, (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOP
: HWND_TOPMOST
),
987 0, 0, 0, 0, SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
988 | (WasVisible
? SWP_SHOWWINDOW
: 0));
991 * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
992 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
996 * Validate that the old parent still exist, since it migth have been
997 * destroyed during the last callbacks to user-mode
1001 if(!IntIsWindow(WndOldParent
->hSelf
))
1003 IntReleaseWindowObject(WndOldParent
);
1007 /* don't dereference the window object here, it must be done by the caller
1008 of IntSetParent() */
1009 return WndOldParent
;
1015 IntSetSystemMenu(PWINDOW_OBJECT Window
, PMENU_OBJECT Menu
)
1017 PMENU_OBJECT OldMenu
;
1018 if(Window
->SystemMenu
)
1020 OldMenu
= IntGetMenuObject(Window
->SystemMenu
);
1023 OldMenu
->MenuInfo
.Flags
&= ~ MF_SYSMENU
;
1024 IntReleaseMenuObject(OldMenu
);
1030 /* FIXME check window style, propably return FALSE ? */
1031 Window
->SystemMenu
= Menu
->MenuInfo
.Self
;
1032 Menu
->MenuInfo
.Flags
|= MF_SYSMENU
;
1035 Window
->SystemMenu
= (HMENU
)0;
1041 /* unlink the window from siblings and parent. children are kept in place. */
1043 IntUnlinkWindow(PWINDOW_OBJECT Wnd
)
1045 PWINDOW_OBJECT WndParent
= Wnd
->Parent
;
1047 if (Wnd
->NextSibling
) Wnd
->NextSibling
->PrevSibling
= Wnd
->PrevSibling
;
1048 else if (WndParent
&& WndParent
->LastChild
== Wnd
) WndParent
->LastChild
= Wnd
->PrevSibling
;
1050 if (Wnd
->PrevSibling
) Wnd
->PrevSibling
->NextSibling
= Wnd
->NextSibling
;
1051 else if (WndParent
&& WndParent
->FirstChild
== Wnd
) WndParent
->FirstChild
= Wnd
->NextSibling
;
1053 Wnd
->PrevSibling
= Wnd
->NextSibling
= Wnd
->Parent
= NULL
;
1059 PWINDOW_OBJECT Window
, Child
;
1061 if(!(Window
= IntGetWindowObject(IntGetDesktopWindow())))
1063 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1067 for(Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
1069 if(Child
->hOwner
&& Child
->Style
& WS_VISIBLE
)
1072 * The desktop has a popup window if one of them has
1073 * an owner window and is visible
1075 IntReleaseWindowObject(Window
);
1080 IntReleaseWindowObject(Window
);
1085 IntIsWindowInDestroy(PWINDOW_OBJECT Window
)
1087 return ((Window
->Status
& WINDOWSTATUS_DESTROYING
) == WINDOWSTATUS_DESTROYING
);
1090 /* FUNCTIONS *****************************************************************/
1096 NtUserAlterWindowStyle(DWORD Unknown0
,
1107 * As best as I can figure, this function is used by EnumWindows,
1108 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
1110 * It's supposed to build a list of HWNDs to return to the caller.
1111 * We can figure out what kind of list by what parameters are
1119 NtUserBuildHwndList(
1131 /* FIXME handle bChildren */
1135 PWINDOW_OBJECT Window
, Child
;
1136 if(!(Window
= IntGetWindowObject(hwndParent
)))
1138 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1142 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1144 if(dwCount
++ < nBufSize
&& pWnd
)
1146 Status
= MmCopyToCaller(pWnd
++, &Child
->hSelf
, sizeof(HWND
));
1147 if(!NT_SUCCESS(Status
))
1149 SetLastNtError(Status
);
1155 IntReleaseWindowObject(Window
);
1160 PW32THREAD W32Thread
;
1161 PLIST_ENTRY Current
;
1162 PWINDOW_OBJECT Window
;
1164 Status
= PsLookupThreadByThreadId((HANDLE
)dwThreadId
, &Thread
);
1165 if(!NT_SUCCESS(Status
))
1167 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1170 if(!(W32Thread
= Thread
->Tcb
.Win32Thread
))
1172 ObDereferenceObject(Thread
);
1173 DPRINT("Thread is not a GUI Thread!\n");
1174 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1178 Current
= W32Thread
->WindowListHead
.Flink
;
1179 while(Current
!= &(W32Thread
->WindowListHead
))
1181 Window
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
1184 if(dwCount
< nBufSize
&& pWnd
)
1186 Status
= MmCopyToCaller(pWnd
++, &Window
->hSelf
, sizeof(HWND
));
1187 if(!NT_SUCCESS(Status
))
1189 SetLastNtError(Status
);
1194 Current
= Current
->Flink
;
1197 ObDereferenceObject(Thread
);
1201 PDESKTOP_OBJECT Desktop
;
1202 PWINDOW_OBJECT Window
, Child
;
1204 if(hDesktop
== NULL
&& !(Desktop
= IntGetActiveDesktop()))
1206 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1212 Status
= IntValidateDesktopHandle(hDesktop
,
1216 if(!NT_SUCCESS(Status
))
1218 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1222 if(!(Window
= IntGetWindowObject(Desktop
->DesktopWindow
)))
1225 ObDereferenceObject(Desktop
);
1226 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1230 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1232 if(dwCount
++ < nBufSize
&& pWnd
)
1234 Status
= MmCopyToCaller(pWnd
++, &Child
->hSelf
, sizeof(HWND
));
1235 if(!NT_SUCCESS(Status
))
1237 SetLastNtError(Status
);
1243 IntReleaseWindowObject(Window
);
1245 ObDereferenceObject(Desktop
);
1256 NtUserChildWindowFromPointEx(HWND hwndParent
,
1261 PWINDOW_OBJECT Parent
;
1266 if(!(Parent
= IntGetWindowObject(hwndParent
)))
1268 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1275 if(Parent
->hSelf
!= IntGetDesktopWindow())
1277 Pt
.x
+= Parent
->ClientRect
.left
;
1278 Pt
.y
+= Parent
->ClientRect
.top
;
1281 if(!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
))
1283 IntReleaseWindowObject(Parent
);
1287 Ret
= Parent
->hSelf
;
1288 if((List
= IntWinListChildren(Parent
)))
1290 for(phWnd
= List
; *phWnd
; phWnd
++)
1292 PWINDOW_OBJECT Child
;
1293 if((Child
= IntGetWindowObject(*phWnd
)))
1295 if(!(Child
->Style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
))
1297 IntReleaseWindowObject(Child
);
1300 if((Child
->Style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
))
1302 IntReleaseWindowObject(Child
);
1305 if((Child
->ExStyle
& WS_EX_TRANSPARENT
) && (uiFlags
& CWP_SKIPTRANSPARENT
))
1307 IntReleaseWindowObject(Child
);
1310 if(IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
1313 IntReleaseWindowObject(Child
);
1316 IntReleaseWindowObject(Child
);
1322 IntReleaseWindowObject(Parent
);
1328 * calculates the default position of a window
1331 IntCalcDefPosSize(PWINDOW_OBJECT Parent
, PWINDOW_OBJECT Window
, RECT
*rc
, BOOL IncPos
)
1338 IntGdiIntersectRect(rc
, rc
, &Parent
->ClientRect
);
1342 Pos
.x
= Parent
->TiledCounter
* (UserGetSystemMetrics(SM_CXSIZE
) + UserGetSystemMetrics(SM_CXFRAME
));
1343 Pos
.y
= Parent
->TiledCounter
* (UserGetSystemMetrics(SM_CYSIZE
) + UserGetSystemMetrics(SM_CYFRAME
));
1344 if(Pos
.x
> ((rc
->right
- rc
->left
) / 4) ||
1345 Pos
.y
> ((rc
->bottom
- rc
->top
) / 4))
1347 /* reset counter and position */
1350 Parent
->TiledCounter
= 0;
1352 Parent
->TiledCounter
++;
1363 Sz
.cx
= EngMulDiv(rc
->right
- rc
->left
, 3, 4);
1364 Sz
.cy
= EngMulDiv(rc
->bottom
- rc
->top
, 3, 4);
1368 rc
->right
= rc
->left
+ Sz
.cx
;
1369 rc
->bottom
= rc
->top
+ Sz
.cy
;
1378 co_IntCreateWindowEx(DWORD dwExStyle
,
1379 PUNICODE_STRING ClassName
,
1380 PUNICODE_STRING WindowName
,
1388 HINSTANCE hInstance
,
1391 BOOL bUnicodeWindow
)
1393 PWINSTATION_OBJECT WinSta
;
1394 PWNDCLASS_OBJECT Class
;
1395 PWINDOW_OBJECT Window
;
1396 PWINDOW_OBJECT ParentWindow
, OwnerWindow
;
1397 HWND ParentWindowHandle
;
1398 HWND OwnerWindowHandle
;
1399 PMENU_OBJECT SystemMenu
;
1404 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1409 CBT_CREATEWNDW CbtCreate
;
1416 ParentWindowHandle
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
1417 OwnerWindowHandle
= NULL
;
1419 if (hWndParent
== HWND_MESSAGE
)
1422 * native ole32.OleInitialize uses HWND_MESSAGE to create the
1423 * message window (style: WS_POPUP|WS_DISABLED)
1425 DPRINT1("FIXME - Parent is HWND_MESSAGE\n");
1427 else if (hWndParent
)
1429 if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1430 ParentWindowHandle
= hWndParent
;
1432 OwnerWindowHandle
= UserGetAncestor(hWndParent
, GA_ROOT
);
1434 else if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1436 return (HWND
)0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1439 if (NULL
!= ParentWindowHandle
)
1441 ParentWindow
= IntGetWindowObject(ParentWindowHandle
);
1445 ParentWindow
= NULL
;
1448 /* FIXME: parent must belong to the current process */
1450 /* Check the class. */
1451 ClassFound
= ClassReferenceClassByNameOrAtom(&Class
, ClassName
->Buffer
, hInstance
);
1454 if (IS_ATOM(ClassName
->Buffer
))
1456 DPRINT1("Class 0x%x not found\n", (DWORD_PTR
) ClassName
->Buffer
);
1460 DPRINT1("Class %wZ not found\n", ClassName
);
1462 if (NULL
!= ParentWindow
)
1464 IntReleaseWindowObject(ParentWindow
);
1466 SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS
);
1470 /* Check the window station. */
1471 if (PsGetWin32Thread()->Desktop
== NULL
)
1473 ClassDereferenceObject(Class
);
1474 if (NULL
!= ParentWindow
)
1476 IntReleaseWindowObject(ParentWindow
);
1478 DPRINT("Thread is not attached to a desktop! Cannot create window!\n");
1481 WinSta
= PsGetWin32Thread()->Desktop
->WindowStation
;
1482 ObReferenceObjectByPointer(WinSta
, KernelMode
, ExWindowStationObjectType
, 0);
1484 /* Create the window object. */
1485 Window
= (PWINDOW_OBJECT
)
1486 ObmCreateObject(gHandleTable
, &Handle
,
1487 otWindow
, sizeof(WINDOW_OBJECT
) + Class
->cbWndExtra
1490 DPRINT("Created object with handle %X\n", Handle
);
1493 ObDereferenceObject(WinSta
);
1494 ClassDereferenceObject(Class
);
1495 if (NULL
!= ParentWindow
)
1497 IntReleaseWindowObject(ParentWindow
);
1499 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1502 ObDereferenceObject(WinSta
);
1504 if (NULL
== PsGetWin32Thread()->Desktop
->DesktopWindow
)
1506 /* If there is no desktop window yet, we must be creating it */
1507 PsGetWin32Thread()->Desktop
->DesktopWindow
= Handle
;
1511 * Fill out the structure describing it.
1513 Window
->Class
= Class
;
1515 InsertTailList(&Class
->ClassWindowsListHead
, &Window
->ClassListEntry
);
1517 Window
->ExStyle
= dwExStyle
;
1518 Window
->Style
= dwStyle
& ~WS_VISIBLE
;
1519 DPRINT("1: Style is now %lx\n", Window
->Style
);
1521 Window
->SystemMenu
= (HMENU
)0;
1522 Window
->ContextHelpId
= 0;
1524 Window
->Instance
= hInstance
;
1525 Window
->hSelf
= Handle
;
1526 if (0 != (dwStyle
& WS_CHILD
))
1528 Window
->IDMenu
= (UINT
) hMenu
;
1532 IntSetMenu(Window
, hMenu
, &MenuChanged
);
1534 Window
->MessageQueue
= PsGetWin32Thread()->MessageQueue
;
1535 IntReferenceMessageQueue(Window
->MessageQueue
);
1536 Window
->Parent
= ParentWindow
;
1537 if((OwnerWindow
= IntGetWindowObject(OwnerWindowHandle
)))
1539 Window
->hOwner
= OwnerWindowHandle
;
1540 IntReleaseWindowObject(OwnerWindow
);
1543 Window
->hOwner
= NULL
;
1546 Window
->UserData
= 0;
1547 if ((((DWORD
)Class
->lpfnWndProcA
& 0xFFFF0000) != 0xFFFF0000)
1548 && (((DWORD
)Class
->lpfnWndProcW
& 0xFFFF0000) != 0xFFFF0000))
1550 Window
->Unicode
= bUnicodeWindow
;
1554 Window
->Unicode
= Class
->Unicode
;
1556 Window
->WndProcA
= Class
->lpfnWndProcA
;
1557 Window
->WndProcW
= Class
->lpfnWndProcW
;
1558 Window
->OwnerThread
= PsGetCurrentThread();
1559 Window
->FirstChild
= NULL
;
1560 Window
->LastChild
= NULL
;
1561 Window
->PrevSibling
= NULL
;
1562 Window
->NextSibling
= NULL
;
1564 /* extra window data */
1565 if (Class
->cbWndExtra
!= 0)
1567 Window
->ExtraData
= (PCHAR
)(Window
+ 1);
1568 Window
->ExtraDataSize
= Class
->cbWndExtra
;
1569 RtlZeroMemory(Window
->ExtraData
, Window
->ExtraDataSize
);
1573 Window
->ExtraData
= NULL
;
1574 Window
->ExtraDataSize
= 0;
1577 InitializeListHead(&Window
->PropListHead
);
1578 InitializeListHead(&Window
->WndObjListHead
);
1580 if (NULL
!= WindowName
->Buffer
)
1582 Window
->WindowName
.MaximumLength
= WindowName
->MaximumLength
;
1583 Window
->WindowName
.Length
= WindowName
->Length
;
1584 Window
->WindowName
.Buffer
= ExAllocatePoolWithTag(PagedPool
, WindowName
->MaximumLength
,
1586 if (NULL
== Window
->WindowName
.Buffer
)
1588 ClassDereferenceObject(Class
);
1589 DPRINT1("Failed to allocate mem for window name\n");
1590 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1593 RtlCopyMemory(Window
->WindowName
.Buffer
, WindowName
->Buffer
, WindowName
->MaximumLength
);
1597 RtlInitUnicodeString(&Window
->WindowName
, NULL
);
1602 * This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1603 * tested for WS_POPUP
1605 if ((dwExStyle
& WS_EX_DLGMODALFRAME
) ||
1606 ((!(dwExStyle
& WS_EX_STATICEDGE
)) &&
1607 (dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
))))
1608 dwExStyle
|= WS_EX_WINDOWEDGE
;
1610 dwExStyle
&= ~WS_EX_WINDOWEDGE
;
1612 /* Correct the window style. */
1613 if (!(dwStyle
& WS_CHILD
))
1615 Window
->Style
|= WS_CLIPSIBLINGS
;
1616 DPRINT("3: Style is now %lx\n", Window
->Style
);
1617 if (!(dwStyle
& WS_POPUP
))
1619 Window
->Style
|= WS_CAPTION
;
1620 Window
->Flags
|= WINDOWOBJECT_NEED_SIZE
;
1621 DPRINT("4: Style is now %lx\n", Window
->Style
);
1625 /* create system menu */
1626 if((Window
->Style
& WS_SYSMENU
) &&
1627 (Window
->Style
& WS_CAPTION
) == WS_CAPTION
)
1629 SystemMenu
= IntGetSystemMenu(Window
, TRUE
, TRUE
);
1632 Window
->SystemMenu
= SystemMenu
->MenuInfo
.Self
;
1633 IntReleaseMenuObject(SystemMenu
);
1637 /* Insert the window into the thread's window list. */
1638 InsertTailList (&PsGetWin32Thread()->WindowListHead
, &Window
->ThreadListEntry
);
1640 /* Allocate a DCE for this window. */
1641 if (dwStyle
& CS_OWNDC
)
1643 Window
->Dce
= DceAllocDCE(Window
->hSelf
, DCE_WINDOW_DC
);
1645 /* FIXME: Handle "CS_CLASSDC" */
1653 Cs
.lpCreateParams
= lpParam
;
1654 Cs
.hInstance
= hInstance
;
1656 Cs
.hwndParent
= ParentWindowHandle
;
1662 Cs
.lpszName
= (LPCWSTR
) WindowName
;
1663 Cs
.lpszClass
= (LPCWSTR
) ClassName
;
1664 Cs
.dwExStyle
= dwExStyle
;
1665 CbtCreate
.lpcs
= &Cs
;
1666 CbtCreate
.hwndInsertAfter
= HWND_TOP
;
1667 if (co_HOOK_CallHooks(WH_CBT
, HCBT_CREATEWND
, (WPARAM
) Handle
, (LPARAM
) &CbtCreate
))
1669 if (NULL
!= ParentWindow
)
1671 IntReleaseWindowObject(ParentWindow
);
1674 /* FIXME - Delete window object and remove it from the thread windows list */
1675 /* FIXME - delete allocated DCE */
1677 ClassDereferenceObject(Class
);
1678 DPRINT1("CBT-hook returned !0\n");
1687 /* default positioning for overlapped windows */
1688 if(!(Window
->Style
& (WS_POPUP
| WS_CHILD
)))
1691 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
1692 BOOL CalculatedDefPosSize
= FALSE
;
1694 IntGetDesktopWorkArea(Window
->OwnerThread
->Tcb
.Win32Thread
->Desktop
, &WorkArea
);
1697 ProcessParams
= PsGetCurrentProcess()->Peb
->ProcessParameters
;
1699 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1701 CalculatedDefPosSize
= IntCalcDefPosSize(ParentWindow
, Window
, &rc
, TRUE
);
1703 if(ProcessParams
->WindowFlags
& STARTF_USEPOSITION
)
1705 ProcessParams
->WindowFlags
&= ~STARTF_USEPOSITION
;
1706 Pos
.x
= WorkArea
.left
+ ProcessParams
->StartingX
;
1707 Pos
.y
= WorkArea
.top
+ ProcessParams
->StartingY
;
1715 /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
1716 y is something else */
1717 if(y
!= CW_USEDEFAULT
&& y
!= CW_USEDEFAULT16
)
1722 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1724 if(!CalculatedDefPosSize
)
1726 IntCalcDefPosSize(ParentWindow
, Window
, &rc
, FALSE
);
1728 if(ProcessParams
->WindowFlags
& STARTF_USESIZE
)
1730 ProcessParams
->WindowFlags
&= ~STARTF_USESIZE
;
1731 Size
.cx
= ProcessParams
->CountX
;
1732 Size
.cy
= ProcessParams
->CountY
;
1736 Size
.cx
= rc
.right
- rc
.left
;
1737 Size
.cy
= rc
.bottom
- rc
.top
;
1740 /* move the window if necessary */
1742 Pos
.x
= max(rc
.left
, 0);
1744 Pos
.y
= max(rc
.top
, 0);
1749 /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
1750 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1755 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1762 /* Initialize the window dimensions. */
1763 Window
->WindowRect
.left
= Pos
.x
;
1764 Window
->WindowRect
.top
= Pos
.y
;
1765 Window
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1766 Window
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1767 if (0 != (Window
->Style
& WS_CHILD
) && ParentWindow
)
1769 IntGdiOffsetRect(&(Window
->WindowRect
), ParentWindow
->ClientRect
.left
,
1770 ParentWindow
->ClientRect
.top
);
1772 Window
->ClientRect
= Window
->WindowRect
;
1775 * Get the size and position of the window.
1777 if ((dwStyle
& WS_THICKFRAME
) || !(dwStyle
& (WS_POPUP
| WS_CHILD
)))
1779 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1781 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1782 co_WinPosGetMinMaxInfo(Window
, &MaxSize
, &MaxPos
, &MinTrack
,
1784 if (MaxSize
.x
< nWidth
) nWidth
= MaxSize
.x
;
1785 if (MaxSize
.y
< nHeight
) nHeight
= MaxSize
.y
;
1786 if (nWidth
< MinTrack
.x
) nWidth
= MinTrack
.x
;
1787 if (nHeight
< MinTrack
.y
) nHeight
= MinTrack
.y
;
1788 if (nWidth
< 0) nWidth
= 0;
1789 if (nHeight
< 0) nHeight
= 0;
1792 Window
->WindowRect
.left
= Pos
.x
;
1793 Window
->WindowRect
.top
= Pos
.y
;
1794 Window
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1795 Window
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1796 if (0 != (Window
->Style
& WS_CHILD
) && ParentWindow
)
1798 IntGdiOffsetRect(&(Window
->WindowRect
), ParentWindow
->ClientRect
.left
,
1799 ParentWindow
->ClientRect
.top
);
1801 Window
->ClientRect
= Window
->WindowRect
;
1803 /* FIXME: Initialize the window menu. */
1805 /* Send a NCCREATE message. */
1811 DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d\n", Cs
.style
, Cs
.dwExStyle
, Cs
.hwndParent
);
1812 DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1813 DPRINT("IntCreateWindowEx(): About to send NCCREATE message.\n");
1814 Result
= co_IntSendMessage(Window
->hSelf
, WM_NCCREATE
, 0, (LPARAM
) &Cs
);
1817 /* FIXME: Cleanup. */
1818 if (NULL
!= ParentWindow
)
1820 IntReleaseWindowObject(ParentWindow
);
1822 DPRINT("IntCreateWindowEx(): NCCREATE message failed.\n");
1826 /* Calculate the non-client size. */
1827 MaxPos
.x
= Window
->WindowRect
.left
;
1828 MaxPos
.y
= Window
->WindowRect
.top
;
1829 DPRINT("IntCreateWindowEx(): About to get non-client size.\n");
1830 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1831 Result
= co_WinPosGetNonClientSize(Window
->hSelf
,
1832 &Window
->WindowRect
,
1833 &Window
->ClientRect
);
1834 IntGdiOffsetRect(&Window
->WindowRect
,
1835 MaxPos
.x
- Window
->WindowRect
.left
,
1836 MaxPos
.y
- Window
->WindowRect
.top
);
1838 if (NULL
!= ParentWindow
)
1840 /* link the window into the parent's child list */
1841 if ((dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
1843 PWINDOW_OBJECT PrevSibling
;
1844 if((PrevSibling
= ParentWindow
->LastChild
))
1845 IntReferenceWindowObject(PrevSibling
);
1846 /* link window as bottom sibling */
1847 IntLinkWindow(Window
, ParentWindow
, PrevSibling
/*prev sibling*/);
1849 IntReleaseWindowObject(PrevSibling
);
1853 /* link window as top sibling (but after topmost siblings) */
1854 PWINDOW_OBJECT InsertAfter
, Sibling
;
1855 if (0 == (dwExStyle
& WS_EX_TOPMOST
))
1858 Sibling
= ParentWindow
->FirstChild
;
1859 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
1861 InsertAfter
= Sibling
;
1862 Sibling
= Sibling
->NextSibling
;
1869 if (NULL
!= InsertAfter
)
1871 IntReferenceWindowObject(InsertAfter
);
1873 IntLinkWindow(Window
, ParentWindow
, InsertAfter
/* prev sibling */);
1874 if (NULL
!= InsertAfter
)
1876 IntReleaseWindowObject(InsertAfter
);
1881 /* Send the WM_CREATE message. */
1882 DPRINT("IntCreateWindowEx(): about to send CREATE message.\n");
1883 Result
= co_IntSendMessage(Window
->hSelf
, WM_CREATE
, 0, (LPARAM
) &Cs
);
1884 if (Result
== (LRESULT
)-1)
1886 /* FIXME: Cleanup. */
1887 if (NULL
!= ParentWindow
)
1889 IntReleaseWindowObject(ParentWindow
);
1891 ClassDereferenceObject(Class
);
1892 DPRINT("IntCreateWindowEx(): send CREATE message failed.\n");
1896 /* Send move and size messages. */
1897 if (!(Window
->Flags
& WINDOWOBJECT_NEED_SIZE
))
1901 DPRINT("IntCreateWindow(): About to send WM_SIZE\n");
1903 if ((Window
->ClientRect
.right
- Window
->ClientRect
.left
) < 0 ||
1904 (Window
->ClientRect
.bottom
- Window
->ClientRect
.top
) < 0)
1906 DPRINT("Sending bogus WM_SIZE\n");
1909 lParam
= MAKE_LONG(Window
->ClientRect
.right
-
1910 Window
->ClientRect
.left
,
1911 Window
->ClientRect
.bottom
-
1912 Window
->ClientRect
.top
);
1913 co_IntSendMessage(Window
->hSelf
, WM_SIZE
, SIZE_RESTORED
,
1916 DPRINT("IntCreateWindow(): About to send WM_MOVE\n");
1918 if (0 != (Window
->Style
& WS_CHILD
) && ParentWindow
)
1920 lParam
= MAKE_LONG(Window
->ClientRect
.left
- ParentWindow
->ClientRect
.left
,
1921 Window
->ClientRect
.top
- ParentWindow
->ClientRect
.top
);
1925 lParam
= MAKE_LONG(Window
->ClientRect
.left
,
1926 Window
->ClientRect
.top
);
1928 co_IntSendMessage(Window
->hSelf
, WM_MOVE
, 0, lParam
);
1930 /* Call WNDOBJ change procs */
1931 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
1934 /* Show or maybe minimize or maximize the window. */
1935 if (Window
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1940 SwFlag
= (Window
->Style
& WS_MINIMIZE
) ? SW_MINIMIZE
:
1942 co_WinPosMinMaximize(Window
, SwFlag
, &NewPos
);
1944 ((Window
->Style
& WS_CHILD
) || UserGetActiveWindow()) ?
1945 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
:
1946 SWP_NOZORDER
| SWP_FRAMECHANGED
;
1947 DPRINT("IntCreateWindow(): About to minimize/maximize\n");
1948 DPRINT("%d,%d %dx%d\n", NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
);
1949 co_WinPosSetWindowPos(Window
->hSelf
, 0, NewPos
.left
, NewPos
.top
,
1950 NewPos
.right
, NewPos
.bottom
, SwFlag
);
1953 /* Notify the parent window of a new child. */
1954 if ((Window
->Style
& WS_CHILD
) &&
1955 (!(Window
->ExStyle
& WS_EX_NOPARENTNOTIFY
)) && ParentWindow
)
1957 DPRINT("IntCreateWindow(): About to notify parent\n");
1958 co_IntSendMessage(ParentWindow
->hSelf
,
1960 MAKEWPARAM(WM_CREATE
, Window
->IDMenu
),
1961 (LPARAM
)Window
->hSelf
);
1964 if ((!hWndParent
) && (!HasOwner
)) {
1965 DPRINT("Sending CREATED notify\n");
1966 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Handle
);
1968 DPRINT("Not sending CREATED notify, %x %d\n", ParentWindow
, HasOwner
);
1971 if (NULL
!= ParentWindow
)
1973 IntReleaseWindowObject(ParentWindow
);
1976 /* Initialize and show the window's scrollbars */
1977 if (Window
->Style
& WS_VSCROLL
)
1979 co_UserShowScrollBar(Window
->hSelf
, SB_VERT
, TRUE
);
1981 if (Window
->Style
& WS_HSCROLL
)
1983 co_UserShowScrollBar(Window
->hSelf
, SB_HORZ
, TRUE
);
1986 if (dwStyle
& WS_VISIBLE
)
1988 DPRINT("IntCreateWindow(): About to show window\n");
1989 co_WinPosShowWindow(Window
->hSelf
, dwShowMode
);
1992 DPRINT("IntCreateWindow(): = %X\n", Handle
);
1993 DPRINT("WindowObject->SystemMenu = 0x%x\n", Window
->SystemMenu
);
1994 return((HWND
)Handle
);
1998 NtUserCreateWindowEx(DWORD dwExStyle
,
1999 PUNICODE_STRING UnsafeClassName
,
2000 PUNICODE_STRING UnsafeWindowName
,
2008 HINSTANCE hInstance
,
2011 BOOL bUnicodeWindow
)
2014 UNICODE_STRING WindowName
;
2015 UNICODE_STRING ClassName
;
2017 DECLARE_RETURN(HWND
);
2019 DPRINT("Enter NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
2020 UserEnterExclusive();
2022 /* Get the class name (string or atom) */
2023 Status
= MmCopyFromCaller(&ClassName
, UnsafeClassName
, sizeof(UNICODE_STRING
));
2024 if (! NT_SUCCESS(Status
))
2026 SetLastNtError(Status
);
2029 if (! IS_ATOM(ClassName
.Buffer
))
2031 Status
= IntSafeCopyUnicodeStringTerminateNULL(&ClassName
, UnsafeClassName
);
2032 if (! NT_SUCCESS(Status
))
2034 SetLastNtError(Status
);
2039 /* safely copy the window name */
2040 if (NULL
!= UnsafeWindowName
)
2042 Status
= IntSafeCopyUnicodeString(&WindowName
, UnsafeWindowName
);
2043 if (! NT_SUCCESS(Status
))
2045 if (! IS_ATOM(ClassName
.Buffer
))
2047 RtlFreeUnicodeString(&ClassName
);
2049 SetLastNtError(Status
);
2055 RtlInitUnicodeString(&WindowName
, NULL
);
2058 NewWindow
= co_IntCreateWindowEx(dwExStyle
, &ClassName
, &WindowName
, dwStyle
, x
, y
, nWidth
, nHeight
,
2059 hWndParent
, hMenu
, hInstance
, lpParam
, dwShowMode
, bUnicodeWindow
);
2061 RtlFreeUnicodeString(&WindowName
);
2062 if (! IS_ATOM(ClassName
.Buffer
))
2064 RtlFreeUnicodeString(&ClassName
);
2070 DPRINT("Leave NtUserCreateWindowEx, ret=%i\n",_ret_
);
2079 NtUserDeferWindowPos(HDWP WinPosInfo
,
2081 HWND WndInsertAfter
,
2094 BOOLEAN FASTCALL
co_UserDestroyWindow(PWINDOW_OBJECT Window
)
2103 /* Check for owner thread and desktop window */
2104 if ((Window
->OwnerThread
!= PsGetCurrentThread()) || IntIsDesktopWindow(Window
))
2106 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2110 /* Look whether the focus is within the tree of windows we will
2113 if (!co_WinPosShowWindow(Window
->hSelf
, SW_HIDE
))
2115 if (UserGetActiveWindow() == Window
->hSelf
)
2117 co_WinPosActivateOtherWindow(Window
);
2121 if (Window
->MessageQueue
->ActiveWindow
== Window
->hSelf
)
2122 Window
->MessageQueue
->ActiveWindow
= NULL
;
2123 if (Window
->MessageQueue
->FocusWindow
== Window
->hSelf
)
2124 Window
->MessageQueue
->FocusWindow
= NULL
;
2125 if (Window
->MessageQueue
->CaptureWindow
== Window
->hSelf
)
2126 Window
->MessageQueue
->CaptureWindow
= NULL
;
2128 IntDereferenceMessageQueue(Window
->MessageQueue
);
2131 if (co_HOOK_CallHooks(WH_CBT
, HCBT_DESTROYWND
, (WPARAM
) hwnd
, 0, TRUE
))
2137 IntEngWindowChanged(Window
, WOC_DELETE
);
2138 isChild
= (0 != (Window
->Style
& WS_CHILD
));
2143 if (! USER_IsExitingThread(GetCurrentThreadId()))
2145 send_parent_notify(hwnd
, WM_DESTROY
);
2148 else if (NULL
!= GetWindow(Wnd
, GW_OWNER
))
2150 co_HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
2151 /* FIXME: clean up palette - see "Internals" p.352 */
2155 if (!IntIsWindow(Window
->hSelf
))
2160 /* Recursively destroy owned windows */
2165 BOOL GotOne
= FALSE
;
2168 PWINDOW_OBJECT Child
, Desktop
;
2170 Desktop
= IntGetWindowObject(IntGetDesktopWindow());
2171 Children
= IntWinListChildren(Desktop
);
2172 IntReleaseWindowObject(Desktop
);
2175 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
2177 Child
= IntGetWindowObject(*ChildHandle
);
2180 if (Child
->hOwner
!= Window
->hSelf
)
2182 IntReleaseWindowObject(Child
);
2186 if (IntWndBelongsToThread(Child
, PsGetWin32Thread()))
2188 co_UserDestroyWindow(Child
);
2189 IntReleaseWindowObject(Child
);
2194 if (Child
->hOwner
!= NULL
)
2196 Child
->hOwner
= NULL
;
2199 IntReleaseWindowObject(Child
);
2201 ExFreePool(Children
);
2210 if (!IntIsWindow(Window
->hSelf
))
2215 /* Destroy the window storage */
2216 co_IntDestroyWindow(Window
, PsGetWin32Process(), PsGetWin32Thread(), TRUE
);
2228 NtUserDestroyWindow(HWND Wnd
)
2230 PWINDOW_OBJECT Window
;
2231 DECLARE_RETURN(BOOLEAN
);
2233 DPRINT("Enter NtUserDestroyWindow\n");
2234 UserEnterExclusive();
2236 Window
= IntGetWindowObject(Wnd
);
2242 RETURN(co_UserDestroyWindow(Window
));
2245 DPRINT("Leave NtUserDestroyWindow, ret=%i\n",_ret_
);
2257 NtUserDrawMenuBarTemp(
2264 /* we'll use this function just for caching the menu bar */
2274 NtUserEndDeferWindowPosEx(DWORD Unknown0
,
2287 NtUserFillWindow(DWORD Unknown0
,
2299 IntFindWindow(PWINDOW_OBJECT Parent
,
2300 PWINDOW_OBJECT ChildAfter
,
2302 PUNICODE_STRING WindowName
)
2304 BOOL CheckWindowName
;
2310 CheckWindowName
= (WindowName
&& (WindowName
->Length
> 0));
2312 if((List
= IntWinListChildren(Parent
)))
2317 /* skip handles before and including ChildAfter */
2318 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->hSelf
));
2321 /* search children */
2324 PWINDOW_OBJECT Child
;
2325 if(!(Child
= IntGetWindowObject(*(phWnd
++))))
2330 /* Do not send WM_GETTEXT messages in the kernel mode version!
2331 The user mode version however calls GetWindowText() which will
2332 send WM_GETTEXT messages to windows belonging to its processes */
2333 if((!CheckWindowName
|| !RtlCompareUnicodeString(WindowName
, &(Child
->WindowName
), FALSE
)) &&
2334 (!ClassAtom
|| Child
->Class
->Atom
== ClassAtom
))
2337 IntReleaseWindowObject(Child
);
2341 IntReleaseWindowObject(Child
);
2351 * Searches a window's children for a window with the specified
2354 * hwndParent = The window whose childs are to be searched.
2356 * HWND_MESSAGE = message-only windows
2358 * hwndChildAfter = Search starts after this child window.
2359 * NULL = start from beginning
2361 * ucClassName = Class name to search for
2362 * Reguired parameter.
2364 * ucWindowName = Window name
2365 * ->Buffer == NULL = don't care
2368 * The HWND of the window if it was found, otherwise NULL
2374 NtUserFindWindowEx(HWND hwndParent
,
2375 HWND hwndChildAfter
,
2376 PUNICODE_STRING ucClassName
,
2377 PUNICODE_STRING ucWindowName
)
2379 PWINDOW_OBJECT Parent
, ChildAfter
;
2380 UNICODE_STRING ClassName
, WindowName
;
2382 HWND Desktop
, Ret
= NULL
;
2384 DECLARE_RETURN(HWND
);
2386 DPRINT("Enter NtUserFindWindowEx\n");
2389 Desktop
= IntGetCurrentThreadDesktopWindow();
2391 if(hwndParent
== NULL
)
2392 hwndParent
= Desktop
;
2394 else if(hwndParent == HWND_MESSAGE)
2396 hwndParent = IntGetMessageWindow();
2400 if(!(Parent
= IntGetWindowObject(hwndParent
)))
2402 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2407 if(hwndChildAfter
&& !(ChildAfter
= IntGetWindowObject(hwndChildAfter
)))
2409 IntReleaseWindowObject(Parent
);
2410 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2414 /* copy the window name */
2415 Status
= IntSafeCopyUnicodeString(&WindowName
, ucWindowName
);
2416 if(!NT_SUCCESS(Status
))
2418 SetLastNtError(Status
);
2422 /* safely copy the class name */
2423 Status
= MmCopyFromCaller(&ClassName
, ucClassName
, sizeof(UNICODE_STRING
));
2424 if(!NT_SUCCESS(Status
))
2426 SetLastNtError(Status
);
2429 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2432 /* safely copy the class name string (NULL terminated because class-lookup
2434 buf
= ExAllocatePoolWithTag(PagedPool
, ClassName
.Length
+ sizeof(WCHAR
), TAG_STRING
);
2437 SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES
);
2440 Status
= MmCopyFromCaller(buf
, ClassName
.Buffer
, ClassName
.Length
);
2441 if(!NT_SUCCESS(Status
))
2444 SetLastNtError(Status
);
2447 ClassName
.Buffer
= buf
;
2448 /* make sure the string is null-terminated */
2449 buf
+= ClassName
.Length
/ sizeof(WCHAR
);
2453 /* find the class object */
2454 if(ClassName
.Buffer
)
2456 PWINSTATION_OBJECT WinStaObject
;
2458 if (PsGetWin32Thread()->Desktop
== NULL
)
2460 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2464 WinStaObject
= PsGetWin32Thread()->Desktop
->WindowStation
;
2466 Status
= RtlLookupAtomInAtomTable(
2467 WinStaObject
->AtomTable
,
2471 if (!NT_SUCCESS(Status
))
2473 DPRINT1("Failed to lookup class atom!\n");
2474 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST
);
2479 if(Parent
->hSelf
== Desktop
)
2482 PWINDOW_OBJECT TopLevelWindow
;
2483 BOOLEAN CheckWindowName
;
2484 BOOLEAN CheckClassName
;
2485 BOOLEAN WindowMatches
;
2486 BOOLEAN ClassMatches
;
2488 /* windows searches through all top-level windows if the parent is the desktop
2491 if((List
= IntWinListChildren(Parent
)))
2497 /* skip handles before and including ChildAfter */
2498 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->hSelf
));
2501 CheckWindowName
= WindowName
.Length
> 0;
2502 CheckClassName
= ClassName
.Buffer
!= NULL
;
2504 /* search children */
2507 if(!(TopLevelWindow
= IntGetWindowObject(*(phWnd
++))))
2512 /* Do not send WM_GETTEXT messages in the kernel mode version!
2513 The user mode version however calls GetWindowText() which will
2514 send WM_GETTEXT messages to windows belonging to its processes */
2515 WindowMatches
= !CheckWindowName
|| !RtlCompareUnicodeString(
2516 &WindowName
, &TopLevelWindow
->WindowName
, FALSE
);
2517 ClassMatches
= !CheckClassName
||
2518 ClassAtom
== TopLevelWindow
->Class
->Atom
;
2520 if (WindowMatches
&& ClassMatches
)
2522 Ret
= TopLevelWindow
->hSelf
;
2523 IntReleaseWindowObject(TopLevelWindow
);
2527 if (IntFindWindow(TopLevelWindow
, NULL
, ClassAtom
, &WindowName
))
2529 /* window returns the handle of the top-level window, in case it found
2531 Ret
= TopLevelWindow
->hSelf
;
2532 IntReleaseWindowObject(TopLevelWindow
);
2536 IntReleaseWindowObject(TopLevelWindow
);
2542 Ret
= IntFindWindow(Parent
, ChildAfter
, ClassAtom
, &WindowName
);
2545 if(Ret
== NULL
&& hwndParent
== NULL
&& hwndChildAfter
== NULL
)
2547 /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
2548 search the message-only windows. Should this also be done if
2549 Parent is the desktop window??? */
2550 PWINDOW_OBJECT MsgWindows
;
2552 if((MsgWindows
= IntGetWindowObject(IntGetMessageWindow())))
2554 Ret
= IntFindWindow(MsgWindows
, ChildAfter
, ClassAtom
, &WindowName
);
2555 IntReleaseWindowObject(MsgWindows
);
2561 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2562 ExFreePool(ClassName
.Buffer
);
2565 RtlFreeUnicodeString(&WindowName
);
2569 IntReleaseWindowObject(ChildAfter
);
2570 IntReleaseWindowObject(Parent
);
2575 DPRINT("Leave NtUserFindWindowEx, ret %i\n",_ret_
);
2585 NtUserFlashWindowEx(DWORD Unknown0
)
2596 HWND FASTCALL
UserGetAncestor(HWND hWnd
, UINT Type
)
2598 PWINDOW_OBJECT Wnd
, WndAncestor
, Parent
;
2601 if (hWnd
== IntGetDesktopWindow())
2606 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2608 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2616 WndAncestor
= IntGetParentObject(Wnd
);
2629 if(!(Parent
= IntGetParentObject(WndAncestor
)))
2633 if(IntIsDesktopWindow(Parent
))
2635 IntReleaseWindowObject(Parent
);
2639 IntReleaseWindowObject(tmp
);
2640 WndAncestor
= Parent
;
2648 IntReferenceWindowObject(WndAncestor
);
2653 Parent
= IntGetParent(WndAncestor
);
2654 IntReleaseWindowObject(Old
);
2659 WndAncestor
= Parent
;
2666 IntReleaseWindowObject(Wnd
);
2671 hWndAncestor
= (WndAncestor
? WndAncestor
->hSelf
: NULL
);
2672 IntReleaseWindowObject(Wnd
);
2674 if(WndAncestor
&& (WndAncestor
!= Wnd
))
2675 IntReleaseWindowObject(WndAncestor
);
2677 return hWndAncestor
;
2686 NtUserGetAncestor(HWND hWnd
, UINT Type
)
2688 DECLARE_RETURN(HWND
);
2690 DPRINT("Enter NtUserGetAncestor\n");
2691 UserEnterExclusive();
2693 RETURN(UserGetAncestor(hWnd
, Type
));
2696 DPRINT("Leave NtUserGetAncestor, ret=%i\n",_ret_
);
2702 * Returns client window rectangle relative to the upper-left corner of client area.
2704 * \param hWnd window handle.
2705 * \param Rect pointer to the buffer where the coordinates are returned.
2712 NtUserGetClientRect(HWND hWnd
, LPRECT Rect
)
2714 PWINDOW_OBJECT Window
;
2716 DECLARE_RETURN(BOOL
);
2718 DPRINT("Enter NtUserGetClientRect\n");
2721 if(!(Window
= IntGetWindowObject(hWnd
)))
2723 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2727 IntGetClientRect(Window
, &SafeRect
);
2728 IntReleaseWindowObject(Window
);
2730 if(!NT_SUCCESS(MmCopyToCaller(Rect
, &SafeRect
, sizeof(RECT
))))
2737 DPRINT("Leave NtUserGetClientRect, ret=%i\n",_ret_
);
2747 NtUserGetDesktopWindow()
2749 DECLARE_RETURN(HWND
);
2751 DPRINT("Enter NtUserGetDesktopWindow\n");
2754 RETURN( IntGetDesktopWindow());
2757 DPRINT("Leave NtUserGetDesktopWindow, ret=%i\n",_ret_
);
2767 NtUserGetInternalWindowPos(DWORD Unknown0
,
2781 NtUserGetLastActivePopup(HWND hWnd
)
2784 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2785 * not changed anywhere.
2786 * -- Filip, 01/nov/2003
2792 IntAcquireWinLockShared();
2794 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2796 IntReleaseWinLock();
2797 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2801 hWndLastPopup
= Wnd
->hWndLastPopup
;
2803 IntReleaseWinLock();
2805 return hWndLastPopup
;
2814 * The NtUserGetParent function retrieves a handle to the specified window's
2818 * Note that, despite its name, this function can return an owner window
2819 * instead of a parent window.
2826 NtUserGetParent(HWND hWnd
)
2828 PWINDOW_OBJECT Wnd
, WndParent
;
2829 HWND hWndParent
= NULL
;
2830 DECLARE_RETURN(HWND
);
2832 DPRINT("Enter NtUserGetParent\n");
2833 UserEnterExclusive();
2835 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2837 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2841 WndParent
= IntGetParent(Wnd
);
2844 hWndParent
= WndParent
->hSelf
;
2845 IntReleaseWindowObject(WndParent
);
2848 IntReleaseWindowObject(Wnd
);
2850 RETURN( hWndParent
);
2853 DPRINT("Leave NtUserGetParent, ret=%i\n",_ret_
);
2862 UserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2864 PWINDOW_OBJECT Wnd
= NULL
, WndParent
= NULL
, WndOldParent
;
2865 HWND hWndOldParent
= NULL
;
2867 if (IntIsBroadcastHwnd(hWndChild
) || IntIsBroadcastHwnd(hWndNewParent
))
2869 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2873 if (hWndChild
== IntGetDesktopWindow())
2875 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2881 if (!(WndParent
= IntGetWindowObject(hWndNewParent
)))
2883 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2889 if (!(WndParent
= IntGetWindowObject(IntGetDesktopWindow())))
2891 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2896 if (!(Wnd
= IntGetWindowObject(hWndChild
)))
2898 IntReleaseWindowObject(WndParent
);
2899 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2903 WndOldParent
= IntSetParent(Wnd
, WndParent
);
2907 hWndOldParent
= WndOldParent
->hSelf
;
2908 IntReleaseWindowObject(WndOldParent
);
2911 IntReleaseWindowObject(Wnd
);
2912 IntReleaseWindowObject(WndParent
);
2914 return( hWndOldParent
);
2922 * The NtUserSetParent function changes the parent window of the specified
2926 * The new parent window and the child window must belong to the same
2927 * application. If the window identified by the hWndChild parameter is
2928 * visible, the system performs the appropriate redrawing and repainting.
2929 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2930 * or WS_POPUP window styles of the window whose parent is being changed.
2937 NtUserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2939 DECLARE_RETURN(HWND
);
2941 DPRINT("Enter NtUserSetParent\n");
2942 UserEnterExclusive();
2944 RETURN( UserSetParent(hWndChild
, hWndNewParent
));
2947 DPRINT("Leave NtUserSetParent, ret=%i\n",_ret_
);
2955 HWND FASTCALL
UserGetShellWindow()
2957 PWINSTATION_OBJECT WinStaObject
;
2960 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
2965 if (!NT_SUCCESS(Status
))
2967 SetLastNtError(Status
);
2971 Ret
= (HWND
)WinStaObject
->ShellWindow
;
2973 ObDereferenceObject(WinStaObject
);
2979 * NtUserGetShellWindow
2981 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
2988 NtUserGetShellWindow()
2990 DECLARE_RETURN(HWND
);
2992 DPRINT("Enter NtUserGetShellWindow\n");
2995 RETURN( UserGetShellWindow() );
2998 DPRINT("Leave NtUserGetShellWindow, ret=%i\n",_ret_
);
3004 * NtUserSetShellWindowEx
3006 * This is undocumented function to set global shell window. The global
3007 * shell window has special handling of window position.
3014 NtUserSetShellWindowEx(HWND hwndShell
, HWND hwndListView
)
3016 PWINSTATION_OBJECT WinStaObject
;
3017 DECLARE_RETURN(BOOL
);
3019 DPRINT("Enter NtUserSetShellWindowEx\n");
3020 UserEnterExclusive();
3022 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
3027 if (!NT_SUCCESS(Status
))
3029 SetLastNtError(Status
);
3034 * Test if we are permitted to change the shell window.
3036 if (WinStaObject
->ShellWindow
)
3038 ObDereferenceObject(WinStaObject
);
3043 * Move shell window into background.
3045 if (hwndListView
&& hwndListView
!= hwndShell
)
3048 * Disabled for now to get Explorer working.
3049 * -- Filip, 01/nov/2003
3052 co_WinPosSetWindowPos(hwndListView
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
3055 if (UserGetWindowLong(hwndListView
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
3057 ObDereferenceObject(WinStaObject
);
3062 if (UserGetWindowLong(hwndShell
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
3064 ObDereferenceObject(WinStaObject
);
3068 co_WinPosSetWindowPos(hwndShell
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
3070 WinStaObject
->ShellWindow
= hwndShell
;
3071 WinStaObject
->ShellListView
= hwndListView
;
3073 ObDereferenceObject(WinStaObject
);
3077 DPRINT("Leave NtUserSetShellWindowEx, ret=%i\n",_ret_
);
3083 * NtUserGetSystemMenu
3085 * The NtUserGetSystemMenu function allows the application to access the
3086 * window menu (also known as the system menu or the control menu) for
3087 * copying and modifying.
3091 * Handle to the window that will own a copy of the window menu.
3093 * Specifies the action to be taken. If this parameter is FALSE,
3094 * NtUserGetSystemMenu returns a handle to the copy of the window menu
3095 * currently in use. The copy is initially identical to the window menu
3096 * but it can be modified.
3097 * If this parameter is TRUE, GetSystemMenu resets the window menu back
3098 * to the default state. The previous window menu, if any, is destroyed.
3101 * If the bRevert parameter is FALSE, the return value is a handle to a
3102 * copy of the window menu. If the bRevert parameter is TRUE, the return
3110 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
3113 PWINDOW_OBJECT Window
;
3115 DECLARE_RETURN(HMENU
);
3117 DPRINT("Enter NtUserGetSystemMenu\n");
3120 if (!(Window
= IntGetWindowObject(hWnd
)))
3122 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3126 if (!(Menu
= IntGetSystemMenu(Window
, bRevert
, FALSE
)))
3128 Result
= Menu
->MenuInfo
.Self
;
3129 IntReleaseMenuObject(Menu
);
3132 IntReleaseWindowObject(Window
);
3136 DPRINT("Leave NtUserGetSystemMenu, ret=%i\n",_ret_
);
3142 * NtUserSetSystemMenu
3149 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
3151 BOOL Result
= FALSE
;
3152 PWINDOW_OBJECT Window
;
3154 DECLARE_RETURN(BOOL
);
3156 DPRINT("Enter NtUserSetSystemMenu\n");
3157 UserEnterExclusive();
3159 if (!(Window
= IntGetWindowObject(hWnd
)))
3161 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3168 * Assign new menu handle.
3170 Menu
= IntGetMenuObject(hMenu
);
3173 IntReleaseWindowObject(Window
);
3174 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
3178 Result
= IntSetSystemMenu(Window
, Menu
);
3180 IntReleaseMenuObject(Menu
);
3183 IntReleaseWindowObject(Window
);
3188 DPRINT("Leave NtUserSetSystemMenu, ret=%i\n",_ret_
);
3197 UserGetWindow(HWND hWnd
, UINT Relationship
)
3199 PWINDOW_OBJECT Parent
, Window
;
3200 HWND hWndResult
= NULL
;
3202 if (!(Window
= UserGetWindowObjectNoRef(hWnd
))) return NULL
;
3204 switch (Relationship
)
3207 if((Parent
= Window
->Parent
))
3209 if (Parent
->FirstChild
)
3210 hWndResult
= Parent
->FirstChild
->hSelf
;
3215 if((Parent
= Window
->Parent
))
3217 if (Parent
->LastChild
)
3218 hWndResult
= Parent
->LastChild
->hSelf
;
3223 if (Window
->NextSibling
)
3224 hWndResult
= Window
->NextSibling
->hSelf
;
3228 if (Window
->PrevSibling
)
3229 hWndResult
= Window
->PrevSibling
->hSelf
;
3233 if((Parent
= IntGetWindowObject(Window
->hOwner
)))
3235 hWndResult
= Parent
->hSelf
;
3236 IntReleaseWindowObject(Parent
);
3240 if (Window
->FirstChild
)
3241 hWndResult
= Window
->FirstChild
->hSelf
;
3253 * The NtUserGetWindow function retrieves a handle to a window that has the
3254 * specified relationship (Z order or owner) to the specified window.
3261 NtUserGetWindow(HWND hWnd
, UINT Relationship
)
3263 DECLARE_RETURN(HWND
);
3265 DPRINT("Enter NtUserGetWindow\n");
3268 RETURN(UserGetWindow(hWnd
, Relationship
));
3271 DPRINT("Leave NtUserGetWindow, ret=%i\n",_ret_
);
3280 * NtUserGetWindowLong
3282 * The NtUserGetWindowLong function retrieves information about the specified
3283 * window. The function also retrieves the 32-bit (long) value at the
3284 * specified offset into the extra window memory.
3291 UserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3293 PWINDOW_OBJECT Window
, Parent
;
3296 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3298 if (!(Window
= IntGetWindowObject(hWnd
)))
3300 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3305 * WndProc is only available to the owner process
3307 if (GWL_WNDPROC
== Index
3308 && Window
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
3310 SetLastWin32Error(ERROR_ACCESS_DENIED
);
3314 if ((INT
)Index
>= 0)
3316 if ((Index
+ sizeof(LONG
)) > Window
->ExtraDataSize
)
3318 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3321 Result
= *((LONG
*)(Window
->ExtraData
+ Index
));
3328 Result
= Window
->ExStyle
;
3332 Result
= Window
->Style
;
3337 Result
= (LONG
) Window
->WndProcA
;
3339 Result
= (LONG
) Window
->WndProcW
;
3343 Result
= (LONG
) Window
->Instance
;
3346 case GWL_HWNDPARENT
:
3347 Parent
= Window
->Parent
;
3350 if (Parent
&& Parent
->hSelf
== IntGetDesktopWindow())
3351 Result
= (LONG
) UserGetWindow(Window
->hSelf
, GW_OWNER
);
3353 Result
= (LONG
) Parent
->hSelf
;
3358 Result
= (LONG
) Window
->IDMenu
;
3362 Result
= Window
->UserData
;
3366 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index
);
3367 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3373 IntReleaseWindowObject(Window
);
3382 * NtUserGetWindowLong
3384 * The NtUserGetWindowLong function retrieves information about the specified
3385 * window. The function also retrieves the 32-bit (long) value at the
3386 * specified offset into the extra window memory.
3393 NtUserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3395 DECLARE_RETURN(LONG
);
3397 DPRINT("Enter NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3398 UserEnterExclusive();
3400 RETURN(UserGetWindowLong(hWnd
, Index
, Ansi
));
3403 DPRINT("Leave NtUserGetWindowLong, ret=%i\n",_ret_
);
3412 UserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3414 PWINDOW_OBJECT Window
, Parent
;
3415 PWINSTATION_OBJECT WindowStation
;
3419 if (hWnd
== IntGetDesktopWindow())
3421 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3425 if (!(Window
= IntGetWindowObject(hWnd
)))
3427 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3431 if ((INT
)Index
>= 0)
3433 if ((Index
+ sizeof(LONG
)) > Window
->ExtraDataSize
)
3435 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3436 IntReleaseWindowObject(Window
);
3439 OldValue
= *((LONG
*)(Window
->ExtraData
+ Index
));
3440 *((LONG
*)(Window
->ExtraData
+ Index
)) = NewValue
;
3447 OldValue
= (LONG
) Window
->ExStyle
;
3448 Style
.styleOld
= OldValue
;
3449 Style
.styleNew
= NewValue
;
3452 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3454 WindowStation
= Window
->OwnerThread
->Tcb
.Win32Thread
->Desktop
->WindowStation
;
3457 if (hWnd
== WindowStation
->ShellWindow
|| hWnd
== WindowStation
->ShellListView
)
3458 Style
.styleNew
&= ~WS_EX_TOPMOST
;
3461 co_IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3462 Window
->ExStyle
= (DWORD
)Style
.styleNew
;
3463 co_IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3467 OldValue
= (LONG
) Window
->Style
;
3468 Style
.styleOld
= OldValue
;
3469 Style
.styleNew
= NewValue
;
3470 co_IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_STYLE
, (LPARAM
) &Style
);
3471 Window
->Style
= (DWORD
)Style
.styleNew
;
3472 co_IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_STYLE
, (LPARAM
) &Style
);
3476 /* FIXME: should check if window belongs to current process */
3479 OldValue
= (LONG
) Window
->WndProcA
;
3480 Window
->WndProcA
= (WNDPROC
) NewValue
;
3481 Window
->WndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,FALSE
);
3482 Window
->Unicode
= FALSE
;
3486 OldValue
= (LONG
) Window
->WndProcW
;
3487 Window
->WndProcW
= (WNDPROC
) NewValue
;
3488 Window
->WndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,TRUE
);
3489 Window
->Unicode
= TRUE
;
3494 OldValue
= (LONG
) Window
->Instance
;
3495 Window
->Instance
= (HINSTANCE
) NewValue
;
3498 case GWL_HWNDPARENT
:
3499 Parent
= IntGetParentObject(Window
);
3500 if (Parent
&& (Parent
->hSelf
== IntGetDesktopWindow()))
3501 OldValue
= (LONG
) IntSetOwner(Window
->hSelf
, (HWND
) NewValue
);
3503 OldValue
= (LONG
) UserSetParent(Window
->hSelf
, (HWND
) NewValue
);
3505 IntReleaseWindowObject(Parent
);
3509 OldValue
= (LONG
) Window
->IDMenu
;
3510 Window
->IDMenu
= (UINT
) NewValue
;
3514 OldValue
= Window
->UserData
;
3515 Window
->UserData
= NewValue
;
3519 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index
);
3520 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3526 IntReleaseWindowObject(Window
);
3534 * NtUserSetWindowLong
3536 * The NtUserSetWindowLong function changes an attribute of the specified
3537 * window. The function also sets the 32-bit (long) value at the specified
3538 * offset into the extra window memory.
3545 NtUserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3547 DECLARE_RETURN(LONG
);
3549 DPRINT("Enter NtUserSetWindowLong\n");
3550 UserEnterExclusive();
3552 RETURN( UserSetWindowLong(hWnd
, Index
, NewValue
, Ansi
));
3555 DPRINT("Leave NtUserSetWindowLong, ret=%i\n",_ret_
);
3561 * NtUserSetWindowWord
3563 * Legacy function similar to NtUserSetWindowLong.
3570 NtUserSetWindowWord(HWND hWnd
, INT Index
, WORD NewValue
)
3572 PWINDOW_OBJECT Window
;
3574 DECLARE_RETURN(WORD
);
3576 DPRINT("Enter NtUserSetWindowWord\n");
3577 UserEnterExclusive();
3583 case GWL_HWNDPARENT
:
3584 RETURN( UserSetWindowLong(hWnd
, Index
, (UINT
)NewValue
, TRUE
));
3588 SetLastWin32Error(ERROR_INVALID_INDEX
);
3593 if (!(Window
= IntGetWindowObject(hWnd
)))
3595 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3599 if (Index
> Window
->ExtraDataSize
- sizeof(WORD
))
3601 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3602 IntReleaseWindowObject(Window
);
3606 OldValue
= *((WORD
*)(Window
->ExtraData
+ Index
));
3607 *((WORD
*)(Window
->ExtraData
+ Index
)) = NewValue
;
3609 IntReleaseWindowObject(Window
);
3614 DPRINT("Leave NtUserSetWindowWord, ret=%i\n",_ret_
);
3623 NtUserGetWindowPlacement(HWND hWnd
,
3624 WINDOWPLACEMENT
*lpwndpl
)
3626 PWINDOW_OBJECT Window
;
3627 PINTERNALPOS InternalPos
;
3629 WINDOWPLACEMENT Safepl
;
3631 DECLARE_RETURN(BOOL
);
3633 DPRINT("Enter NtUserGetWindowPlacement\n");
3636 if (!(Window
= IntGetWindowObject(hWnd
)))
3638 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3642 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3643 if(!NT_SUCCESS(Status
))
3645 SetLastNtError(Status
);
3646 IntReleaseWindowObject(Window
);
3649 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3651 IntReleaseWindowObject(Window
);
3656 Safepl
.showCmd
= ((Window
->Flags
& WINDOWOBJECT_RESTOREMAX
) ? SW_MAXIMIZE
: SW_SHOWNORMAL
);
3658 Size
.x
= Window
->WindowRect
.left
;
3659 Size
.y
= Window
->WindowRect
.top
;
3660 InternalPos
= WinPosInitInternalPos(Window
, &Size
,
3661 &Window
->WindowRect
);
3664 Safepl
.rcNormalPosition
= InternalPos
->NormalRect
;
3665 Safepl
.ptMinPosition
= InternalPos
->IconPos
;
3666 Safepl
.ptMaxPosition
= InternalPos
->MaxPos
;
3670 IntReleaseWindowObject(Window
);
3674 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3675 if(!NT_SUCCESS(Status
))
3677 SetLastNtError(Status
);
3678 IntReleaseWindowObject(Window
);
3682 IntReleaseWindowObject(Window
);
3686 DPRINT("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
3693 * Return the dimension of the window in the screen coordinates.
3694 * \param hWnd window handle.
3695 * \param Rect pointer to the buffer where the coordinates are returned.
3701 NtUserGetWindowRect(HWND hWnd
, LPRECT Rect
)
3705 DECLARE_RETURN(BOOL
);
3707 DPRINT("Enter NtUserGetWindowRect\n");
3710 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3712 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3715 Status
= MmCopyToCaller(Rect
, &Wnd
->WindowRect
, sizeof(RECT
));
3716 if (!NT_SUCCESS(Status
))
3718 IntReleaseWindowObject(Wnd
);
3719 SetLastNtError(Status
);
3723 IntReleaseWindowObject(Wnd
);
3727 DPRINT("Leave NtUserGetWindowRect, ret=%i\n",_ret_
);
3737 NtUserGetWindowThreadProcessId(HWND hWnd
, LPDWORD UnsafePid
)
3741 DECLARE_RETURN(DWORD
);
3743 DPRINT("Enter NtUserGetWindowThreadProcessId\n");
3746 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3748 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3752 tid
= (DWORD
)IntGetWndThreadId(Wnd
);
3753 pid
= (DWORD
)IntGetWndProcessId(Wnd
);
3755 if (UnsafePid
) MmCopyToCaller(UnsafePid
, &pid
, sizeof(DWORD
));
3760 DPRINT("Leave NtUserGetWindowThreadProcessId, ret=%i\n",_ret_
);
3770 NtUserLockWindowUpdate(DWORD Unknown0
)
3790 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3791 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3792 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3796 QueryWindow based on KJK::Hyperion and James Tabor.
3798 0 = QWUniqueProcessId
3799 1 = QWUniqueThreadId
3800 4 = QWIsHung Implements IsHungAppWindow found
3803 9 = QWKillWindow When I called this with hWnd ==
3804 DesktopWindow, it shutdown the system
3811 NtUserQueryWindow(HWND hWnd
, DWORD Index
)
3813 PWINDOW_OBJECT Window
= IntGetWindowObject(hWnd
);
3815 DECLARE_RETURN(UINT
);
3817 DPRINT("Enter NtUserQueryWindow\n");
3822 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3828 case QUERY_WINDOW_UNIQUE_PROCESS_ID
:
3829 Result
= (DWORD
)IntGetWndProcessId(Window
);
3832 case QUERY_WINDOW_UNIQUE_THREAD_ID
:
3833 Result
= (DWORD
)IntGetWndThreadId(Window
);
3836 case QUERY_WINDOW_ISHUNG
:
3837 Result
= (DWORD
)MsqIsHung(Window
->MessageQueue
);
3841 Result
= (DWORD
)NULL
;
3845 IntReleaseWindowObject(Window
);
3851 DPRINT("Leave NtUserQueryWindow, ret=%i\n",_ret_
);
3861 NtUserRealChildWindowFromPoint(DWORD Unknown0
,
3875 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe
)
3877 UNICODE_STRING SafeMessageName
;
3880 DECLARE_RETURN(UINT
);
3882 DPRINT("Enter NtUserRegisterWindowMessage\n");
3883 UserEnterExclusive();
3885 if(MessageNameUnsafe
== NULL
)
3887 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3891 Status
= IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName
, MessageNameUnsafe
);
3892 if(!NT_SUCCESS(Status
))
3894 SetLastNtError(Status
);
3898 Ret
= (UINT
)IntAddAtom(SafeMessageName
.Buffer
);
3900 RtlFreeUnicodeString(&SafeMessageName
);
3904 DPRINT("Leave NtUserRegisterWindowMessage, ret=%i\n",_ret_
);
3914 NtUserSetImeOwnerWindow(DWORD Unknown0
,
3927 NtUserSetInternalWindowPos(DWORD Unknown0
,
3943 NtUserSetLayeredWindowAttributes(DWORD Unknown0
,
3958 NtUserSetLogonNotifyWindow(DWORD Unknown0
)
3975 PWINDOW_OBJECT Window
;
3977 DECLARE_RETURN(BOOL
);
3979 DPRINT("Enter NtUserSetMenu\n");
3980 UserEnterExclusive();
3982 if (!(Window
= IntGetWindowObject(hWnd
)))
3984 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3988 if (! IntSetMenu(Window
, Menu
, &Changed
))
3990 IntReleaseWindowObject(Window
);
3994 IntReleaseWindowObject(Window
);
3996 if (Changed
&& Repaint
)
3998 co_WinPosSetWindowPos(hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
3999 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
4005 DPRINT("Leave NtUserSetMenu, ret=%i\n",_ret_
);
4015 NtUserSetWindowFNID(DWORD Unknown0
,
4029 NtUserSetWindowPlacement(HWND hWnd
,
4030 WINDOWPLACEMENT
*lpwndpl
)
4032 PWINDOW_OBJECT Window
;
4033 WINDOWPLACEMENT Safepl
;
4035 DECLARE_RETURN(BOOL
);
4037 DPRINT("Enter NtUserSetWindowPlacement\n");
4038 UserEnterExclusive();
4040 if (!(Window
= IntGetWindowObject(hWnd
)))
4042 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4045 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
4046 if(!NT_SUCCESS(Status
))
4048 SetLastNtError(Status
);
4049 IntReleaseWindowObject(Window
);
4052 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
4054 IntReleaseWindowObject(Window
);
4058 if ((Window
->Style
& (WS_MAXIMIZE
| WS_MINIMIZE
)) == 0)
4060 co_WinPosSetWindowPos(Window
->hSelf
, NULL
,
4061 Safepl
.rcNormalPosition
.left
, Safepl
.rcNormalPosition
.top
,
4062 Safepl
.rcNormalPosition
.right
- Safepl
.rcNormalPosition
.left
,
4063 Safepl
.rcNormalPosition
.bottom
- Safepl
.rcNormalPosition
.top
,
4064 SWP_NOZORDER
| SWP_NOACTIVATE
);
4067 /* FIXME - change window status */
4068 co_WinPosShowWindow(Window
->hSelf
, Safepl
.showCmd
);
4070 if (Window
->InternalPos
== NULL
)
4071 Window
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
4072 Window
->InternalPos
->NormalRect
= Safepl
.rcNormalPosition
;
4073 Window
->InternalPos
->IconPos
= Safepl
.ptMinPosition
;
4074 Window
->InternalPos
->MaxPos
= Safepl
.ptMaxPosition
;
4076 IntReleaseWindowObject(Window
);
4080 DPRINT("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
4092 HWND hWndInsertAfter
,
4099 DECLARE_RETURN(BOOL
);
4101 DPRINT("Enter NtUserSetWindowPos\n");
4102 UserEnterExclusive();
4104 RETURN( co_WinPosSetWindowPos(hWnd
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
));
4107 DPRINT("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
4114 IntGetWindowRgn(HWND hWnd
, HRGN hRgn
)
4117 PWINDOW_OBJECT Window
;
4121 if(!(Window
= IntGetWindowObject(hWnd
)))
4123 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4128 IntReleaseWindowObject(Window
);
4132 /* Create a new window region using the window rectangle */
4133 VisRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->WindowRect
);
4134 NtGdiOffsetRgn(VisRgn
, -Window
->WindowRect
.left
, -Window
->WindowRect
.top
);
4135 /* if there's a region assigned to the window, combine them both */
4136 if(Window
->WindowRegion
&& !(Window
->Style
& WS_MINIMIZE
))
4137 NtGdiCombineRgn(VisRgn
, VisRgn
, Window
->WindowRegion
, RGN_AND
);
4138 /* Copy the region into hRgn */
4139 NtGdiCombineRgn(hRgn
, VisRgn
, NULL
, RGN_COPY
);
4141 if((pRgn
= RGNDATA_LockRgn(hRgn
)))
4143 Ret
= pRgn
->rdh
.iType
;
4144 RGNDATA_UnlockRgn(pRgn
);
4149 NtGdiDeleteObject(VisRgn
);
4151 IntReleaseWindowObject(Window
);
4156 IntGetWindowRgnBox(HWND hWnd
, RECT
*Rect
)
4159 PWINDOW_OBJECT Window
;
4163 if(!(Window
= IntGetWindowObject(hWnd
)))
4165 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4170 IntReleaseWindowObject(Window
);
4174 /* Create a new window region using the window rectangle */
4175 VisRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->WindowRect
);
4176 NtGdiOffsetRgn(VisRgn
, -Window
->WindowRect
.left
, -Window
->WindowRect
.top
);
4177 /* if there's a region assigned to the window, combine them both */
4178 if(Window
->WindowRegion
&& !(Window
->Style
& WS_MINIMIZE
))
4179 NtGdiCombineRgn(VisRgn
, VisRgn
, Window
->WindowRegion
, RGN_AND
);
4181 if((pRgn
= RGNDATA_LockRgn(VisRgn
)))
4183 Ret
= pRgn
->rdh
.iType
;
4184 *Rect
= pRgn
->rdh
.rcBound
;
4185 RGNDATA_UnlockRgn(pRgn
);
4190 NtGdiDeleteObject(VisRgn
);
4192 IntReleaseWindowObject(Window
);
4206 PWINDOW_OBJECT Window
;
4207 DECLARE_RETURN(INT
);
4209 DPRINT("Enter NtUserSetWindowRgn\n");
4210 UserEnterExclusive();
4212 if (!(Window
= IntGetWindowObject(hWnd
)))
4214 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4218 /* FIXME - Verify if hRgn is a valid handle!!!!
4219 Propably make this operation thread-safe, but maybe it's not necessary */
4221 if(Window
->WindowRegion
)
4223 /* Delete no longer needed region handle */
4224 NtGdiDeleteObject(Window
->WindowRegion
);
4226 Window
->WindowRegion
= hRgn
;
4228 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
4232 co_UserRedrawWindow(Window
, NULL
, NULL
, RDW_INVALIDATE
);
4235 IntReleaseWindowObject(Window
);
4239 DPRINT("Leave NtUserSystemParametersInfo, ret=%i\n",_ret_
);
4249 NtUserShowWindow(HWND hWnd
,
4252 DECLARE_RETURN(BOOL
);
4254 DPRINT("Enter NtUserShowWindow\n");
4255 UserEnterExclusive();
4257 RETURN( co_WinPosShowWindow(hWnd
, nCmdShow
));
4260 DPRINT("Leave NtUserShowWindow, ret=%i\n",_ret_
);
4270 NtUserShowWindowAsync(DWORD Unknown0
,
4283 NtUserUpdateLayeredWindow(DWORD Unknown0
,
4303 NtUserValidateRect(HWND hWnd
, const RECT
* Rect
)
4305 return (VOID
)NtUserRedrawWindow(hWnd
, Rect
, 0, RDW_VALIDATE
| RDW_NOCHILDREN
);
4313 NtUserWindowFromPoint(LONG X
, LONG Y
)
4317 PWINDOW_OBJECT DesktopWindow
, Window
= NULL
;
4318 DECLARE_RETURN(HWND
);
4320 DPRINT("Enter NtUserWindowFromPoint\n");
4321 UserEnterExclusive();
4323 if ((DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow())))
4330 Hit
= co_WinPosWindowFromPoint(DesktopWindow
, PsGetWin32Thread()->MessageQueue
, &pt
, &Window
);
4334 Ret
= Window
->hSelf
;
4335 IntReleaseWindowObject(Window
);
4336 IntReleaseWindowObject(DesktopWindow
);
4340 IntReleaseWindowObject(DesktopWindow
);
4346 DPRINT("Leave NtUserWindowFromPoint, ret=%i\n",_ret_
);
4356 * Undocumented function that is called from DefWindowProc to set
4364 NtUserDefSetText(HWND hWnd
, PUNICODE_STRING WindowText
)
4366 PWINDOW_OBJECT Window
, Parent
, Owner
;
4367 UNICODE_STRING SafeText
;
4369 DECLARE_RETURN(INT
);
4371 DPRINT("Enter NtUserDefSetText\n");
4372 UserEnterExclusive();
4374 if(!(Window
= IntGetWindowObject(hWnd
)))
4376 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4382 Status
= IntSafeCopyUnicodeString(&SafeText
, WindowText
);
4383 if(!NT_SUCCESS(Status
))
4385 SetLastNtError(Status
);
4386 IntReleaseWindowObject(Window
);
4392 RtlInitUnicodeString(&SafeText
, NULL
);
4395 /* FIXME - do this thread-safe! otherwise one could crash here! */
4396 RtlFreeUnicodeString(&Window
->WindowName
);
4398 Window
->WindowName
= SafeText
;
4400 /* Send shell notifications */
4402 Owner
= IntGetOwner(Window
);
4403 Parent
= IntGetParent(Window
);
4405 if ((!Owner
) && (!Parent
))
4407 co_IntShellHookNotify(HSHELL_REDRAW
, (LPARAM
) hWnd
);
4412 IntReleaseWindowObject(Owner
);
4417 IntReleaseWindowObject(Parent
);
4420 IntReleaseWindowObject(Window
);
4424 DPRINT("Leave NtUserDefSetText, ret=%i\n",_ret_
);
4430 * NtUserInternalGetWindowText
4437 NtUserInternalGetWindowText(HWND hWnd
, LPWSTR lpString
, INT nMaxCount
)
4439 PWINDOW_OBJECT Window
;
4442 DECLARE_RETURN(INT
);
4444 DPRINT("Enter NtUserInternalGetWindowText\n");
4447 if(lpString
&& (nMaxCount
<= 1))
4449 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
4453 if(!(Window
= IntGetWindowObject(hWnd
)))
4455 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4459 /* FIXME - do this thread-safe! otherwise one could crash here! */
4460 Result
= Window
->WindowName
.Length
/ sizeof(WCHAR
);
4463 const WCHAR Terminator
= L
'\0';
4465 WCHAR
*Buffer
= (WCHAR
*)lpString
;
4467 Copy
= min(nMaxCount
- 1, Result
);
4470 Status
= MmCopyToCaller(Buffer
, Window
->WindowName
.Buffer
, Copy
* sizeof(WCHAR
));
4471 if(!NT_SUCCESS(Status
))
4473 SetLastNtError(Status
);
4474 IntReleaseWindowObject(Window
);
4480 Status
= MmCopyToCaller(Buffer
, &Terminator
, sizeof(WCHAR
));
4481 if(!NT_SUCCESS(Status
))
4483 SetLastNtError(Status
);
4484 IntReleaseWindowObject(Window
);
4491 IntReleaseWindowObject(Window
);
4495 DPRINT("Leave NtUserInternalGetWindowText, ret=%i\n",_ret_
);
4501 NtUserDereferenceWndProcHandle(WNDPROC wpHandle
, WndProcHandle
*Data
)
4503 DECLARE_RETURN(DWORD
);
4505 DPRINT("Enter NtUserDereferenceWndProcHandle\n");
4508 WndProcHandle Entry
;
4509 if (((DWORD
)wpHandle
& 0xFFFF0000) == 0xFFFF0000)
4511 Entry
= WndProcHandlesArray
[(DWORD
)wpHandle
& 0x0000FFFF];
4512 Data
->WindowProc
= Entry
.WindowProc
;
4513 Data
->IsUnicode
= Entry
.IsUnicode
;
4514 Data
->ProcessID
= Entry
.ProcessID
;
4522 DPRINT("Leave NtUserDereferenceWndProcHandle, ret=%i\n",_ret_
);
4528 IntAddWndProcHandle(WNDPROC WindowProc
, BOOL IsUnicode
)
4533 WndProcHandle
*OldArray
;
4536 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4538 if (WndProcHandlesArray
[i
].WindowProc
== NULL
)
4546 OldArray
= WndProcHandlesArray
;
4547 OldArraySize
= WndProcHandlesArraySize
;
4548 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,(OldArraySize
+ WPH_SIZE
) * sizeof(WndProcHandle
), TAG_WINPROCLST
);
4549 WndProcHandlesArraySize
= OldArraySize
+ WPH_SIZE
;
4550 RtlCopyMemory(WndProcHandlesArray
,OldArray
,OldArraySize
* sizeof(WndProcHandle
));
4551 ExFreePool(OldArray
);
4552 FreeSpot
= OldArraySize
+ 1;
4554 WndProcHandlesArray
[FreeSpot
].WindowProc
= WindowProc
;
4555 WndProcHandlesArray
[FreeSpot
].IsUnicode
= IsUnicode
;
4556 WndProcHandlesArray
[FreeSpot
].ProcessID
= PsGetCurrentProcessId();
4557 return FreeSpot
+ 0xFFFF0000;
4561 IntRemoveWndProcHandle(WNDPROC Handle
)
4564 position
= (DWORD
)Handle
& 0x0000FFFF;
4565 if (position
> WndProcHandlesArraySize
)
4569 WndProcHandlesArray
[position
].WindowProc
= NULL
;
4570 WndProcHandlesArray
[position
].IsUnicode
= FALSE
;
4571 WndProcHandlesArray
[position
].ProcessID
= NULL
;
4576 IntRemoveProcessWndProcHandles(HANDLE ProcessID
)
4579 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4581 if (WndProcHandlesArray
[i
].ProcessID
== ProcessID
)
4583 WndProcHandlesArray
[i
].WindowProc
= NULL
;
4584 WndProcHandlesArray
[i
].IsUnicode
= FALSE
;
4585 WndProcHandlesArray
[i
].ProcessID
= NULL
;
4591 #define WIN_NEEDS_SHOW_OWNEDPOPUP (0x00000040)
4595 IntShowOwnedPopups( HWND owner
, BOOL fShow
)
4598 PWINDOW_OBJECT Window
, pWnd
;
4601 if(!(Window
= IntGetWindowObject(owner
)))
4603 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4607 win_array
= IntWinListChildren( Window
);
4608 IntReleaseWindowObject(Window
);
4610 if (!win_array
) return TRUE
;
4612 while (win_array
[count
]) count
++;
4613 while (--count
>= 0)
4615 if (UserGetWindow( win_array
[count
], GW_OWNER
) != owner
) continue;
4616 if (!(pWnd
= IntGetWindowObject( win_array
[count
] ))) continue;
4617 // if (pWnd == WND_OTHER_PROCESS) continue;
4621 if (pWnd
->Flags
& WIN_NEEDS_SHOW_OWNEDPOPUP
)
4623 IntReleaseWindowObject( pWnd
);
4624 /* In Windows, ShowOwnedPopups(TRUE) generates
4625 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
4626 * regardless of the state of the owner
4628 co_IntSendMessage(win_array
[count
], WM_SHOWWINDOW
, SW_SHOWNORMAL
, SW_PARENTOPENING
);
4634 if (pWnd
->Style
& WS_VISIBLE
)
4636 IntReleaseWindowObject( pWnd
);
4637 /* In Windows, ShowOwnedPopups(FALSE) generates
4638 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
4639 * regardless of the state of the owner
4641 co_IntSendMessage(win_array
[count
], WM_SHOWWINDOW
, SW_HIDE
, SW_PARENTCLOSING
);
4645 IntReleaseWindowObject( pWnd
);
4647 ExFreePool( win_array
);