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
)
156 return IntGetWindowObject(hWnd
);
162 PWINDOW_OBJECT FASTCALL
163 IntGetOwner(PWINDOW_OBJECT Wnd
)
169 return IntGetWindowObject(hWnd
);
172 PWINDOW_OBJECT FASTCALL
173 IntGetParentObject(PWINDOW_OBJECT Wnd
)
177 hParent
= Wnd
->Parent
;
178 return IntGetWindowObject(hParent
);
184 * Compile a list of all child window handles from given window.
187 * This function is similar to Wine WIN_ListChildren. The caller
188 * must free the returned list with ExFreePool.
192 IntWinListChildren(PWINDOW_OBJECT Window
)
194 PWINDOW_OBJECT Child
;
196 UINT Index
, NumChildren
= 0;
198 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
201 List
= ExAllocatePoolWithTag(PagedPool
, (NumChildren
+ 1) * sizeof(HWND
), TAG_WINLIST
);
204 DPRINT1("Failed to allocate memory for children array\n");
205 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
208 for (Child
= Window
->FirstChild
, Index
= 0;
210 Child
= Child
->NextSibling
, ++Index
)
211 List
[Index
] = Child
->hSelf
;
217 /***********************************************************************
220 static void IntSendDestroyMsg(HWND Wnd
)
223 PWINDOW_OBJECT Window
, Owner
, Parent
;
227 if (GetGUIThreadInfo(GetCurrentThreadId(), &info
))
229 if (Wnd
== info
.hwndCaret
)
236 Window
= IntGetWindowObject(Wnd
);
238 Owner
= IntGetOwner(Window
);
240 Parent
= IntGetParent(Window
);
242 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
) Wnd
);
244 IntReleaseWindowObject(Parent
);
246 IntReleaseWindowObject(Owner
);
249 IntReleaseWindowObject(Window
);
252 /* The window could already be destroyed here */
255 * Send the WM_DESTROY to the window.
258 co_IntSendMessage(Wnd
, WM_DESTROY
, 0, 0);
261 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
262 * make sure that the window still exists when we come back.
270 if (!(pWndArray
= WIN_ListChildren( hwnd
))) return;
272 /* start from the end (FIXME: is this needed?) */
273 for (i
= 0; pWndArray
[i
]; i
++) ;
277 if (IsWindow( pWndArray
[i
] )) WIN_SendDestroyMsg( pWndArray
[i
] );
279 HeapFree(GetProcessHeap(), 0, pWndArray
);
283 DPRINT("destroyed itself while in WM_DESTROY!\n");
288 /***********************************************************************
291 * Destroy storage associated to a window. "Internals" p.358
293 static LRESULT
co_IntDestroyWindow(PWINDOW_OBJECT Window
,
294 PW32PROCESS ProcessData
,
295 PW32THREAD ThreadData
,
296 BOOLEAN SendMessages
)
300 PWINDOW_OBJECT Child
;
302 BOOLEAN BelongsToThreadData
;
306 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
308 DPRINT("Tried to call IntDestroyWindow() twice\n");
311 Window
->Status
|= WINDOWSTATUS_DESTROYING
;
312 Window
->Flags
&= ~WS_VISIBLE
;
313 /* remove the window already at this point from the thread window list so we
314 don't get into trouble when destroying the thread windows while we're still
315 in IntDestroyWindow() */
316 RemoveEntryList(&Window
->ThreadListEntry
);
318 BelongsToThreadData
= IntWndBelongsToThread(Window
, ThreadData
);
320 IntDeRegisterShellHookWindow(Window
->hSelf
);
324 /* Send destroy messages */
325 IntSendDestroyMsg(Window
->hSelf
);
328 /* free child windows */
329 Children
= IntWinListChildren(Window
);
332 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
334 if ((Child
= IntGetWindowObject(*ChildHandle
)))
336 if(!IntWndBelongsToThread(Child
, ThreadData
))
338 /* send WM_DESTROY messages to windows not belonging to the same thread */
339 IntSendDestroyMsg(Child
->hSelf
);
342 co_IntDestroyWindow(Child
, ProcessData
, ThreadData
, SendMessages
);
343 IntReleaseWindowObject(Child
);
346 ExFreePool(Children
);
352 * Clear the update region to make sure no WM_PAINT messages will be
353 * generated for this window while processing the WM_NCDESTROY.
355 co_UserRedrawWindow(Window
, NULL
, 0,
356 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
|
357 RDW_NOINTERNALPAINT
| RDW_NOCHILDREN
);
358 if(BelongsToThreadData
)
359 co_IntSendMessage(Window
->hSelf
, WM_NCDESTROY
, 0, 0);
361 MsqRemoveTimersWindow(ThreadData
->MessageQueue
, Window
->hSelf
);
363 /* flush the message queue */
364 MsqRemoveWindowMessagesFromQueue(Window
);
366 /* from now on no messages can be sent to this window anymore */
367 Window
->Status
|= WINDOWSTATUS_DESTROYED
;
368 /* don't remove the WINDOWSTATUS_DESTROYING bit */
370 /* reset shell window handles */
371 if(ThreadData
->Desktop
)
373 if (Window
->hSelf
== ThreadData
->Desktop
->WindowStation
->ShellWindow
)
374 ThreadData
->Desktop
->WindowStation
->ShellWindow
= NULL
;
376 if (Window
->hSelf
== ThreadData
->Desktop
->WindowStation
->ShellListView
)
377 ThreadData
->Desktop
->WindowStation
->ShellListView
= NULL
;
380 /* Unregister hot keys */
381 UnregisterWindowHotKeys (Window
);
383 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
386 WinPosCheckInternalPos(Window
->hSelf
);
387 if (Window
->hSelf
== GetCapture())
392 /* free resources associated with the window */
393 TIMER_RemoveWindowTimers(Window
->hSelf
);
396 if (!(Window
->Style
& WS_CHILD
) && Window
->IDMenu
397 && (Menu
= IntGetMenuObject((HMENU
)Window
->IDMenu
)))
399 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
401 IntReleaseMenuObject(Menu
);
404 if(Window
->SystemMenu
405 && (Menu
= IntGetMenuObject(Window
->SystemMenu
)))
407 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
408 Window
->SystemMenu
= (HMENU
)0;
409 IntReleaseMenuObject(Menu
);
412 DceFreeWindowDCE(Window
); /* Always do this to catch orphaned DCs */
414 WINPROC_FreeProc(Window
->winproc
, WIN_PROC_WINDOW
);
415 CLASS_RemoveWindow(Window
->Class
);
418 IntUnlinkWindow(Window
);
420 IntReferenceWindowObject(Window
);
421 ObmCloseHandle(gHandleTable
, Window
->hSelf
);
423 IntDestroyScrollBars(Window
);
425 /* remove the window from the class object */
426 RemoveEntryList(&Window
->ClassListEntry
);
428 /* dereference the class */
429 ClassDereferenceObject(Window
->Class
);
430 Window
->Class
= NULL
;
432 if(Window
->WindowRegion
)
434 NtGdiDeleteObject(Window
->WindowRegion
);
437 RtlFreeUnicodeString(&Window
->WindowName
);
439 IntReleaseWindowObject(Window
);
445 IntGetWindowBorderMeasures(PWINDOW_OBJECT Window
, UINT
*cx
, UINT
*cy
)
447 if(HAS_DLGFRAME(Window
->Style
, Window
->ExStyle
) && !(Window
->Style
& WS_MINIMIZE
))
449 *cx
= UserGetSystemMetrics(SM_CXDLGFRAME
);
450 *cy
= UserGetSystemMetrics(SM_CYDLGFRAME
);
454 if(HAS_THICKFRAME(Window
->Style
, Window
->ExStyle
)&& !(Window
->Style
& WS_MINIMIZE
))
456 *cx
= UserGetSystemMetrics(SM_CXFRAME
);
457 *cy
= UserGetSystemMetrics(SM_CYFRAME
);
459 else if(HAS_THINFRAME(Window
->Style
, Window
->ExStyle
))
461 *cx
= UserGetSystemMetrics(SM_CXBORDER
);
462 *cy
= UserGetSystemMetrics(SM_CYBORDER
);
472 IntGetWindowInfo(PWINDOW_OBJECT Window
, PWINDOWINFO pwi
)
474 pwi
->cbSize
= sizeof(WINDOWINFO
);
475 pwi
->rcWindow
= Window
->WindowRect
;
476 pwi
->rcClient
= Window
->ClientRect
;
477 pwi
->dwStyle
= Window
->Style
;
478 pwi
->dwExStyle
= Window
->ExStyle
;
479 pwi
->dwWindowStatus
= (UserGetForegroundWindow() == Window
->hSelf
); /* WS_ACTIVECAPTION */
480 IntGetWindowBorderMeasures(Window
, &pwi
->cxWindowBorders
, &pwi
->cyWindowBorders
);
481 pwi
->atomWindowType
= (Window
->Class
? Window
->Class
->Atom
: 0);
482 pwi
->wCreatorVersion
= 0x400; /* FIXME - return a real version number */
488 PWINDOW_OBJECT Window
,
492 PMENU_OBJECT OldMenu
, NewMenu
= NULL
;
494 if ((Window
->Style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
496 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
500 *Changed
= (Window
->IDMenu
!= (UINT
) Menu
);
508 OldMenu
= IntGetMenuObject((HMENU
) Window
->IDMenu
);
509 ASSERT(NULL
== OldMenu
|| OldMenu
->MenuInfo
.Wnd
== Window
->hSelf
);
518 NewMenu
= IntGetMenuObject(Menu
);
523 IntReleaseMenuObject(OldMenu
);
525 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
528 if (NULL
!= NewMenu
->MenuInfo
.Wnd
)
530 /* Can't use the same menu for two windows */
533 IntReleaseMenuObject(OldMenu
);
535 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
541 Window
->IDMenu
= (UINT
) Menu
;
544 NewMenu
->MenuInfo
.Wnd
= Window
->hSelf
;
545 IntReleaseMenuObject(NewMenu
);
549 OldMenu
->MenuInfo
.Wnd
= NULL
;
550 IntReleaseMenuObject(OldMenu
);
557 /* INTERNAL ******************************************************************/
561 co_DestroyThreadWindows(struct _ETHREAD
*Thread
)
564 PW32PROCESS Win32Process
;
565 PW32THREAD Win32Thread
;
566 PWINDOW_OBJECT
*List
, *pWnd
;
569 Win32Thread
= Thread
->Tcb
.Win32Thread
;
570 Win32Process
= (PW32PROCESS
)Thread
->ThreadsProcess
->Win32Process
;
572 Current
= Win32Thread
->WindowListHead
.Flink
;
573 while (Current
!= &(Win32Thread
->WindowListHead
))
576 Current
= Current
->Flink
;
581 List
= ExAllocatePool(PagedPool
, (Cnt
+ 1) * sizeof(PWINDOW_OBJECT
));
584 DPRINT("Not enough memory to allocate window handle list\n");
588 Current
= Win32Thread
->WindowListHead
.Flink
;
589 while (Current
!= &(Win32Thread
->WindowListHead
))
591 *pWnd
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
592 IntReferenceWindowObject(*pWnd
);
594 Current
= Current
->Flink
;
598 for(pWnd
= List
; *pWnd
; pWnd
++)
600 co_UserDestroyWindow(*pWnd
);
601 IntReleaseWindowObject(*pWnd
);
612 * Returns client window rectangle relative to the upper-left corner of client area.
614 * \note Does not check the validity of the parameters
617 IntGetClientRect(PWINDOW_OBJECT Window
, PRECT Rect
)
622 Rect
->left
= Rect
->top
= 0;
623 Rect
->right
= Window
->ClientRect
.right
- Window
->ClientRect
.left
;
624 Rect
->bottom
= Window
->ClientRect
.bottom
- Window
->ClientRect
.top
;
630 IntGetFocusWindow(VOID
)
632 PUSER_MESSAGE_QUEUE Queue
;
633 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
638 Queue
= (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
643 return(Queue
->FocusWindow
);
647 PMENU_OBJECT FASTCALL
648 IntGetSystemMenu(PWINDOW_OBJECT Window
, BOOL bRevert
, BOOL RetMenu
)
650 PMENU_OBJECT Menu
, NewMenu
, SysMenu
, ret
= NULL
;
651 PW32THREAD W32Thread
;
652 HMENU hNewMenu
, hSysMenu
;
653 ROSMENUITEMINFO ItemInfo
;
657 W32Thread
= PsGetWin32Thread();
659 if(!W32Thread
->Desktop
)
662 if(Window
->SystemMenu
)
664 Menu
= IntGetMenuObject(Window
->SystemMenu
);
667 IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
668 Window
->SystemMenu
= (HMENU
)0;
669 IntReleaseMenuObject(Menu
);
673 if(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
)
675 /* clone system menu */
676 Menu
= IntGetMenuObject(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
);
680 NewMenu
= IntCloneMenu(Menu
);
683 Window
->SystemMenu
= NewMenu
->MenuInfo
.Self
;
684 NewMenu
->MenuInfo
.Flags
|= MF_SYSMENU
;
685 NewMenu
->MenuInfo
.Wnd
= Window
->hSelf
;
687 //IntReleaseMenuObject(NewMenuObject);
689 IntReleaseMenuObject(Menu
);
693 hSysMenu
= UserCreateMenu(FALSE
);
698 SysMenu
= IntGetMenuObject(hSysMenu
);
701 UserDestroyMenu(hSysMenu
);
704 SysMenu
->MenuInfo
.Flags
|= MF_SYSMENU
;
705 SysMenu
->MenuInfo
.Wnd
= Window
->hSelf
;
706 hNewMenu
= co_IntLoadSysMenuTemplate();
709 IntReleaseMenuObject(SysMenu
);
710 UserDestroyMenu(hSysMenu
);
713 Menu
= IntGetMenuObject(hNewMenu
);
716 IntReleaseMenuObject(SysMenu
);
717 UserDestroyMenu(hSysMenu
);
721 NewMenu
= IntCloneMenu(Menu
);
724 NewMenu
->MenuInfo
.Flags
|= MF_SYSMENU
| MF_POPUP
;
725 IntReleaseMenuObject(NewMenu
);
726 UserSetMenuDefaultItem(NewMenu
->MenuInfo
.Self
, SC_CLOSE
, FALSE
);
728 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
729 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
730 ItemInfo
.fType
= MF_POPUP
;
731 ItemInfo
.fState
= MFS_ENABLED
;
732 ItemInfo
.dwTypeData
= NULL
;
734 ItemInfo
.hSubMenu
= NewMenu
->MenuInfo
.Self
;
735 IntInsertMenuItem(SysMenu
, (UINT
) -1, TRUE
, &ItemInfo
);
737 Window
->SystemMenu
= SysMenu
->MenuInfo
.Self
;
741 IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
742 IntReleaseMenuObject(Menu
);
751 if(Window
->SystemMenu
)
752 return IntGetMenuObject((HMENU
)Window
->SystemMenu
);
760 IntIsChildWindow(HWND Parent
, HWND Child
)
762 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
764 if(!(BaseWindow
= IntGetWindowObject(Child
)))
772 if (Window
->hSelf
== Parent
)
774 if(Window
!= BaseWindow
)
775 IntReleaseWindowObject(Window
);
776 IntReleaseWindowObject(BaseWindow
);
779 if(!(Window
->Style
& WS_CHILD
))
781 if(Window
!= BaseWindow
)
782 IntReleaseWindowObject(Window
);
786 Window
= IntGetParentObject(Window
);
787 if(Old
!= BaseWindow
)
788 IntReleaseWindowObject(Old
);
791 IntReleaseWindowObject(BaseWindow
);
796 IntIsWindowVisible(HWND hWnd
)
798 PWINDOW_OBJECT BaseWindow
, Window
, Old
;
800 if(!(BaseWindow
= IntGetWindowObject(hWnd
)))
808 if(!(Window
->Style
& WS_CHILD
))
812 if(!(Window
->Style
& WS_VISIBLE
))
814 if(Window
!= BaseWindow
)
815 IntReleaseWindowObject(Window
);
816 IntReleaseWindowObject(BaseWindow
);
820 Window
= IntGetParentObject(Window
);
821 if(Old
!= BaseWindow
)
822 IntReleaseWindowObject(Old
);
827 if(Window
->Style
& WS_VISIBLE
)
829 if(Window
!= BaseWindow
)
830 IntReleaseWindowObject(Window
);
831 IntReleaseWindowObject(BaseWindow
);
834 if(Window
!= BaseWindow
)
835 IntReleaseWindowObject(Window
);
837 IntReleaseWindowObject(BaseWindow
);
842 /* link the window into siblings and parent. children are kept in place. */
846 PWINDOW_OBJECT WndParent
,
847 PWINDOW_OBJECT WndPrevSibling
/* set to NULL if top sibling */
850 PWINDOW_OBJECT Parent
;
852 Wnd
->Parent
= WndParent
->hSelf
;
853 if ((Wnd
->PrevSibling
= WndPrevSibling
))
855 /* link after WndPrevSibling */
856 if ((Wnd
->NextSibling
= WndPrevSibling
->NextSibling
))
857 Wnd
->NextSibling
->PrevSibling
= Wnd
;
858 else if ((Parent
= IntGetWindowObject(Wnd
->Parent
)))
860 if(Parent
->LastChild
== WndPrevSibling
)
861 Parent
->LastChild
= Wnd
;
862 IntReleaseWindowObject(Parent
);
864 Wnd
->PrevSibling
->NextSibling
= Wnd
;
869 Parent
= IntGetWindowObject(Wnd
->Parent
);
870 if ((Wnd
->NextSibling
= WndParent
->FirstChild
))
871 Wnd
->NextSibling
->PrevSibling
= Wnd
;
874 Parent
->LastChild
= Wnd
;
875 Parent
->FirstChild
= Wnd
;
876 IntReleaseWindowObject(Parent
);
881 Parent
->FirstChild
= Wnd
;
882 IntReleaseWindowObject(Parent
);
889 IntSetOwner(HWND hWnd
, HWND hWndNewOwner
)
891 PWINDOW_OBJECT Wnd
, WndOldOwner
, WndNewOwner
;
894 Wnd
= IntGetWindowObject(hWnd
);
898 WndOldOwner
= IntGetWindowObject(Wnd
->Owner
);
901 ret
= WndOldOwner
->hSelf
;
902 IntReleaseWindowObject(WndOldOwner
);
909 if((WndNewOwner
= IntGetWindowObject(hWndNewOwner
)))
911 Wnd
->Owner
= hWndNewOwner
;
912 IntReleaseWindowObject(WndNewOwner
);
917 IntReleaseWindowObject(Wnd
);
921 PWINDOW_OBJECT FASTCALL
922 IntSetParent(PWINDOW_OBJECT Wnd
, PWINDOW_OBJECT WndNewParent
)
924 PWINDOW_OBJECT WndOldParent
, Sibling
, InsertAfter
;
925 HWND hWnd
, hWndNewParent
, hWndOldParent
;
930 ASSERT(WndNewParent
);
933 hWndNewParent
= WndNewParent
->hSelf
;
936 * Windows hides the window first, then shows it again
937 * including the WM_SHOWWINDOW messages and all
939 WasVisible
= co_WinPosShowWindow(hWnd
, SW_HIDE
);
941 /* Validate that window and parent still exist */
942 if (!IntIsWindow(hWnd
) || !IntIsWindow(hWndNewParent
))
945 /* Window must belong to current process */
946 if (Wnd
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
949 WndOldParent
= IntGetParentObject(Wnd
);
950 hWndOldParent
= (WndOldParent
? WndOldParent
->hSelf
: NULL
);
952 if (WndNewParent
!= WndOldParent
)
954 IntUnlinkWindow(Wnd
);
956 if (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
))
958 /* Not a TOPMOST window, put after TOPMOSTs of new parent */
959 Sibling
= WndNewParent
->FirstChild
;
960 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
962 InsertAfter
= Sibling
;
963 Sibling
= Sibling
->NextSibling
;
966 if (NULL
== InsertAfter
)
968 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
972 IntReferenceWindowObject(InsertAfter
);
973 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
974 IntReleaseWindowObject(InsertAfter
);
977 if (WndNewParent
->hSelf
!= IntGetDesktopWindow()) /* a child window */
979 if (!(Wnd
->Style
& WS_CHILD
))
981 //if ( Wnd->Menu ) DestroyMenu ( Wnd->menu );
982 IntSetMenu(Wnd
, NULL
, &MenuChanged
);
988 * SetParent additionally needs to make hwnd the top window
989 * in the z-order and send the expected WM_WINDOWPOSCHANGING and
990 * WM_WINDOWPOSCHANGED notification messages.
992 co_WinPosSetWindowPos(hWnd
, (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOP
: HWND_TOPMOST
),
993 0, 0, 0, 0, SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
994 | (WasVisible
? SWP_SHOWWINDOW
: 0));
997 * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
998 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
1002 * Validate that the old parent still exist, since it migth have been
1003 * destroyed during the last callbacks to user-mode
1007 if(!IntIsWindow(WndOldParent
->hSelf
))
1009 IntReleaseWindowObject(WndOldParent
);
1013 /* don't dereference the window object here, it must be done by the caller
1014 of IntSetParent() */
1015 return WndOldParent
;
1021 IntSetSystemMenu(PWINDOW_OBJECT Window
, PMENU_OBJECT Menu
)
1023 PMENU_OBJECT OldMenu
;
1024 if(Window
->SystemMenu
)
1026 OldMenu
= IntGetMenuObject(Window
->SystemMenu
);
1029 OldMenu
->MenuInfo
.Flags
&= ~ MF_SYSMENU
;
1030 IntReleaseMenuObject(OldMenu
);
1036 /* FIXME check window style, propably return FALSE ? */
1037 Window
->SystemMenu
= Menu
->MenuInfo
.Self
;
1038 Menu
->MenuInfo
.Flags
|= MF_SYSMENU
;
1041 Window
->SystemMenu
= (HMENU
)0;
1047 /* unlink the window from siblings and parent. children are kept in place. */
1049 IntUnlinkWindow(PWINDOW_OBJECT Wnd
)
1051 PWINDOW_OBJECT WndParent
;
1053 if((WndParent
= IntGetWindowObject(Wnd
->Parent
)))
1058 if (Wnd
->NextSibling
) Wnd
->NextSibling
->PrevSibling
= Wnd
->PrevSibling
;
1059 else if (WndParent
&& WndParent
->LastChild
== Wnd
) WndParent
->LastChild
= Wnd
->PrevSibling
;
1061 if (Wnd
->PrevSibling
) Wnd
->PrevSibling
->NextSibling
= Wnd
->NextSibling
;
1062 else if (WndParent
&& WndParent
->FirstChild
== Wnd
) WndParent
->FirstChild
= Wnd
->NextSibling
;
1066 IntReleaseWindowObject(WndParent
);
1068 Wnd
->PrevSibling
= Wnd
->NextSibling
= Wnd
->Parent
= NULL
;
1074 PWINDOW_OBJECT Window
, Child
;
1076 if(!(Window
= IntGetWindowObject(IntGetDesktopWindow())))
1078 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1082 for(Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
1084 if(Child
->Owner
&& Child
->Style
& WS_VISIBLE
)
1087 * The desktop has a popup window if one of them has
1088 * an owner window and is visible
1090 IntReleaseWindowObject(Window
);
1095 IntReleaseWindowObject(Window
);
1100 IntIsWindowInDestroy(PWINDOW_OBJECT Window
)
1102 return ((Window
->Status
& WINDOWSTATUS_DESTROYING
) == WINDOWSTATUS_DESTROYING
);
1105 /* FUNCTIONS *****************************************************************/
1111 NtUserAlterWindowStyle(DWORD Unknown0
,
1122 * As best as I can figure, this function is used by EnumWindows,
1123 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
1125 * It's supposed to build a list of HWNDs to return to the caller.
1126 * We can figure out what kind of list by what parameters are
1134 NtUserBuildHwndList(
1146 /* FIXME handle bChildren */
1150 PWINDOW_OBJECT Window
, Child
;
1151 if(!(Window
= IntGetWindowObject(hwndParent
)))
1153 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1157 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1159 if(dwCount
++ < nBufSize
&& pWnd
)
1161 Status
= MmCopyToCaller(pWnd
++, &Child
->hSelf
, sizeof(HWND
));
1162 if(!NT_SUCCESS(Status
))
1164 SetLastNtError(Status
);
1170 IntReleaseWindowObject(Window
);
1175 PW32THREAD W32Thread
;
1176 PLIST_ENTRY Current
;
1177 PWINDOW_OBJECT Window
;
1179 Status
= PsLookupThreadByThreadId((HANDLE
)dwThreadId
, &Thread
);
1180 if(!NT_SUCCESS(Status
))
1182 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1185 if(!(W32Thread
= Thread
->Tcb
.Win32Thread
))
1187 ObDereferenceObject(Thread
);
1188 DPRINT("Thread is not a GUI Thread!\n");
1189 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1193 Current
= W32Thread
->WindowListHead
.Flink
;
1194 while(Current
!= &(W32Thread
->WindowListHead
))
1196 Window
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
1199 if(dwCount
< nBufSize
&& pWnd
)
1201 Status
= MmCopyToCaller(pWnd
++, &Window
->hSelf
, sizeof(HWND
));
1202 if(!NT_SUCCESS(Status
))
1204 SetLastNtError(Status
);
1209 Current
= Current
->Flink
;
1212 ObDereferenceObject(Thread
);
1216 PDESKTOP_OBJECT Desktop
;
1217 PWINDOW_OBJECT Window
, Child
;
1219 if(hDesktop
== NULL
&& !(Desktop
= IntGetActiveDesktop()))
1221 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1227 Status
= IntValidateDesktopHandle(hDesktop
,
1231 if(!NT_SUCCESS(Status
))
1233 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1237 if(!(Window
= IntGetWindowObject(Desktop
->DesktopWindow
)))
1240 ObDereferenceObject(Desktop
);
1241 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1245 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1247 if(dwCount
++ < nBufSize
&& pWnd
)
1249 Status
= MmCopyToCaller(pWnd
++, &Child
->hSelf
, sizeof(HWND
));
1250 if(!NT_SUCCESS(Status
))
1252 SetLastNtError(Status
);
1258 IntReleaseWindowObject(Window
);
1260 ObDereferenceObject(Desktop
);
1271 NtUserChildWindowFromPointEx(HWND hwndParent
,
1276 PWINDOW_OBJECT Parent
;
1281 if(!(Parent
= IntGetWindowObject(hwndParent
)))
1283 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1290 if(Parent
->hSelf
!= IntGetDesktopWindow())
1292 Pt
.x
+= Parent
->ClientRect
.left
;
1293 Pt
.y
+= Parent
->ClientRect
.top
;
1296 if(!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
))
1298 IntReleaseWindowObject(Parent
);
1302 Ret
= Parent
->hSelf
;
1303 if((List
= IntWinListChildren(Parent
)))
1305 for(phWnd
= List
; *phWnd
; phWnd
++)
1307 PWINDOW_OBJECT Child
;
1308 if((Child
= IntGetWindowObject(*phWnd
)))
1310 if(!(Child
->Style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
))
1312 IntReleaseWindowObject(Child
);
1315 if((Child
->Style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
))
1317 IntReleaseWindowObject(Child
);
1320 if((Child
->ExStyle
& WS_EX_TRANSPARENT
) && (uiFlags
& CWP_SKIPTRANSPARENT
))
1322 IntReleaseWindowObject(Child
);
1325 if(IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
1328 IntReleaseWindowObject(Child
);
1331 IntReleaseWindowObject(Child
);
1337 IntReleaseWindowObject(Parent
);
1343 * calculates the default position of a window
1346 IntCalcDefPosSize(PWINDOW_OBJECT Parent
, PWINDOW_OBJECT Window
, RECT
*rc
, BOOL IncPos
)
1353 IntGdiIntersectRect(rc
, rc
, &Parent
->ClientRect
);
1357 Pos
.x
= Parent
->TiledCounter
* (UserGetSystemMetrics(SM_CXSIZE
) + UserGetSystemMetrics(SM_CXFRAME
));
1358 Pos
.y
= Parent
->TiledCounter
* (UserGetSystemMetrics(SM_CYSIZE
) + UserGetSystemMetrics(SM_CYFRAME
));
1359 if(Pos
.x
> ((rc
->right
- rc
->left
) / 4) ||
1360 Pos
.y
> ((rc
->bottom
- rc
->top
) / 4))
1362 /* reset counter and position */
1365 Parent
->TiledCounter
= 0;
1367 Parent
->TiledCounter
++;
1378 Sz
.cx
= EngMulDiv(rc
->right
- rc
->left
, 3, 4);
1379 Sz
.cy
= EngMulDiv(rc
->bottom
- rc
->top
, 3, 4);
1383 rc
->right
= rc
->left
+ Sz
.cx
;
1384 rc
->bottom
= rc
->top
+ Sz
.cy
;
1393 co_IntCreateWindowEx(DWORD dwExStyle
,
1394 PUNICODE_STRING ClassName
,
1395 PUNICODE_STRING WindowName
,
1403 HINSTANCE hInstance
,
1406 BOOL bUnicodeWindow
)
1408 PWINSTATION_OBJECT WinSta
;
1409 PWNDCLASS_OBJECT Class
;
1410 PWINDOW_OBJECT Window
;
1411 PWINDOW_OBJECT ParentWindow
, OwnerWindow
;
1412 HWND ParentWindowHandle
;
1413 HWND OwnerWindowHandle
;
1414 PMENU_OBJECT SystemMenu
;
1419 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1424 CBT_CREATEWNDW CbtCreate
;
1431 ParentWindowHandle
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
1432 OwnerWindowHandle
= NULL
;
1434 if (hWndParent
== HWND_MESSAGE
)
1437 * native ole32.OleInitialize uses HWND_MESSAGE to create the
1438 * message window (style: WS_POPUP|WS_DISABLED)
1440 DPRINT1("FIXME - Parent is HWND_MESSAGE\n");
1442 else if (hWndParent
)
1444 if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1445 ParentWindowHandle
= hWndParent
;
1447 OwnerWindowHandle
= UserGetAncestor(hWndParent
, GA_ROOT
);
1449 else if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1451 return (HWND
)0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1454 if (NULL
!= ParentWindowHandle
)
1456 ParentWindow
= IntGetWindowObject(ParentWindowHandle
);
1460 ParentWindow
= NULL
;
1463 /* FIXME: parent must belong to the current process */
1465 /* Check the class. */
1466 ClassFound
= ClassReferenceClassByNameOrAtom(&Class
, ClassName
->Buffer
, hInstance
);
1469 if (IS_ATOM(ClassName
->Buffer
))
1471 DPRINT1("Class 0x%x not found\n", (DWORD_PTR
) ClassName
->Buffer
);
1475 DPRINT1("Class %wZ not found\n", ClassName
);
1477 if (NULL
!= ParentWindow
)
1479 IntReleaseWindowObject(ParentWindow
);
1481 SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS
);
1485 /* Check the window station. */
1486 if (PsGetWin32Thread()->Desktop
== NULL
)
1488 ClassDereferenceObject(Class
);
1489 if (NULL
!= ParentWindow
)
1491 IntReleaseWindowObject(ParentWindow
);
1493 DPRINT("Thread is not attached to a desktop! Cannot create window!\n");
1496 WinSta
= PsGetWin32Thread()->Desktop
->WindowStation
;
1497 ObReferenceObjectByPointer(WinSta
, KernelMode
, ExWindowStationObjectType
, 0);
1499 /* Create the window object. */
1500 Window
= (PWINDOW_OBJECT
)
1501 ObmCreateObject(gHandleTable
, &Handle
,
1502 otWindow
, sizeof(WINDOW_OBJECT
) + Class
->cbWndExtra
1505 DPRINT("Created object with handle %X\n", Handle
);
1508 ObDereferenceObject(WinSta
);
1509 ClassDereferenceObject(Class
);
1510 if (NULL
!= ParentWindow
)
1512 IntReleaseWindowObject(ParentWindow
);
1514 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1517 ObDereferenceObject(WinSta
);
1519 if (NULL
== PsGetWin32Thread()->Desktop
->DesktopWindow
)
1521 /* If there is no desktop window yet, we must be creating it */
1522 PsGetWin32Thread()->Desktop
->DesktopWindow
= Handle
;
1526 * Fill out the structure describing it.
1528 Window
->Class
= Class
;
1530 InsertTailList(&Class
->ClassWindowsListHead
, &Window
->ClassListEntry
);
1532 Window
->ExStyle
= dwExStyle
;
1533 Window
->Style
= dwStyle
& ~WS_VISIBLE
;
1534 DPRINT("1: Style is now %lx\n", Window
->Style
);
1536 Window
->SystemMenu
= (HMENU
)0;
1537 Window
->ContextHelpId
= 0;
1539 Window
->Instance
= hInstance
;
1540 Window
->hSelf
= Handle
;
1541 if (0 != (dwStyle
& WS_CHILD
))
1543 Window
->IDMenu
= (UINT
) hMenu
;
1547 IntSetMenu(Window
, hMenu
, &MenuChanged
);
1549 Window
->MessageQueue
= PsGetWin32Thread()->MessageQueue
;
1550 IntReferenceMessageQueue(Window
->MessageQueue
);
1551 Window
->Parent
= (ParentWindow
? ParentWindow
->hSelf
: NULL
);
1552 if((OwnerWindow
= IntGetWindowObject(OwnerWindowHandle
)))
1554 Window
->Owner
= OwnerWindowHandle
;
1555 IntReleaseWindowObject(OwnerWindow
);
1558 Window
->Owner
= NULL
;
1561 Window
->UserData
= 0;
1562 if ((((DWORD
)Class
->lpfnWndProcA
& 0xFFFF0000) != 0xFFFF0000)
1563 && (((DWORD
)Class
->lpfnWndProcW
& 0xFFFF0000) != 0xFFFF0000))
1565 Window
->Unicode
= bUnicodeWindow
;
1569 Window
->Unicode
= Class
->Unicode
;
1571 Window
->WndProcA
= Class
->lpfnWndProcA
;
1572 Window
->WndProcW
= Class
->lpfnWndProcW
;
1573 Window
->OwnerThread
= PsGetCurrentThread();
1574 Window
->FirstChild
= NULL
;
1575 Window
->LastChild
= NULL
;
1576 Window
->PrevSibling
= NULL
;
1577 Window
->NextSibling
= NULL
;
1579 /* extra window data */
1580 if (Class
->cbWndExtra
!= 0)
1582 Window
->ExtraData
= (PCHAR
)(Window
+ 1);
1583 Window
->ExtraDataSize
= Class
->cbWndExtra
;
1584 RtlZeroMemory(Window
->ExtraData
, Window
->ExtraDataSize
);
1588 Window
->ExtraData
= NULL
;
1589 Window
->ExtraDataSize
= 0;
1592 InitializeListHead(&Window
->PropListHead
);
1593 InitializeListHead(&Window
->WndObjListHead
);
1595 if (NULL
!= WindowName
->Buffer
)
1597 Window
->WindowName
.MaximumLength
= WindowName
->MaximumLength
;
1598 Window
->WindowName
.Length
= WindowName
->Length
;
1599 Window
->WindowName
.Buffer
= ExAllocatePoolWithTag(PagedPool
, WindowName
->MaximumLength
,
1601 if (NULL
== Window
->WindowName
.Buffer
)
1603 ClassDereferenceObject(Class
);
1604 DPRINT1("Failed to allocate mem for window name\n");
1605 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1608 RtlCopyMemory(Window
->WindowName
.Buffer
, WindowName
->Buffer
, WindowName
->MaximumLength
);
1612 RtlInitUnicodeString(&Window
->WindowName
, NULL
);
1617 * This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1618 * tested for WS_POPUP
1620 if ((dwExStyle
& WS_EX_DLGMODALFRAME
) ||
1621 ((!(dwExStyle
& WS_EX_STATICEDGE
)) &&
1622 (dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
))))
1623 dwExStyle
|= WS_EX_WINDOWEDGE
;
1625 dwExStyle
&= ~WS_EX_WINDOWEDGE
;
1627 /* Correct the window style. */
1628 if (!(dwStyle
& WS_CHILD
))
1630 Window
->Style
|= WS_CLIPSIBLINGS
;
1631 DPRINT("3: Style is now %lx\n", Window
->Style
);
1632 if (!(dwStyle
& WS_POPUP
))
1634 Window
->Style
|= WS_CAPTION
;
1635 Window
->Flags
|= WINDOWOBJECT_NEED_SIZE
;
1636 DPRINT("4: Style is now %lx\n", Window
->Style
);
1640 /* create system menu */
1641 if((Window
->Style
& WS_SYSMENU
) &&
1642 (Window
->Style
& WS_CAPTION
) == WS_CAPTION
)
1644 SystemMenu
= IntGetSystemMenu(Window
, TRUE
, TRUE
);
1647 Window
->SystemMenu
= SystemMenu
->MenuInfo
.Self
;
1648 IntReleaseMenuObject(SystemMenu
);
1652 /* Insert the window into the thread's window list. */
1653 InsertTailList (&PsGetWin32Thread()->WindowListHead
, &Window
->ThreadListEntry
);
1655 /* Allocate a DCE for this window. */
1656 if (dwStyle
& CS_OWNDC
)
1658 Window
->Dce
= DceAllocDCE(Window
->hSelf
, DCE_WINDOW_DC
);
1660 /* FIXME: Handle "CS_CLASSDC" */
1668 Cs
.lpCreateParams
= lpParam
;
1669 Cs
.hInstance
= hInstance
;
1671 Cs
.hwndParent
= ParentWindowHandle
;
1677 Cs
.lpszName
= (LPCWSTR
) WindowName
;
1678 Cs
.lpszClass
= (LPCWSTR
) ClassName
;
1679 Cs
.dwExStyle
= dwExStyle
;
1680 CbtCreate
.lpcs
= &Cs
;
1681 CbtCreate
.hwndInsertAfter
= HWND_TOP
;
1682 if (co_HOOK_CallHooks(WH_CBT
, HCBT_CREATEWND
, (WPARAM
) Handle
, (LPARAM
) &CbtCreate
))
1684 if (NULL
!= ParentWindow
)
1686 IntReleaseWindowObject(ParentWindow
);
1689 /* FIXME - Delete window object and remove it from the thread windows list */
1690 /* FIXME - delete allocated DCE */
1692 ClassDereferenceObject(Class
);
1693 DPRINT1("CBT-hook returned !0\n");
1702 /* default positioning for overlapped windows */
1703 if(!(Window
->Style
& (WS_POPUP
| WS_CHILD
)))
1706 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
1707 BOOL CalculatedDefPosSize
= FALSE
;
1709 IntGetDesktopWorkArea(Window
->OwnerThread
->Tcb
.Win32Thread
->Desktop
, &WorkArea
);
1712 ProcessParams
= PsGetCurrentProcess()->Peb
->ProcessParameters
;
1714 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1716 CalculatedDefPosSize
= IntCalcDefPosSize(ParentWindow
, Window
, &rc
, TRUE
);
1718 if(ProcessParams
->WindowFlags
& STARTF_USEPOSITION
)
1720 ProcessParams
->WindowFlags
&= ~STARTF_USEPOSITION
;
1721 Pos
.x
= WorkArea
.left
+ ProcessParams
->StartingX
;
1722 Pos
.y
= WorkArea
.top
+ ProcessParams
->StartingY
;
1730 /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
1731 y is something else */
1732 if(y
!= CW_USEDEFAULT
&& y
!= CW_USEDEFAULT16
)
1737 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1739 if(!CalculatedDefPosSize
)
1741 IntCalcDefPosSize(ParentWindow
, Window
, &rc
, FALSE
);
1743 if(ProcessParams
->WindowFlags
& STARTF_USESIZE
)
1745 ProcessParams
->WindowFlags
&= ~STARTF_USESIZE
;
1746 Size
.cx
= ProcessParams
->CountX
;
1747 Size
.cy
= ProcessParams
->CountY
;
1751 Size
.cx
= rc
.right
- rc
.left
;
1752 Size
.cy
= rc
.bottom
- rc
.top
;
1755 /* move the window if necessary */
1757 Pos
.x
= max(rc
.left
, 0);
1759 Pos
.y
= max(rc
.top
, 0);
1764 /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
1765 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1770 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1777 /* Initialize the window dimensions. */
1778 Window
->WindowRect
.left
= Pos
.x
;
1779 Window
->WindowRect
.top
= Pos
.y
;
1780 Window
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1781 Window
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1782 if (0 != (Window
->Style
& WS_CHILD
) && ParentWindow
)
1784 IntGdiOffsetRect(&(Window
->WindowRect
), ParentWindow
->ClientRect
.left
,
1785 ParentWindow
->ClientRect
.top
);
1787 Window
->ClientRect
= Window
->WindowRect
;
1790 * Get the size and position of the window.
1792 if ((dwStyle
& WS_THICKFRAME
) || !(dwStyle
& (WS_POPUP
| WS_CHILD
)))
1794 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1796 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1797 co_WinPosGetMinMaxInfo(Window
, &MaxSize
, &MaxPos
, &MinTrack
,
1799 if (MaxSize
.x
< nWidth
) nWidth
= MaxSize
.x
;
1800 if (MaxSize
.y
< nHeight
) nHeight
= MaxSize
.y
;
1801 if (nWidth
< MinTrack
.x
) nWidth
= MinTrack
.x
;
1802 if (nHeight
< MinTrack
.y
) nHeight
= MinTrack
.y
;
1803 if (nWidth
< 0) nWidth
= 0;
1804 if (nHeight
< 0) nHeight
= 0;
1807 Window
->WindowRect
.left
= Pos
.x
;
1808 Window
->WindowRect
.top
= Pos
.y
;
1809 Window
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1810 Window
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1811 if (0 != (Window
->Style
& WS_CHILD
) && ParentWindow
)
1813 IntGdiOffsetRect(&(Window
->WindowRect
), ParentWindow
->ClientRect
.left
,
1814 ParentWindow
->ClientRect
.top
);
1816 Window
->ClientRect
= Window
->WindowRect
;
1818 /* FIXME: Initialize the window menu. */
1820 /* Send a NCCREATE message. */
1826 DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d\n", Cs
.style
, Cs
.dwExStyle
, Cs
.hwndParent
);
1827 DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1828 DPRINT("IntCreateWindowEx(): About to send NCCREATE message.\n");
1829 Result
= co_IntSendMessage(Window
->hSelf
, WM_NCCREATE
, 0, (LPARAM
) &Cs
);
1832 /* FIXME: Cleanup. */
1833 if (NULL
!= ParentWindow
)
1835 IntReleaseWindowObject(ParentWindow
);
1837 DPRINT("IntCreateWindowEx(): NCCREATE message failed.\n");
1841 /* Calculate the non-client size. */
1842 MaxPos
.x
= Window
->WindowRect
.left
;
1843 MaxPos
.y
= Window
->WindowRect
.top
;
1844 DPRINT("IntCreateWindowEx(): About to get non-client size.\n");
1845 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1846 Result
= co_WinPosGetNonClientSize(Window
->hSelf
,
1847 &Window
->WindowRect
,
1848 &Window
->ClientRect
);
1849 IntGdiOffsetRect(&Window
->WindowRect
,
1850 MaxPos
.x
- Window
->WindowRect
.left
,
1851 MaxPos
.y
- Window
->WindowRect
.top
);
1853 if (NULL
!= ParentWindow
)
1855 /* link the window into the parent's child list */
1856 if ((dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
1858 PWINDOW_OBJECT PrevSibling
;
1859 if((PrevSibling
= ParentWindow
->LastChild
))
1860 IntReferenceWindowObject(PrevSibling
);
1861 /* link window as bottom sibling */
1862 IntLinkWindow(Window
, ParentWindow
, PrevSibling
/*prev sibling*/);
1864 IntReleaseWindowObject(PrevSibling
);
1868 /* link window as top sibling (but after topmost siblings) */
1869 PWINDOW_OBJECT InsertAfter
, Sibling
;
1870 if (0 == (dwExStyle
& WS_EX_TOPMOST
))
1873 Sibling
= ParentWindow
->FirstChild
;
1874 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
1876 InsertAfter
= Sibling
;
1877 Sibling
= Sibling
->NextSibling
;
1884 if (NULL
!= InsertAfter
)
1886 IntReferenceWindowObject(InsertAfter
);
1888 IntLinkWindow(Window
, ParentWindow
, InsertAfter
/* prev sibling */);
1889 if (NULL
!= InsertAfter
)
1891 IntReleaseWindowObject(InsertAfter
);
1896 /* Send the WM_CREATE message. */
1897 DPRINT("IntCreateWindowEx(): about to send CREATE message.\n");
1898 Result
= co_IntSendMessage(Window
->hSelf
, WM_CREATE
, 0, (LPARAM
) &Cs
);
1899 if (Result
== (LRESULT
)-1)
1901 /* FIXME: Cleanup. */
1902 if (NULL
!= ParentWindow
)
1904 IntReleaseWindowObject(ParentWindow
);
1906 ClassDereferenceObject(Class
);
1907 DPRINT("IntCreateWindowEx(): send CREATE message failed.\n");
1911 /* Send move and size messages. */
1912 if (!(Window
->Flags
& WINDOWOBJECT_NEED_SIZE
))
1916 DPRINT("IntCreateWindow(): About to send WM_SIZE\n");
1918 if ((Window
->ClientRect
.right
- Window
->ClientRect
.left
) < 0 ||
1919 (Window
->ClientRect
.bottom
- Window
->ClientRect
.top
) < 0)
1921 DPRINT("Sending bogus WM_SIZE\n");
1924 lParam
= MAKE_LONG(Window
->ClientRect
.right
-
1925 Window
->ClientRect
.left
,
1926 Window
->ClientRect
.bottom
-
1927 Window
->ClientRect
.top
);
1928 co_IntSendMessage(Window
->hSelf
, WM_SIZE
, SIZE_RESTORED
,
1931 DPRINT("IntCreateWindow(): About to send WM_MOVE\n");
1933 if (0 != (Window
->Style
& WS_CHILD
) && ParentWindow
)
1935 lParam
= MAKE_LONG(Window
->ClientRect
.left
- ParentWindow
->ClientRect
.left
,
1936 Window
->ClientRect
.top
- ParentWindow
->ClientRect
.top
);
1940 lParam
= MAKE_LONG(Window
->ClientRect
.left
,
1941 Window
->ClientRect
.top
);
1943 co_IntSendMessage(Window
->hSelf
, WM_MOVE
, 0, lParam
);
1945 /* Call WNDOBJ change procs */
1946 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
1949 /* Show or maybe minimize or maximize the window. */
1950 if (Window
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1955 SwFlag
= (Window
->Style
& WS_MINIMIZE
) ? SW_MINIMIZE
:
1957 co_WinPosMinMaximize(Window
, SwFlag
, &NewPos
);
1959 ((Window
->Style
& WS_CHILD
) || UserGetActiveWindow()) ?
1960 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
:
1961 SWP_NOZORDER
| SWP_FRAMECHANGED
;
1962 DPRINT("IntCreateWindow(): About to minimize/maximize\n");
1963 DPRINT("%d,%d %dx%d\n", NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
);
1964 co_WinPosSetWindowPos(Window
->hSelf
, 0, NewPos
.left
, NewPos
.top
,
1965 NewPos
.right
, NewPos
.bottom
, SwFlag
);
1968 /* Notify the parent window of a new child. */
1969 if ((Window
->Style
& WS_CHILD
) &&
1970 (!(Window
->ExStyle
& WS_EX_NOPARENTNOTIFY
)) && ParentWindow
)
1972 DPRINT("IntCreateWindow(): About to notify parent\n");
1973 co_IntSendMessage(ParentWindow
->hSelf
,
1975 MAKEWPARAM(WM_CREATE
, Window
->IDMenu
),
1976 (LPARAM
)Window
->hSelf
);
1979 if ((!hWndParent
) && (!HasOwner
)) {
1980 DPRINT("Sending CREATED notify\n");
1981 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Handle
);
1983 DPRINT("Not sending CREATED notify, %x %d\n", ParentWindow
, HasOwner
);
1986 if (NULL
!= ParentWindow
)
1988 IntReleaseWindowObject(ParentWindow
);
1991 /* Initialize and show the window's scrollbars */
1992 if (Window
->Style
& WS_VSCROLL
)
1994 co_UserShowScrollBar(Window
->hSelf
, SB_VERT
, TRUE
);
1996 if (Window
->Style
& WS_HSCROLL
)
1998 co_UserShowScrollBar(Window
->hSelf
, SB_HORZ
, TRUE
);
2001 if (dwStyle
& WS_VISIBLE
)
2003 DPRINT("IntCreateWindow(): About to show window\n");
2004 co_WinPosShowWindow(Window
->hSelf
, dwShowMode
);
2007 DPRINT("IntCreateWindow(): = %X\n", Handle
);
2008 DPRINT("WindowObject->SystemMenu = 0x%x\n", Window
->SystemMenu
);
2009 return((HWND
)Handle
);
2013 NtUserCreateWindowEx(DWORD dwExStyle
,
2014 PUNICODE_STRING UnsafeClassName
,
2015 PUNICODE_STRING UnsafeWindowName
,
2023 HINSTANCE hInstance
,
2026 BOOL bUnicodeWindow
)
2029 UNICODE_STRING WindowName
;
2030 UNICODE_STRING ClassName
;
2032 DECLARE_RETURN(HWND
);
2034 DPRINT("Enter NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
2035 UserEnterExclusive();
2037 /* Get the class name (string or atom) */
2038 Status
= MmCopyFromCaller(&ClassName
, UnsafeClassName
, sizeof(UNICODE_STRING
));
2039 if (! NT_SUCCESS(Status
))
2041 SetLastNtError(Status
);
2044 if (! IS_ATOM(ClassName
.Buffer
))
2046 Status
= IntSafeCopyUnicodeStringTerminateNULL(&ClassName
, UnsafeClassName
);
2047 if (! NT_SUCCESS(Status
))
2049 SetLastNtError(Status
);
2054 /* safely copy the window name */
2055 if (NULL
!= UnsafeWindowName
)
2057 Status
= IntSafeCopyUnicodeString(&WindowName
, UnsafeWindowName
);
2058 if (! NT_SUCCESS(Status
))
2060 if (! IS_ATOM(ClassName
.Buffer
))
2062 RtlFreeUnicodeString(&ClassName
);
2064 SetLastNtError(Status
);
2070 RtlInitUnicodeString(&WindowName
, NULL
);
2073 NewWindow
= co_IntCreateWindowEx(dwExStyle
, &ClassName
, &WindowName
, dwStyle
, x
, y
, nWidth
, nHeight
,
2074 hWndParent
, hMenu
, hInstance
, lpParam
, dwShowMode
, bUnicodeWindow
);
2076 RtlFreeUnicodeString(&WindowName
);
2077 if (! IS_ATOM(ClassName
.Buffer
))
2079 RtlFreeUnicodeString(&ClassName
);
2085 DPRINT("Leave NtUserCreateWindowEx, ret=%i\n",_ret_
);
2094 NtUserDeferWindowPos(HDWP WinPosInfo
,
2096 HWND WndInsertAfter
,
2109 BOOLEAN FASTCALL
co_UserDestroyWindow(PWINDOW_OBJECT Window
)
2118 /* Check for owner thread and desktop window */
2119 if ((Window
->OwnerThread
!= PsGetCurrentThread()) || IntIsDesktopWindow(Window
))
2121 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2125 /* Look whether the focus is within the tree of windows we will
2128 if (!co_WinPosShowWindow(Window
->hSelf
, SW_HIDE
))
2130 if (UserGetActiveWindow() == Window
->hSelf
)
2132 co_WinPosActivateOtherWindow(Window
);
2136 if (Window
->MessageQueue
->ActiveWindow
== Window
->hSelf
)
2137 Window
->MessageQueue
->ActiveWindow
= NULL
;
2138 if (Window
->MessageQueue
->FocusWindow
== Window
->hSelf
)
2139 Window
->MessageQueue
->FocusWindow
= NULL
;
2140 if (Window
->MessageQueue
->CaptureWindow
== Window
->hSelf
)
2141 Window
->MessageQueue
->CaptureWindow
= NULL
;
2143 IntDereferenceMessageQueue(Window
->MessageQueue
);
2146 if (co_HOOK_CallHooks(WH_CBT
, HCBT_DESTROYWND
, (WPARAM
) hwnd
, 0, TRUE
))
2152 IntEngWindowChanged(Window
, WOC_DELETE
);
2153 isChild
= (0 != (Window
->Style
& WS_CHILD
));
2158 if (! USER_IsExitingThread(GetCurrentThreadId()))
2160 send_parent_notify(hwnd
, WM_DESTROY
);
2163 else if (NULL
!= GetWindow(Wnd
, GW_OWNER
))
2165 co_HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
2166 /* FIXME: clean up palette - see "Internals" p.352 */
2170 if (!IntIsWindow(Window
->hSelf
))
2175 /* Recursively destroy owned windows */
2180 BOOL GotOne
= FALSE
;
2183 PWINDOW_OBJECT Child
, Desktop
;
2185 Desktop
= IntGetWindowObject(IntGetDesktopWindow());
2186 Children
= IntWinListChildren(Desktop
);
2187 IntReleaseWindowObject(Desktop
);
2190 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
2192 Child
= IntGetWindowObject(*ChildHandle
);
2195 if (Child
->Owner
!= Window
->hSelf
)
2197 IntReleaseWindowObject(Child
);
2201 if (IntWndBelongsToThread(Child
, PsGetWin32Thread()))
2203 co_UserDestroyWindow(Child
);
2204 IntReleaseWindowObject(Child
);
2209 if (Child
->Owner
!= NULL
)
2211 Child
->Owner
= NULL
;
2214 IntReleaseWindowObject(Child
);
2216 ExFreePool(Children
);
2225 if (!IntIsWindow(Window
->hSelf
))
2230 /* Destroy the window storage */
2231 co_IntDestroyWindow(Window
, PsGetWin32Process(), PsGetWin32Thread(), TRUE
);
2243 NtUserDestroyWindow(HWND Wnd
)
2245 PWINDOW_OBJECT Window
;
2246 DECLARE_RETURN(BOOLEAN
);
2248 DPRINT("Enter NtUserDestroyWindow\n");
2249 UserEnterExclusive();
2251 Window
= IntGetWindowObject(Wnd
);
2257 RETURN(co_UserDestroyWindow(Window
));
2260 DPRINT("Leave NtUserDestroyWindow, ret=%i\n",_ret_
);
2272 NtUserDrawMenuBarTemp(
2279 /* we'll use this function just for caching the menu bar */
2289 NtUserEndDeferWindowPosEx(DWORD Unknown0
,
2302 NtUserFillWindow(DWORD Unknown0
,
2314 IntFindWindow(PWINDOW_OBJECT Parent
,
2315 PWINDOW_OBJECT ChildAfter
,
2317 PUNICODE_STRING WindowName
)
2319 BOOL CheckWindowName
;
2325 CheckWindowName
= (WindowName
&& (WindowName
->Length
> 0));
2327 if((List
= IntWinListChildren(Parent
)))
2332 /* skip handles before and including ChildAfter */
2333 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->hSelf
));
2336 /* search children */
2339 PWINDOW_OBJECT Child
;
2340 if(!(Child
= IntGetWindowObject(*(phWnd
++))))
2345 /* Do not send WM_GETTEXT messages in the kernel mode version!
2346 The user mode version however calls GetWindowText() which will
2347 send WM_GETTEXT messages to windows belonging to its processes */
2348 if((!CheckWindowName
|| !RtlCompareUnicodeString(WindowName
, &(Child
->WindowName
), FALSE
)) &&
2349 (!ClassAtom
|| Child
->Class
->Atom
== ClassAtom
))
2352 IntReleaseWindowObject(Child
);
2356 IntReleaseWindowObject(Child
);
2366 * Searches a window's children for a window with the specified
2369 * hwndParent = The window whose childs are to be searched.
2371 * HWND_MESSAGE = message-only windows
2373 * hwndChildAfter = Search starts after this child window.
2374 * NULL = start from beginning
2376 * ucClassName = Class name to search for
2377 * Reguired parameter.
2379 * ucWindowName = Window name
2380 * ->Buffer == NULL = don't care
2383 * The HWND of the window if it was found, otherwise NULL
2389 NtUserFindWindowEx(HWND hwndParent
,
2390 HWND hwndChildAfter
,
2391 PUNICODE_STRING ucClassName
,
2392 PUNICODE_STRING ucWindowName
)
2394 PWINDOW_OBJECT Parent
, ChildAfter
;
2395 UNICODE_STRING ClassName
, WindowName
;
2397 HWND Desktop
, Ret
= NULL
;
2399 DECLARE_RETURN(HWND
);
2401 DPRINT("Enter NtUserFindWindowEx\n");
2404 Desktop
= IntGetCurrentThreadDesktopWindow();
2406 if(hwndParent
== NULL
)
2407 hwndParent
= Desktop
;
2409 else if(hwndParent == HWND_MESSAGE)
2411 hwndParent = IntGetMessageWindow();
2415 if(!(Parent
= IntGetWindowObject(hwndParent
)))
2417 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2422 if(hwndChildAfter
&& !(ChildAfter
= IntGetWindowObject(hwndChildAfter
)))
2424 IntReleaseWindowObject(Parent
);
2425 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2429 /* copy the window name */
2430 Status
= IntSafeCopyUnicodeString(&WindowName
, ucWindowName
);
2431 if(!NT_SUCCESS(Status
))
2433 SetLastNtError(Status
);
2437 /* safely copy the class name */
2438 Status
= MmCopyFromCaller(&ClassName
, ucClassName
, sizeof(UNICODE_STRING
));
2439 if(!NT_SUCCESS(Status
))
2441 SetLastNtError(Status
);
2444 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2447 /* safely copy the class name string (NULL terminated because class-lookup
2449 buf
= ExAllocatePoolWithTag(PagedPool
, ClassName
.Length
+ sizeof(WCHAR
), TAG_STRING
);
2452 SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES
);
2455 Status
= MmCopyFromCaller(buf
, ClassName
.Buffer
, ClassName
.Length
);
2456 if(!NT_SUCCESS(Status
))
2459 SetLastNtError(Status
);
2462 ClassName
.Buffer
= buf
;
2463 /* make sure the string is null-terminated */
2464 buf
+= ClassName
.Length
/ sizeof(WCHAR
);
2468 /* find the class object */
2469 if(ClassName
.Buffer
)
2471 PWINSTATION_OBJECT WinStaObject
;
2473 if (PsGetWin32Thread()->Desktop
== NULL
)
2475 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2479 WinStaObject
= PsGetWin32Thread()->Desktop
->WindowStation
;
2481 Status
= RtlLookupAtomInAtomTable(
2482 WinStaObject
->AtomTable
,
2486 if (!NT_SUCCESS(Status
))
2488 DPRINT1("Failed to lookup class atom!\n");
2489 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST
);
2494 if(Parent
->hSelf
== Desktop
)
2497 PWINDOW_OBJECT TopLevelWindow
;
2498 BOOLEAN CheckWindowName
;
2499 BOOLEAN CheckClassName
;
2500 BOOLEAN WindowMatches
;
2501 BOOLEAN ClassMatches
;
2503 /* windows searches through all top-level windows if the parent is the desktop
2506 if((List
= IntWinListChildren(Parent
)))
2512 /* skip handles before and including ChildAfter */
2513 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->hSelf
));
2516 CheckWindowName
= WindowName
.Length
> 0;
2517 CheckClassName
= ClassName
.Buffer
!= NULL
;
2519 /* search children */
2522 if(!(TopLevelWindow
= IntGetWindowObject(*(phWnd
++))))
2527 /* Do not send WM_GETTEXT messages in the kernel mode version!
2528 The user mode version however calls GetWindowText() which will
2529 send WM_GETTEXT messages to windows belonging to its processes */
2530 WindowMatches
= !CheckWindowName
|| !RtlCompareUnicodeString(
2531 &WindowName
, &TopLevelWindow
->WindowName
, FALSE
);
2532 ClassMatches
= !CheckClassName
||
2533 ClassAtom
== TopLevelWindow
->Class
->Atom
;
2535 if (WindowMatches
&& ClassMatches
)
2537 Ret
= TopLevelWindow
->hSelf
;
2538 IntReleaseWindowObject(TopLevelWindow
);
2542 if (IntFindWindow(TopLevelWindow
, NULL
, ClassAtom
, &WindowName
))
2544 /* window returns the handle of the top-level window, in case it found
2546 Ret
= TopLevelWindow
->hSelf
;
2547 IntReleaseWindowObject(TopLevelWindow
);
2551 IntReleaseWindowObject(TopLevelWindow
);
2557 Ret
= IntFindWindow(Parent
, ChildAfter
, ClassAtom
, &WindowName
);
2560 if(Ret
== NULL
&& hwndParent
== NULL
&& hwndChildAfter
== NULL
)
2562 /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
2563 search the message-only windows. Should this also be done if
2564 Parent is the desktop window??? */
2565 PWINDOW_OBJECT MsgWindows
;
2567 if((MsgWindows
= IntGetWindowObject(IntGetMessageWindow())))
2569 Ret
= IntFindWindow(MsgWindows
, ChildAfter
, ClassAtom
, &WindowName
);
2570 IntReleaseWindowObject(MsgWindows
);
2576 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2577 ExFreePool(ClassName
.Buffer
);
2580 RtlFreeUnicodeString(&WindowName
);
2584 IntReleaseWindowObject(ChildAfter
);
2585 IntReleaseWindowObject(Parent
);
2590 DPRINT("Leave NtUserFindWindowEx, ret %i\n",_ret_
);
2600 NtUserFlashWindowEx(DWORD Unknown0
)
2611 HWND FASTCALL
UserGetAncestor(HWND hWnd
, UINT Type
)
2613 PWINDOW_OBJECT Wnd
, WndAncestor
, Parent
;
2616 if (hWnd
== IntGetDesktopWindow())
2621 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2623 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2631 WndAncestor
= IntGetParentObject(Wnd
);
2644 if(!(Parent
= IntGetParentObject(WndAncestor
)))
2648 if(IntIsDesktopWindow(Parent
))
2650 IntReleaseWindowObject(Parent
);
2654 IntReleaseWindowObject(tmp
);
2655 WndAncestor
= Parent
;
2663 IntReferenceWindowObject(WndAncestor
);
2668 Parent
= IntGetParent(WndAncestor
);
2669 IntReleaseWindowObject(Old
);
2674 WndAncestor
= Parent
;
2681 IntReleaseWindowObject(Wnd
);
2686 hWndAncestor
= (WndAncestor
? WndAncestor
->hSelf
: NULL
);
2687 IntReleaseWindowObject(Wnd
);
2689 if(WndAncestor
&& (WndAncestor
!= Wnd
))
2690 IntReleaseWindowObject(WndAncestor
);
2692 return hWndAncestor
;
2701 NtUserGetAncestor(HWND hWnd
, UINT Type
)
2703 DECLARE_RETURN(HWND
);
2705 DPRINT("Enter NtUserGetAncestor\n");
2706 UserEnterExclusive();
2708 RETURN(UserGetAncestor(hWnd
, Type
));
2711 DPRINT("Leave NtUserGetAncestor, ret=%i\n",_ret_
);
2717 * Returns client window rectangle relative to the upper-left corner of client area.
2719 * \param hWnd window handle.
2720 * \param Rect pointer to the buffer where the coordinates are returned.
2727 NtUserGetClientRect(HWND hWnd
, LPRECT Rect
)
2729 PWINDOW_OBJECT Window
;
2731 DECLARE_RETURN(BOOL
);
2733 DPRINT("Enter NtUserGetClientRect\n");
2736 if(!(Window
= IntGetWindowObject(hWnd
)))
2738 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2742 IntGetClientRect(Window
, &SafeRect
);
2743 IntReleaseWindowObject(Window
);
2745 if(!NT_SUCCESS(MmCopyToCaller(Rect
, &SafeRect
, sizeof(RECT
))))
2752 DPRINT("Leave NtUserGetClientRect, ret=%i\n",_ret_
);
2762 NtUserGetDesktopWindow()
2764 DECLARE_RETURN(HWND
);
2766 DPRINT("Enter NtUserGetDesktopWindow\n");
2769 RETURN( IntGetDesktopWindow());
2772 DPRINT("Leave NtUserGetDesktopWindow, ret=%i\n",_ret_
);
2782 NtUserGetInternalWindowPos(DWORD Unknown0
,
2796 NtUserGetLastActivePopup(HWND hWnd
)
2799 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2800 * not changed anywhere.
2801 * -- Filip, 01/nov/2003
2807 IntAcquireWinLockShared();
2809 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2811 IntReleaseWinLock();
2812 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2816 hWndLastPopup
= Wnd
->hWndLastPopup
;
2818 IntReleaseWinLock();
2820 return hWndLastPopup
;
2829 * The NtUserGetParent function retrieves a handle to the specified window's
2833 * Note that, despite its name, this function can return an owner window
2834 * instead of a parent window.
2841 NtUserGetParent(HWND hWnd
)
2843 PWINDOW_OBJECT Wnd
, WndParent
;
2844 HWND hWndParent
= NULL
;
2845 DECLARE_RETURN(HWND
);
2847 DPRINT("Enter NtUserGetParent\n");
2848 UserEnterExclusive();
2850 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2852 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2856 WndParent
= IntGetParent(Wnd
);
2859 hWndParent
= WndParent
->hSelf
;
2860 IntReleaseWindowObject(WndParent
);
2863 IntReleaseWindowObject(Wnd
);
2865 RETURN( hWndParent
);
2868 DPRINT("Leave NtUserGetParent, ret=%i\n",_ret_
);
2877 UserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2879 PWINDOW_OBJECT Wnd
= NULL
, WndParent
= NULL
, WndOldParent
;
2880 HWND hWndOldParent
= NULL
;
2882 if (IntIsBroadcastHwnd(hWndChild
) || IntIsBroadcastHwnd(hWndNewParent
))
2884 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2888 if (hWndChild
== IntGetDesktopWindow())
2890 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2896 if (!(WndParent
= IntGetWindowObject(hWndNewParent
)))
2898 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2904 if (!(WndParent
= IntGetWindowObject(IntGetDesktopWindow())))
2906 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2911 if (!(Wnd
= IntGetWindowObject(hWndChild
)))
2913 IntReleaseWindowObject(WndParent
);
2914 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2918 WndOldParent
= IntSetParent(Wnd
, WndParent
);
2922 hWndOldParent
= WndOldParent
->hSelf
;
2923 IntReleaseWindowObject(WndOldParent
);
2926 IntReleaseWindowObject(Wnd
);
2927 IntReleaseWindowObject(WndParent
);
2929 return( hWndOldParent
);
2937 * The NtUserSetParent function changes the parent window of the specified
2941 * The new parent window and the child window must belong to the same
2942 * application. If the window identified by the hWndChild parameter is
2943 * visible, the system performs the appropriate redrawing and repainting.
2944 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2945 * or WS_POPUP window styles of the window whose parent is being changed.
2952 NtUserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2954 DECLARE_RETURN(HWND
);
2956 DPRINT("Enter NtUserSetParent\n");
2957 UserEnterExclusive();
2959 RETURN( UserSetParent(hWndChild
, hWndNewParent
));
2962 DPRINT("Leave NtUserSetParent, ret=%i\n",_ret_
);
2970 HWND FASTCALL
UserGetShellWindow()
2972 PWINSTATION_OBJECT WinStaObject
;
2975 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
2980 if (!NT_SUCCESS(Status
))
2982 SetLastNtError(Status
);
2986 Ret
= (HWND
)WinStaObject
->ShellWindow
;
2988 ObDereferenceObject(WinStaObject
);
2994 * NtUserGetShellWindow
2996 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
3003 NtUserGetShellWindow()
3005 DECLARE_RETURN(HWND
);
3007 DPRINT("Enter NtUserGetShellWindow\n");
3010 RETURN( UserGetShellWindow() );
3013 DPRINT("Leave NtUserGetShellWindow, ret=%i\n",_ret_
);
3019 * NtUserSetShellWindowEx
3021 * This is undocumented function to set global shell window. The global
3022 * shell window has special handling of window position.
3029 NtUserSetShellWindowEx(HWND hwndShell
, HWND hwndListView
)
3031 PWINSTATION_OBJECT WinStaObject
;
3032 DECLARE_RETURN(BOOL
);
3034 DPRINT("Enter NtUserSetShellWindowEx\n");
3035 UserEnterExclusive();
3037 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
3042 if (!NT_SUCCESS(Status
))
3044 SetLastNtError(Status
);
3049 * Test if we are permitted to change the shell window.
3051 if (WinStaObject
->ShellWindow
)
3053 ObDereferenceObject(WinStaObject
);
3058 * Move shell window into background.
3060 if (hwndListView
&& hwndListView
!= hwndShell
)
3063 * Disabled for now to get Explorer working.
3064 * -- Filip, 01/nov/2003
3067 co_WinPosSetWindowPos(hwndListView
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
3070 if (UserGetWindowLong(hwndListView
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
3072 ObDereferenceObject(WinStaObject
);
3077 if (UserGetWindowLong(hwndShell
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
3079 ObDereferenceObject(WinStaObject
);
3083 co_WinPosSetWindowPos(hwndShell
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
3085 WinStaObject
->ShellWindow
= hwndShell
;
3086 WinStaObject
->ShellListView
= hwndListView
;
3088 ObDereferenceObject(WinStaObject
);
3092 DPRINT("Leave NtUserSetShellWindowEx, ret=%i\n",_ret_
);
3098 * NtUserGetSystemMenu
3100 * The NtUserGetSystemMenu function allows the application to access the
3101 * window menu (also known as the system menu or the control menu) for
3102 * copying and modifying.
3106 * Handle to the window that will own a copy of the window menu.
3108 * Specifies the action to be taken. If this parameter is FALSE,
3109 * NtUserGetSystemMenu returns a handle to the copy of the window menu
3110 * currently in use. The copy is initially identical to the window menu
3111 * but it can be modified.
3112 * If this parameter is TRUE, GetSystemMenu resets the window menu back
3113 * to the default state. The previous window menu, if any, is destroyed.
3116 * If the bRevert parameter is FALSE, the return value is a handle to a
3117 * copy of the window menu. If the bRevert parameter is TRUE, the return
3125 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
3128 PWINDOW_OBJECT Window
;
3130 DECLARE_RETURN(HMENU
);
3132 DPRINT("Enter NtUserGetSystemMenu\n");
3135 if (!(Window
= IntGetWindowObject(hWnd
)))
3137 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3141 if (!(Menu
= IntGetSystemMenu(Window
, bRevert
, FALSE
)))
3143 Result
= Menu
->MenuInfo
.Self
;
3144 IntReleaseMenuObject(Menu
);
3147 IntReleaseWindowObject(Window
);
3151 DPRINT("Leave NtUserGetSystemMenu, ret=%i\n",_ret_
);
3157 * NtUserSetSystemMenu
3164 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
3166 BOOL Result
= FALSE
;
3167 PWINDOW_OBJECT Window
;
3169 DECLARE_RETURN(BOOL
);
3171 DPRINT("Enter NtUserSetSystemMenu\n");
3172 UserEnterExclusive();
3174 if (!(Window
= IntGetWindowObject(hWnd
)))
3176 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3183 * Assign new menu handle.
3185 Menu
= IntGetMenuObject(hMenu
);
3188 IntReleaseWindowObject(Window
);
3189 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
3193 Result
= IntSetSystemMenu(Window
, Menu
);
3195 IntReleaseMenuObject(Menu
);
3198 IntReleaseWindowObject(Window
);
3203 DPRINT("Leave NtUserSetSystemMenu, ret=%i\n",_ret_
);
3212 UserGetWindow(HWND hWnd
, UINT Relationship
)
3214 PWINDOW_OBJECT Parent
, Window
;
3215 HWND hWndResult
= NULL
;
3217 if (!(Window
= IntGetWindowObject(hWnd
))) return NULL
;
3219 switch (Relationship
)
3222 if((Parent
= IntGetParentObject(Window
)))
3224 if (Parent
->FirstChild
)
3225 hWndResult
= Parent
->FirstChild
->hSelf
;
3227 IntReleaseWindowObject(Parent
);
3232 if((Parent
= IntGetParentObject(Window
)))
3234 if (Parent
->LastChild
)
3235 hWndResult
= Parent
->LastChild
->hSelf
;
3237 IntReleaseWindowObject(Parent
);
3242 if (Window
->NextSibling
)
3243 hWndResult
= Window
->NextSibling
->hSelf
;
3247 if (Window
->PrevSibling
)
3248 hWndResult
= Window
->PrevSibling
->hSelf
;
3252 if((Parent
= IntGetWindowObject(Window
->Owner
)))
3254 hWndResult
= Parent
->hSelf
;
3255 IntReleaseWindowObject(Parent
);
3259 if (Window
->FirstChild
)
3260 hWndResult
= Window
->FirstChild
->hSelf
;
3264 IntReleaseWindowObject(Window
);
3274 * The NtUserGetWindow function retrieves a handle to a window that has the
3275 * specified relationship (Z order or owner) to the specified window.
3282 NtUserGetWindow(HWND hWnd
, UINT Relationship
)
3284 DECLARE_RETURN(HWND
);
3286 DPRINT("Enter NtUserGetWindow\n");
3289 RETURN(UserGetWindow(hWnd
, Relationship
));
3292 DPRINT("Leave NtUserGetWindow, ret=%i\n",_ret_
);
3301 * NtUserGetWindowLong
3303 * The NtUserGetWindowLong function retrieves information about the specified
3304 * window. The function also retrieves the 32-bit (long) value at the
3305 * specified offset into the extra window memory.
3312 UserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3314 PWINDOW_OBJECT Window
, Parent
;
3317 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3319 if (!(Window
= IntGetWindowObject(hWnd
)))
3321 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3326 * WndProc is only available to the owner process
3328 if (GWL_WNDPROC
== Index
3329 && Window
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
3331 SetLastWin32Error(ERROR_ACCESS_DENIED
);
3335 if ((INT
)Index
>= 0)
3337 if ((Index
+ sizeof(LONG
)) > Window
->ExtraDataSize
)
3339 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3342 Result
= *((LONG
*)(Window
->ExtraData
+ Index
));
3349 Result
= Window
->ExStyle
;
3353 Result
= Window
->Style
;
3358 Result
= (LONG
) Window
->WndProcA
;
3360 Result
= (LONG
) Window
->WndProcW
;
3364 Result
= (LONG
) Window
->Instance
;
3367 case GWL_HWNDPARENT
:
3368 Parent
= IntGetWindowObject(Window
->Parent
);
3371 if (Parent
&& Parent
->hSelf
== IntGetDesktopWindow())
3372 Result
= (LONG
) UserGetWindow(Window
->hSelf
, GW_OWNER
);
3374 Result
= (LONG
) Parent
->hSelf
;
3375 IntReleaseWindowObject(Parent
);
3380 Result
= (LONG
) Window
->IDMenu
;
3384 Result
= Window
->UserData
;
3388 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index
);
3389 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3395 IntReleaseWindowObject(Window
);
3404 * NtUserGetWindowLong
3406 * The NtUserGetWindowLong function retrieves information about the specified
3407 * window. The function also retrieves the 32-bit (long) value at the
3408 * specified offset into the extra window memory.
3415 NtUserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3417 DECLARE_RETURN(LONG
);
3419 DPRINT("Enter NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3420 UserEnterExclusive();
3422 RETURN(UserGetWindowLong(hWnd
, Index
, Ansi
));
3425 DPRINT("Leave NtUserGetWindowLong, ret=%i\n",_ret_
);
3434 UserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3436 PWINDOW_OBJECT Window
, Parent
;
3437 PWINSTATION_OBJECT WindowStation
;
3441 if (hWnd
== IntGetDesktopWindow())
3443 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3447 if (!(Window
= IntGetWindowObject(hWnd
)))
3449 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3453 if ((INT
)Index
>= 0)
3455 if ((Index
+ sizeof(LONG
)) > Window
->ExtraDataSize
)
3457 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3458 IntReleaseWindowObject(Window
);
3461 OldValue
= *((LONG
*)(Window
->ExtraData
+ Index
));
3462 *((LONG
*)(Window
->ExtraData
+ Index
)) = NewValue
;
3469 OldValue
= (LONG
) Window
->ExStyle
;
3470 Style
.styleOld
= OldValue
;
3471 Style
.styleNew
= NewValue
;
3474 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3476 WindowStation
= Window
->OwnerThread
->Tcb
.Win32Thread
->Desktop
->WindowStation
;
3479 if (hWnd
== WindowStation
->ShellWindow
|| hWnd
== WindowStation
->ShellListView
)
3480 Style
.styleNew
&= ~WS_EX_TOPMOST
;
3483 co_IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3484 Window
->ExStyle
= (DWORD
)Style
.styleNew
;
3485 co_IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3489 OldValue
= (LONG
) Window
->Style
;
3490 Style
.styleOld
= OldValue
;
3491 Style
.styleNew
= NewValue
;
3492 co_IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_STYLE
, (LPARAM
) &Style
);
3493 Window
->Style
= (DWORD
)Style
.styleNew
;
3494 co_IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_STYLE
, (LPARAM
) &Style
);
3498 /* FIXME: should check if window belongs to current process */
3501 OldValue
= (LONG
) Window
->WndProcA
;
3502 Window
->WndProcA
= (WNDPROC
) NewValue
;
3503 Window
->WndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,FALSE
);
3504 Window
->Unicode
= FALSE
;
3508 OldValue
= (LONG
) Window
->WndProcW
;
3509 Window
->WndProcW
= (WNDPROC
) NewValue
;
3510 Window
->WndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,TRUE
);
3511 Window
->Unicode
= TRUE
;
3516 OldValue
= (LONG
) Window
->Instance
;
3517 Window
->Instance
= (HINSTANCE
) NewValue
;
3520 case GWL_HWNDPARENT
:
3521 Parent
= IntGetParentObject(Window
);
3522 if (Parent
&& (Parent
->hSelf
== IntGetDesktopWindow()))
3523 OldValue
= (LONG
) IntSetOwner(Window
->hSelf
, (HWND
) NewValue
);
3525 OldValue
= (LONG
) UserSetParent(Window
->hSelf
, (HWND
) NewValue
);
3527 IntReleaseWindowObject(Parent
);
3531 OldValue
= (LONG
) Window
->IDMenu
;
3532 Window
->IDMenu
= (UINT
) NewValue
;
3536 OldValue
= Window
->UserData
;
3537 Window
->UserData
= NewValue
;
3541 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index
);
3542 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3548 IntReleaseWindowObject(Window
);
3556 * NtUserSetWindowLong
3558 * The NtUserSetWindowLong function changes an attribute of the specified
3559 * window. The function also sets the 32-bit (long) value at the specified
3560 * offset into the extra window memory.
3567 NtUserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3569 DECLARE_RETURN(LONG
);
3571 DPRINT("Enter NtUserSetWindowLong\n");
3572 UserEnterExclusive();
3574 RETURN( UserSetWindowLong(hWnd
, Index
, NewValue
, Ansi
));
3577 DPRINT("Leave NtUserSetWindowLong, ret=%i\n",_ret_
);
3583 * NtUserSetWindowWord
3585 * Legacy function similar to NtUserSetWindowLong.
3592 NtUserSetWindowWord(HWND hWnd
, INT Index
, WORD NewValue
)
3594 PWINDOW_OBJECT Window
;
3596 DECLARE_RETURN(WORD
);
3598 DPRINT("Enter NtUserSetWindowWord\n");
3599 UserEnterExclusive();
3605 case GWL_HWNDPARENT
:
3606 RETURN( UserSetWindowLong(hWnd
, Index
, (UINT
)NewValue
, TRUE
));
3610 SetLastWin32Error(ERROR_INVALID_INDEX
);
3615 if (!(Window
= IntGetWindowObject(hWnd
)))
3617 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3621 if (Index
> Window
->ExtraDataSize
- sizeof(WORD
))
3623 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3624 IntReleaseWindowObject(Window
);
3628 OldValue
= *((WORD
*)(Window
->ExtraData
+ Index
));
3629 *((WORD
*)(Window
->ExtraData
+ Index
)) = NewValue
;
3631 IntReleaseWindowObject(Window
);
3636 DPRINT("Leave NtUserSetWindowWord, ret=%i\n",_ret_
);
3645 NtUserGetWindowPlacement(HWND hWnd
,
3646 WINDOWPLACEMENT
*lpwndpl
)
3648 PWINDOW_OBJECT Window
;
3649 PINTERNALPOS InternalPos
;
3651 WINDOWPLACEMENT Safepl
;
3653 DECLARE_RETURN(BOOL
);
3655 DPRINT("Enter NtUserGetWindowPlacement\n");
3658 if (!(Window
= IntGetWindowObject(hWnd
)))
3660 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3664 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3665 if(!NT_SUCCESS(Status
))
3667 SetLastNtError(Status
);
3668 IntReleaseWindowObject(Window
);
3671 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3673 IntReleaseWindowObject(Window
);
3678 Safepl
.showCmd
= ((Window
->Flags
& WINDOWOBJECT_RESTOREMAX
) ? SW_MAXIMIZE
: SW_SHOWNORMAL
);
3680 Size
.x
= Window
->WindowRect
.left
;
3681 Size
.y
= Window
->WindowRect
.top
;
3682 InternalPos
= WinPosInitInternalPos(Window
, &Size
,
3683 &Window
->WindowRect
);
3686 Safepl
.rcNormalPosition
= InternalPos
->NormalRect
;
3687 Safepl
.ptMinPosition
= InternalPos
->IconPos
;
3688 Safepl
.ptMaxPosition
= InternalPos
->MaxPos
;
3692 IntReleaseWindowObject(Window
);
3696 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3697 if(!NT_SUCCESS(Status
))
3699 SetLastNtError(Status
);
3700 IntReleaseWindowObject(Window
);
3704 IntReleaseWindowObject(Window
);
3708 DPRINT("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
3715 * Return the dimension of the window in the screen coordinates.
3716 * \param hWnd window handle.
3717 * \param Rect pointer to the buffer where the coordinates are returned.
3723 NtUserGetWindowRect(HWND hWnd
, LPRECT Rect
)
3727 DECLARE_RETURN(BOOL
);
3729 DPRINT("Enter NtUserGetWindowRect\n");
3732 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3734 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3737 Status
= MmCopyToCaller(Rect
, &Wnd
->WindowRect
, sizeof(RECT
));
3738 if (!NT_SUCCESS(Status
))
3740 IntReleaseWindowObject(Wnd
);
3741 SetLastNtError(Status
);
3745 IntReleaseWindowObject(Wnd
);
3749 DPRINT("Leave NtUserGetWindowRect, ret=%i\n",_ret_
);
3759 NtUserGetWindowThreadProcessId(HWND hWnd
, LPDWORD UnsafePid
)
3763 DECLARE_RETURN(DWORD
);
3765 DPRINT("Enter NtUserGetWindowThreadProcessId\n");
3768 if (!(Wnd
= IntGetWindowObject(hWnd
)))
3770 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3774 tid
= (DWORD
)IntGetWndThreadId(Wnd
);
3775 pid
= (DWORD
)IntGetWndProcessId(Wnd
);
3777 if (UnsafePid
) MmCopyToCaller(UnsafePid
, &pid
, sizeof(DWORD
));
3782 DPRINT("Leave NtUserGetWindowThreadProcessId, ret=%i\n",_ret_
);
3792 NtUserLockWindowUpdate(DWORD Unknown0
)
3812 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3813 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3814 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3818 QueryWindow based on KJK::Hyperion and James Tabor.
3820 0 = QWUniqueProcessId
3821 1 = QWUniqueThreadId
3822 4 = QWIsHung Implements IsHungAppWindow found
3825 9 = QWKillWindow When I called this with hWnd ==
3826 DesktopWindow, it shutdown the system
3833 NtUserQueryWindow(HWND hWnd
, DWORD Index
)
3835 PWINDOW_OBJECT Window
= IntGetWindowObject(hWnd
);
3837 DECLARE_RETURN(UINT
);
3839 DPRINT("Enter NtUserQueryWindow\n");
3844 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3850 case QUERY_WINDOW_UNIQUE_PROCESS_ID
:
3851 Result
= (DWORD
)IntGetWndProcessId(Window
);
3854 case QUERY_WINDOW_UNIQUE_THREAD_ID
:
3855 Result
= (DWORD
)IntGetWndThreadId(Window
);
3858 case QUERY_WINDOW_ISHUNG
:
3859 Result
= (DWORD
)MsqIsHung(Window
->MessageQueue
);
3863 Result
= (DWORD
)NULL
;
3867 IntReleaseWindowObject(Window
);
3873 DPRINT("Leave NtUserQueryWindow, ret=%i\n",_ret_
);
3883 NtUserRealChildWindowFromPoint(DWORD Unknown0
,
3897 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe
)
3899 UNICODE_STRING SafeMessageName
;
3902 DECLARE_RETURN(UINT
);
3904 DPRINT("Enter NtUserRegisterWindowMessage\n");
3905 UserEnterExclusive();
3907 if(MessageNameUnsafe
== NULL
)
3909 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3913 Status
= IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName
, MessageNameUnsafe
);
3914 if(!NT_SUCCESS(Status
))
3916 SetLastNtError(Status
);
3920 Ret
= (UINT
)IntAddAtom(SafeMessageName
.Buffer
);
3922 RtlFreeUnicodeString(&SafeMessageName
);
3926 DPRINT("Leave NtUserRegisterWindowMessage, ret=%i\n",_ret_
);
3936 NtUserSetImeOwnerWindow(DWORD Unknown0
,
3949 NtUserSetInternalWindowPos(DWORD Unknown0
,
3965 NtUserSetLayeredWindowAttributes(DWORD Unknown0
,
3980 NtUserSetLogonNotifyWindow(DWORD Unknown0
)
3997 PWINDOW_OBJECT Window
;
3999 DECLARE_RETURN(BOOL
);
4001 DPRINT("Enter NtUserSetMenu\n");
4002 UserEnterExclusive();
4004 if (!(Window
= IntGetWindowObject(hWnd
)))
4006 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4010 if (! IntSetMenu(Window
, Menu
, &Changed
))
4012 IntReleaseWindowObject(Window
);
4016 IntReleaseWindowObject(Window
);
4018 if (Changed
&& Repaint
)
4020 co_WinPosSetWindowPos(hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
4021 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
4027 DPRINT("Leave NtUserSetMenu, ret=%i\n",_ret_
);
4037 NtUserSetWindowFNID(DWORD Unknown0
,
4051 NtUserSetWindowPlacement(HWND hWnd
,
4052 WINDOWPLACEMENT
*lpwndpl
)
4054 PWINDOW_OBJECT Window
;
4055 WINDOWPLACEMENT Safepl
;
4057 DECLARE_RETURN(BOOL
);
4059 DPRINT("Enter NtUserSetWindowPlacement\n");
4060 UserEnterExclusive();
4062 if (!(Window
= IntGetWindowObject(hWnd
)))
4064 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4067 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
4068 if(!NT_SUCCESS(Status
))
4070 SetLastNtError(Status
);
4071 IntReleaseWindowObject(Window
);
4074 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
4076 IntReleaseWindowObject(Window
);
4080 if ((Window
->Style
& (WS_MAXIMIZE
| WS_MINIMIZE
)) == 0)
4082 co_WinPosSetWindowPos(Window
->hSelf
, NULL
,
4083 Safepl
.rcNormalPosition
.left
, Safepl
.rcNormalPosition
.top
,
4084 Safepl
.rcNormalPosition
.right
- Safepl
.rcNormalPosition
.left
,
4085 Safepl
.rcNormalPosition
.bottom
- Safepl
.rcNormalPosition
.top
,
4086 SWP_NOZORDER
| SWP_NOACTIVATE
);
4089 /* FIXME - change window status */
4090 co_WinPosShowWindow(Window
->hSelf
, Safepl
.showCmd
);
4092 if (Window
->InternalPos
== NULL
)
4093 Window
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
4094 Window
->InternalPos
->NormalRect
= Safepl
.rcNormalPosition
;
4095 Window
->InternalPos
->IconPos
= Safepl
.ptMinPosition
;
4096 Window
->InternalPos
->MaxPos
= Safepl
.ptMaxPosition
;
4098 IntReleaseWindowObject(Window
);
4102 DPRINT("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
4114 HWND hWndInsertAfter
,
4121 DECLARE_RETURN(BOOL
);
4123 DPRINT("Enter NtUserSetWindowPos\n");
4124 UserEnterExclusive();
4126 RETURN( co_WinPosSetWindowPos(hWnd
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
));
4129 DPRINT("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
4136 IntGetWindowRgn(HWND hWnd
, HRGN hRgn
)
4139 PWINDOW_OBJECT Window
;
4143 if(!(Window
= IntGetWindowObject(hWnd
)))
4145 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4150 IntReleaseWindowObject(Window
);
4154 /* Create a new window region using the window rectangle */
4155 VisRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->WindowRect
);
4156 NtGdiOffsetRgn(VisRgn
, -Window
->WindowRect
.left
, -Window
->WindowRect
.top
);
4157 /* if there's a region assigned to the window, combine them both */
4158 if(Window
->WindowRegion
&& !(Window
->Style
& WS_MINIMIZE
))
4159 NtGdiCombineRgn(VisRgn
, VisRgn
, Window
->WindowRegion
, RGN_AND
);
4160 /* Copy the region into hRgn */
4161 NtGdiCombineRgn(hRgn
, VisRgn
, NULL
, RGN_COPY
);
4163 if((pRgn
= RGNDATA_LockRgn(hRgn
)))
4165 Ret
= pRgn
->rdh
.iType
;
4166 RGNDATA_UnlockRgn(pRgn
);
4171 NtGdiDeleteObject(VisRgn
);
4173 IntReleaseWindowObject(Window
);
4178 IntGetWindowRgnBox(HWND hWnd
, RECT
*Rect
)
4181 PWINDOW_OBJECT Window
;
4185 if(!(Window
= IntGetWindowObject(hWnd
)))
4187 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4192 IntReleaseWindowObject(Window
);
4196 /* Create a new window region using the window rectangle */
4197 VisRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->WindowRect
);
4198 NtGdiOffsetRgn(VisRgn
, -Window
->WindowRect
.left
, -Window
->WindowRect
.top
);
4199 /* if there's a region assigned to the window, combine them both */
4200 if(Window
->WindowRegion
&& !(Window
->Style
& WS_MINIMIZE
))
4201 NtGdiCombineRgn(VisRgn
, VisRgn
, Window
->WindowRegion
, RGN_AND
);
4203 if((pRgn
= RGNDATA_LockRgn(VisRgn
)))
4205 Ret
= pRgn
->rdh
.iType
;
4206 *Rect
= pRgn
->rdh
.rcBound
;
4207 RGNDATA_UnlockRgn(pRgn
);
4212 NtGdiDeleteObject(VisRgn
);
4214 IntReleaseWindowObject(Window
);
4228 PWINDOW_OBJECT Window
;
4229 DECLARE_RETURN(INT
);
4231 DPRINT("Enter NtUserSetWindowRgn\n");
4232 UserEnterExclusive();
4234 if (!(Window
= IntGetWindowObject(hWnd
)))
4236 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4240 /* FIXME - Verify if hRgn is a valid handle!!!!
4241 Propably make this operation thread-safe, but maybe it's not necessary */
4243 if(Window
->WindowRegion
)
4245 /* Delete no longer needed region handle */
4246 NtGdiDeleteObject(Window
->WindowRegion
);
4248 Window
->WindowRegion
= hRgn
;
4250 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
4254 co_UserRedrawWindow(Window
, NULL
, NULL
, RDW_INVALIDATE
);
4257 IntReleaseWindowObject(Window
);
4261 DPRINT("Leave NtUserSystemParametersInfo, ret=%i\n",_ret_
);
4271 NtUserShowWindow(HWND hWnd
,
4274 DECLARE_RETURN(BOOL
);
4276 DPRINT("Enter NtUserShowWindow\n");
4277 UserEnterExclusive();
4279 RETURN( co_WinPosShowWindow(hWnd
, nCmdShow
));
4282 DPRINT("Leave NtUserShowWindow, ret=%i\n",_ret_
);
4292 NtUserShowWindowAsync(DWORD Unknown0
,
4305 NtUserUpdateLayeredWindow(DWORD Unknown0
,
4325 NtUserValidateRect(HWND hWnd
, const RECT
* Rect
)
4327 return (VOID
)NtUserRedrawWindow(hWnd
, Rect
, 0, RDW_VALIDATE
| RDW_NOCHILDREN
);
4335 NtUserWindowFromPoint(LONG X
, LONG Y
)
4339 PWINDOW_OBJECT DesktopWindow
, Window
= NULL
;
4340 DECLARE_RETURN(HWND
);
4342 DPRINT("Enter NtUserWindowFromPoint\n");
4343 UserEnterExclusive();
4345 if ((DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow())))
4352 Hit
= co_WinPosWindowFromPoint(DesktopWindow
, PsGetWin32Thread()->MessageQueue
, &pt
, &Window
);
4356 Ret
= Window
->hSelf
;
4357 IntReleaseWindowObject(Window
);
4358 IntReleaseWindowObject(DesktopWindow
);
4362 IntReleaseWindowObject(DesktopWindow
);
4368 DPRINT("Leave NtUserWindowFromPoint, ret=%i\n",_ret_
);
4378 * Undocumented function that is called from DefWindowProc to set
4386 NtUserDefSetText(HWND hWnd
, PUNICODE_STRING WindowText
)
4388 PWINDOW_OBJECT Window
, Parent
, Owner
;
4389 UNICODE_STRING SafeText
;
4391 DECLARE_RETURN(INT
);
4393 DPRINT("Enter NtUserDefSetText\n");
4394 UserEnterExclusive();
4396 if(!(Window
= IntGetWindowObject(hWnd
)))
4398 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4404 Status
= IntSafeCopyUnicodeString(&SafeText
, WindowText
);
4405 if(!NT_SUCCESS(Status
))
4407 SetLastNtError(Status
);
4408 IntReleaseWindowObject(Window
);
4414 RtlInitUnicodeString(&SafeText
, NULL
);
4417 /* FIXME - do this thread-safe! otherwise one could crash here! */
4418 RtlFreeUnicodeString(&Window
->WindowName
);
4420 Window
->WindowName
= SafeText
;
4422 /* Send shell notifications */
4424 Owner
= IntGetOwner(Window
);
4425 Parent
= IntGetParent(Window
);
4427 if ((!Owner
) && (!Parent
))
4429 co_IntShellHookNotify(HSHELL_REDRAW
, (LPARAM
) hWnd
);
4434 IntReleaseWindowObject(Owner
);
4439 IntReleaseWindowObject(Parent
);
4442 IntReleaseWindowObject(Window
);
4446 DPRINT("Leave NtUserDefSetText, ret=%i\n",_ret_
);
4452 * NtUserInternalGetWindowText
4459 NtUserInternalGetWindowText(HWND hWnd
, LPWSTR lpString
, INT nMaxCount
)
4461 PWINDOW_OBJECT Window
;
4464 DECLARE_RETURN(INT
);
4466 DPRINT("Enter NtUserInternalGetWindowText\n");
4469 if(lpString
&& (nMaxCount
<= 1))
4471 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
4475 if(!(Window
= IntGetWindowObject(hWnd
)))
4477 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4481 /* FIXME - do this thread-safe! otherwise one could crash here! */
4482 Result
= Window
->WindowName
.Length
/ sizeof(WCHAR
);
4485 const WCHAR Terminator
= L
'\0';
4487 WCHAR
*Buffer
= (WCHAR
*)lpString
;
4489 Copy
= min(nMaxCount
- 1, Result
);
4492 Status
= MmCopyToCaller(Buffer
, Window
->WindowName
.Buffer
, Copy
* sizeof(WCHAR
));
4493 if(!NT_SUCCESS(Status
))
4495 SetLastNtError(Status
);
4496 IntReleaseWindowObject(Window
);
4502 Status
= MmCopyToCaller(Buffer
, &Terminator
, sizeof(WCHAR
));
4503 if(!NT_SUCCESS(Status
))
4505 SetLastNtError(Status
);
4506 IntReleaseWindowObject(Window
);
4513 IntReleaseWindowObject(Window
);
4517 DPRINT("Leave NtUserInternalGetWindowText, ret=%i\n",_ret_
);
4523 NtUserDereferenceWndProcHandle(WNDPROC wpHandle
, WndProcHandle
*Data
)
4525 DECLARE_RETURN(DWORD
);
4527 DPRINT("Enter NtUserDereferenceWndProcHandle\n");
4530 WndProcHandle Entry
;
4531 if (((DWORD
)wpHandle
& 0xFFFF0000) == 0xFFFF0000)
4533 Entry
= WndProcHandlesArray
[(DWORD
)wpHandle
& 0x0000FFFF];
4534 Data
->WindowProc
= Entry
.WindowProc
;
4535 Data
->IsUnicode
= Entry
.IsUnicode
;
4536 Data
->ProcessID
= Entry
.ProcessID
;
4544 DPRINT("Leave NtUserDereferenceWndProcHandle, ret=%i\n",_ret_
);
4550 IntAddWndProcHandle(WNDPROC WindowProc
, BOOL IsUnicode
)
4555 WndProcHandle
*OldArray
;
4558 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4560 if (WndProcHandlesArray
[i
].WindowProc
== NULL
)
4568 OldArray
= WndProcHandlesArray
;
4569 OldArraySize
= WndProcHandlesArraySize
;
4570 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,(OldArraySize
+ WPH_SIZE
) * sizeof(WndProcHandle
), TAG_WINPROCLST
);
4571 WndProcHandlesArraySize
= OldArraySize
+ WPH_SIZE
;
4572 RtlCopyMemory(WndProcHandlesArray
,OldArray
,OldArraySize
* sizeof(WndProcHandle
));
4573 ExFreePool(OldArray
);
4574 FreeSpot
= OldArraySize
+ 1;
4576 WndProcHandlesArray
[FreeSpot
].WindowProc
= WindowProc
;
4577 WndProcHandlesArray
[FreeSpot
].IsUnicode
= IsUnicode
;
4578 WndProcHandlesArray
[FreeSpot
].ProcessID
= PsGetCurrentProcessId();
4579 return FreeSpot
+ 0xFFFF0000;
4583 IntRemoveWndProcHandle(WNDPROC Handle
)
4586 position
= (DWORD
)Handle
& 0x0000FFFF;
4587 if (position
> WndProcHandlesArraySize
)
4591 WndProcHandlesArray
[position
].WindowProc
= NULL
;
4592 WndProcHandlesArray
[position
].IsUnicode
= FALSE
;
4593 WndProcHandlesArray
[position
].ProcessID
= NULL
;
4598 IntRemoveProcessWndProcHandles(HANDLE ProcessID
)
4601 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4603 if (WndProcHandlesArray
[i
].ProcessID
== ProcessID
)
4605 WndProcHandlesArray
[i
].WindowProc
= NULL
;
4606 WndProcHandlesArray
[i
].IsUnicode
= FALSE
;
4607 WndProcHandlesArray
[i
].ProcessID
= NULL
;
4613 #define WIN_NEEDS_SHOW_OWNEDPOPUP (0x00000040)
4617 IntShowOwnedPopups( HWND owner
, BOOL fShow
)
4620 PWINDOW_OBJECT Window
, pWnd
;
4623 if(!(Window
= IntGetWindowObject(owner
)))
4625 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
4629 win_array
= IntWinListChildren( Window
);
4630 IntReleaseWindowObject(Window
);
4632 if (!win_array
) return TRUE
;
4634 while (win_array
[count
]) count
++;
4635 while (--count
>= 0)
4637 if (UserGetWindow( win_array
[count
], GW_OWNER
) != owner
) continue;
4638 if (!(pWnd
= IntGetWindowObject( win_array
[count
] ))) continue;
4639 // if (pWnd == WND_OTHER_PROCESS) continue;
4643 if (pWnd
->Flags
& WIN_NEEDS_SHOW_OWNEDPOPUP
)
4645 IntReleaseWindowObject( pWnd
);
4646 /* In Windows, ShowOwnedPopups(TRUE) generates
4647 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
4648 * regardless of the state of the owner
4650 co_IntSendMessage(win_array
[count
], WM_SHOWWINDOW
, SW_SHOWNORMAL
, SW_PARENTOPENING
);
4656 if (pWnd
->Style
& WS_VISIBLE
)
4658 IntReleaseWindowObject( pWnd
);
4659 /* In Windows, ShowOwnedPopups(FALSE) generates
4660 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
4661 * regardless of the state of the owner
4663 co_IntSendMessage(win_array
[count
], WM_SHOWWINDOW
, SW_HIDE
, SW_PARENTCLOSING
);
4667 IntReleaseWindowObject( pWnd
);
4669 ExFreePool( win_array
);