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 ***********************************************************/
79 PWINDOW_OBJECT FASTCALL
IntGetWindowObject(HWND hWnd
)
81 PWINDOW_OBJECT Window
;
83 if (!hWnd
) return NULL
;
85 Window
= UserGetWindowObject(hWnd
);
88 ASSERT(USER_BODY_TO_HEADER(Window
)->RefCount
>= 0);
90 USER_BODY_TO_HEADER(Window
)->RefCount
++;
96 PWINDOW_OBJECT FASTCALL
UserGetWindowObject(HWND hWnd
)
98 PWINDOW_OBJECT Window
;
102 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
106 Window
= (PWINDOW_OBJECT
)UserGetObject(&gHandleTable
, hWnd
, otWindow
);
107 if (!Window
|| 0 != (Window
->Status
& WINDOWSTATUS_DESTROYED
))
109 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
113 ASSERT(USER_BODY_TO_HEADER(Window
)->RefCount
>= 0);
121 * The function determines whether the specified window handle identifies
122 * an existing window.
126 * Handle to the window to test.
129 * If the window handle identifies an existing window, the return value
130 * is TRUE. If the window handle does not identify an existing window,
131 * the return value is FALSE.
135 IntIsWindow(HWND hWnd
)
137 PWINDOW_OBJECT Window
;
139 if (!(Window
= UserGetWindowObject(hWnd
)))
148 Caller must NOT dereference retval!
149 But if caller want the returned value to persist spanning a co_ call,
150 it must reference the value (because the owner is not garanteed to
151 exist just because the owned window exist)!
153 PWINDOW_OBJECT FASTCALL
154 IntGetParent(PWINDOW_OBJECT Wnd
)
156 if (Wnd
->Style
& WS_POPUP
)
158 return UserGetWindowObject(Wnd
->hOwner
);
160 else if (Wnd
->Style
& WS_CHILD
)
170 Caller must NOT dereference retval!
171 But if caller want the returned value to persist spanning a co_ call,
172 it must reference the value (because the owner is not garanteed to
173 exist just because the owned window exist)!
175 PWINDOW_OBJECT FASTCALL
176 IntGetOwner(PWINDOW_OBJECT Wnd
)
178 return UserGetWindowObject(Wnd
->hOwner
);
186 * Compile a list of all child window handles from given window.
189 * This function is similar to Wine WIN_ListChildren. The caller
190 * must free the returned list with ExFreePool.
194 IntWinListChildren(PWINDOW_OBJECT Window
)
196 PWINDOW_OBJECT Child
;
198 UINT Index
, NumChildren
= 0;
200 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
203 List
= ExAllocatePoolWithTag(PagedPool
, (NumChildren
+ 1) * sizeof(HWND
), TAG_WINLIST
);
206 DPRINT1("Failed to allocate memory for children array\n");
207 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
210 for (Child
= Window
->FirstChild
, Index
= 0;
212 Child
= Child
->NextSibling
, ++Index
)
213 List
[Index
] = Child
->hSelf
;
219 /***********************************************************************
222 static void IntSendDestroyMsg(HWND hWnd
)
225 PWINDOW_OBJECT Window
;
230 if (GetGUIThreadInfo(GetCurrentThreadId(), &info
))
232 if (hWnd
== info
.hwndCaret
)
239 Window
= UserGetWindowObject(hWnd
);
242 // USER_REFERENCE_ENTRY Ref;
243 // UserRefObjectCo(Window, &Ref);
245 if (!IntGetOwner(Window
) && !IntGetParent(Window
))
247 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
) hWnd
);
250 // UserDerefObjectCo(Window);
253 /* The window could already be destroyed here */
256 * Send the WM_DESTROY to the window.
259 co_IntSendMessage(hWnd
, WM_DESTROY
, 0, 0);
262 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
263 * make sure that the window still exists when we come back.
272 if (!(pWndArray
= WIN_ListChildren( hwnd
)))
275 /* start from the end (FIXME: is this needed?) */
276 for (i
= 0; pWndArray
[i
]; i
++)
281 if (IsWindow( pWndArray
[i
] ))
282 WIN_SendDestroyMsg( pWndArray
[i
] );
284 HeapFree(GetProcessHeap(), 0, pWndArray
);
288 DPRINT("destroyed itself while in WM_DESTROY!\n");
293 /***********************************************************************
296 * Destroy storage associated to a window. "Internals" p.358
298 * This is the "functional" DestroyWindows function ei. all stuff
299 * done in CreateWindow is undone here and not in DestroyWindow:-P
302 static LRESULT
co_UserFreeWindow(PWINDOW_OBJECT Window
,
303 PW32PROCESS ProcessData
,
304 PW32THREAD ThreadData
,
305 BOOLEAN SendMessages
)
309 PWINDOW_OBJECT Child
;
311 BOOLEAN BelongsToThreadData
;
315 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
317 DPRINT("Tried to call IntDestroyWindow() twice\n");
320 Window
->Status
|= WINDOWSTATUS_DESTROYING
;
321 Window
->Style
&= ~WS_VISIBLE
;
322 /* remove the window already at this point from the thread window list so we
323 don't get into trouble when destroying the thread windows while we're still
324 in IntDestroyWindow() */
325 RemoveEntryList(&Window
->ThreadListEntry
);
327 BelongsToThreadData
= IntWndBelongsToThread(Window
, ThreadData
);
329 IntDeRegisterShellHookWindow(Window
->hSelf
);
333 /* Send destroy messages */
334 IntSendDestroyMsg(Window
->hSelf
);
337 /* free child windows */
338 Children
= IntWinListChildren(Window
);
341 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
343 if ((Child
= IntGetWindowObject(*ChildHandle
)))
345 if(!IntWndBelongsToThread(Child
, ThreadData
))
347 /* send WM_DESTROY messages to windows not belonging to the same thread */
348 IntSendDestroyMsg(Child
->hSelf
);
351 co_UserFreeWindow(Child
, ProcessData
, ThreadData
, SendMessages
);
353 UserDerefObject(Child
);
356 ExFreePool(Children
);
362 * Clear the update region to make sure no WM_PAINT messages will be
363 * generated for this window while processing the WM_NCDESTROY.
365 co_UserRedrawWindow(Window
, NULL
, 0,
366 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
|
367 RDW_NOINTERNALPAINT
| RDW_NOCHILDREN
);
368 if(BelongsToThreadData
)
369 co_IntSendMessage(Window
->hSelf
, WM_NCDESTROY
, 0, 0);
371 MsqRemoveTimersWindow(ThreadData
->MessageQueue
, Window
->hSelf
);
373 /* flush the message queue */
374 MsqRemoveWindowMessagesFromQueue(Window
);
376 /* from now on no messages can be sent to this window anymore */
377 Window
->Status
|= WINDOWSTATUS_DESTROYED
;
378 /* don't remove the WINDOWSTATUS_DESTROYING bit */
380 /* reset shell window handles */
381 if(ThreadData
->Desktop
)
383 if (Window
->hSelf
== ThreadData
->Desktop
->WindowStation
->ShellWindow
)
384 ThreadData
->Desktop
->WindowStation
->ShellWindow
= NULL
;
386 if (Window
->hSelf
== ThreadData
->Desktop
->WindowStation
->ShellListView
)
387 ThreadData
->Desktop
->WindowStation
->ShellListView
= NULL
;
390 /* Unregister hot keys */
391 UnregisterWindowHotKeys (Window
);
393 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
397 WinPosCheckInternalPos(Window
->hSelf
);
398 if (Window
->hSelf
== GetCapture())
403 /* free resources associated with the window */
404 TIMER_RemoveWindowTimers(Window
->hSelf
);
407 if (!(Window
->Style
& WS_CHILD
) && Window
->IDMenu
408 && (Menu
= UserGetMenuObject((HMENU
)Window
->IDMenu
)))
410 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
414 if(Window
->SystemMenu
415 && (Menu
= UserGetMenuObject(Window
->SystemMenu
)))
417 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
418 Window
->SystemMenu
= (HMENU
)0;
421 DceFreeWindowDCE(Window
); /* Always do this to catch orphaned DCs */
424 WINPROC_FreeProc(Window
->winproc
, WIN_PROC_WINDOW
);
425 CLASS_RemoveWindow(Window
->Class
);
428 IntUnlinkWindow(Window
);
430 UserRefObject(Window
);
431 ObmDeleteObject(Window
->hSelf
, otWindow
);
433 IntDestroyScrollBars(Window
);
435 /* dereference the class */
436 ClassDerefObject(Window
->Class
);
437 Window
->Class
= NULL
;
439 if(Window
->WindowRegion
)
441 NtGdiDeleteObject(Window
->WindowRegion
);
444 RtlFreeUnicodeString(&Window
->WindowName
);
446 UserDerefObject(Window
);
452 IntGetWindowBorderMeasures(PWINDOW_OBJECT Window
, UINT
*cx
, UINT
*cy
)
454 if(HAS_DLGFRAME(Window
->Style
, Window
->ExStyle
) && !(Window
->Style
& WS_MINIMIZE
))
456 *cx
= UserGetSystemMetrics(SM_CXDLGFRAME
);
457 *cy
= UserGetSystemMetrics(SM_CYDLGFRAME
);
461 if(HAS_THICKFRAME(Window
->Style
, Window
->ExStyle
)&& !(Window
->Style
& WS_MINIMIZE
))
463 *cx
= UserGetSystemMetrics(SM_CXFRAME
);
464 *cy
= UserGetSystemMetrics(SM_CYFRAME
);
466 else if(HAS_THINFRAME(Window
->Style
, Window
->ExStyle
))
468 *cx
= UserGetSystemMetrics(SM_CXBORDER
);
469 *cy
= UserGetSystemMetrics(SM_CYBORDER
);
479 IntGetWindowInfo(PWINDOW_OBJECT Window
, PWINDOWINFO pwi
)
481 pwi
->cbSize
= sizeof(WINDOWINFO
);
482 pwi
->rcWindow
= Window
->WindowRect
;
483 pwi
->rcClient
= Window
->ClientRect
;
484 pwi
->dwStyle
= Window
->Style
;
485 pwi
->dwExStyle
= Window
->ExStyle
;
486 pwi
->dwWindowStatus
= (UserGetForegroundWindow() == Window
->hSelf
); /* WS_ACTIVECAPTION */
487 IntGetWindowBorderMeasures(Window
, &pwi
->cxWindowBorders
, &pwi
->cyWindowBorders
);
488 pwi
->atomWindowType
= (Window
->Class
? Window
->Class
->Atom
: 0);
489 pwi
->wCreatorVersion
= 0x400; /* FIXME - return a real version number */
495 PWINDOW_OBJECT Window
,
499 PMENU_OBJECT OldMenu
, NewMenu
= NULL
;
501 if ((Window
->Style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
503 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
507 *Changed
= (Window
->IDMenu
!= (UINT
) Menu
);
515 OldMenu
= IntGetMenuObject((HMENU
) Window
->IDMenu
);
516 ASSERT(NULL
== OldMenu
|| OldMenu
->MenuInfo
.Wnd
== Window
->hSelf
);
525 NewMenu
= IntGetMenuObject(Menu
);
530 IntReleaseMenuObject(OldMenu
);
532 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
535 if (NULL
!= NewMenu
->MenuInfo
.Wnd
)
537 /* Can't use the same menu for two windows */
540 IntReleaseMenuObject(OldMenu
);
542 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
548 Window
->IDMenu
= (UINT
) Menu
;
551 NewMenu
->MenuInfo
.Wnd
= Window
->hSelf
;
552 IntReleaseMenuObject(NewMenu
);
556 OldMenu
->MenuInfo
.Wnd
= NULL
;
557 IntReleaseMenuObject(OldMenu
);
564 /* INTERNAL ******************************************************************/
568 co_DestroyThreadWindows(struct _ETHREAD
*Thread
)
573 USER_REFERENCE_ENTRY Ref
;
574 WThread
= (PW32THREAD
)Thread
->Tcb
.Win32Thread
;
576 while (!IsListEmpty(&WThread
->WindowListHead
))
578 Current
= WThread
->WindowListHead
.Flink
;
579 Wnd
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
581 DPRINT1("thread cleanup: while destroy wnds, wnd=0x%x\n",Wnd
);
583 /* window removes itself from the list */
586 fixme: it is critical that the window removes itself! if now, we will loop
590 //ASSERT(co_UserDestroyWindow(Wnd));
592 UserRefObjectCo(Wnd
, &Ref
);//faxme: temp hack??
593 if (!co_UserDestroyWindow(Wnd
))
595 DPRINT1("Unable to destroy window 0x%x at thread cleanup... This is _VERY_ bad!\n", Wnd
);
597 UserDerefObjectCo(Wnd
);//faxme: temp hack??
605 * Returns client window rectangle relative to the upper-left corner of client area.
607 * \note Does not check the validity of the parameters
610 IntGetClientRect(PWINDOW_OBJECT Window
, PRECT Rect
)
615 Rect
->left
= Rect
->top
= 0;
616 Rect
->right
= Window
->ClientRect
.right
- Window
->ClientRect
.left
;
617 Rect
->bottom
= Window
->ClientRect
.bottom
- Window
->ClientRect
.top
;
623 IntGetFocusWindow(VOID
)
625 PUSER_MESSAGE_QUEUE Queue
;
626 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
631 Queue
= (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
636 return(Queue
->FocusWindow
);
640 PMENU_OBJECT FASTCALL
641 IntGetSystemMenu(PWINDOW_OBJECT Window
, BOOL bRevert
, BOOL RetMenu
)
643 PMENU_OBJECT Menu
, NewMenu
= NULL
, SysMenu
= NULL
, ret
= NULL
;
644 PW32THREAD W32Thread
;
645 HMENU hNewMenu
, hSysMenu
;
646 ROSMENUITEMINFO ItemInfo
;
650 W32Thread
= PsGetWin32Thread();
652 if(!W32Thread
->Desktop
)
655 if(Window
->SystemMenu
)
657 Menu
= UserGetMenuObject(Window
->SystemMenu
);
660 IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
661 Window
->SystemMenu
= (HMENU
)0;
665 if(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
)
667 /* clone system menu */
668 Menu
= UserGetMenuObject(W32Thread
->Desktop
->WindowStation
->SystemMenuTemplate
);
672 NewMenu
= IntCloneMenu(Menu
);
675 Window
->SystemMenu
= NewMenu
->MenuInfo
.Self
;
676 NewMenu
->MenuInfo
.Flags
|= MF_SYSMENU
;
677 NewMenu
->MenuInfo
.Wnd
= Window
->hSelf
;
679 //IntReleaseMenuObject(NewMenu);
684 hSysMenu
= UserCreateMenu(FALSE
);
685 if (NULL
== hSysMenu
)
689 SysMenu
= IntGetMenuObject(hSysMenu
);
692 UserDestroyMenu(hSysMenu
);
695 SysMenu
->MenuInfo
.Flags
|= MF_SYSMENU
;
696 SysMenu
->MenuInfo
.Wnd
= Window
->hSelf
;
697 hNewMenu
= co_IntLoadSysMenuTemplate();
700 IntReleaseMenuObject(SysMenu
);
701 UserDestroyMenu(hSysMenu
);
704 Menu
= IntGetMenuObject(hNewMenu
);
707 IntReleaseMenuObject(SysMenu
);
708 UserDestroyMenu(hSysMenu
);
712 NewMenu
= IntCloneMenu(Menu
);
715 NewMenu
->MenuInfo
.Flags
|= MF_SYSMENU
| MF_POPUP
;
716 IntReleaseMenuObject(NewMenu
);
717 UserSetMenuDefaultItem(NewMenu
, SC_CLOSE
, FALSE
);
719 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
720 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
721 ItemInfo
.fType
= MF_POPUP
;
722 ItemInfo
.fState
= MFS_ENABLED
;
723 ItemInfo
.dwTypeData
= NULL
;
725 ItemInfo
.hSubMenu
= NewMenu
->MenuInfo
.Self
;
726 IntInsertMenuItem(SysMenu
, (UINT
) -1, TRUE
, &ItemInfo
);
728 Window
->SystemMenu
= SysMenu
->MenuInfo
.Self
;
732 IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
733 IntReleaseMenuObject(Menu
);
742 if(Window
->SystemMenu
)
743 return IntGetMenuObject((HMENU
)Window
->SystemMenu
);
751 IntIsChildWindow(PWINDOW_OBJECT Parent
, PWINDOW_OBJECT BaseWindow
)
753 PWINDOW_OBJECT Window
;
758 if (Window
== Parent
)
762 if(!(Window
->Style
& WS_CHILD
))
767 Window
= Window
->Parent
;
774 IntIsWindowVisible(PWINDOW_OBJECT BaseWindow
)
776 PWINDOW_OBJECT Window
;
781 if(!(Window
->Style
& WS_CHILD
))
785 if(!(Window
->Style
& WS_VISIBLE
))
790 Window
= Window
->Parent
;
793 if(Window
&& Window
->Style
& WS_VISIBLE
)
802 /* link the window into siblings and parent. children are kept in place. */
806 PWINDOW_OBJECT WndParent
,
807 PWINDOW_OBJECT WndPrevSibling
/* set to NULL if top sibling */
810 PWINDOW_OBJECT Parent
;
812 Wnd
->Parent
= WndParent
;
813 if ((Wnd
->PrevSibling
= WndPrevSibling
))
815 /* link after WndPrevSibling */
816 if ((Wnd
->NextSibling
= WndPrevSibling
->NextSibling
))
817 Wnd
->NextSibling
->PrevSibling
= Wnd
;
818 else if ((Parent
= Wnd
->Parent
))
820 if(Parent
->LastChild
== WndPrevSibling
)
821 Parent
->LastChild
= Wnd
;
823 Wnd
->PrevSibling
->NextSibling
= Wnd
;
828 Parent
= Wnd
->Parent
;
829 if ((Wnd
->NextSibling
= WndParent
->FirstChild
))
830 Wnd
->NextSibling
->PrevSibling
= Wnd
;
833 Parent
->LastChild
= Wnd
;
834 Parent
->FirstChild
= Wnd
;
839 Parent
->FirstChild
= Wnd
;
846 IntSetOwner(HWND hWnd
, HWND hWndNewOwner
)
848 PWINDOW_OBJECT Wnd
, WndOldOwner
, WndNewOwner
;
851 Wnd
= IntGetWindowObject(hWnd
);
855 WndOldOwner
= IntGetWindowObject(Wnd
->hOwner
);
858 ret
= WndOldOwner
->hSelf
;
859 UserDerefObject(WndOldOwner
);
866 if((WndNewOwner
= UserGetWindowObject(hWndNewOwner
)))
868 Wnd
->hOwner
= hWndNewOwner
;
873 UserDerefObject(Wnd
);
877 PWINDOW_OBJECT FASTCALL
878 co_IntSetParent(PWINDOW_OBJECT Wnd
, PWINDOW_OBJECT WndNewParent
)
880 PWINDOW_OBJECT WndOldParent
, Sibling
, InsertAfter
;
881 // HWND hWnd, hWndNewParent;
885 ASSERT(WndNewParent
);
887 ASSERT_REFS_CO(WndNewParent
);
889 // hWnd = Wnd->hSelf;
890 // hWndNewParent = WndNewParent->hSelf;
893 * Windows hides the window first, then shows it again
894 * including the WM_SHOWWINDOW messages and all
896 WasVisible
= co_WinPosShowWindow(Wnd
, SW_HIDE
);
898 // /* Validate that window and parent still exist */
899 // if (!IntIsWindow(hWnd) || !IntIsWindow(hWndNewParent))
902 /* Window must belong to current process */
903 if (Wnd
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
906 WndOldParent
= Wnd
->Parent
;
908 if (WndOldParent
) UserRefObject(WndOldParent
); /* caller must deref */
910 if (WndNewParent
!= WndOldParent
)
912 IntUnlinkWindow(Wnd
);
914 if (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
))
916 /* Not a TOPMOST window, put after TOPMOSTs of new parent */
917 Sibling
= WndNewParent
->FirstChild
;
918 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
920 InsertAfter
= Sibling
;
921 Sibling
= Sibling
->NextSibling
;
924 if (NULL
== InsertAfter
)
926 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
930 // UserRefObject(InsertAfter);
931 IntLinkWindow(Wnd
, WndNewParent
, InsertAfter
/*prev sibling*/);
932 // UserDerefObject(InsertAfter);
937 * SetParent additionally needs to make hwnd the top window
938 * in the z-order and send the expected WM_WINDOWPOSCHANGING and
939 * WM_WINDOWPOSCHANGED notification messages.
941 co_WinPosSetWindowPos(Wnd
, (0 == (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOP
: HWND_TOPMOST
),
942 0, 0, 0, 0, SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
943 | (WasVisible
? SWP_SHOWWINDOW
: 0));
946 * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
947 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
951 * Validate that the old parent still exist, since it migth have been
952 * destroyed during the last callbacks to user-mode
956 // if(!IntIsWindow(WndOldParent->hSelf))
958 // UserDerefObject(WndOldParent);
962 /* don't dereference the window object here, it must be done by the caller
964 // return WndOldParent;
967 return WndOldParent
;//NULL;
971 IntSetSystemMenu(PWINDOW_OBJECT Window
, PMENU_OBJECT Menu
)
973 PMENU_OBJECT OldMenu
;
974 if(Window
->SystemMenu
)
976 OldMenu
= IntGetMenuObject(Window
->SystemMenu
);
979 OldMenu
->MenuInfo
.Flags
&= ~ MF_SYSMENU
;
980 IntReleaseMenuObject(OldMenu
);
986 /* FIXME check window style, propably return FALSE ? */
987 Window
->SystemMenu
= Menu
->MenuInfo
.Self
;
988 Menu
->MenuInfo
.Flags
|= MF_SYSMENU
;
991 Window
->SystemMenu
= (HMENU
)0;
997 /* unlink the window from siblings and parent. children are kept in place. */
999 IntUnlinkWindow(PWINDOW_OBJECT Wnd
)
1001 PWINDOW_OBJECT WndParent
= Wnd
->Parent
;
1003 if (Wnd
->NextSibling
)
1004 Wnd
->NextSibling
->PrevSibling
= Wnd
->PrevSibling
;
1005 else if (WndParent
&& WndParent
->LastChild
== Wnd
)
1006 WndParent
->LastChild
= Wnd
->PrevSibling
;
1008 if (Wnd
->PrevSibling
)
1009 Wnd
->PrevSibling
->NextSibling
= Wnd
->NextSibling
;
1010 else if (WndParent
&& WndParent
->FirstChild
== Wnd
)
1011 WndParent
->FirstChild
= Wnd
->NextSibling
;
1013 Wnd
->PrevSibling
= Wnd
->NextSibling
= Wnd
->Parent
= NULL
;
1019 PWINDOW_OBJECT Window
, Child
;
1021 if(!(Window
= UserGetWindowObject(IntGetDesktopWindow())))
1026 for(Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
1028 if(Child
->hOwner
&& Child
->Style
& WS_VISIBLE
)
1031 * The desktop has a popup window if one of them has
1032 * an owner window and is visible
1042 IntIsWindowInDestroy(PWINDOW_OBJECT Window
)
1044 return ((Window
->Status
& WINDOWSTATUS_DESTROYING
) == WINDOWSTATUS_DESTROYING
);
1047 /* FUNCTIONS *****************************************************************/
1053 NtUserAlterWindowStyle(DWORD Unknown0
,
1064 * As best as I can figure, this function is used by EnumWindows,
1065 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
1067 * It's supposed to build a list of HWNDs to return to the caller.
1068 * We can figure out what kind of list by what parameters are
1076 NtUserBuildHwndList(
1088 /* FIXME handle bChildren */
1092 PWINDOW_OBJECT Window
, Child
;
1093 if(!(Window
= UserGetWindowObject(hwndParent
)))
1098 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1100 if(dwCount
++ < nBufSize
&& pWnd
)
1102 Status
= MmCopyToCaller(pWnd
++, &Child
->hSelf
, sizeof(HWND
));
1103 if(!NT_SUCCESS(Status
))
1105 SetLastNtError(Status
);
1114 PW32THREAD W32Thread
;
1115 PLIST_ENTRY Current
;
1116 PWINDOW_OBJECT Window
;
1118 Status
= PsLookupThreadByThreadId((HANDLE
)dwThreadId
, &Thread
);
1119 if(!NT_SUCCESS(Status
))
1121 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1124 if(!(W32Thread
= (PW32THREAD
)Thread
->Tcb
.Win32Thread
))
1126 ObDereferenceObject(Thread
);
1127 DPRINT("Thread is not a GUI Thread!\n");
1128 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1132 Current
= W32Thread
->WindowListHead
.Flink
;
1133 while(Current
!= &(W32Thread
->WindowListHead
))
1135 Window
= CONTAINING_RECORD(Current
, WINDOW_OBJECT
, ThreadListEntry
);
1138 if(dwCount
< nBufSize
&& pWnd
)
1140 Status
= MmCopyToCaller(pWnd
++, &Window
->hSelf
, sizeof(HWND
));
1141 if(!NT_SUCCESS(Status
))
1143 SetLastNtError(Status
);
1148 Current
= Current
->Flink
;
1151 ObDereferenceObject(Thread
);
1155 PDESKTOP_OBJECT Desktop
;
1156 PWINDOW_OBJECT Window
, Child
;
1158 if(hDesktop
== NULL
&& !(Desktop
= IntGetActiveDesktop()))
1160 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1166 Status
= IntValidateDesktopHandle(hDesktop
,
1170 if(!NT_SUCCESS(Status
))
1172 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1176 if(!(Window
= UserGetWindowObject(Desktop
->DesktopWindow
)))
1178 if(hDesktop
) ObDereferenceObject(Desktop
);
1182 for(Child
= Window
->FirstChild
; Child
!= NULL
; Child
= Child
->NextSibling
)
1184 if(dwCount
++ < nBufSize
&& pWnd
)
1186 Status
= MmCopyToCaller(pWnd
++, &Child
->hSelf
, sizeof(HWND
));
1187 if(!NT_SUCCESS(Status
))
1189 SetLastNtError(Status
);
1195 if(hDesktop
) ObDereferenceObject(Desktop
);
1206 NtUserChildWindowFromPointEx(HWND hwndParent
,
1211 PWINDOW_OBJECT Parent
;
1216 if(!(Parent
= UserGetWindowObject(hwndParent
)))
1224 if(Parent
->hSelf
!= IntGetDesktopWindow())
1226 Pt
.x
+= Parent
->ClientRect
.left
;
1227 Pt
.y
+= Parent
->ClientRect
.top
;
1230 if(!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
))
1235 Ret
= Parent
->hSelf
;
1236 if((List
= IntWinListChildren(Parent
)))
1238 for(phWnd
= List
; *phWnd
; phWnd
++)
1240 PWINDOW_OBJECT Child
;
1241 if((Child
= UserGetWindowObject(*phWnd
)))
1243 if(!(Child
->Style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
))
1247 if((Child
->Style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
))
1251 if((Child
->ExStyle
& WS_EX_TRANSPARENT
) && (uiFlags
& CWP_SKIPTRANSPARENT
))
1255 if(IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
1270 * calculates the default position of a window
1273 IntCalcDefPosSize(PWINDOW_OBJECT Parent
, PWINDOW_OBJECT Window
, RECT
*rc
, BOOL IncPos
)
1280 IntGdiIntersectRect(rc
, rc
, &Parent
->ClientRect
);
1284 Pos
.x
= Parent
->TiledCounter
* (UserGetSystemMetrics(SM_CXSIZE
) + UserGetSystemMetrics(SM_CXFRAME
));
1285 Pos
.y
= Parent
->TiledCounter
* (UserGetSystemMetrics(SM_CYSIZE
) + UserGetSystemMetrics(SM_CYFRAME
));
1286 if(Pos
.x
> ((rc
->right
- rc
->left
) / 4) ||
1287 Pos
.y
> ((rc
->bottom
- rc
->top
) / 4))
1289 /* reset counter and position */
1292 Parent
->TiledCounter
= 0;
1294 Parent
->TiledCounter
++;
1305 Sz
.cx
= EngMulDiv(rc
->right
- rc
->left
, 3, 4);
1306 Sz
.cy
= EngMulDiv(rc
->bottom
- rc
->top
, 3, 4);
1310 rc
->right
= rc
->left
+ Sz
.cx
;
1311 rc
->bottom
= rc
->top
+ Sz
.cy
;
1320 co_IntCreateWindowEx(DWORD dwExStyle
,
1321 PUNICODE_STRING ClassName
,
1322 PUNICODE_STRING WindowName
,
1330 HINSTANCE hInstance
,
1333 BOOL bUnicodeWindow
)
1335 PWINSTATION_OBJECT WinSta
;
1336 PWNDCLASS_OBJECT Class
= NULL
;
1337 PWINDOW_OBJECT Window
= NULL
;
1338 PWINDOW_OBJECT ParentWindow
= NULL
, OwnerWindow
;
1339 HWND ParentWindowHandle
;
1340 HWND OwnerWindowHandle
;
1341 PMENU_OBJECT SystemMenu
;
1347 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1354 CBT_CREATEWNDW CbtCreate
;
1357 DECLARE_RETURN(HWND
);
1359 USER_REFERENCE_ENTRY ParentRef
, Ref
;
1361 ParentWindowHandle
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
1362 OwnerWindowHandle
= NULL
;
1364 if (hWndParent
== HWND_MESSAGE
)
1367 * native ole32.OleInitialize uses HWND_MESSAGE to create the
1368 * message window (style: WS_POPUP|WS_DISABLED)
1370 DPRINT1("FIXME - Parent is HWND_MESSAGE\n");
1372 else if (hWndParent
)
1374 if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1375 ParentWindowHandle
= hWndParent
;
1379 PWINDOW_OBJECT Par
= UserGetWindowObject(hWndParent
), Root
;
1380 if (Par
&& (Root
= UserGetAncestor(Par
, GA_ROOT
)))
1381 OwnerWindowHandle
= Root
->hSelf
;
1384 else if ((dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1386 RETURN( (HWND
)0); /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1389 // if (NULL != ParentWindowHandle)
1391 ParentWindow
= UserGetWindowObject(ParentWindowHandle
);
1393 if (ParentWindow
) UserRefObjectCo(ParentWindow
, &ParentRef
);
1397 // ParentWindow = NULL;
1400 /* FIXME: parent must belong to the current process */
1402 /* Check the class. */
1403 Class
= ClassGetClassByNameOrAtom(ClassName
->Buffer
, hInstance
);
1406 if (IS_ATOM(ClassName
->Buffer
))
1408 DPRINT1("Class 0x%x not found\n", (DWORD_PTR
) ClassName
->Buffer
);
1412 DPRINT1("Class %wZ not found\n", ClassName
);
1415 SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS
);
1419 ClassRefObject(Class
);
1421 /* Check the window station. */
1422 if (PsGetWin32Thread()->Desktop
== NULL
)
1424 DPRINT("Thread is not attached to a desktop! Cannot create window!\n");
1427 WinSta
= PsGetWin32Thread()->Desktop
->WindowStation
;
1429 //FIXME: Reference thread/desktop instead
1430 ObReferenceObjectByPointer(WinSta
, KernelMode
, ExWindowStationObjectType
, 0);
1432 /* Create the window object. */
1433 Window
= (PWINDOW_OBJECT
)
1434 ObmCreateObject(&gHandleTable
, (PHANDLE
)&hWnd
,
1435 otWindow
, sizeof(WINDOW_OBJECT
) + Class
->cbWndExtra
1438 DPRINT("Created object with handle %X\n", hWnd
);
1441 ObDereferenceObject(WinSta
);
1442 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1446 UserRefObjectCo(Window
, &Ref
);
1448 ObDereferenceObject(WinSta
);
1450 if (NULL
== PsGetWin32Thread()->Desktop
->DesktopWindow
)
1452 /* If there is no desktop window yet, we must be creating it */
1453 PsGetWin32Thread()->Desktop
->DesktopWindow
= hWnd
;
1457 * Fill out the structure describing it.
1459 Window
->Class
= Class
;
1460 Window
->SystemMenu
= (HMENU
)0;
1461 Window
->ContextHelpId
= 0;
1463 Window
->Instance
= hInstance
;
1464 Window
->hSelf
= hWnd
;
1467 hMenu
= Class
->hMenu
;
1469 if (0 != (dwStyle
& WS_CHILD
))
1471 Window
->IDMenu
= (UINT
) hMenu
;
1475 IntSetMenu(Window
, hMenu
, &MenuChanged
);
1478 Window
->MessageQueue
= PsGetWin32Thread()->MessageQueue
;
1479 IntReferenceMessageQueue(Window
->MessageQueue
);
1480 Window
->Parent
= ParentWindow
;
1482 if((OwnerWindow
= UserGetWindowObject(OwnerWindowHandle
)))
1484 Window
->hOwner
= OwnerWindowHandle
;
1489 Window
->hOwner
= NULL
;
1493 Window
->UserData
= 0;
1495 if ((((DWORD
)Class
->lpfnWndProcA
& 0xFFFF0000) != 0xFFFF0000)
1496 && (((DWORD
)Class
->lpfnWndProcW
& 0xFFFF0000) != 0xFFFF0000))
1498 Window
->Unicode
= bUnicodeWindow
;
1502 Window
->Unicode
= Class
->Unicode
;
1504 Window
->WndProcA
= Class
->lpfnWndProcA
;
1505 Window
->WndProcW
= Class
->lpfnWndProcW
;
1506 Window
->OwnerThread
= PsGetCurrentThread();
1507 Window
->FirstChild
= NULL
;
1508 Window
->LastChild
= NULL
;
1509 Window
->PrevSibling
= NULL
;
1510 Window
->NextSibling
= NULL
;
1511 Window
->ExtraDataSize
= Class
->cbWndExtra
;
1513 /* extra window data */
1514 if (Class
->cbWndExtra
)
1515 Window
->ExtraData
= (PCHAR
)(Window
+ 1);
1517 InitializeListHead(&Window
->PropListHead
);
1518 InitializeListHead(&Window
->WndObjListHead
);
1520 if (NULL
!= WindowName
->Buffer
)
1522 Window
->WindowName
.MaximumLength
= WindowName
->MaximumLength
;
1523 Window
->WindowName
.Length
= WindowName
->Length
;
1524 Window
->WindowName
.Buffer
= ExAllocatePoolWithTag(PagedPool
, WindowName
->MaximumLength
,
1526 if (NULL
== Window
->WindowName
.Buffer
)
1528 DPRINT1("Failed to allocate mem for window name\n");
1529 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1532 RtlCopyMemory(Window
->WindowName
.Buffer
, WindowName
->Buffer
, WindowName
->MaximumLength
);
1536 RtlInitUnicodeString(&Window
->WindowName
, NULL
);
1541 * This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1542 * tested for WS_POPUP
1544 if ((dwExStyle
& WS_EX_DLGMODALFRAME
) ||
1545 ((!(dwExStyle
& WS_EX_STATICEDGE
)) &&
1546 (dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
))))
1547 dwExStyle
|= WS_EX_WINDOWEDGE
;
1549 dwExStyle
&= ~WS_EX_WINDOWEDGE
;
1551 /* Correct the window style. */
1552 if (!(dwStyle
& WS_CHILD
))
1554 dwStyle
|= WS_CLIPSIBLINGS
;
1555 DPRINT("3: Style is now %lx\n", dwStyle
);
1556 if (!(dwStyle
& WS_POPUP
))
1558 dwStyle
|= WS_CAPTION
;
1559 Window
->Flags
|= WINDOWOBJECT_NEED_SIZE
;
1560 DPRINT("4: Style is now %lx\n", dwStyle
);
1564 /* create system menu */
1565 if((dwStyle
& WS_SYSMENU
) &&
1566 (dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1568 SystemMenu
= IntGetSystemMenu(Window
, TRUE
, TRUE
);
1571 Window
->SystemMenu
= SystemMenu
->MenuInfo
.Self
;
1572 IntReleaseMenuObject(SystemMenu
);
1576 /* Insert the window into the thread's window list. */
1577 InsertTailList (&PsGetWin32Thread()->WindowListHead
, &Window
->ThreadListEntry
);
1579 /* Allocate a DCE for this window. */
1580 if (dwStyle
& CS_OWNDC
)
1582 Window
->Dce
= DceAllocDCE(Window
, DCE_WINDOW_DC
);
1584 /* FIXME: Handle "CS_CLASSDC" */
1591 Window
->ExStyle
= dwExStyle
;
1592 Window
->Style
= dwStyle
& ~WS_VISIBLE
;
1595 Cs
.lpCreateParams
= lpParam
;
1596 Cs
.hInstance
= hInstance
;
1598 Cs
.hwndParent
= ParentWindowHandle
;
1603 Cs
.style
= Window
->Style
;
1604 Cs
.lpszName
= (LPCWSTR
) WindowName
;
1605 Cs
.lpszClass
= (LPCWSTR
) ClassName
;
1606 Cs
.dwExStyle
= dwExStyle
;
1607 CbtCreate
.lpcs
= &Cs
;
1608 CbtCreate
.hwndInsertAfter
= HWND_TOP
;
1609 if (co_HOOK_CallHooks(WH_CBT
, HCBT_CREATEWND
, (WPARAM
) hWnd
, (LPARAM
) &CbtCreate
))
1611 /* FIXME - Delete window object and remove it from the thread windows list */
1612 /* FIXME - delete allocated DCE */
1613 DPRINT1("CBT-hook returned !0\n");
1614 RETURN( (HWND
) NULL
);
1622 /* default positioning for overlapped windows */
1623 if(!(Window
->Style
& (WS_POPUP
| WS_CHILD
)))
1626 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
1627 BOOL CalculatedDefPosSize
= FALSE
;
1629 IntGetDesktopWorkArea(((PW32THREAD
)Window
->OwnerThread
->Tcb
.Win32Thread
)->Desktop
, &WorkArea
);
1632 ProcessParams
= PsGetCurrentProcess()->Peb
->ProcessParameters
;
1634 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1636 CalculatedDefPosSize
= IntCalcDefPosSize(ParentWindow
, Window
, &rc
, TRUE
);
1638 if(ProcessParams
->WindowFlags
& STARTF_USEPOSITION
)
1640 ProcessParams
->WindowFlags
&= ~STARTF_USEPOSITION
;
1641 Pos
.x
= WorkArea
.left
+ ProcessParams
->StartingX
;
1642 Pos
.y
= WorkArea
.top
+ ProcessParams
->StartingY
;
1650 /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
1651 y is something else */
1652 if(y
!= CW_USEDEFAULT
&& y
!= CW_USEDEFAULT16
)
1657 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1659 if(!CalculatedDefPosSize
)
1661 IntCalcDefPosSize(ParentWindow
, Window
, &rc
, FALSE
);
1663 if(ProcessParams
->WindowFlags
& STARTF_USESIZE
)
1665 ProcessParams
->WindowFlags
&= ~STARTF_USESIZE
;
1666 Size
.cx
= ProcessParams
->CountX
;
1667 Size
.cy
= ProcessParams
->CountY
;
1671 Size
.cx
= rc
.right
- rc
.left
;
1672 Size
.cy
= rc
.bottom
- rc
.top
;
1675 /* move the window if necessary */
1677 Pos
.x
= max(rc
.left
, 0);
1679 Pos
.y
= max(rc
.top
, 0);
1684 /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
1685 if(x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
1690 if(nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
)
1697 /* Initialize the window dimensions. */
1698 Window
->WindowRect
.left
= Pos
.x
;
1699 Window
->WindowRect
.top
= Pos
.y
;
1700 Window
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1701 Window
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1702 if (0 != (Window
->Style
& WS_CHILD
) && ParentWindow
)
1704 IntGdiOffsetRect(&(Window
->WindowRect
), ParentWindow
->ClientRect
.left
,
1705 ParentWindow
->ClientRect
.top
);
1707 Window
->ClientRect
= Window
->WindowRect
;
1710 * Get the size and position of the window.
1712 if ((dwStyle
& WS_THICKFRAME
) || !(dwStyle
& (WS_POPUP
| WS_CHILD
)))
1714 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
1716 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1717 co_WinPosGetMinMaxInfo(Window
, &MaxSize
, &MaxPos
, &MinTrack
,
1719 if (MaxSize
.x
< Size
.cx
)
1720 Size
.cx
= MaxSize
.x
;
1721 if (MaxSize
.y
< Size
.cy
)
1722 Size
.cy
= MaxSize
.y
;
1723 if (Size
.cx
< MinTrack
.x
)
1724 Size
.cx
= MinTrack
.x
;
1725 if (Size
.cy
< MinTrack
.y
)
1726 Size
.cy
= MinTrack
.y
;
1733 Window
->WindowRect
.left
= Pos
.x
;
1734 Window
->WindowRect
.top
= Pos
.y
;
1735 Window
->WindowRect
.right
= Pos
.x
+ Size
.cx
;
1736 Window
->WindowRect
.bottom
= Pos
.y
+ Size
.cy
;
1737 if (0 != (Window
->Style
& WS_CHILD
) && ParentWindow
)
1739 IntGdiOffsetRect(&(Window
->WindowRect
), ParentWindow
->ClientRect
.left
,
1740 ParentWindow
->ClientRect
.top
);
1742 Window
->ClientRect
= Window
->WindowRect
;
1744 /* FIXME: Initialize the window menu. */
1746 /* Send a NCCREATE message. */
1752 DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d\n", Cs
.style
, Cs
.dwExStyle
, Cs
.hwndParent
);
1753 DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, Size
.cx
, Size
.cy
);
1754 DPRINT("IntCreateWindowEx(): About to send NCCREATE message.\n");
1755 Result
= co_IntSendMessage(Window
->hSelf
, WM_NCCREATE
, 0, (LPARAM
) &Cs
);
1758 /* FIXME: Cleanup. */
1759 DPRINT("IntCreateWindowEx(): NCCREATE message failed.\n");
1763 /* Calculate the non-client size. */
1764 MaxPos
.x
= Window
->WindowRect
.left
;
1765 MaxPos
.y
= Window
->WindowRect
.top
;
1766 DPRINT("IntCreateWindowEx(): About to get non-client size.\n");
1767 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1768 Result
= co_WinPosGetNonClientSize(Window
,
1769 &Window
->WindowRect
,
1770 &Window
->ClientRect
);
1773 IntGdiOffsetRect(&Window
->WindowRect
,
1774 MaxPos
.x
- Window
->WindowRect
.left
,
1775 MaxPos
.y
- Window
->WindowRect
.top
);
1777 if (NULL
!= ParentWindow
)
1779 /* link the window into the parent's child list */
1780 if ((dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
1782 PWINDOW_OBJECT PrevSibling
;
1784 PrevSibling
= ParentWindow
->LastChild
;
1786 /* link window as bottom sibling */
1787 IntLinkWindow(Window
, ParentWindow
, PrevSibling
/*prev sibling*/);
1791 /* link window as top sibling (but after topmost siblings) */
1792 PWINDOW_OBJECT InsertAfter
, Sibling
;
1793 if (!(dwExStyle
& WS_EX_TOPMOST
))
1796 Sibling
= ParentWindow
->FirstChild
;
1797 while (Sibling
&& (Sibling
->ExStyle
& WS_EX_TOPMOST
))
1799 InsertAfter
= Sibling
;
1800 Sibling
= Sibling
->NextSibling
;
1808 IntLinkWindow(Window
, ParentWindow
, InsertAfter
/* prev sibling */);
1813 /* Send the WM_CREATE message. */
1814 DPRINT("IntCreateWindowEx(): about to send CREATE message.\n");
1815 Result
= co_IntSendMessage(Window
->hSelf
, WM_CREATE
, 0, (LPARAM
) &Cs
);
1818 if (Result
== (LRESULT
)-1)
1820 /* FIXME: Cleanup. */
1821 DPRINT("IntCreateWindowEx(): send CREATE message failed.\n");
1826 /* Send move and size messages. */
1827 if (!(Window
->Flags
& WINDOWOBJECT_NEED_SIZE
))
1831 DPRINT("IntCreateWindow(): About to send WM_SIZE\n");
1833 if ((Window
->ClientRect
.right
- Window
->ClientRect
.left
) < 0 ||
1834 (Window
->ClientRect
.bottom
- Window
->ClientRect
.top
) < 0)
1836 DPRINT("Sending bogus WM_SIZE\n");
1840 lParam
= MAKE_LONG(Window
->ClientRect
.right
-
1841 Window
->ClientRect
.left
,
1842 Window
->ClientRect
.bottom
-
1843 Window
->ClientRect
.top
);
1844 co_IntSendMessage(Window
->hSelf
, WM_SIZE
, SIZE_RESTORED
,
1848 DPRINT("IntCreateWindow(): About to send WM_MOVE\n");
1850 if (0 != (Window
->Style
& WS_CHILD
) && ParentWindow
)
1852 lParam
= MAKE_LONG(Window
->ClientRect
.left
- ParentWindow
->ClientRect
.left
,
1853 Window
->ClientRect
.top
- ParentWindow
->ClientRect
.top
);
1857 lParam
= MAKE_LONG(Window
->ClientRect
.left
,
1858 Window
->ClientRect
.top
);
1862 co_IntSendMessage(Window
->hSelf
, WM_MOVE
, 0, lParam
);
1865 /* Call WNDOBJ change procs */
1866 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
1871 /* Show or maybe minimize or maximize the window. */
1872 if (Window
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1877 SwFlag
= (Window
->Style
& WS_MINIMIZE
) ? SW_MINIMIZE
:
1879 co_WinPosMinMaximize(Window
, SwFlag
, &NewPos
);
1881 ((Window
->Style
& WS_CHILD
) || UserGetActiveWindow()) ?
1882 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
:
1883 SWP_NOZORDER
| SWP_FRAMECHANGED
;
1884 DPRINT("IntCreateWindow(): About to minimize/maximize\n");
1885 DPRINT("%d,%d %dx%d\n", NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
);
1886 co_WinPosSetWindowPos(Window
, 0, NewPos
.left
, NewPos
.top
,
1887 NewPos
.right
, NewPos
.bottom
, SwFlag
);
1890 /* Notify the parent window of a new child. */
1891 if ((Window
->Style
& WS_CHILD
) &&
1892 (!(Window
->ExStyle
& WS_EX_NOPARENTNOTIFY
)) && ParentWindow
)
1894 DPRINT("IntCreateWindow(): About to notify parent\n");
1895 co_IntSendMessage(ParentWindow
->hSelf
,
1897 MAKEWPARAM(WM_CREATE
, Window
->IDMenu
),
1898 (LPARAM
)Window
->hSelf
);
1901 if ((!hWndParent
) && (!HasOwner
))
1903 DPRINT("Sending CREATED notify\n");
1904 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)hWnd
);
1908 DPRINT("Not sending CREATED notify, %x %d\n", ParentWindow
, HasOwner
);
1911 /* Initialize and show the window's scrollbars */
1912 if (Window
->Style
& WS_VSCROLL
)
1914 co_UserShowScrollBar(Window
, SB_VERT
, TRUE
);
1916 if (Window
->Style
& WS_HSCROLL
)
1918 co_UserShowScrollBar(Window
, SB_HORZ
, TRUE
);
1921 if (dwStyle
& WS_VISIBLE
)
1923 DPRINT("IntCreateWindow(): About to show window\n");
1924 co_WinPosShowWindow(Window
, dwShowMode
);
1927 DPRINT("IntCreateWindow(): = %X\n", hWnd
);
1928 DPRINT("WindowObject->SystemMenu = 0x%x\n", Window
->SystemMenu
);
1932 if (Window
) UserDerefObjectCo(Window
);
1933 if (ParentWindow
) UserDerefObjectCo(ParentWindow
);
1934 if (!_ret_
&& Class
) ClassDerefObject(Class
); /* only deref if failure (return 0) */
1939 NtUserCreateWindowEx(DWORD dwExStyle
,
1940 PUNICODE_STRING UnsafeClassName
,
1941 PUNICODE_STRING UnsafeWindowName
,
1949 HINSTANCE hInstance
,
1952 BOOL bUnicodeWindow
)
1955 UNICODE_STRING WindowName
;
1956 UNICODE_STRING ClassName
;
1958 DECLARE_RETURN(HWND
);
1960 DPRINT("Enter NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x
, y
, nWidth
, nHeight
);
1961 UserEnterExclusive();
1963 /* Get the class name (string or atom) */
1964 Status
= MmCopyFromCaller(&ClassName
, UnsafeClassName
, sizeof(UNICODE_STRING
));
1965 if (! NT_SUCCESS(Status
))
1967 SetLastNtError(Status
);
1970 if (! IS_ATOM(ClassName
.Buffer
))
1972 Status
= IntSafeCopyUnicodeStringTerminateNULL(&ClassName
, UnsafeClassName
);
1973 if (! NT_SUCCESS(Status
))
1975 SetLastNtError(Status
);
1980 /* safely copy the window name */
1981 if (NULL
!= UnsafeWindowName
)
1983 Status
= IntSafeCopyUnicodeString(&WindowName
, UnsafeWindowName
);
1984 if (! NT_SUCCESS(Status
))
1986 if (! IS_ATOM(ClassName
.Buffer
))
1988 RtlFreeUnicodeString(&ClassName
);
1990 SetLastNtError(Status
);
1996 RtlInitUnicodeString(&WindowName
, NULL
);
1999 NewWindow
= co_IntCreateWindowEx(dwExStyle
, &ClassName
, &WindowName
, dwStyle
, x
, y
, nWidth
, nHeight
,
2000 hWndParent
, hMenu
, hInstance
, lpParam
, dwShowMode
, bUnicodeWindow
);
2002 RtlFreeUnicodeString(&WindowName
);
2003 if (! IS_ATOM(ClassName
.Buffer
))
2005 RtlFreeUnicodeString(&ClassName
);
2011 DPRINT("Leave NtUserCreateWindowEx, ret=%i\n",_ret_
);
2020 NtUserDeferWindowPos(HDWP WinPosInfo
,
2022 HWND WndInsertAfter
,
2035 BOOLEAN FASTCALL
co_UserDestroyWindow(PWINDOW_OBJECT Window
)
2039 ASSERT_REFS_CO(Window
); //fixme: temp hack?
2041 /* Check for owner thread */
2042 if ((Window
->OwnerThread
!= PsGetCurrentThread()))
2044 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2048 /* Look whether the focus is within the tree of windows we will
2051 if (!co_WinPosShowWindow(Window
, SW_HIDE
))
2053 if (UserGetActiveWindow() == Window
->hSelf
)
2055 co_WinPosActivateOtherWindow(Window
);
2059 if (Window
->MessageQueue
->ActiveWindow
== Window
->hSelf
)
2060 Window
->MessageQueue
->ActiveWindow
= NULL
;
2061 if (Window
->MessageQueue
->FocusWindow
== Window
->hSelf
)
2062 Window
->MessageQueue
->FocusWindow
= NULL
;
2063 if (Window
->MessageQueue
->CaptureWindow
== Window
->hSelf
)
2064 Window
->MessageQueue
->CaptureWindow
= NULL
;
2066 IntDereferenceMessageQueue(Window
->MessageQueue
);
2070 if (co_HOOK_CallHooks(WH_CBT
, HCBT_DESTROYWND
, (WPARAM
) hwnd
, 0, TRUE
))
2076 IntEngWindowChanged(Window
, WOC_DELETE
);
2077 isChild
= (0 != (Window
->Style
& WS_CHILD
));
2083 if (! USER_IsExitingThread(GetCurrentThreadId()))
2085 send_parent_notify(hwnd
, WM_DESTROY
);
2088 else if (NULL
!= GetWindow(Wnd
, GW_OWNER
))
2090 co_HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, (WPARAM
)hwnd
, 0L, TRUE
);
2091 /* FIXME: clean up palette - see "Internals" p.352 */
2095 if (!IntIsWindow(Window
->hSelf
))
2100 /* Recursively destroy owned windows */
2105 BOOL GotOne
= FALSE
;
2108 PWINDOW_OBJECT Child
, Desktop
;
2110 Desktop
= IntIsDesktopWindow(Window
) ? Window
:
2111 UserGetWindowObject(IntGetDesktopWindow());
2112 Children
= IntWinListChildren(Desktop
);
2116 for (ChildHandle
= Children
; *ChildHandle
; ++ChildHandle
)
2118 Child
= UserGetWindowObject(*ChildHandle
);
2121 if (Child
->hOwner
!= Window
->hSelf
)
2126 if (IntWndBelongsToThread(Child
, PsGetWin32Thread()))
2128 USER_REFERENCE_ENTRY ChildRef
;
2129 UserRefObjectCo(Child
, &ChildRef
);//temp hack?
2130 co_UserDestroyWindow(Child
);
2131 UserDerefObjectCo(Child
);//temp hack?
2137 if (Child
->hOwner
!= NULL
)
2139 Child
->hOwner
= NULL
;
2143 ExFreePool(Children
);
2152 if (!IntIsWindow(Window
->hSelf
))
2157 /* Destroy the window storage */
2158 co_UserFreeWindow(Window
, PsGetWin32Process(), PsGetWin32Thread(), TRUE
);
2170 NtUserDestroyWindow(HWND Wnd
)
2172 PWINDOW_OBJECT Window
;
2173 DECLARE_RETURN(BOOLEAN
);
2175 USER_REFERENCE_ENTRY Ref
;
2177 DPRINT("Enter NtUserDestroyWindow\n");
2178 UserEnterExclusive();
2180 if (!(Window
= UserGetWindowObject(Wnd
)))
2185 UserRefObjectCo(Window
, &Ref
);//faxme: dunno if win should be reffed during destroy..
2186 ret
= co_UserDestroyWindow(Window
);
2187 UserDerefObjectCo(Window
);//faxme: dunno if win should be reffed during destroy..
2192 DPRINT("Leave NtUserDestroyWindow, ret=%i\n",_ret_
);
2204 NtUserDrawMenuBarTemp(
2211 /* we'll use this function just for caching the menu bar */
2221 NtUserEndDeferWindowPosEx(DWORD Unknown0
,
2234 NtUserFillWindow(DWORD Unknown0
,
2246 IntFindWindow(PWINDOW_OBJECT Parent
,
2247 PWINDOW_OBJECT ChildAfter
,
2249 PUNICODE_STRING WindowName
)
2251 BOOL CheckWindowName
;
2257 CheckWindowName
= (WindowName
&& (WindowName
->Length
> 0));
2259 if((List
= IntWinListChildren(Parent
)))
2264 /* skip handles before and including ChildAfter */
2265 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->hSelf
))
2269 /* search children */
2272 PWINDOW_OBJECT Child
;
2273 if(!(Child
= UserGetWindowObject(*(phWnd
++))))
2278 /* Do not send WM_GETTEXT messages in the kernel mode version!
2279 The user mode version however calls GetWindowText() which will
2280 send WM_GETTEXT messages to windows belonging to its processes */
2281 if((!CheckWindowName
|| !RtlCompareUnicodeString(WindowName
, &(Child
->WindowName
), TRUE
)) &&
2282 (!ClassAtom
|| Child
->Class
->Atom
== ClassAtom
))
2297 * Searches a window's children for a window with the specified
2300 * hwndParent = The window whose childs are to be searched.
2302 * HWND_MESSAGE = message-only windows
2304 * hwndChildAfter = Search starts after this child window.
2305 * NULL = start from beginning
2307 * ucClassName = Class name to search for
2308 * Reguired parameter.
2310 * ucWindowName = Window name
2311 * ->Buffer == NULL = don't care
2314 * The HWND of the window if it was found, otherwise NULL
2320 NtUserFindWindowEx(HWND hwndParent
,
2321 HWND hwndChildAfter
,
2322 PUNICODE_STRING ucClassName
,
2323 PUNICODE_STRING ucWindowName
)
2325 PWINDOW_OBJECT Parent
, ChildAfter
;
2326 UNICODE_STRING ClassName
, WindowName
;
2328 HWND Desktop
, Ret
= NULL
;
2330 DECLARE_RETURN(HWND
);
2332 DPRINT("Enter NtUserFindWindowEx\n");
2335 Desktop
= IntGetCurrentThreadDesktopWindow();
2337 if(hwndParent
== NULL
)
2338 hwndParent
= Desktop
;
2340 else if(hwndParent == HWND_MESSAGE)
2342 hwndParent = IntGetMessageWindow();
2346 if(!(Parent
= UserGetWindowObject(hwndParent
)))
2352 if(hwndChildAfter
&& !(ChildAfter
= UserGetWindowObject(hwndChildAfter
)))
2357 /* copy the window name */
2358 Status
= IntSafeCopyUnicodeString(&WindowName
, ucWindowName
);
2359 if(!NT_SUCCESS(Status
))
2361 SetLastNtError(Status
);
2365 /* safely copy the class name */
2366 Status
= MmCopyFromCaller(&ClassName
, ucClassName
, sizeof(UNICODE_STRING
));
2367 if(!NT_SUCCESS(Status
))
2369 SetLastNtError(Status
);
2372 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2375 /* safely copy the class name string (NULL terminated because class-lookup
2377 buf
= ExAllocatePoolWithTag(PagedPool
, ClassName
.Length
+ sizeof(WCHAR
), TAG_STRING
);
2380 SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES
);
2383 Status
= MmCopyFromCaller(buf
, ClassName
.Buffer
, ClassName
.Length
);
2384 if(!NT_SUCCESS(Status
))
2387 SetLastNtError(Status
);
2390 ClassName
.Buffer
= buf
;
2391 /* make sure the string is null-terminated */
2392 buf
+= ClassName
.Length
/ sizeof(WCHAR
);
2396 /* find the class object */
2397 if(ClassName
.Buffer
)
2399 PWINSTATION_OBJECT WinStaObject
;
2401 if (PsGetWin32Thread()->Desktop
== NULL
)
2403 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2407 WinStaObject
= PsGetWin32Thread()->Desktop
->WindowStation
;
2409 Status
= RtlLookupAtomInAtomTable(
2410 WinStaObject
->AtomTable
,
2414 if (!NT_SUCCESS(Status
))
2416 DPRINT1("Failed to lookup class atom!\n");
2417 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST
);
2422 if(Parent
->hSelf
== Desktop
)
2425 PWINDOW_OBJECT TopLevelWindow
;
2426 BOOLEAN CheckWindowName
;
2427 BOOLEAN CheckClassName
;
2428 BOOLEAN WindowMatches
;
2429 BOOLEAN ClassMatches
;
2431 /* windows searches through all top-level windows if the parent is the desktop
2434 if((List
= IntWinListChildren(Parent
)))
2440 /* skip handles before and including ChildAfter */
2441 while(*phWnd
&& (*(phWnd
++) != ChildAfter
->hSelf
))
2445 CheckWindowName
= WindowName
.Length
> 0;
2446 CheckClassName
= ClassName
.Buffer
!= NULL
;
2448 /* search children */
2451 if(!(TopLevelWindow
= UserGetWindowObject(*(phWnd
++))))
2456 /* Do not send WM_GETTEXT messages in the kernel mode version!
2457 The user mode version however calls GetWindowText() which will
2458 send WM_GETTEXT messages to windows belonging to its processes */
2459 WindowMatches
= !CheckWindowName
|| !RtlCompareUnicodeString(
2460 &WindowName
, &TopLevelWindow
->WindowName
, TRUE
);
2461 ClassMatches
= !CheckClassName
||
2462 ClassAtom
== TopLevelWindow
->Class
->Atom
;
2464 if (WindowMatches
&& ClassMatches
)
2466 Ret
= TopLevelWindow
->hSelf
;
2470 if (IntFindWindow(TopLevelWindow
, NULL
, ClassAtom
, &WindowName
))
2472 /* window returns the handle of the top-level window, in case it found
2474 Ret
= TopLevelWindow
->hSelf
;
2483 Ret
= IntFindWindow(Parent
, ChildAfter
, ClassAtom
, &WindowName
);
2487 if(Ret
== NULL
&& hwndParent
== NULL
&& hwndChildAfter
== NULL
)
2489 /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
2490 search the message-only windows. Should this also be done if
2491 Parent is the desktop window??? */
2492 PWINDOW_OBJECT MsgWindows
;
2494 if((MsgWindows
= UserGetWindowObject(IntGetMessageWindow())))
2496 Ret
= IntFindWindow(MsgWindows
, ChildAfter
, ClassAtom
, &WindowName
);
2502 if(ClassName
.Length
> 0 && ClassName
.Buffer
)
2503 ExFreePool(ClassName
.Buffer
);
2506 RtlFreeUnicodeString(&WindowName
);
2513 DPRINT("Leave NtUserFindWindowEx, ret %i\n",_ret_
);
2523 NtUserFlashWindowEx(DWORD Unknown0
)
2534 PWINDOW_OBJECT FASTCALL
UserGetAncestor(PWINDOW_OBJECT Wnd
, UINT Type
)
2536 PWINDOW_OBJECT WndAncestor
, Parent
;
2538 if (Wnd
->hSelf
== IntGetDesktopWindow())
2547 WndAncestor
= Wnd
->Parent
;
2558 if(!(Parent
= WndAncestor
->Parent
))
2562 if(IntIsDesktopWindow(Parent
))
2567 WndAncestor
= Parent
;
2578 PWINDOW_OBJECT Parent
, Old
;
2581 Parent
= IntGetParent(WndAncestor
);
2589 // UserDerefObject(Parent);
2591 WndAncestor
= Parent
;
2611 NtUserGetAncestor(HWND hWnd
, UINT Type
)
2613 PWINDOW_OBJECT Window
, Ancestor
;
2614 DECLARE_RETURN(HWND
);
2616 DPRINT("Enter NtUserGetAncestor\n");
2617 UserEnterExclusive();
2619 if (!(Window
= UserGetWindowObject(hWnd
)))
2624 Ancestor
= UserGetAncestor(Window
, Type
);
2625 /* faxme: can UserGetAncestor ever return NULL for a valid window? */
2627 RETURN(Ancestor
? Ancestor
->hSelf
: NULL
);
2630 DPRINT("Leave NtUserGetAncestor, ret=%i\n",_ret_
);
2636 * Returns client window rectangle relative to the upper-left corner of client area.
2638 * \param hWnd window handle.
2639 * \param Rect pointer to the buffer where the coordinates are returned.
2646 NtUserGetClientRect(HWND hWnd
, LPRECT Rect
)
2648 PWINDOW_OBJECT Window
;
2650 DECLARE_RETURN(BOOL
);
2652 DPRINT("Enter NtUserGetClientRect\n");
2655 if(!(Window
= UserGetWindowObject(hWnd
)))
2660 IntGetClientRect(Window
, &SafeRect
);
2662 if(!NT_SUCCESS(MmCopyToCaller(Rect
, &SafeRect
, sizeof(RECT
))))
2669 DPRINT("Leave NtUserGetClientRect, ret=%i\n",_ret_
);
2679 NtUserGetDesktopWindow()
2681 DECLARE_RETURN(HWND
);
2683 DPRINT("Enter NtUserGetDesktopWindow\n");
2686 RETURN( IntGetDesktopWindow());
2689 DPRINT("Leave NtUserGetDesktopWindow, ret=%i\n",_ret_
);
2699 NtUserGetInternalWindowPos(DWORD Unknown0
,
2713 NtUserGetLastActivePopup(HWND hWnd
)
2716 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2717 * not changed anywhere.
2718 * -- Filip, 01/nov/2003
2724 if (!(Wnd
= UserGetWindowObject(hWnd
)))
2729 hWndLastPopup
= Wnd
->hWndLastPopup
;
2731 return hWndLastPopup
;
2741 * The NtUserGetParent function retrieves a handle to the specified window's
2745 * Note that, despite its name, this function can return an owner window
2746 * instead of a parent window.
2753 NtUserGetParent(HWND hWnd
)
2755 PWINDOW_OBJECT Wnd
, WndParent
;
2756 HWND hWndParent
= NULL
;
2757 DECLARE_RETURN(HWND
);
2759 DPRINT("Enter NtUserGetParent\n");
2760 UserEnterExclusive();
2762 if (!(Wnd
= UserGetWindowObject(hWnd
)))
2767 WndParent
= IntGetParent(Wnd
);
2770 hWndParent
= WndParent
->hSelf
;
2773 RETURN( hWndParent
);
2776 DPRINT("Leave NtUserGetParent, ret=%i\n",_ret_
);
2785 co_UserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2787 PWINDOW_OBJECT Wnd
= NULL
, WndParent
= NULL
, WndOldParent
;
2788 HWND hWndOldParent
= NULL
;
2789 USER_REFERENCE_ENTRY Ref
, ParentRef
;
2791 if (IntIsBroadcastHwnd(hWndChild
) || IntIsBroadcastHwnd(hWndNewParent
))
2793 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2797 if (hWndChild
== IntGetDesktopWindow())
2799 SetLastWin32Error(ERROR_ACCESS_DENIED
);
2805 if (!(WndParent
= UserGetWindowObject(hWndNewParent
)))
2812 if (!(WndParent
= UserGetWindowObject(IntGetDesktopWindow())))
2818 if (!(Wnd
= UserGetWindowObject(hWndChild
)))
2823 UserRefObjectCo(Wnd
, &Ref
);
2824 UserRefObjectCo(WndParent
, &ParentRef
);
2826 WndOldParent
= co_IntSetParent(Wnd
, WndParent
);
2828 UserDerefObjectCo(WndParent
);
2829 UserDerefObjectCo(Wnd
);
2833 hWndOldParent
= WndOldParent
->hSelf
;
2834 UserDerefObject(WndOldParent
);
2837 return( hWndOldParent
);
2845 * The NtUserSetParent function changes the parent window of the specified
2849 * The new parent window and the child window must belong to the same
2850 * application. If the window identified by the hWndChild parameter is
2851 * visible, the system performs the appropriate redrawing and repainting.
2852 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2853 * or WS_POPUP window styles of the window whose parent is being changed.
2860 NtUserSetParent(HWND hWndChild
, HWND hWndNewParent
)
2862 DECLARE_RETURN(HWND
);
2864 DPRINT("Enter NtUserSetParent\n");
2865 UserEnterExclusive();
2867 RETURN( co_UserSetParent(hWndChild
, hWndNewParent
));
2870 DPRINT("Leave NtUserSetParent, ret=%i\n",_ret_
);
2878 HWND FASTCALL
UserGetShellWindow()
2880 PWINSTATION_OBJECT WinStaObject
;
2883 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
2888 if (!NT_SUCCESS(Status
))
2890 SetLastNtError(Status
);
2894 Ret
= (HWND
)WinStaObject
->ShellWindow
;
2896 ObDereferenceObject(WinStaObject
);
2902 * NtUserGetShellWindow
2904 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
2911 NtUserGetShellWindow()
2913 DECLARE_RETURN(HWND
);
2915 DPRINT("Enter NtUserGetShellWindow\n");
2918 RETURN( UserGetShellWindow() );
2921 DPRINT("Leave NtUserGetShellWindow, ret=%i\n",_ret_
);
2927 * NtUserSetShellWindowEx
2929 * This is undocumented function to set global shell window. The global
2930 * shell window has special handling of window position.
2937 NtUserSetShellWindowEx(HWND hwndShell
, HWND hwndListView
)
2939 PWINSTATION_OBJECT WinStaObject
;
2940 PWINDOW_OBJECT WndShell
;
2941 DECLARE_RETURN(BOOL
);
2942 USER_REFERENCE_ENTRY Ref
;
2945 DPRINT("Enter NtUserSetShellWindowEx\n");
2946 UserEnterExclusive();
2948 if (!(WndShell
= UserGetWindowObject(hwndShell
)))
2953 Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
2958 if (!NT_SUCCESS(Status
))
2960 SetLastNtError(Status
);
2965 * Test if we are permitted to change the shell window.
2967 if (WinStaObject
->ShellWindow
)
2969 ObDereferenceObject(WinStaObject
);
2974 * Move shell window into background.
2976 if (hwndListView
&& hwndListView
!= hwndShell
)
2979 * Disabled for now to get Explorer working.
2980 * -- Filip, 01/nov/2003
2983 co_WinPosSetWindowPos(hwndListView
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
2986 if (UserGetWindowLong(hwndListView
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2988 ObDereferenceObject(WinStaObject
);
2993 if (UserGetWindowLong(hwndShell
, GWL_EXSTYLE
, FALSE
) & WS_EX_TOPMOST
)
2995 ObDereferenceObject(WinStaObject
);
2999 UserRefObjectCo(WndShell
, &Ref
);
3000 co_WinPosSetWindowPos(WndShell
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOACTIVATE
);
3002 WinStaObject
->ShellWindow
= hwndShell
;
3003 WinStaObject
->ShellListView
= hwndListView
;
3005 UserDerefObjectCo(WndShell
);
3007 ObDereferenceObject(WinStaObject
);
3011 DPRINT("Leave NtUserSetShellWindowEx, ret=%i\n",_ret_
);
3017 * NtUserGetSystemMenu
3019 * The NtUserGetSystemMenu function allows the application to access the
3020 * window menu (also known as the system menu or the control menu) for
3021 * copying and modifying.
3025 * Handle to the window that will own a copy of the window menu.
3027 * Specifies the action to be taken. If this parameter is FALSE,
3028 * NtUserGetSystemMenu returns a handle to the copy of the window menu
3029 * currently in use. The copy is initially identical to the window menu
3030 * but it can be modified.
3031 * If this parameter is TRUE, GetSystemMenu resets the window menu back
3032 * to the default state. The previous window menu, if any, is destroyed.
3035 * If the bRevert parameter is FALSE, the return value is a handle to a
3036 * copy of the window menu. If the bRevert parameter is TRUE, the return
3044 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
3046 PWINDOW_OBJECT Window
;
3048 DECLARE_RETURN(HMENU
);
3050 DPRINT("Enter NtUserGetSystemMenu\n");
3053 if (!(Window
= UserGetWindowObject(hWnd
)))
3058 if (!(Menu
= IntGetSystemMenu(Window
, bRevert
, FALSE
)))
3063 RETURN(Menu
->MenuInfo
.Self
);
3066 DPRINT("Leave NtUserGetSystemMenu, ret=%i\n",_ret_
);
3072 * NtUserSetSystemMenu
3079 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
3081 BOOL Result
= FALSE
;
3082 PWINDOW_OBJECT Window
;
3084 DECLARE_RETURN(BOOL
);
3086 DPRINT("Enter NtUserSetSystemMenu\n");
3087 UserEnterExclusive();
3089 if (!(Window
= UserGetWindowObject(hWnd
)))
3097 * Assign new menu handle.
3099 if (!(Menu
= UserGetMenuObject(hMenu
)))
3104 Result
= IntSetSystemMenu(Window
, Menu
);
3110 DPRINT("Leave NtUserSetSystemMenu, ret=%i\n",_ret_
);
3119 UserGetWindow(HWND hWnd
, UINT Relationship
)
3121 PWINDOW_OBJECT Parent
, Window
;
3122 HWND hWndResult
= NULL
;
3124 if (!(Window
= UserGetWindowObject(hWnd
)))
3127 switch (Relationship
)
3130 if((Parent
= Window
->Parent
))
3132 if (Parent
->FirstChild
)
3133 hWndResult
= Parent
->FirstChild
->hSelf
;
3138 if((Parent
= Window
->Parent
))
3140 if (Parent
->LastChild
)
3141 hWndResult
= Parent
->LastChild
->hSelf
;
3146 if (Window
->NextSibling
)
3147 hWndResult
= Window
->NextSibling
->hSelf
;
3151 if (Window
->PrevSibling
)
3152 hWndResult
= Window
->PrevSibling
->hSelf
;
3156 if((Parent
= UserGetWindowObject(Window
->hOwner
)))
3158 hWndResult
= Parent
->hSelf
;
3162 if (Window
->FirstChild
)
3163 hWndResult
= Window
->FirstChild
->hSelf
;
3175 * The NtUserGetWindow function retrieves a handle to a window that has the
3176 * specified relationship (Z order or owner) to the specified window.
3183 NtUserGetWindow(HWND hWnd
, UINT Relationship
)
3185 DECLARE_RETURN(HWND
);
3187 DPRINT("Enter NtUserGetWindow\n");
3190 RETURN(UserGetWindow(hWnd
, Relationship
));
3193 DPRINT("Leave NtUserGetWindow, ret=%i\n",_ret_
);
3202 * NtUserGetWindowLong
3204 * The NtUserGetWindowLong function retrieves information about the specified
3205 * window. The function also retrieves the 32-bit (long) value at the
3206 * specified offset into the extra window memory.
3213 UserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3215 PWINDOW_OBJECT Window
, Parent
;
3218 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3220 if (!(Window
= UserGetWindowObject(hWnd
)))
3226 * WndProc is only available to the owner process
3228 if (GWL_WNDPROC
== Index
3229 && Window
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
3231 SetLastWin32Error(ERROR_ACCESS_DENIED
);
3235 if ((INT
)Index
>= 0)
3237 if ((Index
+ sizeof(LONG
)) > Window
->ExtraDataSize
)
3239 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3242 Result
= *((LONG
*)(Window
->ExtraData
+ Index
));
3249 Result
= Window
->ExStyle
;
3253 Result
= Window
->Style
;
3258 Result
= (LONG
) Window
->WndProcA
;
3260 Result
= (LONG
) Window
->WndProcW
;
3264 Result
= (LONG
) Window
->Instance
;
3267 case GWL_HWNDPARENT
:
3268 Parent
= Window
->Parent
;
3271 if (Parent
&& Parent
->hSelf
== IntGetDesktopWindow())
3272 Result
= (LONG
) UserGetWindow(Window
->hSelf
, GW_OWNER
);
3274 Result
= (LONG
) Parent
->hSelf
;
3279 Result
= (LONG
) Window
->IDMenu
;
3283 Result
= Window
->UserData
;
3287 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index
);
3288 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
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 NtUserGetWindowLong(HWND hWnd
, DWORD Index
, BOOL Ansi
)
3314 DECLARE_RETURN(LONG
);
3316 DPRINT("Enter NtUserGetWindowLong(%x,%d,%d)\n", hWnd
, (INT
)Index
, Ansi
);
3317 UserEnterExclusive();
3319 RETURN(UserGetWindowLong(hWnd
, Index
, Ansi
));
3322 DPRINT("Leave NtUserGetWindowLong, ret=%i\n",_ret_
);
3331 co_UserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3333 PWINDOW_OBJECT Window
, Parent
;
3334 PWINSTATION_OBJECT WindowStation
;
3338 if (hWnd
== IntGetDesktopWindow())
3340 SetLastWin32Error(STATUS_ACCESS_DENIED
);
3344 if (!(Window
= UserGetWindowObject(hWnd
)))
3349 if ((INT
)Index
>= 0)
3351 if ((Index
+ sizeof(LONG
)) > Window
->ExtraDataSize
)
3353 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3356 OldValue
= *((LONG
*)(Window
->ExtraData
+ Index
));
3357 *((LONG
*)(Window
->ExtraData
+ Index
)) = NewValue
;
3364 OldValue
= (LONG
) Window
->ExStyle
;
3365 Style
.styleOld
= OldValue
;
3366 Style
.styleNew
= NewValue
;
3369 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3371 WindowStation
= ((PW32THREAD
)Window
->OwnerThread
->Tcb
.Win32Thread
)->Desktop
->WindowStation
;
3374 if (hWnd
== WindowStation
->ShellWindow
|| hWnd
== WindowStation
->ShellListView
)
3375 Style
.styleNew
&= ~WS_EX_TOPMOST
;
3378 co_IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3379 Window
->ExStyle
= (DWORD
)Style
.styleNew
;
3380 co_IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_EXSTYLE
, (LPARAM
) &Style
);
3384 OldValue
= (LONG
) Window
->Style
;
3385 Style
.styleOld
= OldValue
;
3386 Style
.styleNew
= NewValue
;
3387 co_IntSendMessage(hWnd
, WM_STYLECHANGING
, GWL_STYLE
, (LPARAM
) &Style
);
3388 Window
->Style
= (DWORD
)Style
.styleNew
;
3389 co_IntSendMessage(hWnd
, WM_STYLECHANGED
, GWL_STYLE
, (LPARAM
) &Style
);
3393 /* FIXME: should check if window belongs to current process */
3396 OldValue
= (LONG
) Window
->WndProcA
;
3397 Window
->WndProcA
= (WNDPROC
) NewValue
;
3398 Window
->WndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,FALSE
);
3399 Window
->Unicode
= FALSE
;
3403 OldValue
= (LONG
) Window
->WndProcW
;
3404 Window
->WndProcW
= (WNDPROC
) NewValue
;
3405 Window
->WndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)NewValue
,TRUE
);
3406 Window
->Unicode
= TRUE
;
3411 OldValue
= (LONG
) Window
->Instance
;
3412 Window
->Instance
= (HINSTANCE
) NewValue
;
3415 case GWL_HWNDPARENT
:
3416 Parent
= Window
->Parent
;
3417 if (Parent
&& (Parent
->hSelf
== IntGetDesktopWindow()))
3418 OldValue
= (LONG
) IntSetOwner(Window
->hSelf
, (HWND
) NewValue
);
3420 OldValue
= (LONG
) co_UserSetParent(Window
->hSelf
, (HWND
) NewValue
);
3424 OldValue
= (LONG
) Window
->IDMenu
;
3425 Window
->IDMenu
= (UINT
) NewValue
;
3429 OldValue
= Window
->UserData
;
3430 Window
->UserData
= NewValue
;
3434 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index
);
3435 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3447 * NtUserSetWindowLong
3449 * The NtUserSetWindowLong function changes an attribute of the specified
3450 * window. The function also sets the 32-bit (long) value at the specified
3451 * offset into the extra window memory.
3458 NtUserSetWindowLong(HWND hWnd
, DWORD Index
, LONG NewValue
, BOOL Ansi
)
3460 DECLARE_RETURN(LONG
);
3462 DPRINT("Enter NtUserSetWindowLong\n");
3463 UserEnterExclusive();
3465 RETURN( co_UserSetWindowLong(hWnd
, Index
, NewValue
, Ansi
));
3468 DPRINT("Leave NtUserSetWindowLong, ret=%i\n",_ret_
);
3474 * NtUserSetWindowWord
3476 * Legacy function similar to NtUserSetWindowLong.
3483 NtUserSetWindowWord(HWND hWnd
, INT Index
, WORD NewValue
)
3485 PWINDOW_OBJECT Window
;
3487 DECLARE_RETURN(WORD
);
3489 DPRINT("Enter NtUserSetWindowWord\n");
3490 UserEnterExclusive();
3492 if (!(Window
= UserGetWindowObject(hWnd
)))
3501 case GWL_HWNDPARENT
:
3502 RETURN( co_UserSetWindowLong(Window
->hSelf
, Index
, (UINT
)NewValue
, TRUE
));
3506 SetLastWin32Error(ERROR_INVALID_INDEX
);
3511 if (Index
> Window
->ExtraDataSize
- sizeof(WORD
))
3513 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3517 OldValue
= *((WORD
*)(Window
->ExtraData
+ Index
));
3518 *((WORD
*)(Window
->ExtraData
+ Index
)) = NewValue
;
3523 DPRINT("Leave NtUserSetWindowWord, ret=%i\n",_ret_
);
3532 NtUserGetWindowPlacement(HWND hWnd
,
3533 WINDOWPLACEMENT
*lpwndpl
)
3535 PWINDOW_OBJECT Window
;
3536 PINTERNALPOS InternalPos
;
3538 WINDOWPLACEMENT Safepl
;
3540 DECLARE_RETURN(BOOL
);
3542 DPRINT("Enter NtUserGetWindowPlacement\n");
3545 if (!(Window
= UserGetWindowObject(hWnd
)))
3550 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3551 if(!NT_SUCCESS(Status
))
3553 SetLastNtError(Status
);
3556 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3562 if (0 == (Window
->Style
& WS_VISIBLE
))
3564 Safepl
.showCmd
= SW_HIDE
;
3566 else if (0 != (Window
->Flags
& WINDOWOBJECT_RESTOREMAX
) ||
3567 0 != (Window
->Style
& WS_MAXIMIZE
))
3569 Safepl
.showCmd
= SW_MAXIMIZE
;
3571 else if (0 != (Window
->Style
& WS_MINIMIZE
))
3573 Safepl
.showCmd
= SW_MINIMIZE
;
3575 else if (0 != (Window
->Style
& WS_MINIMIZE
))
3577 Safepl
.showCmd
= SW_SHOWNORMAL
;
3580 Size
.x
= Window
->WindowRect
.left
;
3581 Size
.y
= Window
->WindowRect
.top
;
3582 InternalPos
= WinPosInitInternalPos(Window
, &Size
,
3583 &Window
->WindowRect
);
3586 Safepl
.rcNormalPosition
= InternalPos
->NormalRect
;
3587 Safepl
.ptMinPosition
= InternalPos
->IconPos
;
3588 Safepl
.ptMaxPosition
= InternalPos
->MaxPos
;
3595 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3596 if(!NT_SUCCESS(Status
))
3598 SetLastNtError(Status
);
3605 DPRINT("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
3612 * Return the dimension of the window in the screen coordinates.
3613 * \param hWnd window handle.
3614 * \param Rect pointer to the buffer where the coordinates are returned.
3620 NtUserGetWindowRect(HWND hWnd
, LPRECT Rect
)
3624 DECLARE_RETURN(BOOL
);
3626 DPRINT("Enter NtUserGetWindowRect\n");
3629 if (!(Wnd
= UserGetWindowObject(hWnd
)))
3633 Status
= MmCopyToCaller(Rect
, &Wnd
->WindowRect
, sizeof(RECT
));
3634 if (!NT_SUCCESS(Status
))
3636 SetLastNtError(Status
);
3643 DPRINT("Leave NtUserGetWindowRect, ret=%i\n",_ret_
);
3653 NtUserGetWindowThreadProcessId(HWND hWnd
, LPDWORD UnsafePid
)
3657 DECLARE_RETURN(DWORD
);
3659 DPRINT("Enter NtUserGetWindowThreadProcessId\n");
3662 if (!(Wnd
= UserGetWindowObject(hWnd
)))
3667 tid
= (DWORD
)IntGetWndThreadId(Wnd
);
3668 pid
= (DWORD
)IntGetWndProcessId(Wnd
);
3671 MmCopyToCaller(UnsafePid
, &pid
, sizeof(DWORD
));
3676 DPRINT("Leave NtUserGetWindowThreadProcessId, ret=%i\n",_ret_
);
3686 NtUserLockWindowUpdate(DWORD Unknown0
)
3706 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3707 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3708 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3712 QueryWindow based on KJK::Hyperion and James Tabor.
3714 0 = QWUniqueProcessId
3715 1 = QWUniqueThreadId
3716 4 = QWIsHung Implements IsHungAppWindow found
3719 9 = QWKillWindow When I called this with hWnd ==
3720 DesktopWindow, it shutdown the system
3727 NtUserQueryWindow(HWND hWnd
, DWORD Index
)
3729 PWINDOW_OBJECT Window
;
3731 DECLARE_RETURN(UINT
);
3733 DPRINT("Enter NtUserQueryWindow\n");
3736 if (!(Window
= UserGetWindowObject(hWnd
)))
3743 case QUERY_WINDOW_UNIQUE_PROCESS_ID
:
3744 Result
= (DWORD
)IntGetWndProcessId(Window
);
3747 case QUERY_WINDOW_UNIQUE_THREAD_ID
:
3748 Result
= (DWORD
)IntGetWndThreadId(Window
);
3751 case QUERY_WINDOW_ISHUNG
:
3752 Result
= (DWORD
)MsqIsHung(Window
->MessageQueue
);
3756 Result
= (DWORD
)NULL
;
3763 DPRINT("Leave NtUserQueryWindow, ret=%i\n",_ret_
);
3773 NtUserRealChildWindowFromPoint(DWORD Unknown0
,
3787 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe
)
3789 UNICODE_STRING SafeMessageName
;
3792 DECLARE_RETURN(UINT
);
3794 DPRINT("Enter NtUserRegisterWindowMessage\n");
3795 UserEnterExclusive();
3797 if(MessageNameUnsafe
== NULL
)
3799 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
3803 Status
= IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName
, MessageNameUnsafe
);
3804 if(!NT_SUCCESS(Status
))
3806 SetLastNtError(Status
);
3810 Ret
= (UINT
)IntAddAtom(SafeMessageName
.Buffer
);
3812 RtlFreeUnicodeString(&SafeMessageName
);
3816 DPRINT("Leave NtUserRegisterWindowMessage, ret=%i\n",_ret_
);
3826 NtUserSetImeOwnerWindow(DWORD Unknown0
,
3839 NtUserSetInternalWindowPos(DWORD Unknown0
,
3855 NtUserSetLayeredWindowAttributes(DWORD Unknown0
,
3870 NtUserSetLogonNotifyWindow(DWORD Unknown0
)
3887 PWINDOW_OBJECT Window
;
3889 DECLARE_RETURN(BOOL
);
3891 DPRINT("Enter NtUserSetMenu\n");
3892 UserEnterExclusive();
3894 if (!(Window
= UserGetWindowObject(hWnd
)))
3899 if (! IntSetMenu(Window
, Menu
, &Changed
))
3904 if (Changed
&& Repaint
)
3906 USER_REFERENCE_ENTRY Ref
;
3908 UserRefObjectCo(Window
, &Ref
);
3909 co_WinPosSetWindowPos(Window
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
3910 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
3912 UserDerefObjectCo(Window
);
3918 DPRINT("Leave NtUserSetMenu, ret=%i\n",_ret_
);
3928 NtUserSetWindowFNID(DWORD Unknown0
,
3942 NtUserSetWindowPlacement(HWND hWnd
,
3943 WINDOWPLACEMENT
*lpwndpl
)
3945 PWINDOW_OBJECT Window
;
3946 WINDOWPLACEMENT Safepl
;
3948 DECLARE_RETURN(BOOL
);
3949 USER_REFERENCE_ENTRY Ref
;
3951 DPRINT("Enter NtUserSetWindowPlacement\n");
3952 UserEnterExclusive();
3954 if (!(Window
= UserGetWindowObject(hWnd
)))
3958 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3959 if(!NT_SUCCESS(Status
))
3961 SetLastNtError(Status
);
3964 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3969 UserRefObjectCo(Window
, &Ref
);
3971 if ((Window
->Style
& (WS_MAXIMIZE
| WS_MINIMIZE
)) == 0)
3973 co_WinPosSetWindowPos(Window
, NULL
,
3974 Safepl
.rcNormalPosition
.left
, Safepl
.rcNormalPosition
.top
,
3975 Safepl
.rcNormalPosition
.right
- Safepl
.rcNormalPosition
.left
,
3976 Safepl
.rcNormalPosition
.bottom
- Safepl
.rcNormalPosition
.top
,
3977 SWP_NOZORDER
| SWP_NOACTIVATE
);
3980 /* FIXME - change window status */
3981 co_WinPosShowWindow(Window
, Safepl
.showCmd
);
3983 if (Window
->InternalPos
== NULL
)
3984 Window
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
3985 Window
->InternalPos
->NormalRect
= Safepl
.rcNormalPosition
;
3986 Window
->InternalPos
->IconPos
= Safepl
.ptMinPosition
;
3987 Window
->InternalPos
->MaxPos
= Safepl
.ptMaxPosition
;
3989 UserDerefObjectCo(Window
);
3993 DPRINT("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
4005 HWND hWndInsertAfter
,
4012 DECLARE_RETURN(BOOL
);
4013 PWINDOW_OBJECT Window
;
4015 USER_REFERENCE_ENTRY Ref
;
4017 DPRINT("Enter NtUserSetWindowPos\n");
4018 UserEnterExclusive();
4020 if (!(Window
= UserGetWindowObject(hWnd
)))
4025 UserRefObjectCo(Window
, &Ref
);
4026 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
4027 UserDerefObjectCo(Window
);
4032 DPRINT("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
4039 IntGetWindowRgn(PWINDOW_OBJECT Window
, HRGN hRgn
)
4054 /* Create a new window region using the window rectangle */
4055 VisRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->WindowRect
);
4056 NtGdiOffsetRgn(VisRgn
, -Window
->WindowRect
.left
, -Window
->WindowRect
.top
);
4057 /* if there's a region assigned to the window, combine them both */
4058 if(Window
->WindowRegion
&& !(Window
->Style
& WS_MINIMIZE
))
4059 NtGdiCombineRgn(VisRgn
, VisRgn
, Window
->WindowRegion
, RGN_AND
);
4060 /* Copy the region into hRgn */
4061 NtGdiCombineRgn(hRgn
, VisRgn
, NULL
, RGN_COPY
);
4063 if((pRgn
= RGNDATA_LockRgn(hRgn
)))
4065 Ret
= pRgn
->rdh
.iType
;
4066 RGNDATA_UnlockRgn(pRgn
);
4071 NtGdiDeleteObject(VisRgn
);
4077 IntGetWindowRgnBox(PWINDOW_OBJECT Window
, RECT
*Rect
)
4092 /* Create a new window region using the window rectangle */
4093 VisRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->WindowRect
);
4094 NtGdiOffsetRgn(VisRgn
, -Window
->WindowRect
.left
, -Window
->WindowRect
.top
);
4095 /* if there's a region assigned to the window, combine them both */
4096 if(Window
->WindowRegion
&& !(Window
->Style
& WS_MINIMIZE
))
4097 NtGdiCombineRgn(VisRgn
, VisRgn
, Window
->WindowRegion
, RGN_AND
);
4099 if((pRgn
= RGNDATA_LockRgn(VisRgn
)))
4101 Ret
= pRgn
->rdh
.iType
;
4102 *Rect
= pRgn
->rdh
.rcBound
;
4103 RGNDATA_UnlockRgn(pRgn
);
4108 NtGdiDeleteObject(VisRgn
);
4123 PWINDOW_OBJECT Window
;
4124 DECLARE_RETURN(INT
);
4126 DPRINT("Enter NtUserSetWindowRgn\n");
4127 UserEnterExclusive();
4129 if (!(Window
= UserGetWindowObject(hWnd
)))
4134 /* FIXME - Verify if hRgn is a valid handle!!!!
4135 Propably make this operation thread-safe, but maybe it's not necessary */
4137 if(Window
->WindowRegion
)
4139 /* Delete no longer needed region handle */
4140 NtGdiDeleteObject(Window
->WindowRegion
);
4142 Window
->WindowRegion
= hRgn
;
4144 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
4148 USER_REFERENCE_ENTRY Ref
;
4149 UserRefObjectCo(Window
, &Ref
);
4150 co_UserRedrawWindow(Window
, NULL
, NULL
, RDW_INVALIDATE
);
4151 UserDerefObjectCo(Window
);
4157 DPRINT("Leave NtUserSystemParametersInfo, ret=%i\n",_ret_
);
4167 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
4169 PWINDOW_OBJECT Window
;
4171 DECLARE_RETURN(BOOL
);
4172 USER_REFERENCE_ENTRY Ref
;
4174 DPRINT("Enter NtUserShowWindow\n");
4175 UserEnterExclusive();
4177 if (!(Window
= UserGetWindowObject(hWnd
)))
4182 UserRefObjectCo(Window
, &Ref
);
4183 ret
= co_WinPosShowWindow(Window
, nCmdShow
);
4184 UserDerefObjectCo(Window
);
4189 DPRINT("Leave NtUserShowWindow, ret=%i\n",_ret_
);
4199 NtUserShowWindowAsync(HWND hWnd
, LONG nCmdShow
)
4205 return NtUserShowWindow(hWnd
, nCmdShow
);
4214 NtUserUpdateLayeredWindow(DWORD Unknown0
,
4236 NtUserWindowFromPoint(LONG X
, LONG Y
)
4240 PWINDOW_OBJECT DesktopWindow
= NULL
, Window
= NULL
;
4241 DECLARE_RETURN(HWND
);
4242 USER_REFERENCE_ENTRY Ref
;
4244 DPRINT("Enter NtUserWindowFromPoint\n");
4245 UserEnterExclusive();
4247 if ((DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow())))
4254 //hmm... threads live on desktops thus we have a reference on the desktop and indirectly the desktop window
4255 //its possible this referencing is useless, thou it shouldnt hurt...
4256 UserRefObjectCo(DesktopWindow
, &Ref
);
4258 Hit
= co_WinPosWindowFromPoint(DesktopWindow
, PsGetWin32Thread()->MessageQueue
, &pt
, &Window
);
4262 Ret
= Window
->hSelf
;
4271 if (Window
) UserDerefObject(Window
);
4272 if (DesktopWindow
) UserDerefObjectCo(DesktopWindow
);
4274 DPRINT("Leave NtUserWindowFromPoint, ret=%i\n",_ret_
);
4284 * Undocumented function that is called from DefWindowProc to set
4292 NtUserDefSetText(HWND hWnd
, PUNICODE_STRING WindowText
)
4294 PWINDOW_OBJECT Window
;
4295 UNICODE_STRING SafeText
;
4297 DECLARE_RETURN(INT
);
4299 DPRINT("Enter NtUserDefSetText\n");
4300 UserEnterExclusive();
4302 if(!(Window
= UserGetWindowObject(hWnd
)))
4309 Status
= IntSafeCopyUnicodeString(&SafeText
, WindowText
);
4310 if(!NT_SUCCESS(Status
))
4312 SetLastNtError(Status
);
4318 RtlInitUnicodeString(&SafeText
, NULL
);
4321 /* FIXME - do this thread-safe! otherwise one could crash here! */
4322 RtlFreeUnicodeString(&Window
->WindowName
);
4324 Window
->WindowName
= SafeText
;
4326 /* Send shell notifications */
4327 if (!IntGetOwner(Window
) && !IntGetParent(Window
))
4329 co_IntShellHookNotify(HSHELL_REDRAW
, (LPARAM
) hWnd
);
4335 DPRINT("Leave NtUserDefSetText, ret=%i\n",_ret_
);
4341 * NtUserInternalGetWindowText
4348 NtUserInternalGetWindowText(HWND hWnd
, LPWSTR lpString
, INT nMaxCount
)
4350 PWINDOW_OBJECT Window
;
4353 DECLARE_RETURN(INT
);
4355 DPRINT("Enter NtUserInternalGetWindowText\n");
4358 if(lpString
&& (nMaxCount
<= 1))
4360 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
4364 if(!(Window
= UserGetWindowObject(hWnd
)))
4369 /* FIXME - do this thread-safe! otherwise one could crash here! */
4370 Result
= Window
->WindowName
.Length
/ sizeof(WCHAR
);
4373 const WCHAR Terminator
= L
'\0';
4375 WCHAR
*Buffer
= (WCHAR
*)lpString
;
4377 Copy
= min(nMaxCount
- 1, Result
);
4380 Status
= MmCopyToCaller(Buffer
, Window
->WindowName
.Buffer
, Copy
* sizeof(WCHAR
));
4381 if(!NT_SUCCESS(Status
))
4383 SetLastNtError(Status
);
4389 Status
= MmCopyToCaller(Buffer
, &Terminator
, sizeof(WCHAR
));
4390 if(!NT_SUCCESS(Status
))
4392 SetLastNtError(Status
);
4402 DPRINT("Leave NtUserInternalGetWindowText, ret=%i\n",_ret_
);
4408 NtUserDereferenceWndProcHandle(WNDPROC wpHandle
, WndProcHandle
*Data
)
4410 DECLARE_RETURN(DWORD
);
4411 WndProcHandle Entry
;
4413 DPRINT("Enter NtUserDereferenceWndProcHandle\n");
4416 if (((DWORD
)wpHandle
& 0xFFFF0000) == 0xFFFF0000)
4418 Entry
= WndProcHandlesArray
[(DWORD
)wpHandle
& 0x0000FFFF];
4419 Data
->WindowProc
= Entry
.WindowProc
;
4420 Data
->IsUnicode
= Entry
.IsUnicode
;
4421 Data
->ProcessID
= Entry
.ProcessID
;
4431 DPRINT("Leave NtUserDereferenceWndProcHandle, ret=%i\n",_ret_
);
4437 IntAddWndProcHandle(WNDPROC WindowProc
, BOOL IsUnicode
)
4442 WndProcHandle
*OldArray
;
4445 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4447 if (WndProcHandlesArray
[i
].WindowProc
== NULL
)
4455 OldArray
= WndProcHandlesArray
;
4456 OldArraySize
= WndProcHandlesArraySize
;
4457 WndProcHandlesArray
= ExAllocatePoolWithTag(PagedPool
,(OldArraySize
+ WPH_SIZE
) * sizeof(WndProcHandle
), TAG_WINPROCLST
);
4458 WndProcHandlesArraySize
= OldArraySize
+ WPH_SIZE
;
4459 RtlCopyMemory(WndProcHandlesArray
,OldArray
,OldArraySize
* sizeof(WndProcHandle
));
4460 ExFreePool(OldArray
);
4461 FreeSpot
= OldArraySize
+ 1;
4463 WndProcHandlesArray
[FreeSpot
].WindowProc
= WindowProc
;
4464 WndProcHandlesArray
[FreeSpot
].IsUnicode
= IsUnicode
;
4465 WndProcHandlesArray
[FreeSpot
].ProcessID
= PsGetCurrentProcessId();
4466 return FreeSpot
+ 0xFFFF0000;
4470 IntRemoveWndProcHandle(WNDPROC Handle
)
4473 position
= (DWORD
)Handle
& 0x0000FFFF;
4474 if (position
> WndProcHandlesArraySize
)
4478 WndProcHandlesArray
[position
].WindowProc
= NULL
;
4479 WndProcHandlesArray
[position
].IsUnicode
= FALSE
;
4480 WndProcHandlesArray
[position
].ProcessID
= NULL
;
4485 IntRemoveProcessWndProcHandles(HANDLE ProcessID
)
4488 for (i
= 0;i
< WndProcHandlesArraySize
;i
++)
4490 if (WndProcHandlesArray
[i
].ProcessID
== ProcessID
)
4492 WndProcHandlesArray
[i
].WindowProc
= NULL
;
4493 WndProcHandlesArray
[i
].IsUnicode
= FALSE
;
4494 WndProcHandlesArray
[i
].ProcessID
= NULL
;
4500 #define WIN_NEEDS_SHOW_OWNEDPOPUP (0x00000040)
4504 IntShowOwnedPopups(PWINDOW_OBJECT OwnerWnd
, BOOL fShow
)
4507 PWINDOW_OBJECT pWnd
;
4512 win_array
= IntWinListChildren(OwnerWnd
);//faxme: use desktop?
4517 while (win_array
[count
])
4519 while (--count
>= 0)
4521 if (UserGetWindow( win_array
[count
], GW_OWNER
) != OwnerWnd
->hSelf
)
4523 if (!(pWnd
= UserGetWindowObject( win_array
[count
] )))
4525 // if (pWnd == WND_OTHER_PROCESS) continue;
4529 if (pWnd
->Flags
& WIN_NEEDS_SHOW_OWNEDPOPUP
)
4531 /* In Windows, ShowOwnedPopups(TRUE) generates
4532 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
4533 * regardless of the state of the owner
4535 co_IntSendMessage(win_array
[count
], WM_SHOWWINDOW
, SW_SHOWNORMAL
, SW_PARENTOPENING
);
4541 if (pWnd
->Style
& WS_VISIBLE
)
4543 /* In Windows, ShowOwnedPopups(FALSE) generates
4544 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
4545 * regardless of the state of the owner
4547 co_IntSendMessage(win_array
[count
], WM_SHOWWINDOW
, SW_HIDE
, SW_PARENTCLOSING
);
4553 ExFreePool( win_array
);