2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
23 * FILE: subsys/win32k/ntuser/window.c
24 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * 06-06-2001 CSH Created
29 /* INCLUDES ******************************************************************/
36 static WndProcHandle
*WndProcHandlesArray
= 0;
37 static WORD WndProcHandlesArraySize
= 0;
38 #define WPH_SIZE 0x40 /* the size to add to the WndProcHandle array each time */
40 /* dialog resources appear to pass this in 16 bits, handle them properly */
41 #define CW_USEDEFAULT16 (0x8000)
43 #define POINT_IN_RECT(p, r) (((r.bottom >= p.y) && (r.top <= p.y))&&((r.left <= p.x )&&( r.right >= p.x )))
45 /* PRIVATE FUNCTIONS **********************************************************/
50 * Initialize windowing implementation.
56 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,WPH_SIZE
* sizeof(WndProcHandle
), TAG_WINPROCLST
);
57 WndProcHandlesArraySize
= WPH_SIZE
;
58 return STATUS_SUCCESS
;
64 * Cleanup windowing implementation.
68 CleanupWindowImpl(VOID
)
70 ExFreePool(WndProcHandlesArray
);
71 WndProcHandlesArray
= 0;
72 WndProcHandlesArraySize
= 0;
73 return STATUS_SUCCESS
;
76 /* HELPER FUNCTIONS ***********************************************************/
78 VOID FASTCALL
IntReleaseWindowObject(PWINDOW_OBJECT Window
)
83 ASSERT(USER_BODY_TO_HEADER(Window)->RefCount >= 1);
85 USER_BODY_TO_HEADER(Window)->RefCount--;
87 if (USER_BODY_TO_HEADER(Window)->RefCount == 0 && USER_BODY_TO_HEADER(Window)->destroyed)
92 ObmDereferenceObject(Window
);
96 PWINDOW_OBJECT FASTCALL
IntGetWindowObject(HWND hWnd
)
98 PWINDOW_OBJECT Window
;
100 if (!hWnd
) return NULL
;
102 Window
= UserGetWindowObject(hWnd
);
105 ASSERT(USER_BODY_TO_HEADER(Window
)->RefCount
>= 0);
107 USER_BODY_TO_HEADER(Window
)->RefCount
++;
113 PWINDOW_OBJECT FASTCALL
UserGetWindowObject(HWND hWnd
)
115 PWINDOW_OBJECT Window
;
117 if (!hWnd
) return NULL
;
119 Window
= (PWINDOW_OBJECT
)UserGetObject(&gHandleTable
, hWnd
, otWindow
);
122 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
126 ASSERT(USER_BODY_TO_HEADER(Window
)->RefCount
>= 0);
134 * The function determines whether the specified window handle identifies
135 * an existing window.
139 * Handle to the window to test.
142 * If the window handle identifies an existing window, the return value
143 * is TRUE. If the window handle does not identify an existing window,
144 * the return value is FALSE.
148 IntIsWindow(HWND hWnd
)
150 PWINDOW_OBJECT Window
;
152 if (!(Window
= IntGetWindowObject(hWnd
)))
155 IntReleaseWindowObject(Window
);
162 PWINDOW_OBJECT FASTCALL
163 IntGetParent(PWINDOW_OBJECT Wnd
)
167 if (Wnd
->Style
& WS_POPUP
)
170 return IntGetWindowObject(hWnd
);
172 else if (Wnd
->Style
& WS_CHILD
)
178 IntReferenceWindowObject(par
);
180 //return IntGetWindowObject(hWnd);
186 PWINDOW_OBJECT FASTCALL
187 IntGetOwner(PWINDOW_OBJECT Wnd
)
193 return IntGetWindowObject(hWnd
);
196 PWINDOW_OBJECT FASTCALL
197 IntGetParentObject(PWINDOW_OBJECT Wnd
)
203 IntReferenceWindowObject(par
);
210 * Compile a list of all child window handles from given window.
213 * This function is similar to Wine WIN_ListChildren. The caller
214 * must free the returned list with ExFreePool.
218 IntWinListChildren(PWINDOW_OBJECT Window
)
220 PWINDOW_OBJECT Child
;
222 UINT Index
, NumChildren
= 0;
224 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
227 List
= ExAllocatePoolWithTag(PagedPool
, (NumChildren
+ 1) * sizeof(HWND
), TAG_WINLIST
);
230 DPRINT1("Failed to allocate memory for children array\n");
231 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
234 for (Child
= Window
->FirstChild
, Index
= 0;
236 Child
= Child
->NextSibling
, ++Index
)
237 List
[Index
] = Child
->hSelf
;
243 /***********************************************************************
246 static void IntSendDestroyMsg(HWND Wnd
)
249 PWINDOW_OBJECT Window
, Owner
, Parent
;
254 if (GetGUIThreadInfo(GetCurrentThreadId(), &info
))
256 if (Wnd
== info
.hwndCaret
)
263 Window
= IntGetWindowObject(Wnd
);
266 Owner
= IntGetOwner(Window
);
269 Parent
= IntGetParent(Window
);
271 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
) Wnd
);
273 IntReleaseWindowObject(Parent
);
277 IntReleaseWindowObject(Owner
);
280 IntReleaseWindowObject(Window
);
283 /* The window could already be destroyed here */
286 * Send the WM_DESTROY to the window.
289 co_IntSendMessage(Wnd
, WM_DESTROY
, 0, 0);
292 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
293 * make sure that the window still exists when we come back.
302 if (!(pWndArray
= WIN_ListChildren( hwnd
)))
305 /* start from the end (FIXME: is this needed?) */
306 for (i
= 0; pWndArray
[i
]; i
++)
311 if (IsWindow( pWndArray
[i
] ))
312 WIN_SendDestroyMsg( pWndArray
[i
] );
314 HeapFree(GetProcessHeap(), 0, pWndArray
);
318 DPRINT("destroyed itself while in WM_DESTROY!\n");
323 /***********************************************************************
326 * Destroy storage associated to a window. "Internals" p.358
328 static LRESULT
co_IntDestroyWindow(PWINDOW_OBJECT Window
,
329 PW32PROCESS ProcessData
,
330 PW32THREAD ThreadData
,
331 BOOLEAN SendMessages
)
335 PWINDOW_OBJECT Child
;
337 BOOLEAN BelongsToThreadData
;
341 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
343 DPRINT("Tried to call IntDestroyWindow() twice\n");
346 Window
->Status
|= WINDOWSTATUS_DESTROYING
;
347 Window
->Style
&= ~WS_VISIBLE
;
348 /* remove the window already at this point from the thread window list so we
349 don't get into trouble when destroying the thread windows while we're still
350 in IntDestroyWindow() */
351 RemoveEntryList(&Window
->ThreadListEntry
);
353 BelongsToThreadData
= IntWndBelongsToThread(Window
, ThreadData
);
355 IntDeRegisterShellHookWindow(Window
->hSelf
);
359 /* Send destroy messages */
360 IntSendDestroyMsg(Window
->hSelf
);
363 /* free child windows */
364 Children
= IntWinListChildren(Window
);
367 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
369 if ((Child
= IntGetWindowObject(*ChildHandle
)))
371 if(!IntWndBelongsToThread(Child
, ThreadData
))
373 /* send WM_DESTROY messages to windows not belonging to the same thread */
374 IntSendDestroyMsg(Child
->hSelf
);
377 co_IntDestroyWindow(Child
, ProcessData
, ThreadData
, SendMessages
);
378 IntReleaseWindowObject(Child
);
381 ExFreePool(Children
);
387 * Clear the update region to make sure no WM_PAINT messages will be
388 * generated for this window while processing the WM_NCDESTROY.
390 co_UserRedrawWindow(Window
, NULL
, 0,
391 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
|
392 RDW_NOINTERNALPAINT
| RDW_NOCHILDREN
);
393 if(BelongsToThreadData
)
394 co_IntSendMessage(Window
->hSelf
, WM_NCDESTROY
, 0, 0);
396 MsqRemoveTimersWindow(ThreadData
->MessageQueue
, Window
->hSelf
);
398 /* flush the message queue */
399 MsqRemoveWindowMessagesFromQueue(Window
);
401 /* from now on no messages can be sent to this window anymore */
402 Window
->Status
|= WINDOWSTATUS_DESTROYED
;
403 /* don't remove the WINDOWSTATUS_DESTROYING bit */
405 /* reset shell window handles */
406 if(ThreadData
->Desktop
)
408 if (Window
->hSelf
== ThreadData
->Desktop
->WindowStation
->ShellWindow
)
409 ThreadData
->Desktop
->WindowStation
->ShellWindow
= NULL
;
411 if (Window
->hSelf
== ThreadData
->Desktop
->WindowStation
->ShellListView
)
412 ThreadData
->Desktop
->WindowStation
->ShellListView
= NULL
;
415 /* Unregister hot keys */
416 UnregisterWindowHotKeys (Window
);
418 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
422 WinPosCheckInternalPos(Window
->hSelf
);
423 if (Window
->hSelf
== GetCapture())
428 /* free resources associated with the window */
429 TIMER_RemoveWindowTimers(Window
->hSelf
);
432 if (!(Window
->Style
& WS_CHILD
) && Window
->IDMenu
433 && (Menu
= IntGetMenuObject((HMENU
)Window
->IDMenu
)))
435 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
437 IntReleaseMenuObject(Menu
);
440 if(Window
->SystemMenu
441 && (Menu
= IntGetMenuObject(Window
->SystemMenu
)))
443 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
444 Window
->SystemMenu
= (HMENU
)0;
445 IntReleaseMenuObject(Menu
);
448 DceFreeWindowDCE(Window
); /* Always do this to catch orphaned DCs */
451 WINPROC_FreeProc(Window
->winproc
, WIN_PROC_WINDOW
);
452 CLASS_RemoveWindow(Window
->Class
);
455 IntUnlinkWindow(Window
);
457 IntReferenceWindowObject(Window
);
458 ObmDeleteObject(Window
->hSelf
, otWindow
);
460 IntDestroyScrollBars(Window
);
462 /* remove the window from the class object */
463 RemoveEntryList(&Window
->ClassListEntry
);
465 /* dereference the class */
466 ClassDereferenceObject(Window
->Class
);
467 Window
->Class
= NULL
;
469 if(Window
->WindowRegion
)
471 NtGdiDeleteObject(Window
->WindowRegion
);
474 RtlFreeUnicodeString(&Window
->WindowName
);
476 IntReleaseWindowObject(Window
);
482 IntGetWindowBorderMeasures(PWINDOW_OBJECT Window
, UINT
*cx
, UINT
*cy
)
484 if(HAS_DLGFRAME(Window
->Style
, Window
->ExStyle
) && !(Window
->Style
& WS_MINIMIZE
))
486 *cx
= UserGetSystemMetrics(SM_CXDLGFRAME
);
487 *cy
= UserGetSystemMetrics(SM_CYDLGFRAME
);
491 if(HAS_THICKFRAME(Window
->Style
, Window
->ExStyle
)&& !(Window
->Style
& WS_MINIMIZE
))
493 *cx
= UserGetSystemMetrics(SM_CXFRAME
);
494 *cy
= UserGetSystemMetrics(SM_CYFRAME
);
496 else if(HAS_THINFRAME(Window
->Style
, Window
->ExStyle
))
498 *cx
= UserGetSystemMetrics(SM_CXBORDER
);
499 *cy
= UserGetSystemMetrics(SM_CYBORDER
);
509 IntGetWindowInfo(PWINDOW_OBJECT Window
, PWINDOWINFO pwi
)
511 pwi
->cbSize
= sizeof(WINDOWINFO
);
512 pwi
->rcWindow
= Window
->WindowRect
;
513 pwi
->rcClient
= Window
->ClientRect
;
514 pwi
->dwStyle
= Window
->Style
;
515 pwi
->dwExStyle
= Window
->ExStyle
;
516 pwi
->dwWindowStatus
= (UserGetForegroundWindow() == Window
->hSelf
); /* WS_ACTIVECAPTION */
517 IntGetWindowBorderMeasures(Window
, &pwi
->cxWindowBorders
, &pwi
->cyWindowBorders
);
518 pwi
->atomWindowType
= (Window
->Class
? Window
->Class
->Atom
: 0);
519 pwi
->wCreatorVersion
= 0x400; /* FIXME - return a real version number */
525 PWINDOW_OBJECT Window
,
529 PMENU_OBJECT OldMenu
, NewMenu
= NULL
;
531 if ((Window
->Style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
533 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
537 *Changed
= (Window
->IDMenu
!= (UINT
) Menu
);
545 OldMenu
= IntGetMenuObject((HMENU
) Window
->IDMenu
);
546 ASSERT(NULL
== OldMenu
|| OldMenu
->MenuInfo
.Wnd
== Window
->hSelf
);
555 NewMenu
= IntGetMenuObject(Menu
);
560 IntReleaseMenuObject(OldMenu
);
562 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
565 if (NULL
!= NewMenu
->MenuInfo
.Wnd
)
567 /* Can't use the same menu for two windows */
570 IntReleaseMenuObject(OldMenu
);
572 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
578 Window
->IDMenu
= (UINT
) Menu
;
581 NewMenu
->MenuInfo
.Wnd
= Window
->hSelf
;
582 IntReleaseMenuObject(NewMenu
);
586 OldMenu
->MenuInfo
.Wnd
= NULL
;
587 IntReleaseMenuObject(OldMenu
);
594 /* INTERNAL ******************************************************************/
598 co_DestroyThreadWindows(struct _ETHREAD
*Thread
)
601 PW32PROCESS Win32Process
;
602 PW32THREAD Win32Thread
;
603 PWINDOW_OBJECT
*List
, *pWnd
;
606 Win32Thread
= Thread
->Tcb
.Win32Thread
;
607 Win32Process
= (PW32PROCESS
)Thread
->ThreadsProcess
->Win32Process
;
609 Current
= Win32Thread
->WindowListHead
.Flink
;
610 while (Current
!= &(Win32Thread
->WindowListHead
))
613 Current
= Current
->Flink
;
618 List
= ExAllocatePool(PagedPool
, (Cnt
+ 1) * sizeof(PWINDOW_OBJECT
));
621 DPRINT("Not enough memory to allocate window handle list\n");
625 Current
= Win32Thread
->WindowListHead
.Flink
;
626 while (Current
!= &(Win32Thread
->WindowListHead
))
628 *pWnd
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
629 IntReferenceWindowObject(*pWnd
);
631 Current
= Current
->Flink
;
635 for(pWnd
= List
; *pWnd
; pWnd
++)
637 co_UserDestroyWindow(*pWnd
);
638 IntReleaseWindowObject(*pWnd
);
649 * Returns client window rectangle relative to the upper-left corner of client area.
651 * \note Does not check the validity of the parameters
654 IntGetClientRect(PWINDOW_OBJECT Window
, PRECT Rect
)
659 Rect
->left
= Rect
->top
= 0;
660 Rect
->right
= Window
->ClientRect
.right
- Window
->ClientRect
.left
;
661 Rect
->bottom
= Window
->ClientRect
.bottom
- Window
->ClientRect
.top
;
667 IntGetFocusWindow(VOID
)
669 PUSER_MESSAGE_QUEUE Queue
;
670 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
675 Queue
= (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
680 return(Queue
->FocusWindow
);
684 PMENU_OBJECT FASTCALL
685 IntGetSystemMenu(PWINDOW_OBJECT Window
, BOOL bRevert
, BOOL RetMenu
)
687 PMENU_OBJECT Menu
, NewMenu
= NULL
, SysMenu
= NULL
, ret
= NULL
;
688 PW32THREAD W32Thread
;
689 HMENU hNewMenu
, hSysMenu
;
690 ROSMENUITEMINFO ItemInfo
;
694 W32Thread
= PsGetWin32Thread();
696 if(!W32Thread
->Desktop
)
699 if(Window
->SystemMenu
)
701 Menu
= IntGetMenuObject(Window
->SystemMenu
);
704 IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
705 Window
->SystemMenu
= (HMENU
)0;
706 IntReleaseMenuObject(Menu
);
710 if(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
)
712 /* clone system menu */
713 Menu
= IntGetMenuObject(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
);
717 NewMenu
= IntCloneMenu(Menu
);
720 Window
->SystemMenu
= NewMenu
->MenuInfo
.Self
;
721 NewMenu
->MenuInfo
.Flags
|= MF_SYSMENU
;
722 NewMenu
->MenuInfo
.Wnd
= Window
->hSelf
;
724 //IntReleaseMenuObject(NewMenuObject);
726 IntReleaseMenuObject(Menu
);
730 hSysMenu
= UserCreateMenu(FALSE
);
735 SysMenu
= IntGetMenuObject(hSysMenu
);
738 UserDestroyMenu(hSysMenu
);
741 SysMenu
->MenuInfo
.Flags
|= MF_SYSMENU
;
742 SysMenu
->MenuInfo
.Wnd
= Window
->hSelf
;
743 hNewMenu
= co_IntLoadSysMenuTemplate();
746 IntReleaseMenuObject(SysMenu
);
747 UserDestroyMenu(hSysMenu
);
750 Menu
= IntGetMenuObject(hNewMenu
);
753 IntReleaseMenuObject(SysMenu
);
754 UserDestroyMenu(hSysMenu
);
758 NewMenu
= IntCloneMenu(Menu
);
761 NewMenu
->MenuInfo
.Flags
|= MF_SYSMENU
| MF_POPUP
;
762 IntReleaseMenuObject(NewMenu
);
763 UserSetMenuDefaultItem(NewMenu
, SC_CLOSE
, FALSE
);
765 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
766 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
767 ItemInfo
.fType
= MF_POPUP
;
768 ItemInfo
.fState
= MFS_ENABLED
;
769 ItemInfo
.dwTypeData
= NULL
;
771 ItemInfo
.hSubMenu
= NewMenu
->MenuInfo
.Self
;
772 IntInsertMenuItem(SysMenu
, (UINT
) -1, TRUE
, &ItemInfo
);
774 Window
->SystemMenu
= SysMenu
->MenuInfo
.Self
;
778 IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
779 IntReleaseMenuObject(Menu
);
788 if(Window
->SystemMenu
)
789 return IntGetMenuObject((HMENU
)Window
->SystemMenu
);
797 IntIsChildWindow(HWND Parent
, HWND Child
)
799 PWINDOW_OBJECT BaseWindow
, Window
;
801 if(!(BaseWindow
= UserGetWindowObject(Child
)))
809 if (Window
->hSelf
== Parent
)
813 if(!(Window
->Style
& WS_CHILD
))
818 Window
= Window
->Parent
;
825 IntIsWindowVisible(PWINDOW_OBJECT BaseWindow
)
827 PWINDOW_OBJECT Window
;
832 if(!(Window
->Style
& WS_CHILD
))
836 if(!(Window
->Style
& WS_VISIBLE
))
841 Window
= Window
->Parent
;
844 if(Window
&& Window
->Style
& WS_VISIBLE
)
853 /* link the window into siblings and parent. children are kept in place. */
857 PWINDOW_OBJECT WndParent
,
858 PWINDOW_OBJECT WndPrevSibling
/* set to NULL if top sibling */
861 PWINDOW_OBJECT Parent
;
863 Wnd
->Parent
= WndParent
;
864 if ((Wnd
->PrevSibling
= WndPrevSibling
))
866 /* link after WndPrevSibling */
867 if ((Wnd
->NextSibling
= WndPrevSibling
->NextSibling
))
868 Wnd
->NextSibling
->PrevSibling
= Wnd
;
869 else if ((Parent
= Wnd
->Parent
))
871 if(Parent
->LastChild
== WndPrevSibling
)
872 Parent
->LastChild
= Wnd
;
874 Wnd
->PrevSibling
->NextSibling
= Wnd
;
879 Parent
= Wnd
->Parent
;
880 if ((Wnd
->NextSibling
= WndParent
->FirstChild
))
881 Wnd
->NextSibling
->PrevSibling
= Wnd
;
884 Parent
->LastChild
= Wnd
;
885 Parent
->FirstChild
= Wnd
;
890 Parent
->FirstChild
= Wnd
;
897 IntSetOwner(HWND hWnd
, HWND hWndNewOwner
)
899 PWINDOW_OBJECT Wnd
, WndOldOwner
, WndNewOwner
;
902 Wnd
= IntGetWindowObject(hWnd
);
906 WndOldOwner
= IntGetWindowObject(Wnd
->hOwner
);
909 ret
= WndOldOwner
->hSelf
;
910 IntReleaseWindowObject(WndOldOwner
);
917 if((WndNewOwner
= IntGetWindowObject(hWndNewOwner
)))
919 Wnd
->hOwner
= hWndNewOwner
;
920 IntReleaseWindowObject(WndNewOwner
);
925 IntReleaseWindowObject(Wnd
);
929 PWINDOW_OBJECT FASTCALL
930 co_IntSetParent(PWINDOW_OBJECT Wnd
, PWINDOW_OBJECT WndNewParent
)
932 PWINDOW_OBJECT WndOldParent
, Sibling
, InsertAfter
;
933 HWND hWnd
, hWndNewParent
, hWndOldParent
;
938 ASSERT(WndNewParent
);
940 ASSERT_REFS_CO(WndNewParent
);
943 hWndNewParent
= WndNewParent
->hSelf
;
946 * Windows hides the window first, then shows it again
947 * including the WM_SHOWWINDOW messages and all
949 WasVisible
= co_WinPosShowWindow(Wnd
, SW_HIDE
);
951 /* Validate that window and parent still exist */
952 if (!IntIsWindow(hWnd
) || !IntIsWindow(hWndNewParent
))
955 /* Window must belong to current process */
956 if (Wnd
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
959 WndOldParent
= IntGetParentObject(Wnd
);
960 hWndOldParent
= (WndOldParent
? WndOldParent
->hSelf
: NULL
);
962 if (WndNewParent
!= WndOldParent
)
964 IntUnlinkWindow(Wnd
);
966 if (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
))
968 /* Not a TOPMOST window, put after TOPMOSTs of new parent */
969 Sibling
= WndNewParent
->FirstChild
;
970 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
972 InsertAfter
= Sibling
;
973 Sibling
= Sibling
->NextSibling
;
976 if (NULL
== InsertAfter
)
978 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
982 IntReferenceWindowObject(InsertAfter
);
983 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
984 IntReleaseWindowObject(InsertAfter
);
987 if (WndNewParent
->hSelf
!= IntGetDesktopWindow()) /* a child window */
989 if (!(Wnd
->Style
& WS_CHILD
))
991 //if ( Wnd->Menu ) DestroyMenu ( Wnd->menu );
992 IntSetMenu(Wnd
, NULL
, &MenuChanged
);
998 * SetParent additionally needs to make hwnd the top window
999 * in the z-order and send the expected WM_WINDOWPOSCHANGING and
1000 * WM_WINDOWPOSCHANGED notification messages.
1002 co_WinPosSetWindowPos(Wnd
, (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOP
: HWND_TOPMOST
),
1003 0, 0, 0, 0, SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
1004 | (WasVisible
? SWP_SHOWWINDOW
: 0));
1007 * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
1008 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
1012 * Validate that the old parent still exist, since it migth have been
1013 * destroyed during the last callbacks to user-mode
1017 if(!IntIsWindow(WndOldParent
->hSelf
))
1019 IntReleaseWindowObject(WndOldParent
);
1023 /* don't dereference the window object here, it must be done by the caller
1024 of IntSetParent() */
1025 return WndOldParent
;
1031 IntSetSystemMenu(PWINDOW_OBJECT Window
, PMENU_OBJECT Menu
)
1033 PMENU_OBJECT OldMenu
;
1034 if(Window
->SystemMenu
)
1036 OldMenu
= IntGetMenuObject(Window
->SystemMenu
);
1039 OldMenu
->MenuInfo
.Flags
&= ~ MF_SYSMENU
;
1040 IntReleaseMenuObject(OldMenu
);
1046 /* FIXME check window style, propably return FALSE ? */
1047 Window
->SystemMenu
= Menu
->MenuInfo
.Self
;
1048 Menu
->MenuInfo
.Flags
|= MF_SYSMENU
;
1051 Window
->SystemMenu
= (HMENU
)0;
1057 /* unlink the window from siblings and parent. children are kept in place. */
1059 IntUnlinkWindow(PWINDOW_OBJECT Wnd
)
1061 PWINDOW_OBJECT WndParent
= Wnd
->Parent
;
1063 if (Wnd
->NextSibling
)
1064 Wnd
->NextSibling
->PrevSibling
= Wnd
->PrevSibling
;
1065 else if (WndParent
&& WndParent
->LastChild
== Wnd
)
1066 WndParent
->LastChild
= Wnd
->PrevSibling
;
1068 if (Wnd
->PrevSibling
)
1069 Wnd
->PrevSibling
->NextSibling
= Wnd
->NextSibling
;
1070 else if (WndParent
&& WndParent
->FirstChild
== Wnd
)
1071 WndParent
->FirstChild
= Wnd
->NextSibling
;
1073 Wnd
->PrevSibling
= Wnd
->NextSibling
= Wnd
->Parent
= NULL
;
1079 PWINDOW_OBJECT Window
, Child
;
1081 if(!(Window
= IntGetWindowObject(IntGetDesktopWindow())))
1083 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1087 for(Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
1089 if(Child
->hOwner
&& Child
->Style
& WS_VISIBLE
)
1092 * The desktop has a popup window if one of them has
1093 * an owner window and is visible
1095 IntReleaseWindowObject(Window
);
1100 IntReleaseWindowObject(Window
);
1105 IntIsWindowInDestroy(PWINDOW_OBJECT Window
)
1107 return ((Window
->Status
& WINDOWSTATUS_DESTROYING
) == WINDOWSTATUS_DESTROYING
);
1110 /* FUNCTIONS *****************************************************************/
1116 NtUserAlterWindowStyle(DWORD Unknown0
,
1127 * As best as I can figure, this function is used by EnumWindows,
1128 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
1130 * It's supposed to build a list of HWNDs to return to the caller.
1131 * We can figure out what kind of list by what parameters are
1139 NtUserBuildHwndList(
1151 /* FIXME handle bChildren */
1155 PWINDOW_OBJECT Window
, Child
;
1156 if(!(Window
= IntGetWindowObject(hwndParent
)))
1158 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1162 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1164 if(dwCount
++ < nBufSize
&& pWnd
)
1166 Status
= MmCopyToCaller(pWnd
++, &Child
->hSelf
, sizeof(HWND
));
1167 if(!NT_SUCCESS(Status
))
1169 SetLastNtError(Status
);
1175 IntReleaseWindowObject(Window
);
1180 PW32THREAD W32Thread
;
1181 PLIST_ENTRY Current
;
1182 PWINDOW_OBJECT Window
;
1184 Status
= PsLookupThreadByThreadId((HANDLE
)dwThreadId
, &Thread
);
1185 if(!NT_SUCCESS(Status
))
1187 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1190 if(!(W32Thread
= Thread
->Tcb
.Win32Thread
))
1192 ObDereferenceObject(Thread
);
1193 DPRINT("Thread is not a GUI Thread!\n");
1194 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1198 Current
= W32Thread
->WindowListHead
.Flink
;
1199 while(Current
!= &(W32Thread
->WindowListHead
))
1201 Window
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
1204 if(dwCount
< nBufSize
&& pWnd
)
1206 Status
= MmCopyToCaller(pWnd
++, &Window
->hSelf
, sizeof(HWND
));
1207 if(!NT_SUCCESS(Status
))
1209 SetLastNtError(Status
);
1214 Current
= Current
->Flink
;
1217 ObDereferenceObject(Thread
);
1221 PDESKTOP_OBJECT Desktop
;
1222 PWINDOW_OBJECT Window
, Child
;
1224 if(hDesktop
== NULL
&& !(Desktop
= IntGetActiveDesktop()))
1226 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1232 Status
= IntValidateDesktopHandle(hDesktop
,
1236 if(!NT_SUCCESS(Status
))
1238 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1242 if(!(Window
= IntGetWindowObject(Desktop
->DesktopWindow
)))
1245 ObDereferenceObject(Desktop
);
1246 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1250 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1252 if(dwCount
++ < nBufSize
&& pWnd
)
1254 Status
= MmCopyToCaller(pWnd
++, &Child
->hSelf
, sizeof(HWND
));
1255 if(!NT_SUCCESS(Status
))
1257 SetLastNtError(Status
);
1263 IntReleaseWindowObject(Window
);
1265 ObDereferenceObject(Desktop
);
1276 NtUserChildWindowFromPointEx(HWND hwndParent
,
1281 PWINDOW_OBJECT Parent
;
1286 if(!(Parent
= IntGetWindowObject(hwndParent
)))
1288 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1295 if(Parent
->hSelf
!= IntGetDesktopWindow())
1297 Pt
.x
+= Parent
->ClientRect
.left
;
1298 Pt
.y
+= Parent
->ClientRect
.top
;
1301 if(!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
))
1303 IntReleaseWindowObject(Parent
);
1307 Ret
= Parent
->hSelf
;
1308 if((List
= IntWinListChildren(Parent
)))
1310 for(phWnd
= List
; *phWnd
; phWnd
++)
1312 PWINDOW_OBJECT Child
;
1313 if((Child
= IntGetWindowObject(*phWnd
)))
1315 if(!(Child
->Style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
))
1317 IntReleaseWindowObject(Child
);
1320 if((Child
->Style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
))
1322 IntReleaseWindowObject(Child
);
1325 if((Child
->ExStyle
& WS_EX_TRANSPARENT
) && (uiFlags
& CWP_SKIPTRANSPARENT
))
1327 IntReleaseWindowObject(Child
);
1330 if(IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
1333 IntReleaseWindowObject(Child
);
1336 IntReleaseWindowObject(Child
);
1342 IntReleaseWindowObject(Parent
);
1348 * calculates the default position of a window
1351 IntCalcDefPosSize(PWINDOW_OBJECT Parent
, PWINDOW_OBJECT Window
, RECT
*rc
, BOOL IncPos
)
1358 IntGdiIntersectRect(rc
, rc
, &Parent
->ClientRect
);
1362 Pos
.x
= Parent
->TiledCounter
* (UserGetSystemMetrics(SM_CXSIZE
) + UserGetSystemMetrics(SM_CXFRAME
));
1363 Pos
.y
= Parent
->TiledCounter
* (UserGetSystemMetrics(SM_CYSIZE
) + UserGetSystemMetrics(SM_CYFRAME
));
1364 if(Pos
.x
> ((rc
->right
- rc
->left
) / 4) ||
1365 Pos
.y
> ((rc
->bottom
- rc
->top
) / 4))
1367 /* reset counter and position */
1370 Parent
->TiledCounter
= 0;
1372 Parent
->TiledCounter
++;
1383 Sz
.cx
= EngMulDiv(rc
->right
- rc
->left
, 3, 4);
1384 Sz
.cy
= EngMulDiv(rc
->bottom
- rc
->top
, 3, 4);
1388 rc
->right
= rc
->left
+ Sz
.cx
;
1389 rc
->bottom
= rc
->top
+ Sz
.cy
;
1398 co_IntCreateWindowEx(DWORD dwExStyle
,
1399 PUNICODE_STRING ClassName
,
1400 PUNICODE_STRING WindowName
,
1408 HINSTANCE hInstance
,
1411 BOOL bUnicodeWindow
)
1413 PWINSTATION_OBJECT WinSta
;
1414 PWNDCLASS_OBJECT Class
;
1415 PWINDOW_OBJECT Window
= NULL
;
1416 PWINDOW_OBJECT ParentWindow
= NULL
, OwnerWindow
;
1417 HWND ParentWindowHandle
;
1418 HWND OwnerWindowHandle
;
1419 PMENU_OBJECT SystemMenu
;
1425 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1432 CBT_CREATEWNDW CbtCreate
;
1436 DECLARE_RETURN(HWND
);
1439 ParentWindowHandle
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
1440 OwnerWindowHandle
= NULL
;
1442 if (hWndParent
== HWND_MESSAGE
)
1445 * native ole32.OleInitialize uses HWND_MESSAGE to create the
1446 * message window (style: WS_POPUP|WS_DISABLED)
1448 DPRINT1("FIXME - Parent is HWND_MESSAGE\n");
1450 else if (hWndParent
)
1452 if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1453 ParentWindowHandle
= hWndParent
;
1457 PWINDOW_OBJECT Par
= UserGetWindowObject(hWndParent
);
1459 OwnerWindowHandle
= UserGetAncestor(Par
, GA_ROOT
)->hSelf
;
1462 else if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1464 RETURN( (HWND
)0); /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1467 if (NULL
!= ParentWindowHandle
)
1469 ParentWindow
= UserGetWindowObject(ParentWindowHandle
);
1472 UserRefObjectCo(ParentWindow
);
1476 ParentWindow
= NULL
;
1479 /* FIXME: parent must belong to the current process */
1481 /* Check the class. */
1482 ClassFound
= ClassReferenceClassByNameOrAtom(&Class
, ClassName
->Buffer
, hInstance
);
1485 if (IS_ATOM(ClassName
->Buffer
))
1487 DPRINT1("Class 0x%x not found\n", (DWORD_PTR
) ClassName
->Buffer
);
1491 DPRINT1("Class %wZ not found\n", ClassName
);
1494 SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS
);
1498 /* Check the window station. */
1499 if (PsGetWin32Thread()->Desktop
== NULL
)
1501 ClassDereferenceObject(Class
);
1503 DPRINT("Thread is not attached to a desktop! Cannot create window!\n");
1506 WinSta
= PsGetWin32Thread()->Desktop
->WindowStation
;
1507 ObReferenceObjectByPointer(WinSta
, KernelMode
, ExWindowStationObjectType
, 0);
1509 /* Create the window object. */
1510 Window
= (PWINDOW_OBJECT
)
1511 ObmCreateObject(&gHandleTable
, &Handle
,
1512 otWindow
, sizeof(WINDOW_OBJECT
) + Class
->cbWndExtra
1515 DPRINT("Created object with handle %X\n", Handle
);
1518 ObDereferenceObject(WinSta
);
1519 ClassDereferenceObject(Class
);
1520 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1524 UserRefObjectCo(Window
);
1527 ObDereferenceObject(WinSta
);
1529 if (NULL
== PsGetWin32Thread()->Desktop
->DesktopWindow
)
1531 /* If there is no desktop window yet, we must be creating it */
1532 PsGetWin32Thread()->Desktop
->DesktopWindow
= Handle
;
1536 * Fill out the structure describing it.
1538 Window
->Class
= Class
;
1540 InsertTailList(&Class
->ClassWindowsListHead
, &Window
->ClassListEntry
);
1542 Window
->ExStyle
= dwExStyle
;
1543 Window
->Style
= dwStyle
& ~WS_VISIBLE
;
1544 DPRINT("1: Style is now %lx\n", Window
->Style
);
1546 Window
->SystemMenu
= (HMENU
)0;
1547 Window
->ContextHelpId
= 0;
1549 Window
->Instance
= hInstance
;
1550 Window
->hSelf
= Handle
;
1551 if (0 != (dwStyle
& WS_CHILD
))
1553 Window
->IDMenu
= (UINT
) hMenu
;
1557 IntSetMenu(Window
, hMenu
, &MenuChanged
);
1559 Window
->MessageQueue
= PsGetWin32Thread()->MessageQueue
;
1560 IntReferenceMessageQueue(Window
->MessageQueue
);
1561 Window
->Parent
= ParentWindow
;
1562 if((OwnerWindow
= IntGetWindowObject(OwnerWindowHandle
)))
1564 Window
->hOwner
= OwnerWindowHandle
;
1565 IntReleaseWindowObject(OwnerWindow
);
1570 Window
->hOwner
= NULL
;
1573 Window
->UserData
= 0;
1574 if ((((DWORD
)Class
->lpfnWndProcA
& 0xFFFF0000) != 0xFFFF0000)
1575 && (((DWORD
)Class
->lpfnWndProcW
& 0xFFFF0000) != 0xFFFF0000))
1577 Window
->Unicode
= bUnicodeWindow
;
1581 Window
->Unicode
= Class
->Unicode
;
1583 Window
->WndProcA
= Class
->lpfnWndProcA
;
1584 Window
->WndProcW
= Class
->lpfnWndProcW
;
1585 Window
->OwnerThread
= PsGetCurrentThread();
1586 Window
->FirstChild
= NULL
;
1587 Window
->LastChild
= NULL
;
1588 Window
->PrevSibling
= NULL
;
1589 Window
->NextSibling
= NULL
;
1591 /* extra window data */
1592 if (Class
->cbWndExtra
!= 0)
1594 Window
->ExtraData
= (PCHAR
)(Window
+ 1);
1595 Window
->ExtraDataSize
= Class
->cbWndExtra
;
1596 RtlZeroMemory(Window
->ExtraData
, Window
->ExtraDataSize
);
1600 Window
->ExtraData
= NULL
;
1601 Window
->ExtraDataSize
= 0;
1604 InitializeListHead(&Window
->PropListHead
);
1605 InitializeListHead(&Window
->WndObjListHead
);
1607 if (NULL
!= WindowName
->Buffer
)
1609 Window
->WindowName
.MaximumLength
= WindowName
->MaximumLength
;
1610 Window
->WindowName
.Length
= WindowName
->Length
;
1611 Window
->WindowName
.Buffer
= ExAllocatePoolWithTag(PagedPool
, WindowName
->MaximumLength
,
1613 if (NULL
== Window
->WindowName
.Buffer
)
1615 ClassDereferenceObject(Class
);
1616 DPRINT1("Failed to allocate mem for window name\n");
1617 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1620 RtlCopyMemory(Window
->WindowName
.Buffer
, WindowName
->Buffer
, WindowName
->MaximumLength
);
1624 RtlInitUnicodeString(&Window
->WindowName
, NULL
);
1629 * This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1630 * tested for WS_POPUP
1632 if ((dwExStyle
& WS_EX_DLGMODALFRAME
) ||
1633 ((!(dwExStyle
& WS_EX_STATICEDGE
)) &&
1634 (dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
))))
1635 dwExStyle
|= WS_EX_WINDOWEDGE
;
1637 dwExStyle
&= ~WS_EX_WINDOWEDGE
;
1639 /* Correct the window style. */
1640 if (!(dwStyle
& WS_CHILD
))
1642 Window
->Style
|= WS_CLIPSIBLINGS
;
1643 DPRINT("3: Style is now %lx\n", Window
->Style
);
1644 if (!(dwStyle
& WS_POPUP
))
1646 Window
->Style
|= WS_CAPTION
;
1647 Window
->Flags
|= WINDOWOBJECT_NEED_SIZE
;
1648 DPRINT("4: Style is now %lx\n", Window
->Style
);
1652 /* create system menu */
1653 if((Window
->Style
& WS_SYSMENU
) &&
1654 (Window
->Style
& WS_CAPTION
) == WS_CAPTION
)
1656 SystemMenu
= IntGetSystemMenu(Window
, TRUE
, TRUE
);
1659 Window
->SystemMenu
= SystemMenu
->MenuInfo
.Self
;
1660 IntReleaseMenuObject(SystemMenu
);
1664 /* Insert the window into the thread's window list. */
1665 InsertTailList (&PsGetWin32Thread()->WindowListHead
, &Window
->ThreadListEntry
);
1667 /* Allocate a DCE for this window. */
1668 if (dwStyle
& CS_OWNDC
)
1670 Window
->Dce
= DceAllocDCE(Window
, DCE_WINDOW_DC
);
1672 /* FIXME: Handle "CS_CLASSDC" */
1680 Cs
.lpCreateParams
= lpParam
;
1681 Cs
.hInstance
= hInstance
;
1683 Cs
.hwndParent
= ParentWindowHandle
;
1689 Cs
.lpszName
= (LPCWSTR
) WindowName
;
1690 Cs
.lpszClass
= (LPCWSTR
) ClassName
;
1691 Cs
.dwExStyle
= dwExStyle
;
1692 CbtCreate
.lpcs
= &Cs
;
1693 CbtCreate
.hwndInsertAfter
= HWND_TOP
;
1694 if (co_HOOK_CallHooks(WH_CBT
, HCBT_CREATEWND
, (WPARAM
) Handle
, (LPARAM
) &CbtCreate
))
1697 /* FIXME - Delete window object and remove it from the thread windows list */
1698 /* FIXME - delete allocated DCE */
1700 ClassDereferenceObject(Class
);
1701 DPRINT1("CBT-hook returned !0\n");
1702 RETURN( (HWND
) NULL
);
1710 /* default positioning for overlapped windows */
1711 if(!(Window
->Style
& (WS_POPUP
| WS_CHILD
)))
1714 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
1715 BOOL CalculatedDefPosSize
= FALSE
;
1717 IntGetDesktopWorkArea(Window
->OwnerThread
->Tcb
.Win32Thread
->Desktop
, &WorkArea
);
1720 ProcessParams
= PsGetCurrentProcess()->Peb
->ProcessParameters
;
1722 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1724 CalculatedDefPosSize
= IntCalcDefPosSize(ParentWindow
, Window
, &rc
, TRUE
);
1726 if(ProcessParams
->WindowFlags
& STARTF_USEPOSITION
)
1728 ProcessParams
->WindowFlags
&= ~STARTF_USEPOSITION
;
1729 Pos
.x
= WorkArea
.left
+ ProcessParams
->StartingX
;
1730 Pos
.y
= WorkArea
.top
+ ProcessParams
->StartingY
;
1738 /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
1739 y is something else */
1740 if(y
!= CW_USEDEFAULT
&& y
!= CW_USEDEFAULT16
)
1745 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1747 if(!CalculatedDefPosSize
)
1749 IntCalcDefPosSize(ParentWindow
, Window
, &rc
, FALSE
);
1751 if(ProcessParams
->WindowFlags
& STARTF_USESIZE
)
1753 ProcessParams
->WindowFlags
&= ~STARTF_USESIZE
;
1754 Size
.cx
= ProcessParams
->CountX
;
1755 Size
.cy
= ProcessParams
->CountY
;
1759 Size
.cx
= rc
.right
- rc
.left
;
1760 Size
.cy
= rc
.bottom
- rc
.top
;
1763 /* move the window if necessary */
1765 Pos
.x
= max(rc
.left
, 0);
1767 Pos
.y
= max(rc
.top
, 0);
1772 /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
1773 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1778 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1785 /* Initialize the window dimensions. */
1786 Window
->WindowRect
.left
= Pos
.x
;
1787 Window
->WindowRect
.top
= Pos
.y
;
1788 Window
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1789 Window
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1790 if (0 != (Window
->Style
& WS_CHILD
) && ParentWindow
)
1792 IntGdiOffsetRect(&(Window
->WindowRect
), ParentWindow
->ClientRect
.left
,
1793 ParentWindow
->ClientRect
.top
);
1795 Window
->ClientRect
= Window
->WindowRect
;
1798 * Get the size and position of the window.
1800 if ((dwStyle
& WS_THICKFRAME
) || !(dwStyle
& (WS_POPUP
| WS_CHILD
)))
1802 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1804 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1805 co_WinPosGetMinMaxInfo(Window
, &MaxSize
, &MaxPos
, &MinTrack
,
1807 if (MaxSize
.x
< nWidth
)
1809 if (MaxSize
.y
< nHeight
)
1810 nHeight
= MaxSize
.y
;
1811 if (nWidth
< MinTrack
.x
)
1812 nWidth
= MinTrack
.x
;
1813 if (nHeight
< MinTrack
.y
)
1814 nHeight
= MinTrack
.y
;
1821 Window
->WindowRect
.left
= Pos
.x
;
1822 Window
->WindowRect
.top
= Pos
.y
;
1823 Window
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1824 Window
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1825 if (0 != (Window
->Style
& WS_CHILD
) && ParentWindow
)
1827 IntGdiOffsetRect(&(Window
->WindowRect
), ParentWindow
->ClientRect
.left
,
1828 ParentWindow
->ClientRect
.top
);
1830 Window
->ClientRect
= Window
->WindowRect
;
1832 /* FIXME: Initialize the window menu. */
1834 /* Send a NCCREATE message. */
1840 DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d\n", Cs
.style
, Cs
.dwExStyle
, Cs
.hwndParent
);
1841 DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1842 DPRINT("IntCreateWindowEx(): About to send NCCREATE message.\n");
1843 Result
= co_IntSendMessage(Window
->hSelf
, WM_NCCREATE
, 0, (LPARAM
) &Cs
);
1846 /* FIXME: Cleanup. */
1847 DPRINT("IntCreateWindowEx(): NCCREATE message failed.\n");
1851 /* Calculate the non-client size. */
1852 MaxPos
.x
= Window
->WindowRect
.left
;
1853 MaxPos
.y
= Window
->WindowRect
.top
;
1854 DPRINT("IntCreateWindowEx(): About to get non-client size.\n");
1855 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1856 Result
= co_WinPosGetNonClientSize(Window
,
1857 &Window
->WindowRect
,
1858 &Window
->ClientRect
);
1859 IntGdiOffsetRect(&Window
->WindowRect
,
1860 MaxPos
.x
- Window
->WindowRect
.left
,
1861 MaxPos
.y
- Window
->WindowRect
.top
);
1863 if (NULL
!= ParentWindow
)
1865 /* link the window into the parent's child list */
1866 if ((dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
1868 PWINDOW_OBJECT PrevSibling
;
1869 if((PrevSibling
= ParentWindow
->LastChild
))
1870 IntReferenceWindowObject(PrevSibling
);
1871 /* link window as bottom sibling */
1872 IntLinkWindow(Window
, ParentWindow
, PrevSibling
/*prev sibling*/);
1874 IntReleaseWindowObject(PrevSibling
);
1878 /* link window as top sibling (but after topmost siblings) */
1879 PWINDOW_OBJECT InsertAfter
, Sibling
;
1880 if (0 == (dwExStyle
& WS_EX_TOPMOST
))
1883 Sibling
= ParentWindow
->FirstChild
;
1884 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
1886 InsertAfter
= Sibling
;
1887 Sibling
= Sibling
->NextSibling
;
1894 if (NULL
!= InsertAfter
)
1896 IntReferenceWindowObject(InsertAfter
);
1898 IntLinkWindow(Window
, ParentWindow
, InsertAfter
/* prev sibling */);
1899 if (NULL
!= InsertAfter
)
1901 IntReleaseWindowObject(InsertAfter
);
1906 /* Send the WM_CREATE message. */
1907 DPRINT("IntCreateWindowEx(): about to send CREATE message.\n");
1908 Result
= co_IntSendMessage(Window
->hSelf
, WM_CREATE
, 0, (LPARAM
) &Cs
);
1909 if (Result
== (LRESULT
)-1)
1911 /* FIXME: Cleanup. */
1912 ClassDereferenceObject(Class
);
1913 DPRINT("IntCreateWindowEx(): send CREATE message failed.\n");
1917 /* Send move and size messages. */
1918 if (!(Window
->Flags
& WINDOWOBJECT_NEED_SIZE
))
1922 DPRINT("IntCreateWindow(): About to send WM_SIZE\n");
1924 if ((Window
->ClientRect
.right
- Window
->ClientRect
.left
) < 0 ||
1925 (Window
->ClientRect
.bottom
- Window
->ClientRect
.top
) < 0)
1927 DPRINT("Sending bogus WM_SIZE\n");
1930 lParam
= MAKE_LONG(Window
->ClientRect
.right
-
1931 Window
->ClientRect
.left
,
1932 Window
->ClientRect
.bottom
-
1933 Window
->ClientRect
.top
);
1934 co_IntSendMessage(Window
->hSelf
, WM_SIZE
, SIZE_RESTORED
,
1937 DPRINT("IntCreateWindow(): About to send WM_MOVE\n");
1939 if (0 != (Window
->Style
& WS_CHILD
) && ParentWindow
)
1941 lParam
= MAKE_LONG(Window
->ClientRect
.left
- ParentWindow
->ClientRect
.left
,
1942 Window
->ClientRect
.top
- ParentWindow
->ClientRect
.top
);
1946 lParam
= MAKE_LONG(Window
->ClientRect
.left
,
1947 Window
->ClientRect
.top
);
1949 co_IntSendMessage(Window
->hSelf
, WM_MOVE
, 0, lParam
);
1951 /* Call WNDOBJ change procs */
1952 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
1955 /* Show or maybe minimize or maximize the window. */
1956 if (Window
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1961 SwFlag
= (Window
->Style
& WS_MINIMIZE
) ? SW_MINIMIZE
:
1963 co_WinPosMinMaximize(Window
, SwFlag
, &NewPos
);
1965 ((Window
->Style
& WS_CHILD
) || UserGetActiveWindow()) ?
1966 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
:
1967 SWP_NOZORDER
| SWP_FRAMECHANGED
;
1968 DPRINT("IntCreateWindow(): About to minimize/maximize\n");
1969 DPRINT("%d,%d %dx%d\n", NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
);
1970 co_WinPosSetWindowPos(Window
, 0, NewPos
.left
, NewPos
.top
,
1971 NewPos
.right
, NewPos
.bottom
, SwFlag
);
1974 /* Notify the parent window of a new child. */
1975 if ((Window
->Style
& WS_CHILD
) &&
1976 (!(Window
->ExStyle
& WS_EX_NOPARENTNOTIFY
)) && ParentWindow
)
1978 DPRINT("IntCreateWindow(): About to notify parent\n");
1979 co_IntSendMessage(ParentWindow
->hSelf
,
1981 MAKEWPARAM(WM_CREATE
, Window
->IDMenu
),
1982 (LPARAM
)Window
->hSelf
);
1985 if ((!hWndParent
) && (!HasOwner
))
1987 DPRINT("Sending CREATED notify\n");
1988 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Handle
);
1992 DPRINT("Not sending CREATED notify, %x %d\n", ParentWindow
, HasOwner
);
1995 /* Initialize and show the window's scrollbars */
1996 if (Window
->Style
& WS_VSCROLL
)
1998 co_UserShowScrollBar(Window
, SB_VERT
, TRUE
);
2000 if (Window
->Style
& WS_HSCROLL
)
2002 co_UserShowScrollBar(Window
, SB_HORZ
, TRUE
);
2005 if (dwStyle
& WS_VISIBLE
)
2007 DPRINT("IntCreateWindow(): About to show window\n");
2008 co_WinPosShowWindow(Window
, dwShowMode
);
2011 DPRINT("IntCreateWindow(): = %X\n", Handle
);
2012 DPRINT("WindowObject->SystemMenu = 0x%x\n", Window
->SystemMenu
);
2013 RETURN((HWND
)Handle
);
2017 UserDerefObjectCo(Window
);
2019 UserDerefObjectCo(ParentWindow
);
2025 NtUserCreateWindowEx(DWORD dwExStyle
,
2026 PUNICODE_STRING UnsafeClassName
,
2027 PUNICODE_STRING UnsafeWindowName
,
2035 HINSTANCE hInstance
,
2038 BOOL bUnicodeWindow
)
2041 UNICODE_STRING WindowName
;
2042 UNICODE_STRING ClassName
;
2044 DECLARE_RETURN(HWND
);
2046 DPRINT("Enter NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
2047 UserEnterExclusive();
2049 /* Get the class name (string or atom) */
2050 Status
= MmCopyFromCaller(&ClassName
, UnsafeClassName
, sizeof(UNICODE_STRING
));
2051 if (! NT_SUCCESS(Status
))
2053 SetLastNtError(Status
);
2056 if (! IS_ATOM(ClassName
.Buffer
))
2058 Status
= IntSafeCopyUnicodeStringTerminateNULL(&ClassName
, UnsafeClassName
);
2059 if (! NT_SUCCESS(Status
))
2061 SetLastNtError(Status
);
2066 /* safely copy the window name */
2067 if (NULL
!= UnsafeWindowName
)
2069 Status
= IntSafeCopyUnicodeString(&WindowName
, UnsafeWindowName
);
2070 if (! NT_SUCCESS(Status
))
2072 if (! IS_ATOM(ClassName
.Buffer
))
2074 RtlFreeUnicodeString(&ClassName
);
2076 SetLastNtError(Status
);
2082 RtlInitUnicodeString(&WindowName
, NULL
);
2085 NewWindow
= co_IntCreateWindowEx(dwExStyle
, &ClassName
, &WindowName
, dwStyle
, x
, y
, nWidth
, nHeight
,
2086 hWndParent
, hMenu
, hInstance
, lpParam
, dwShowMode
, bUnicodeWindow
);
2088 RtlFreeUnicodeString(&WindowName
);
2089 if (! IS_ATOM(ClassName
.Buffer
))
2091 RtlFreeUnicodeString(&ClassName
);
2097 DPRINT("Leave NtUserCreateWindowEx, ret=%i\n",_ret_
);
2106 NtUserDeferWindowPos(HDWP WinPosInfo
,
2108 HWND WndInsertAfter
,
2121 BOOLEAN FASTCALL
co_UserDestroyWindow(PWINDOW_OBJECT Window
)
2125 ASSERT_REFS_CO(Window
);
2132 /* Check for owner thread and desktop window */
2133 if ((Window
->OwnerThread
!= PsGetCurrentThread()) || IntIsDesktopWindow(Window
))
2135 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2139 /* Look whether the focus is within the tree of windows we will
2142 if (!co_WinPosShowWindow(Window
, SW_HIDE
))
2144 if (UserGetActiveWindow() == Window
->hSelf
)
2146 co_WinPosActivateOtherWindow(Window
);
2150 if (Window
->MessageQueue
->ActiveWindow
== Window
->hSelf
)
2151 Window
->MessageQueue
->ActiveWindow
= NULL
;
2152 if (Window
->MessageQueue
->FocusWindow
== Window
->hSelf
)
2153 Window
->MessageQueue
->FocusWindow
= NULL
;
2154 if (Window
->MessageQueue
->CaptureWindow
== Window
->hSelf
)
2155 Window
->MessageQueue
->CaptureWindow
= NULL
;
2157 IntDereferenceMessageQueue(Window
->MessageQueue
);
2161 if (co_HOOK_CallHooks(WH_CBT
, HCBT_DESTROYWND
, (WPARAM
) hwnd
, 0, TRUE
))
2167 IntEngWindowChanged(Window
, WOC_DELETE
);
2168 isChild
= (0 != (Window
->Style
& WS_CHILD
));
2174 if (! USER_IsExitingThread(GetCurrentThreadId()))
2176 send_parent_notify(hwnd
, WM_DESTROY
);
2179 else if (NULL
!= GetWindow(Wnd
, GW_OWNER
))
2181 co_HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
2182 /* FIXME: clean up palette - see "Internals" p.352 */
2186 if (!IntIsWindow(Window
->hSelf
))
2191 /* Recursively destroy owned windows */
2196 BOOL GotOne
= FALSE
;
2199 PWINDOW_OBJECT Child
, Desktop
;
2201 Desktop
= IntGetWindowObject(IntGetDesktopWindow());
2202 Children
= IntWinListChildren(Desktop
);
2203 IntReleaseWindowObject(Desktop
);
2206 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
2208 Child
= IntGetWindowObject(*ChildHandle
);
2211 if (Child
->hOwner
!= Window
->hSelf
)
2213 IntReleaseWindowObject(Child
);
2217 if (IntWndBelongsToThread(Child
, PsGetWin32Thread()))
2219 co_UserDestroyWindow(Child
);
2220 IntReleaseWindowObject(Child
);
2225 if (Child
->hOwner
!= NULL
)
2227 Child
->hOwner
= NULL
;
2230 IntReleaseWindowObject(Child
);
2232 ExFreePool(Children
);
2241 if (!IntIsWindow(Window
->hSelf
))
2246 /* Destroy the window storage */
2247 co_IntDestroyWindow(Window
, PsGetWin32Process(), PsGetWin32Thread(), TRUE
);
2259 NtUserDestroyWindow(HWND Wnd
)
2261 PWINDOW_OBJECT Window
;
2262 DECLARE_RETURN(BOOLEAN
);
2264 DPRINT("Enter NtUserDestroyWindow\n");
2265 UserEnterExclusive();
2267 Window
= IntGetWindowObject(Wnd
);
2273 RETURN(co_UserDestroyWindow(Window
));
2276 DPRINT("Leave NtUserDestroyWindow, ret=%i\n",_ret_
);
2288 NtUserDrawMenuBarTemp(
2295 /* we'll use this function just for caching the menu bar */
2305 NtUserEndDeferWindowPosEx(DWORD Unknown0
,
2318 NtUserFillWindow(DWORD Unknown0
,
2330 IntFindWindow(PWINDOW_OBJECT Parent
,
2331 PWINDOW_OBJECT ChildAfter
,
2333 PUNICODE_STRING WindowName
)
2335 BOOL CheckWindowName
;
2341 CheckWindowName
= (WindowName
&& (WindowName
->Length
> 0));
2343 if((List
= IntWinListChildren(Parent
)))
2348 /* skip handles before and including ChildAfter */
2349 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->hSelf
))
2353 /* search children */
2356 PWINDOW_OBJECT Child
;
2357 if(!(Child
= IntGetWindowObject(*(phWnd
++))))
2362 /* Do not send WM_GETTEXT messages in the kernel mode version!
2363 The user mode version however calls GetWindowText() which will
2364 send WM_GETTEXT messages to windows belonging to its processes */
2365 if((!CheckWindowName
|| !RtlCompareUnicodeString(WindowName
, &(Child
->WindowName
), FALSE
)) &&
2366 (!ClassAtom
|| Child
->Class
->Atom
== ClassAtom
))
2369 IntReleaseWindowObject(Child
);
2373 IntReleaseWindowObject(Child
);
2383 * Searches a window's children for a window with the specified
2386 * hwndParent = The window whose childs are to be searched.
2388 * HWND_MESSAGE = message-only windows
2390 * hwndChildAfter = Search starts after this child window.
2391 * NULL = start from beginning
2393 * ucClassName = Class name to search for
2394 * Reguired parameter.
2396 * ucWindowName = Window name
2397 * ->Buffer == NULL = don't care
2400 * The HWND of the window if it was found, otherwise NULL
2406 NtUserFindWindowEx(HWND hwndParent
,
2407 HWND hwndChildAfter
,
2408 PUNICODE_STRING ucClassName
,
2409 PUNICODE_STRING ucWindowName
)
2411 PWINDOW_OBJECT Parent
, ChildAfter
;
2412 UNICODE_STRING ClassName
, WindowName
;
2414 HWND Desktop
, Ret
= NULL
;
2416 DECLARE_RETURN(HWND
);
2418 DPRINT("Enter NtUserFindWindowEx\n");
2421 Desktop
= IntGetCurrentThreadDesktopWindow();
2423 if(hwndParent
== NULL
)
2424 hwndParent
= Desktop
;
2426 else if(hwndParent == HWND_MESSAGE)
2428 hwndParent = IntGetMessageWindow();
2432 if(!(Parent
= IntGetWindowObject(hwndParent
)))
2434 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2439 if(hwndChildAfter
&& !(ChildAfter
= IntGetWindowObject(hwndChildAfter
)))
2441 IntReleaseWindowObject(Parent
);
2442 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2446 /* copy the window name */
2447 Status
= IntSafeCopyUnicodeString(&WindowName
, ucWindowName
);
2448 if(!NT_SUCCESS(Status
))
2450 SetLastNtError(Status
);
2454 /* safely copy the class name */
2455 Status
= MmCopyFromCaller(&ClassName
, ucClassName
, sizeof(UNICODE_STRING
));
2456 if(!NT_SUCCESS(Status
))
2458 SetLastNtError(Status
);
2461 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2464 /* safely copy the class name string (NULL terminated because class-lookup
2466 buf
= ExAllocatePoolWithTag(PagedPool
, ClassName
.Length
+ sizeof(WCHAR
), TAG_STRING
);
2469 SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES
);
2472 Status
= MmCopyFromCaller(buf
, ClassName
.Buffer
, ClassName
.Length
);
2473 if(!NT_SUCCESS(Status
))
2476 SetLastNtError(Status
);
2479 ClassName
.Buffer
= buf
;
2480 /* make sure the string is null-terminated */
2481 buf
+= ClassName
.Length
/ sizeof(WCHAR
);
2485 /* find the class object */
2486 if(ClassName
.Buffer
)
2488 PWINSTATION_OBJECT WinStaObject
;
2490 if (PsGetWin32Thread()->Desktop
== NULL
)
2492 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2496 WinStaObject
= PsGetWin32Thread()->Desktop
->WindowStation
;
2498 Status
= RtlLookupAtomInAtomTable(
2499 WinStaObject
->AtomTable
,
2503 if (!NT_SUCCESS(Status
))
2505 DPRINT1("Failed to lookup class atom!\n");
2506 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST
);
2511 if(Parent
->hSelf
== Desktop
)
2514 PWINDOW_OBJECT TopLevelWindow
;
2515 BOOLEAN CheckWindowName
;
2516 BOOLEAN CheckClassName
;
2517 BOOLEAN WindowMatches
;
2518 BOOLEAN ClassMatches
;
2520 /* windows searches through all top-level windows if the parent is the desktop
2523 if((List
= IntWinListChildren(Parent
)))
2529 /* skip handles before and including ChildAfter */
2530 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->hSelf
))
2534 CheckWindowName
= WindowName
.Length
> 0;
2535 CheckClassName
= ClassName
.Buffer
!= NULL
;
2537 /* search children */
2540 if(!(TopLevelWindow
= IntGetWindowObject(*(phWnd
++))))
2545 /* Do not send WM_GETTEXT messages in the kernel mode version!
2546 The user mode version however calls GetWindowText() which will
2547 send WM_GETTEXT messages to windows belonging to its processes */
2548 WindowMatches
= !CheckWindowName
|| !RtlCompareUnicodeString(
2549 &WindowName
, &TopLevelWindow
->WindowName
, FALSE
);
2550 ClassMatches
= !CheckClassName
||
2551 ClassAtom
== TopLevelWindow
->Class
->Atom
;
2553 if (WindowMatches
&& ClassMatches
)
2555 Ret
= TopLevelWindow
->hSelf
;
2556 IntReleaseWindowObject(TopLevelWindow
);
2560 if (IntFindWindow(TopLevelWindow
, NULL
, ClassAtom
, &WindowName
))
2562 /* window returns the handle of the top-level window, in case it found
2564 Ret
= TopLevelWindow
->hSelf
;
2565 IntReleaseWindowObject(TopLevelWindow
);
2569 IntReleaseWindowObject(TopLevelWindow
);
2575 Ret
= IntFindWindow(Parent
, ChildAfter
, ClassAtom
, &WindowName
);
2579 if(Ret
== NULL
&& hwndParent
== NULL
&& hwndChildAfter
== NULL
)
2581 /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
2582 search the message-only windows. Should this also be done if
2583 Parent is the desktop window??? */
2584 PWINDOW_OBJECT MsgWindows
;
2586 if((MsgWindows
= IntGetWindowObject(IntGetMessageWindow())))
2588 Ret
= IntFindWindow(MsgWindows
, ChildAfter
, ClassAtom
, &WindowName
);
2589 IntReleaseWindowObject(MsgWindows
);
2595 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2596 ExFreePool(ClassName
.Buffer
);
2599 RtlFreeUnicodeString(&WindowName
);
2603 IntReleaseWindowObject(ChildAfter
);
2604 IntReleaseWindowObject(Parent
);
2609 DPRINT("Leave NtUserFindWindowEx, ret %i\n",_ret_
);
2619 NtUserFlashWindowEx(DWORD Unknown0
)
2630 PWINDOW_OBJECT FASTCALL
UserGetAncestor(PWINDOW_OBJECT Wnd
, UINT Type
)
2632 PWINDOW_OBJECT WndAncestor
, Parent
;
2634 if (Wnd
->hSelf
== IntGetDesktopWindow())
2643 WndAncestor
= Wnd
->Parent
;
2656 if(!(Parent
= WndAncestor
->Parent
))
2660 if(IntIsDesktopWindow(Parent
))
2665 WndAncestor
= Parent
;
2678 Parent
= IntGetParent(WndAncestor
);
2686 UserDerefObject(Parent
);
2688 WndAncestor
= Parent
;
2708 NtUserGetAncestor(HWND hWnd
, UINT Type
)
2710 PWINDOW_OBJECT Window
, Ancestor
;
2711 DECLARE_RETURN(HWND
);
2713 DPRINT("Enter NtUserGetAncestor\n");
2714 UserEnterExclusive();
2716 if (!(Window
= UserGetWindowObject(hWnd
)))
2721 Ancestor
= UserGetAncestor(Window
, Type
);
2722 /* faxme: can UserGetAncestor ever return NULL for a valid window? */
2724 RETURN(Ancestor
? Ancestor
->hSelf
: NULL
);
2727 DPRINT("Leave NtUserGetAncestor, ret=%i\n",_ret_
);
2733 * Returns client window rectangle relative to the upper-left corner of client area.
2735 * \param hWnd window handle.
2736 * \param Rect pointer to the buffer where the coordinates are returned.
2743 NtUserGetClientRect(HWND hWnd
, LPRECT Rect
)
2745 PWINDOW_OBJECT Window
;
2747 DECLARE_RETURN(BOOL
);
2749 DPRINT("Enter NtUserGetClientRect\n");
2752 if(!(Window
= IntGetWindowObject(hWnd
)))
2754 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2758 IntGetClientRect(Window
, &SafeRect
);
2759 IntReleaseWindowObject(Window
);
2761 if(!NT_SUCCESS(MmCopyToCaller(Rect
, &SafeRect
, sizeof(RECT
))))
2768 DPRINT("Leave NtUserGetClientRect, ret=%i\n",_ret_
);
2778 NtUserGetDesktopWindow()
2780 DECLARE_RETURN(HWND
);
2782 DPRINT("Enter NtUserGetDesktopWindow\n");
2785 RETURN( IntGetDesktopWindow());
2788 DPRINT("Leave NtUserGetDesktopWindow, ret=%i\n",_ret_
);
2798 NtUserGetInternalWindowPos(DWORD Unknown0
,
2812 NtUserGetLastActivePopup(HWND hWnd
)
2815 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2816 * not changed anywhere.
2817 * -- Filip, 01/nov/2003
2823 IntAcquireWinLockShared();
2825 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2827 IntReleaseWinLock();
2828 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2832 hWndLastPopup
= Wnd
->hWndLastPopup
;
2834 IntReleaseWinLock();
2836 return hWndLastPopup
;
2846 * The NtUserGetParent function retrieves a handle to the specified window's
2850 * Note that, despite its name, this function can return an owner window
2851 * instead of a parent window.
2858 NtUserGetParent(HWND hWnd
)
2860 PWINDOW_OBJECT Wnd
, WndParent
;
2861 HWND hWndParent
= NULL
;
2862 DECLARE_RETURN(HWND
);
2864 DPRINT("Enter NtUserGetParent\n");
2865 UserEnterExclusive();
2867 if (!(Wnd
= IntGetWindowObject(hWnd
)))
2869 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2873 WndParent
= IntGetParent(Wnd
);
2876 hWndParent
= WndParent
->hSelf
;
2877 IntReleaseWindowObject(WndParent
);
2880 IntReleaseWindowObject(Wnd
);
2882 RETURN( hWndParent
);
2885 DPRINT("Leave NtUserGetParent, ret=%i\n",_ret_
);
2894 co_UserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2896 PWINDOW_OBJECT Wnd
= NULL
, WndParent
= NULL
, WndOldParent
;
2897 HWND hWndOldParent
= NULL
;
2899 if (IntIsBroadcastHwnd(hWndChild
) || IntIsBroadcastHwnd(hWndNewParent
))
2901 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2905 if (hWndChild
== IntGetDesktopWindow())
2907 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2913 if (!(WndParent
= IntGetWindowObject(hWndNewParent
)))
2915 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2921 if (!(WndParent
= IntGetWindowObject(IntGetDesktopWindow())))
2923 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2928 if (!(Wnd
= IntGetWindowObject(hWndChild
)))
2930 IntReleaseWindowObject(WndParent
);
2931 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
2935 WndOldParent
= co_IntSetParent(Wnd
, WndParent
);
2939 hWndOldParent
= WndOldParent
->hSelf
;
2940 IntReleaseWindowObject(WndOldParent
);
2943 IntReleaseWindowObject(Wnd
);
2944 IntReleaseWindowObject(WndParent
);
2946 return( hWndOldParent
);
2954 * The NtUserSetParent function changes the parent window of the specified
2958 * The new parent window and the child window must belong to the same
2959 * application. If the window identified by the hWndChild parameter is
2960 * visible, the system performs the appropriate redrawing and repainting.
2961 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2962 * or WS_POPUP window styles of the window whose parent is being changed.
2969 NtUserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2971 DECLARE_RETURN(HWND
);
2973 DPRINT("Enter NtUserSetParent\n");
2974 UserEnterExclusive();
2976 RETURN( co_UserSetParent(hWndChild
, hWndNewParent
));
2979 DPRINT("Leave NtUserSetParent, ret=%i\n",_ret_
);
2987 HWND FASTCALL
UserGetShellWindow()
2989 PWINSTATION_OBJECT WinStaObject
;
2992 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
2997 if (!NT_SUCCESS(Status
))
2999 SetLastNtError(Status
);
3003 Ret
= (HWND
)WinStaObject
->ShellWindow
;
3005 ObDereferenceObject(WinStaObject
);
3011 * NtUserGetShellWindow
3013 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
3020 NtUserGetShellWindow()
3022 DECLARE_RETURN(HWND
);
3024 DPRINT("Enter NtUserGetShellWindow\n");
3027 RETURN( UserGetShellWindow() );
3030 DPRINT("Leave NtUserGetShellWindow, ret=%i\n",_ret_
);
3036 * NtUserSetShellWindowEx
3038 * This is undocumented function to set global shell window. The global
3039 * shell window has special handling of window position.
3046 NtUserSetShellWindowEx(HWND hwndShell
, HWND hwndListView
)
3048 PWINSTATION_OBJECT WinStaObject
;
3049 PWINDOW_OBJECT WndShell
;
3050 DECLARE_RETURN(BOOL
);
3052 DPRINT("Enter NtUserSetShellWindowEx\n");
3053 UserEnterExclusive();
3055 if (!(WndShell
= UserGetWindowObject(hwndShell
)))
3060 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
3065 if (!NT_SUCCESS(Status
))
3067 SetLastNtError(Status
);
3072 * Test if we are permitted to change the shell window.
3074 if (WinStaObject
->ShellWindow
)
3076 ObDereferenceObject(WinStaObject
);
3081 * Move shell window into background.
3083 if (hwndListView
&& hwndListView
!= hwndShell
)
3086 * Disabled for now to get Explorer working.
3087 * -- Filip, 01/nov/2003
3090 co_WinPosSetWindowPos(hwndListView
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
3093 if (UserGetWindowLong(hwndListView
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
3095 ObDereferenceObject(WinStaObject
);
3100 if (UserGetWindowLong(hwndShell
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
3102 ObDereferenceObject(WinStaObject
);
3106 UserRefObjectCo(WndShell
);
3107 co_WinPosSetWindowPos(WndShell
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
3109 WinStaObject
->ShellWindow
= hwndShell
;
3110 WinStaObject
->ShellListView
= hwndListView
;
3112 UserDerefObjectCo(WndShell
);
3114 ObDereferenceObject(WinStaObject
);
3118 DPRINT("Leave NtUserSetShellWindowEx, ret=%i\n",_ret_
);
3124 * NtUserGetSystemMenu
3126 * The NtUserGetSystemMenu function allows the application to access the
3127 * window menu (also known as the system menu or the control menu) for
3128 * copying and modifying.
3132 * Handle to the window that will own a copy of the window menu.
3134 * Specifies the action to be taken. If this parameter is FALSE,
3135 * NtUserGetSystemMenu returns a handle to the copy of the window menu
3136 * currently in use. The copy is initially identical to the window menu
3137 * but it can be modified.
3138 * If this parameter is TRUE, GetSystemMenu resets the window menu back
3139 * to the default state. The previous window menu, if any, is destroyed.
3142 * If the bRevert parameter is FALSE, the return value is a handle to a
3143 * copy of the window menu. If the bRevert parameter is TRUE, the return
3151 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
3153 PWINDOW_OBJECT Window
;
3155 DECLARE_RETURN(HMENU
);
3157 DPRINT("Enter NtUserGetSystemMenu\n");
3160 if (!(Window
= UserGetWindowObject(hWnd
)))
3165 if (!(Menu
= IntGetSystemMenu(Window
, bRevert
, FALSE
)))
3170 RETURN(Menu
->MenuInfo
.Self
);
3173 DPRINT("Leave NtUserGetSystemMenu, ret=%i\n",_ret_
);
3179 * NtUserSetSystemMenu
3186 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
3188 BOOL Result
= FALSE
;
3189 PWINDOW_OBJECT Window
;
3191 DECLARE_RETURN(BOOL
);
3193 DPRINT("Enter NtUserSetSystemMenu\n");
3194 UserEnterExclusive();
3196 if (!(Window
= IntGetWindowObject(hWnd
)))
3198 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3205 * Assign new menu handle.
3207 Menu
= IntGetMenuObject(hMenu
);
3210 IntReleaseWindowObject(Window
);
3211 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
3215 Result
= IntSetSystemMenu(Window
, Menu
);
3217 IntReleaseMenuObject(Menu
);
3220 IntReleaseWindowObject(Window
);
3225 DPRINT("Leave NtUserSetSystemMenu, ret=%i\n",_ret_
);
3234 UserGetWindow(HWND hWnd
, UINT Relationship
)
3236 PWINDOW_OBJECT Parent
, Window
;
3237 HWND hWndResult
= NULL
;
3239 if (!(Window
= UserGetWindowObject(hWnd
)))
3242 switch (Relationship
)
3245 if((Parent
= Window
->Parent
))
3247 if (Parent
->FirstChild
)
3248 hWndResult
= Parent
->FirstChild
->hSelf
;
3253 if((Parent
= Window
->Parent
))
3255 if (Parent
->LastChild
)
3256 hWndResult
= Parent
->LastChild
->hSelf
;
3261 if (Window
->NextSibling
)
3262 hWndResult
= Window
->NextSibling
->hSelf
;
3266 if (Window
->PrevSibling
)
3267 hWndResult
= Window
->PrevSibling
->hSelf
;
3271 if((Parent
= IntGetWindowObject(Window
->hOwner
)))
3273 hWndResult
= Parent
->hSelf
;
3274 IntReleaseWindowObject(Parent
);
3278 if (Window
->FirstChild
)
3279 hWndResult
= Window
->FirstChild
->hSelf
;
3291 * The NtUserGetWindow function retrieves a handle to a window that has the
3292 * specified relationship (Z order or owner) to the specified window.
3299 NtUserGetWindow(HWND hWnd
, UINT Relationship
)
3301 DECLARE_RETURN(HWND
);
3303 DPRINT("Enter NtUserGetWindow\n");
3306 RETURN(UserGetWindow(hWnd
, Relationship
));
3309 DPRINT("Leave NtUserGetWindow, ret=%i\n",_ret_
);
3318 * NtUserGetWindowLong
3320 * The NtUserGetWindowLong function retrieves information about the specified
3321 * window. The function also retrieves the 32-bit (long) value at the
3322 * specified offset into the extra window memory.
3329 UserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3331 PWINDOW_OBJECT Window
, Parent
;
3334 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3336 if (!(Window
= IntGetWindowObject(hWnd
)))
3338 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3343 * WndProc is only available to the owner process
3345 if (GWL_WNDPROC
== Index
3346 && Window
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
3348 SetLastWin32Error(ERROR_ACCESS_DENIED
);
3352 if ((INT
)Index
>= 0)
3354 if ((Index
+ sizeof(LONG
)) > Window
->ExtraDataSize
)
3356 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3359 Result
= *((LONG
*)(Window
->ExtraData
+ Index
));
3366 Result
= Window
->ExStyle
;
3370 Result
= Window
->Style
;
3375 Result
= (LONG
) Window
->WndProcA
;
3377 Result
= (LONG
) Window
->WndProcW
;
3381 Result
= (LONG
) Window
->Instance
;
3384 case GWL_HWNDPARENT
:
3385 Parent
= Window
->Parent
;
3388 if (Parent
&& Parent
->hSelf
== IntGetDesktopWindow())
3389 Result
= (LONG
) UserGetWindow(Window
->hSelf
, GW_OWNER
);
3391 Result
= (LONG
) Parent
->hSelf
;
3396 Result
= (LONG
) Window
->IDMenu
;
3400 Result
= Window
->UserData
;
3404 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index
);
3405 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3411 IntReleaseWindowObject(Window
);
3420 * NtUserGetWindowLong
3422 * The NtUserGetWindowLong function retrieves information about the specified
3423 * window. The function also retrieves the 32-bit (long) value at the
3424 * specified offset into the extra window memory.
3431 NtUserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3433 DECLARE_RETURN(LONG
);
3435 DPRINT("Enter NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3436 UserEnterExclusive();
3438 RETURN(UserGetWindowLong(hWnd
, Index
, Ansi
));
3441 DPRINT("Leave NtUserGetWindowLong, ret=%i\n",_ret_
);
3450 co_UserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3452 PWINDOW_OBJECT Window
, Parent
;
3453 PWINSTATION_OBJECT WindowStation
;
3457 if (hWnd
== IntGetDesktopWindow())
3459 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3463 if (!(Window
= IntGetWindowObject(hWnd
)))
3465 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3469 if ((INT
)Index
>= 0)
3471 if ((Index
+ sizeof(LONG
)) > Window
->ExtraDataSize
)
3473 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3474 IntReleaseWindowObject(Window
);
3477 OldValue
= *((LONG
*)(Window
->ExtraData
+ Index
));
3478 *((LONG
*)(Window
->ExtraData
+ Index
)) = NewValue
;
3485 OldValue
= (LONG
) Window
->ExStyle
;
3486 Style
.styleOld
= OldValue
;
3487 Style
.styleNew
= NewValue
;
3490 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3492 WindowStation
= Window
->OwnerThread
->Tcb
.Win32Thread
->Desktop
->WindowStation
;
3495 if (hWnd
== WindowStation
->ShellWindow
|| hWnd
== WindowStation
->ShellListView
)
3496 Style
.styleNew
&= ~WS_EX_TOPMOST
;
3499 co_IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3500 Window
->ExStyle
= (DWORD
)Style
.styleNew
;
3501 co_IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3505 OldValue
= (LONG
) Window
->Style
;
3506 Style
.styleOld
= OldValue
;
3507 Style
.styleNew
= NewValue
;
3508 co_IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_STYLE
, (LPARAM
) &Style
);
3509 Window
->Style
= (DWORD
)Style
.styleNew
;
3510 co_IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_STYLE
, (LPARAM
) &Style
);
3514 /* FIXME: should check if window belongs to current process */
3517 OldValue
= (LONG
) Window
->WndProcA
;
3518 Window
->WndProcA
= (WNDPROC
) NewValue
;
3519 Window
->WndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,FALSE
);
3520 Window
->Unicode
= FALSE
;
3524 OldValue
= (LONG
) Window
->WndProcW
;
3525 Window
->WndProcW
= (WNDPROC
) NewValue
;
3526 Window
->WndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,TRUE
);
3527 Window
->Unicode
= TRUE
;
3532 OldValue
= (LONG
) Window
->Instance
;
3533 Window
->Instance
= (HINSTANCE
) NewValue
;
3536 case GWL_HWNDPARENT
:
3537 Parent
= IntGetParentObject(Window
);
3538 if (Parent
&& (Parent
->hSelf
== IntGetDesktopWindow()))
3539 OldValue
= (LONG
) IntSetOwner(Window
->hSelf
, (HWND
) NewValue
);
3541 OldValue
= (LONG
) co_UserSetParent(Window
->hSelf
, (HWND
) NewValue
);
3543 IntReleaseWindowObject(Parent
);
3547 OldValue
= (LONG
) Window
->IDMenu
;
3548 Window
->IDMenu
= (UINT
) NewValue
;
3552 OldValue
= Window
->UserData
;
3553 Window
->UserData
= NewValue
;
3557 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index
);
3558 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3564 IntReleaseWindowObject(Window
);
3572 * NtUserSetWindowLong
3574 * The NtUserSetWindowLong function changes an attribute of the specified
3575 * window. The function also sets the 32-bit (long) value at the specified
3576 * offset into the extra window memory.
3583 NtUserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3585 DECLARE_RETURN(LONG
);
3587 DPRINT("Enter NtUserSetWindowLong\n");
3588 UserEnterExclusive();
3590 RETURN( co_UserSetWindowLong(hWnd
, Index
, NewValue
, Ansi
));
3593 DPRINT("Leave NtUserSetWindowLong, ret=%i\n",_ret_
);
3599 * NtUserSetWindowWord
3601 * Legacy function similar to NtUserSetWindowLong.
3608 NtUserSetWindowWord(HWND hWnd
, INT Index
, WORD NewValue
)
3610 PWINDOW_OBJECT Window
;
3612 DECLARE_RETURN(WORD
);
3614 DPRINT("Enter NtUserSetWindowWord\n");
3615 UserEnterExclusive();
3621 case GWL_HWNDPARENT
:
3622 RETURN( co_UserSetWindowLong(hWnd
, Index
, (UINT
)NewValue
, TRUE
));
3626 SetLastWin32Error(ERROR_INVALID_INDEX
);
3631 if (!(Window
= IntGetWindowObject(hWnd
)))
3633 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
3637 if (Index
> Window
->ExtraDataSize
- sizeof(WORD
))
3639 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3640 IntReleaseWindowObject(Window
);
3644 OldValue
= *((WORD
*)(Window
->ExtraData
+ Index
));
3645 *((WORD
*)(Window
->ExtraData
+ Index
)) = NewValue
;
3647 IntReleaseWindowObject(Window
);
3652 DPRINT("Leave NtUserSetWindowWord, ret=%i\n",_ret_
);
3661 NtUserGetWindowPlacement(HWND hWnd
,
3662 WINDOWPLACEMENT
*lpwndpl
)
3664 PWINDOW_OBJECT Window
;
3665 PINTERNALPOS InternalPos
;
3667 WINDOWPLACEMENT Safepl
;
3669 DECLARE_RETURN(BOOL
);
3671 DPRINT("Enter NtUserGetWindowPlacement\n");
3674 if (!(Window
= UserGetWindowObject(hWnd
)))
3679 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3680 if(!NT_SUCCESS(Status
))
3682 SetLastNtError(Status
);
3685 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3691 Safepl
.showCmd
= ((Window
->Flags
& WINDOWOBJECT_RESTOREMAX
) ? SW_MAXIMIZE
: SW_SHOWNORMAL
);
3693 Size
.x
= Window
->WindowRect
.left
;
3694 Size
.y
= Window
->WindowRect
.top
;
3695 InternalPos
= WinPosInitInternalPos(Window
, &Size
,
3696 &Window
->WindowRect
);
3699 Safepl
.rcNormalPosition
= InternalPos
->NormalRect
;
3700 Safepl
.ptMinPosition
= InternalPos
->IconPos
;
3701 Safepl
.ptMaxPosition
= InternalPos
->MaxPos
;
3708 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3709 if(!NT_SUCCESS(Status
))
3711 SetLastNtError(Status
);
3718 DPRINT("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
3725 * Return the dimension of the window in the screen coordinates.
3726 * \param hWnd window handle.
3727 * \param Rect pointer to the buffer where the coordinates are returned.
3733 NtUserGetWindowRect(HWND hWnd
, LPRECT Rect
)
3737 DECLARE_RETURN(BOOL
);
3739 DPRINT("Enter NtUserGetWindowRect\n");
3742 if (!(Wnd
= UserGetWindowObject(hWnd
)))
3746 Status
= MmCopyToCaller(Rect
, &Wnd
->WindowRect
, sizeof(RECT
));
3747 if (!NT_SUCCESS(Status
))
3749 SetLastNtError(Status
);
3756 DPRINT("Leave NtUserGetWindowRect, ret=%i\n",_ret_
);
3766 NtUserGetWindowThreadProcessId(HWND hWnd
, LPDWORD UnsafePid
)
3770 DECLARE_RETURN(DWORD
);
3772 DPRINT("Enter NtUserGetWindowThreadProcessId\n");
3775 if (!(Wnd
= UserGetWindowObject(hWnd
)))
3780 tid
= (DWORD
)IntGetWndThreadId(Wnd
);
3781 pid
= (DWORD
)IntGetWndProcessId(Wnd
);
3784 MmCopyToCaller(UnsafePid
, &pid
, sizeof(DWORD
));
3789 DPRINT("Leave NtUserGetWindowThreadProcessId, ret=%i\n",_ret_
);
3799 NtUserLockWindowUpdate(DWORD Unknown0
)
3819 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3820 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3821 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3825 QueryWindow based on KJK::Hyperion and James Tabor.
3827 0 = QWUniqueProcessId
3828 1 = QWUniqueThreadId
3829 4 = QWIsHung Implements IsHungAppWindow found
3832 9 = QWKillWindow When I called this with hWnd ==
3833 DesktopWindow, it shutdown the system
3840 NtUserQueryWindow(HWND hWnd
, DWORD Index
)
3842 PWINDOW_OBJECT Window
;
3844 DECLARE_RETURN(UINT
);
3846 DPRINT("Enter NtUserQueryWindow\n");
3849 if (!(Window
= UserGetWindowObject(hWnd
)))
3856 case QUERY_WINDOW_UNIQUE_PROCESS_ID
:
3857 Result
= (DWORD
)IntGetWndProcessId(Window
);
3860 case QUERY_WINDOW_UNIQUE_THREAD_ID
:
3861 Result
= (DWORD
)IntGetWndThreadId(Window
);
3864 case QUERY_WINDOW_ISHUNG
:
3865 Result
= (DWORD
)MsqIsHung(Window
->MessageQueue
);
3869 Result
= (DWORD
)NULL
;
3876 DPRINT("Leave NtUserQueryWindow, ret=%i\n",_ret_
);
3886 NtUserRealChildWindowFromPoint(DWORD Unknown0
,
3900 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe
)
3902 UNICODE_STRING SafeMessageName
;
3905 DECLARE_RETURN(UINT
);
3907 DPRINT("Enter NtUserRegisterWindowMessage\n");
3908 UserEnterExclusive();
3910 if(MessageNameUnsafe
== NULL
)
3912 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3916 Status
= IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName
, MessageNameUnsafe
);
3917 if(!NT_SUCCESS(Status
))
3919 SetLastNtError(Status
);
3923 Ret
= (UINT
)IntAddAtom(SafeMessageName
.Buffer
);
3925 RtlFreeUnicodeString(&SafeMessageName
);
3929 DPRINT("Leave NtUserRegisterWindowMessage, ret=%i\n",_ret_
);
3939 NtUserSetImeOwnerWindow(DWORD Unknown0
,
3952 NtUserSetInternalWindowPos(DWORD Unknown0
,
3968 NtUserSetLayeredWindowAttributes(DWORD Unknown0
,
3983 NtUserSetLogonNotifyWindow(DWORD Unknown0
)
4000 PWINDOW_OBJECT Window
;
4002 DECLARE_RETURN(BOOL
);
4004 DPRINT("Enter NtUserSetMenu\n");
4005 UserEnterExclusive();
4007 if (!(Window
= UserGetWindowObject(hWnd
)))
4012 if (! IntSetMenu(Window
, Menu
, &Changed
))
4017 if (Changed
&& Repaint
)
4019 UserRefObjectCo(Window
);
4020 co_WinPosSetWindowPos(Window
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
4021 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
4023 UserDerefObjectCo(Window
);
4029 DPRINT("Leave NtUserSetMenu, ret=%i\n",_ret_
);
4039 NtUserSetWindowFNID(DWORD Unknown0
,
4053 NtUserSetWindowPlacement(HWND hWnd
,
4054 WINDOWPLACEMENT
*lpwndpl
)
4056 PWINDOW_OBJECT Window
;
4057 WINDOWPLACEMENT Safepl
;
4059 DECLARE_RETURN(BOOL
);
4061 DPRINT("Enter NtUserSetWindowPlacement\n");
4062 UserEnterExclusive();
4064 if (!(Window
= UserGetWindowObject(hWnd
)))
4068 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
4069 if(!NT_SUCCESS(Status
))
4071 SetLastNtError(Status
);
4074 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
4079 UserRefObjectCo(Window
);
4081 if ((Window
->Style
& (WS_MAXIMIZE
| WS_MINIMIZE
)) == 0)
4083 co_WinPosSetWindowPos(Window
, NULL
,
4084 Safepl
.rcNormalPosition
.left
, Safepl
.rcNormalPosition
.top
,
4085 Safepl
.rcNormalPosition
.right
- Safepl
.rcNormalPosition
.left
,
4086 Safepl
.rcNormalPosition
.bottom
- Safepl
.rcNormalPosition
.top
,
4087 SWP_NOZORDER
| SWP_NOACTIVATE
);
4090 /* FIXME - change window status */
4091 co_WinPosShowWindow(Window
, Safepl
.showCmd
);
4093 if (Window
->InternalPos
== NULL
)
4094 Window
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
4095 Window
->InternalPos
->NormalRect
= Safepl
.rcNormalPosition
;
4096 Window
->InternalPos
->IconPos
= Safepl
.ptMinPosition
;
4097 Window
->InternalPos
->MaxPos
= Safepl
.ptMaxPosition
;
4099 UserDerefObjectCo(Window
);
4103 DPRINT("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
4115 HWND hWndInsertAfter
,
4122 DECLARE_RETURN(BOOL
);
4123 PWINDOW_OBJECT Window
;
4126 DPRINT("Enter NtUserSetWindowPos\n");
4127 UserEnterExclusive();
4129 if (!(Window
= UserGetWindowObject(hWnd
)))
4134 UserRefObjectCo(Window
);
4135 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
4136 UserDerefObjectCo(Window
);
4141 DPRINT("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
4148 IntGetWindowRgn(PWINDOW_OBJECT Window
, HRGN hRgn
)
4163 /* Create a new window region using the window rectangle */
4164 VisRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->WindowRect
);
4165 NtGdiOffsetRgn(VisRgn
, -Window
->WindowRect
.left
, -Window
->WindowRect
.top
);
4166 /* if there's a region assigned to the window, combine them both */
4167 if(Window
->WindowRegion
&& !(Window
->Style
& WS_MINIMIZE
))
4168 NtGdiCombineRgn(VisRgn
, VisRgn
, Window
->WindowRegion
, RGN_AND
);
4169 /* Copy the region into hRgn */
4170 NtGdiCombineRgn(hRgn
, VisRgn
, NULL
, RGN_COPY
);
4172 if((pRgn
= RGNDATA_LockRgn(hRgn
)))
4174 Ret
= pRgn
->rdh
.iType
;
4175 RGNDATA_UnlockRgn(pRgn
);
4180 NtGdiDeleteObject(VisRgn
);
4186 IntGetWindowRgnBox(PWINDOW_OBJECT Window
, RECT
*Rect
)
4201 /* Create a new window region using the window rectangle */
4202 VisRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->WindowRect
);
4203 NtGdiOffsetRgn(VisRgn
, -Window
->WindowRect
.left
, -Window
->WindowRect
.top
);
4204 /* if there's a region assigned to the window, combine them both */
4205 if(Window
->WindowRegion
&& !(Window
->Style
& WS_MINIMIZE
))
4206 NtGdiCombineRgn(VisRgn
, VisRgn
, Window
->WindowRegion
, RGN_AND
);
4208 if((pRgn
= RGNDATA_LockRgn(VisRgn
)))
4210 Ret
= pRgn
->rdh
.iType
;
4211 *Rect
= pRgn
->rdh
.rcBound
;
4212 RGNDATA_UnlockRgn(pRgn
);
4217 NtGdiDeleteObject(VisRgn
);
4232 PWINDOW_OBJECT Window
;
4233 DECLARE_RETURN(INT
);
4235 DPRINT("Enter NtUserSetWindowRgn\n");
4236 UserEnterExclusive();
4238 if (!(Window
= UserGetWindowObject(hWnd
)))
4243 /* FIXME - Verify if hRgn is a valid handle!!!!
4244 Propably make this operation thread-safe, but maybe it's not necessary */
4246 if(Window
->WindowRegion
)
4248 /* Delete no longer needed region handle */
4249 NtGdiDeleteObject(Window
->WindowRegion
);
4251 Window
->WindowRegion
= hRgn
;
4253 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
4257 UserRefObjectCo(Window
);
4258 co_UserRedrawWindow(Window
, NULL
, NULL
, RDW_INVALIDATE
);
4259 UserDerefObjectCo(Window
);
4265 DPRINT("Leave NtUserSystemParametersInfo, ret=%i\n",_ret_
);
4275 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
4277 PWINDOW_OBJECT Window
;
4279 DECLARE_RETURN(BOOL
);
4281 DPRINT("Enter NtUserShowWindow\n");
4282 UserEnterExclusive();
4284 if (!(Window
= UserGetWindowObject(hWnd
)))
4289 UserRefObjectCo(Window
);
4290 ret
= co_WinPosShowWindow(Window
, nCmdShow
);
4291 UserDerefObjectCo(Window
);
4296 DPRINT("Leave NtUserShowWindow, ret=%i\n",_ret_
);
4306 NtUserShowWindowAsync(DWORD Unknown0
,
4319 NtUserUpdateLayeredWindow(DWORD Unknown0
,
4339 NtUserValidateRect(HWND hWnd
, const RECT
* Rect
)
4341 return (VOID
)NtUserRedrawWindow(hWnd
, Rect
, 0, RDW_VALIDATE
| RDW_NOCHILDREN
);
4349 NtUserWindowFromPoint(LONG X
, LONG Y
)
4353 PWINDOW_OBJECT DesktopWindow
, Window
= NULL
;
4354 DECLARE_RETURN(HWND
);
4356 DPRINT("Enter NtUserWindowFromPoint\n");
4357 UserEnterExclusive();
4359 if ((DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow())))
4366 Hit
= co_WinPosWindowFromPoint(DesktopWindow
, PsGetWin32Thread()->MessageQueue
, &pt
, &Window
);
4370 Ret
= Window
->hSelf
;
4371 IntReleaseWindowObject(Window
);
4372 IntReleaseWindowObject(DesktopWindow
);
4376 IntReleaseWindowObject(DesktopWindow
);
4382 DPRINT("Leave NtUserWindowFromPoint, ret=%i\n",_ret_
);
4392 * Undocumented function that is called from DefWindowProc to set
4400 NtUserDefSetText(HWND hWnd
, PUNICODE_STRING WindowText
)
4402 PWINDOW_OBJECT Window
, Parent
, Owner
;
4403 UNICODE_STRING SafeText
;
4405 DECLARE_RETURN(INT
);
4407 DPRINT("Enter NtUserDefSetText\n");
4408 UserEnterExclusive();
4410 if(!(Window
= UserGetWindowObject(hWnd
)))
4417 Status
= IntSafeCopyUnicodeString(&SafeText
, WindowText
);
4418 if(!NT_SUCCESS(Status
))
4420 SetLastNtError(Status
);
4426 RtlInitUnicodeString(&SafeText
, NULL
);
4429 /* FIXME - do this thread-safe! otherwise one could crash here! */
4430 RtlFreeUnicodeString(&Window
->WindowName
);
4432 Window
->WindowName
= SafeText
;
4434 /* Send shell notifications */
4436 Owner
= IntGetOwner(Window
);
4437 Parent
= IntGetParent(Window
);
4439 if ((!Owner
) && (!Parent
))
4441 co_IntShellHookNotify(HSHELL_REDRAW
, (LPARAM
) hWnd
);
4446 IntReleaseWindowObject(Owner
);
4451 IntReleaseWindowObject(Parent
);
4457 DPRINT("Leave NtUserDefSetText, ret=%i\n",_ret_
);
4463 * NtUserInternalGetWindowText
4470 NtUserInternalGetWindowText(HWND hWnd
, LPWSTR lpString
, INT nMaxCount
)
4472 PWINDOW_OBJECT Window
;
4475 DECLARE_RETURN(INT
);
4477 DPRINT("Enter NtUserInternalGetWindowText\n");
4480 if(lpString
&& (nMaxCount
<= 1))
4482 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
4486 if(!(Window
= UserGetWindowObject(hWnd
)))
4491 /* FIXME - do this thread-safe! otherwise one could crash here! */
4492 Result
= Window
->WindowName
.Length
/ sizeof(WCHAR
);
4495 const WCHAR Terminator
= L
'\0';
4497 WCHAR
*Buffer
= (WCHAR
*)lpString
;
4499 Copy
= min(nMaxCount
- 1, Result
);
4502 Status
= MmCopyToCaller(Buffer
, Window
->WindowName
.Buffer
, Copy
* sizeof(WCHAR
));
4503 if(!NT_SUCCESS(Status
))
4505 SetLastNtError(Status
);
4511 Status
= MmCopyToCaller(Buffer
, &Terminator
, sizeof(WCHAR
));
4512 if(!NT_SUCCESS(Status
))
4514 SetLastNtError(Status
);
4524 DPRINT("Leave NtUserInternalGetWindowText, ret=%i\n",_ret_
);
4530 NtUserDereferenceWndProcHandle(WNDPROC wpHandle
, WndProcHandle
*Data
)
4532 DECLARE_RETURN(DWORD
);
4534 DPRINT("Enter NtUserDereferenceWndProcHandle\n");
4537 WndProcHandle Entry
;
4538 if (((DWORD
)wpHandle
& 0xFFFF0000) == 0xFFFF0000)
4540 Entry
= WndProcHandlesArray
[(DWORD
)wpHandle
& 0x0000FFFF];
4541 Data
->WindowProc
= Entry
.WindowProc
;
4542 Data
->IsUnicode
= Entry
.IsUnicode
;
4543 Data
->ProcessID
= Entry
.ProcessID
;
4553 DPRINT("Leave NtUserDereferenceWndProcHandle, ret=%i\n",_ret_
);
4559 IntAddWndProcHandle(WNDPROC WindowProc
, BOOL IsUnicode
)
4564 WndProcHandle
*OldArray
;
4567 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4569 if (WndProcHandlesArray
[i
].WindowProc
== NULL
)
4577 OldArray
= WndProcHandlesArray
;
4578 OldArraySize
= WndProcHandlesArraySize
;
4579 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,(OldArraySize
+ WPH_SIZE
) * sizeof(WndProcHandle
), TAG_WINPROCLST
);
4580 WndProcHandlesArraySize
= OldArraySize
+ WPH_SIZE
;
4581 RtlCopyMemory(WndProcHandlesArray
,OldArray
,OldArraySize
* sizeof(WndProcHandle
));
4582 ExFreePool(OldArray
);
4583 FreeSpot
= OldArraySize
+ 1;
4585 WndProcHandlesArray
[FreeSpot
].WindowProc
= WindowProc
;
4586 WndProcHandlesArray
[FreeSpot
].IsUnicode
= IsUnicode
;
4587 WndProcHandlesArray
[FreeSpot
].ProcessID
= PsGetCurrentProcessId();
4588 return FreeSpot
+ 0xFFFF0000;
4592 IntRemoveWndProcHandle(WNDPROC Handle
)
4595 position
= (DWORD
)Handle
& 0x0000FFFF;
4596 if (position
> WndProcHandlesArraySize
)
4600 WndProcHandlesArray
[position
].WindowProc
= NULL
;
4601 WndProcHandlesArray
[position
].IsUnicode
= FALSE
;
4602 WndProcHandlesArray
[position
].ProcessID
= NULL
;
4607 IntRemoveProcessWndProcHandles(HANDLE ProcessID
)
4610 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4612 if (WndProcHandlesArray
[i
].ProcessID
== ProcessID
)
4614 WndProcHandlesArray
[i
].WindowProc
= NULL
;
4615 WndProcHandlesArray
[i
].IsUnicode
= FALSE
;
4616 WndProcHandlesArray
[i
].ProcessID
= NULL
;
4622 #define WIN_NEEDS_SHOW_OWNEDPOPUP (0x00000040)
4626 IntShowOwnedPopups(PWINDOW_OBJECT OwnerWnd
, BOOL fShow
)
4629 PWINDOW_OBJECT pWnd
;
4634 win_array
= IntWinListChildren(OwnerWnd
);//faxme: use desktop?
4639 while (win_array
[count
])
4641 while (--count
>= 0)
4643 if (UserGetWindow( win_array
[count
], GW_OWNER
) != OwnerWnd
->hSelf
)
4645 if (!(pWnd
= UserGetWindowObject( win_array
[count
] )))
4647 // if (pWnd == WND_OTHER_PROCESS) continue;
4651 if (pWnd
->Flags
& WIN_NEEDS_SHOW_OWNEDPOPUP
)
4653 /* In Windows, ShowOwnedPopups(TRUE) generates
4654 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
4655 * regardless of the state of the owner
4657 co_IntSendMessage(win_array
[count
], WM_SHOWWINDOW
, SW_SHOWNORMAL
, SW_PARENTOPENING
);
4663 if (pWnd
->Style
& WS_VISIBLE
)
4665 /* In Windows, ShowOwnedPopups(FALSE) generates
4666 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
4667 * regardless of the state of the owner
4669 co_IntSendMessage(win_array
[count
], WM_SHOWWINDOW
, SW_HIDE
, SW_PARENTCLOSING
);
4675 ExFreePool( win_array
);