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.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
24 * FILE: subsys/win32k/ntuser/window.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
27 * 06-06-2001 CSH Created
29 /* INCLUDES ******************************************************************/
31 #include <ddk/ntddk.h>
32 #include <internal/safe.h>
33 #include <win32k/win32k.h>
34 #include <include/object.h>
35 #include <include/guicheck.h>
36 #include <include/window.h>
37 #include <include/class.h>
38 #include <include/error.h>
39 #include <include/winsta.h>
40 #include <include/winpos.h>
41 #include <include/callback.h>
42 #include <include/msgqueue.h>
43 #include <include/rect.h>
44 #include <include/dce.h>
45 #include <include/paint.h>
46 #include <include/painting.h>
47 #include <include/scroll.h>
48 #include <include/vis.h>
49 #include <include/menu.h>
52 #include <win32k/debug1.h>
55 #define TAG_WNAM TAG('W', 'N', 'A', 'M')
57 typedef struct _REGISTERED_MESSAGE
61 } REGISTERED_MESSAGE, *PREGISTERED_MESSAGE;
63 static LIST_ENTRY RegisteredMessageListHead;
65 #define REGISTERED_MESSAGE_MIN 0xc000
66 #define REGISTERED_MESSAGE_MAX 0xffff
69 /* globally stored handles to the shell windows */
70 HWND hwndShellWindow = 0;
71 HWND hwndShellListView = 0;
72 DWORD pidShellWindow = 0;
78 InitializeListHead(&RegisteredMessageListHead);
80 return(STATUS_SUCCESS);
84 CleanupWindowImpl(VOID)
86 return(STATUS_SUCCESS);
90 /* HELPER FUNCTIONS ***********************************************************/
92 /* check if hwnd is a broadcast magic handle */
93 inline BOOL IntIsBroadcastHwnd( HWND hwnd )
95 return (hwnd == HWND_BROADCAST || hwnd == HWND_TOPMOST);
99 inline BOOL IntIsDesktopWindow(PWINDOW_OBJECT Wnd)
101 return Wnd->Parent == NULL;
105 static BOOL BuildChildWindowArray(PWINDOW_OBJECT Window, HWND **Children, unsigned *NumChildren)
108 PWINDOW_OBJECT Child;
113 ExAcquireFastMutexUnsafe(&Window->ChildrenListLock);
114 Child = Window->FirstChild;
118 Child = Child->NextSibling;
121 if (0 != *NumChildren)
123 *Children = ExAllocatePoolWithTag(PagedPool, *NumChildren * sizeof(HWND), TAG_WNAM);
124 if (NULL != *Children)
126 Child = Window->FirstChild;
130 (*Children)[Index] = Child->Self;
131 Child = Child->NextSibling;
134 assert(Index == *NumChildren);
138 DPRINT1("Failed to allocate memory for children array\n");
141 ExReleaseFastMutexUnsafe(&Window->ChildrenListLock);
144 return 0 == *NumChildren || NULL != *Children;
148 /***********************************************************************
151 * Destroy storage associated to a window. "Internals" p.358
153 static LRESULT IntDestroyWindow(PWINDOW_OBJECT Window,
154 PW32PROCESS ProcessData,
155 PW32THREAD ThreadData,
156 BOOLEAN SendMessages)
159 unsigned NumChildren;
161 PWINDOW_OBJECT Child;
163 if (! IntWndBelongsToThread(Window, ThreadData))
165 DPRINT1("Window doesn't belong to current thread\n");
169 /* free child windows */
170 if (! BuildChildWindowArray(Window, &Children, &NumChildren))
174 for (Index = NumChildren; 0 < Index; Index--)
176 Child = IntGetWindowObject(Children[Index - 1]);
179 if (IntWndBelongsToThread(Child, ThreadData))
181 IntDestroyWindow(Child, ProcessData, ThreadData, SendMessages);
186 SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
191 if (0 != NumChildren)
193 ExFreePool(Children);
199 * Clear the update region to make sure no WM_PAINT messages will be
200 * generated for this window while processing the WM_NCDESTROY.
202 PaintRedrawWindow(Window, NULL, 0,
203 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN,
207 * Send the WM_NCDESTROY to the window being destroyed.
209 NtUserSendMessage(Window->Self, WM_NCDESTROY, 0, 0);
212 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
215 WinPosCheckInternalPos(Window->Self);
216 if (Window->Self == GetCapture())
221 /* free resources associated with the window */
222 TIMER_RemoveWindowTimers(Window->Self);
226 if (0 == (Window->Style & WS_CHILD))
228 HMENU Menu = (HMENU) NtUserSetWindowLongW(Window->Self, GWL_ID, 0);
234 if (Window->hSysMenu)
236 DestroyMenu(Window->hSysMenu);
237 Window->hSysMenu = 0;
239 DCE_FreeWindowDCE(Window->Self); /* Always do this to catch orphaned DCs */
240 WINPROC_FreeProc(Window->winproc, WIN_PROC_WINDOW);
241 CLASS_RemoveWindow(Window->Class);
244 ExAcquireFastMutexUnsafe(&Window->Parent->ChildrenListLock);
245 IntUnlinkWindow(Window);
246 ExReleaseFastMutexUnsafe(&Window->Parent->ChildrenListLock);
248 ExAcquireFastMutexUnsafe (&ThreadData->WindowListLock);
249 RemoveEntryList(&Window->ThreadListEntry);
250 ExReleaseFastMutexUnsafe (&ThreadData->WindowListLock);
252 IntDestroyScrollBar(Window, SB_VERT);
253 IntDestroyScrollBar(Window, SB_HORZ);
255 Window->Class = NULL;
256 ObmCloseHandle(ProcessData->WindowStation->HandleTable, Window->Self);
258 IntGraphicsCheck(FALSE);
264 /* INTERNAL ******************************************************************/
268 DestroyThreadWindows(struct _ETHREAD *Thread)
270 PLIST_ENTRY LastHead;
271 PW32PROCESS Win32Process;
272 PW32THREAD Win32Thread;
273 PWINDOW_OBJECT Window;
275 Win32Thread = Thread->Win32Thread;
276 Win32Process = Thread->ThreadsProcess->Win32Process;
277 ExAcquireFastMutexUnsafe(&Win32Thread->WindowListLock);
279 while (Win32Thread->WindowListHead.Flink != &(Win32Thread->WindowListHead) &&
280 Win32Thread->WindowListHead.Flink != LastHead)
282 LastHead = Win32Thread->WindowListHead.Flink;
283 Window = CONTAINING_RECORD(Win32Thread->WindowListHead.Flink, WINDOW_OBJECT, ThreadListEntry);
284 ExReleaseFastMutexUnsafe(&Win32Thread->WindowListLock);
285 IntDestroyWindow(Window, Win32Process, Win32Thread, FALSE);
286 ExAcquireFastMutexUnsafe(&Win32Thread->WindowListLock);
288 if (Win32Thread->WindowListHead.Flink == LastHead)
290 /* Window at head of list was not removed, should never happen, infinite loop */
293 ExReleaseFastMutexUnsafe(&Win32Thread->WindowListLock);
298 IntCreateDesktopWindow(PWINSTATION_OBJECT WindowStation,
299 PWNDCLASS_OBJECT DesktopClass,
300 ULONG Width, ULONG Height)
304 PWINDOW_OBJECT WindowObject;
306 /* Create the window object. */
307 WindowObject = (PWINDOW_OBJECT)ObmCreateObject(WindowStation->HandleTable,
310 sizeof(WINDOW_OBJECT));
317 * Fill out the structure describing it.
319 WindowObject->Class = DesktopClass;
320 WindowObject->ExStyle = 0;
321 WindowObject->Style = WS_VISIBLE;
324 WindowObject->Width = Width;
325 WindowObject->Height = Height;
326 WindowObject->ParentHandle = NULL;
327 WindowObject->Parent = NULL;
328 WindowObject->IDMenu = 0;
329 WindowObject->Instance = NULL;
330 WindowObject->Parameters = NULL;
331 WindowObject->Self = Handle;
332 WindowObject->MessageQueue = NULL;
333 WindowObject->ExtraData = NULL;
334 WindowObject->ExtraDataSize = 0;
335 WindowObject->WindowRect.left = 0;
336 WindowObject->WindowRect.top = 0;
337 WindowObject->WindowRect.right = Width;
338 WindowObject->WindowRect.bottom = Height;
339 WindowObject->ClientRect = WindowObject->WindowRect;
340 WindowObject->UserData = 0;
341 /*FIXME: figure out what the correct strange value is and what to do with it (and how to set the wndproc values correctly) */
342 WindowObject->WndProcA = DesktopClass->lpfnWndProcA;
343 WindowObject->WndProcW = DesktopClass->lpfnWndProcW;
344 WindowObject->OwnerThread = PsGetCurrentThread();
345 WindowObject->FirstChild = NULL;
346 WindowObject->LastChild = NULL;
347 WindowObject->PrevSibling = NULL;
348 WindowObject->NextSibling = NULL;
350 ExInitializeFastMutex(&WindowObject->ChildrenListLock);
352 WindowName = ExAllocatePool(NonPagedPool, sizeof(L"DESKTOP"));
353 wcscpy(WindowName, L"DESKTOP");
354 RtlInitUnicodeString(&WindowObject->WindowName, WindowName);
361 IntGetActiveWindow(VOID)
363 PUSER_MESSAGE_QUEUE Queue;
364 Queue = (PUSER_MESSAGE_QUEUE)IntGetActiveDesktop()->ActiveMessageQueue;
371 return(Queue->ActiveWindow);
376 PWINDOW_OBJECT FASTCALL
377 IntGetAncestor(PWINDOW_OBJECT Wnd, UINT Type)
379 if (IntIsDesktopWindow(Wnd)) return NULL;
387 while(!IntIsDesktopWindow(Wnd->Parent))
394 while ((Wnd = IntGetParent(Wnd)));
404 * Returns client window rectangle relative to the upper-left corner of client area.
406 * \note Does not check the validity of the parameters
409 IntGetClientRect(PWINDOW_OBJECT WindowObject, PRECT Rect)
411 ASSERT( WindowObject );
414 Rect->left = Rect->top = 0;
415 Rect->right = WindowObject->ClientRect.right - WindowObject->ClientRect.left;
417 WindowObject->ClientRect.bottom - WindowObject->ClientRect.top;
421 HWND FASTCALL IntGetDesktopWindow(VOID)
423 return IntGetActiveDesktop()->DesktopWindow;
428 IntGetFocusWindow(VOID)
430 PUSER_MESSAGE_QUEUE Queue;
431 PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
436 Queue = (PUSER_MESSAGE_QUEUE)pdo->ActiveMessageQueue;
441 return(Queue->FocusWindow);
445 PWINDOW_OBJECT FASTCALL
446 IntGetParent(PWINDOW_OBJECT Wnd)
448 if (Wnd->Style & WS_POPUP)
450 return IntGetWindowObject(Wnd->ParentHandle); /* wine use HWND for owner window (unknown reason) */
452 else if (Wnd->Style & WS_CHILD)
462 IntGetSystemMenu(PWINDOW_OBJECT WindowObject, BOOL bRevert, BOOL RetMenu)
464 PMENU_OBJECT MenuObject, NewMenuObject;
465 PW32PROCESS W32Process;
466 HMENU NewMenu, ret = (HMENU)0;
470 W32Process = PsGetWin32Process();
472 if(!W32Process->WindowStation)
475 if(WindowObject->SystemMenu)
477 MenuObject = IntGetMenuObject(WindowObject->SystemMenu);
480 IntDestroyMenuObject(MenuObject, FALSE, TRUE);
484 if(W32Process->WindowStation->SystemMenuTemplate)
486 /* clone system menu */
487 MenuObject = IntGetMenuObject(W32Process->WindowStation->SystemMenuTemplate);
491 NewMenuObject = IntCloneMenu(MenuObject);
494 WindowObject->SystemMenu = NewMenuObject->Self;
495 NewMenuObject->IsSystemMenu = TRUE;
496 ret = NewMenuObject->Self;
497 IntReleaseMenuObject(NewMenuObject);
499 IntReleaseMenuObject(MenuObject);
503 NewMenu = IntLoadSysMenuTemplate();
506 MenuObject = IntGetMenuObject(NewMenu);
510 NewMenuObject = IntCloneMenu(MenuObject);
513 WindowObject->SystemMenu = NewMenuObject->Self;
514 NewMenuObject->IsSystemMenu = TRUE;
515 ret = NewMenuObject->Self;
516 IntReleaseMenuObject(NewMenuObject);
518 IntDestroyMenuObject(MenuObject, FALSE, TRUE);
527 return WindowObject->SystemMenu;
532 PWINDOW_OBJECT FASTCALL
533 IntGetWindowObject(HWND hWnd)
535 PWINDOW_OBJECT WindowObject;
538 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->
542 (PVOID*)&WindowObject);
543 if (!NT_SUCCESS(Status))
547 return(WindowObject);
552 IntGetWindowThreadProcessId(PWINDOW_OBJECT Wnd, PDWORD pid)
554 if (pid) *pid = (DWORD) Wnd->OwnerThread->ThreadsProcess->UniqueProcessId;
555 return (DWORD) Wnd->OwnerThread->Cid.UniqueThread;
560 IntInitDesktopWindow(ULONG Width, ULONG Height)
562 PWINDOW_OBJECT DesktopWindow;
565 DesktopWindow = IntGetWindowObject(PsGetWin32Thread()->Desktop->DesktopWindow);
566 if (NULL == DesktopWindow)
570 DesktopWindow->WindowRect.right = Width;
571 DesktopWindow->WindowRect.bottom = Height;
572 DesktopWindow->ClientRect = DesktopWindow->WindowRect;
574 DesktopRgn = UnsafeIntCreateRectRgnIndirect(&(DesktopWindow->WindowRect));
575 VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, DesktopWindow, DesktopRgn);
576 NtGdiDeleteObject(DesktopRgn);
577 IntReleaseWindowObject(DesktopWindow);
582 IntIsChildWindow(HWND Parent, HWND Child)
584 PWINDOW_OBJECT BaseWindow = IntGetWindowObject(Child);
585 PWINDOW_OBJECT Window = BaseWindow;
586 while (Window != NULL && Window->Style & WS_CHILD)
588 if (Window->Self == Parent)
590 IntReleaseWindowObject(BaseWindow);
593 Window = Window->Parent;
595 IntReleaseWindowObject(BaseWindow);
601 IntIsWindowVisible(HWND Wnd)
603 PWINDOW_OBJECT BaseWindow = IntGetWindowObject(Wnd);
604 PWINDOW_OBJECT Window = BaseWindow;
605 BOOLEAN Result = FALSE;
606 while (Window != NULL && Window->Style & WS_CHILD)
608 if (!(Window->Style & WS_VISIBLE))
610 IntReleaseWindowObject(BaseWindow);
613 Window = Window->Parent;
615 if (Window != NULL && Window->Style & WS_VISIBLE)
619 IntReleaseWindowObject(BaseWindow);
624 /* link the window into siblings and parent. children are kept in place. */
628 PWINDOW_OBJECT WndParent,
629 PWINDOW_OBJECT WndPrevSibling /* set to NULL if top sibling */
632 Wnd->Parent = WndParent;
634 if ((Wnd->PrevSibling = WndPrevSibling))
636 /* link after WndPrevSibling */
637 if ((Wnd->NextSibling = WndPrevSibling->NextSibling)) Wnd->NextSibling->PrevSibling = Wnd;
638 else if (Wnd->Parent->LastChild == WndPrevSibling) Wnd->Parent->LastChild = Wnd;
639 Wnd->PrevSibling->NextSibling = Wnd;
644 if ((Wnd->NextSibling = WndParent->FirstChild)) Wnd->NextSibling->PrevSibling = Wnd;
645 else Wnd->Parent->LastChild = Wnd;
646 WndParent->FirstChild = Wnd;
653 IntSetFocusWindow(HWND hWnd)
655 PUSER_MESSAGE_QUEUE OldMessageQueue;
656 PDESKTOP_OBJECT DesktopObject;
657 PWINDOW_OBJECT WindowObject;
660 DPRINT("IntSetFocusWindow(hWnd 0x%x)\n", hWnd);
664 WindowObject = IntGetWindowObject(hWnd);
667 DPRINT("Bad window handle 0x%x\n", hWnd);
668 SetLastWin32Error(ERROR_INVALID_HANDLE);
677 DesktopObject = IntGetActiveDesktop();
680 DPRINT("No active desktop\n");
681 if (WindowObject != NULL)
683 IntReleaseWindowObject(WindowObject);
685 SetLastWin32Error(ERROR_INVALID_HANDLE);
689 hWndOldFocus = (HWND)0;
690 OldMessageQueue = (PUSER_MESSAGE_QUEUE)DesktopObject->ActiveMessageQueue;
691 if (OldMessageQueue != NULL)
693 hWndOldFocus = OldMessageQueue->FocusWindow;
696 if (WindowObject != NULL)
698 WindowObject->MessageQueue->FocusWindow = hWnd;
699 (PUSER_MESSAGE_QUEUE)DesktopObject->ActiveMessageQueue =
700 WindowObject->MessageQueue;
701 IntReleaseWindowObject(WindowObject);
705 (PUSER_MESSAGE_QUEUE)DesktopObject->ActiveMessageQueue = NULL;
708 DPRINT("hWndOldFocus = 0x%x\n", hWndOldFocus);
714 PWINDOW_OBJECT FASTCALL
715 IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent)
717 PWINDOW_OBJECT WndOldParent;
719 HWND hWnd, hWndNewParent, hWndOldParent;
721 if (!WndNewParent) WndNewParent = IntGetWindowObject(IntGetDesktopWindow());
724 hWndNewParent = WndNewParent;
727 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
728 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
730 if (USER_Driver.pSetParent)
731 return USER_Driver.pSetParent( hwnd, parent );
734 /* Windows hides the window first, then shows it again
735 * including the WM_SHOWWINDOW messages and all */
736 was_visible = WinPosShowWindow( hWnd, SW_HIDE );
738 /* validate that window and parent still exist */
739 if (!IntGetWindowObject(hWnd) || !IntGetWindowObject(hWndNewParent)) return NULL;
741 /* window must belong to current process */
742 if (Wnd->OwnerThread->ThreadsProcess != PsGetCurrentProcess()) return NULL;
744 WndOldParent = Wnd->Parent;
745 hWndOldParent = WndOldParent->Self;
747 if (WndNewParent != WndOldParent)
749 IntUnlinkWindow(Wnd);
750 IntLinkWindow(Wnd, WndNewParent, NULL /*prev sibling*/);
752 if (WndNewParent->Self != IntGetDesktopWindow()) /* a child window */
754 if (!(Wnd->Style & WS_CHILD))
756 //if ( Wnd->Menu ) DestroyMenu ( Wnd->menu );
762 /* SetParent additionally needs to make hwnd the topmost window
763 in the x-order and send the expected WM_WINDOWPOSCHANGING and
764 WM_WINDOWPOSCHANGED notification messages.
766 WinPosSetWindowPos( hWnd, HWND_TOPMOST, 0, 0, 0, 0,
767 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
768 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
769 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
771 /* validate that the old parent still exist, since it migth have been destroyed
772 during the last callbacks to user-mode
774 return (IntGetWindowObject(hWndOldParent) ? WndOldParent : NULL);
779 IntReleaseWindowObject(PWINDOW_OBJECT Window)
781 ObmDereferenceObject(Window);
785 /***********************************************************************
788 static void IntSendDestroyMsg(HWND Wnd)
793 if (GetGUIThreadInfo(GetCurrentThreadId(), &info))
795 if (Wnd == info.hwndCaret)
803 * Send the WM_DESTROY to the window.
805 NtUserSendMessage(Wnd, WM_DESTROY, 0, 0);
808 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
809 * make sure that the window still exists when we come back.
817 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
819 /* start from the end (FIXME: is this needed?) */
820 for (i = 0; pWndArray[i]; i++) ;
824 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
826 HeapFree(GetProcessHeap(), 0, pWndArray);
830 DPRINT("destroyed itself while in WM_DESTROY!\n");
837 IntSetSystemMenu(PWINDOW_OBJECT WindowObject, PMENU_OBJECT MenuObject)
839 PMENU_OBJECT OldMenuObject;
840 if(WindowObject->SystemMenu)
842 OldMenuObject = IntGetMenuObject(WindowObject->SystemMenu);
845 OldMenuObject->IsSystemMenu = FALSE;
846 IntReleaseMenuObject(OldMenuObject);
850 WindowObject->SystemMenu = MenuObject->Self;
851 if(MenuObject) /* FIXME check window style, propably return FALSE ? */
852 MenuObject->IsSystemMenu = TRUE;
858 /* unlink the window from siblings and parent. children are kept in place. */
860 IntUnlinkWindow(PWINDOW_OBJECT Wnd)
862 PWINDOW_OBJECT WndParent = Wnd->Parent;
864 if (Wnd->NextSibling) Wnd->NextSibling->PrevSibling = Wnd->PrevSibling;
865 else if (WndParent->LastChild == Wnd) WndParent->LastChild = Wnd->PrevSibling;
867 if (Wnd->PrevSibling) Wnd->PrevSibling->NextSibling = Wnd->NextSibling;
868 else if (WndParent->FirstChild == Wnd) WndParent->FirstChild = Wnd->NextSibling;
869 //else if (parent->first_unlinked == win) parent->first_unlinked = Wnd->NextSibling;
874 IntWndBelongsToThread(PWINDOW_OBJECT Window, PW32THREAD ThreadData)
876 if (Window->OwnerThread && Window->OwnerThread->Win32Thread)
878 return (Window->OwnerThread->Win32Thread == ThreadData);
885 /* FUNCTIONS *****************************************************************/
892 NtUserAlterWindowStyle(DWORD Unknown0,
903 * As best as I can figure, this function is used by EnumWindows,
904 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
906 * It's supposed to build a list of HWNDs to return to the caller.
907 * We can figure out what kind of list by what parameters are
926 /* FIXME handle bChildren */
929 PWINDOW_OBJECT WindowObject = NULL;
930 PWINDOW_OBJECT Child;
932 WindowObject = IntGetWindowObject ( hwndParent );
935 DPRINT("Bad window handle 0x%x\n", hwndParent);
936 SetLastWin32Error(ERROR_INVALID_HANDLE);
940 ExAcquireFastMutex ( &WindowObject->ChildrenListLock );
941 Child = WindowObject->FirstChild;
944 if ( pWnd && dwCount < nBufSize )
945 pWnd[dwCount] = Child->Self;
947 Child = Child->NextSibling;
949 ExReleaseFastMutex ( &WindowObject->ChildrenListLock );
950 IntReleaseWindowObject ( WindowObject );
952 else if ( dwThreadId )
955 struct _ETHREAD* Thread;
956 struct _EPROCESS* ThreadsProcess;
957 struct _W32PROCESS* Win32Process;
958 struct _WINSTATION_OBJECT* WindowStation;
959 PUSER_HANDLE_TABLE HandleTable;
961 PUSER_HANDLE_BLOCK Block = NULL;
964 Status = PsLookupThreadByThreadId ( (PVOID)dwThreadId, &Thread );
965 if ( !NT_SUCCESS(Status) || !Thread )
967 DPRINT("Bad ThreadId 0x%x\n", dwThreadId );
968 SetLastWin32Error(ERROR_INVALID_HANDLE);
971 ThreadsProcess = Thread->ThreadsProcess;
972 ASSERT(ThreadsProcess);
973 Win32Process = ThreadsProcess->Win32Process;
974 ASSERT(Win32Process);
975 WindowStation = Win32Process->WindowStation;
976 ASSERT(WindowStation);
977 HandleTable = (PUSER_HANDLE_TABLE)(WindowStation->HandleTable);
980 ExAcquireFastMutex(&HandleTable->ListLock);
982 Current = HandleTable->ListHead.Flink;
983 while ( Current != &HandleTable->ListHead )
985 Block = CONTAINING_RECORD(Current, USER_HANDLE_BLOCK, ListEntry);
986 for ( i = 0; i < HANDLE_BLOCK_ENTRIES; i++ )
988 PVOID ObjectBody = Block->Handles[i].ObjectBody;
991 if ( pWnd && dwCount < nBufSize )
994 (HWND)ObmReferenceObjectByPointer ( ObjectBody, otWindow );
999 Current = Current->Flink;
1002 ExReleaseFastMutex(&HandleTable->ListLock);
1006 PDESKTOP_OBJECT DesktopObject = NULL;
1008 PWINDOW_OBJECT Child, WndDesktop;
1011 DesktopObject = IntGetDesktopObject ( hDesktop );
1013 DesktopObject = IntGetActiveDesktop();
1016 DPRINT("Bad desktop handle 0x%x\n", hDesktop );
1017 SetLastWin32Error(ERROR_INVALID_HANDLE);
1021 KeAcquireSpinLock ( &DesktopObject->Lock, &OldIrql );
1023 WndDesktop = IntGetWindowObject(DesktopObject->DesktopWindow);
1024 Child = (WndDesktop ? WndDesktop->FirstChild : NULL);
1027 if ( pWnd && dwCount < nBufSize )
1028 pWnd[dwCount] = Child->Self;
1030 Child = Child->NextSibling;
1032 KeReleaseSpinLock ( &DesktopObject->Lock, OldIrql );
1049 /* DrawMenuBar() calls it with Unknown1==0x55 */
1058 NtUserChildWindowFromPointEx(HWND Parent,
1073 NtUserCreateWindowEx(DWORD dwExStyle,
1074 PUNICODE_STRING lpClassName,
1075 PUNICODE_STRING lpWindowName,
1083 HINSTANCE hInstance,
1087 PWINSTATION_OBJECT WinStaObject;
1088 PWNDCLASS_OBJECT ClassObject;
1089 PWINDOW_OBJECT WindowObject;
1090 PWINDOW_OBJECT ParentWindow;
1091 PMENU_OBJECT SystemMenu;
1092 UNICODE_STRING WindowName;
1095 POINT MaxSize, MaxPos, MinTrack, MaxTrack;
1098 DPRINT("NtUserCreateWindowEx\n");
1100 /* Initialize gui state if necessary. */
1101 IntGraphicsCheck(TRUE);
1103 if (!RtlCreateUnicodeString(&WindowName,
1104 NULL == lpWindowName->Buffer ?
1105 L"" : lpWindowName->Buffer))
1107 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
1111 /* FIXME: parent must belong to the current process */
1113 if (hWndParent != NULL)
1115 ParentWindow = IntGetWindowObject(hWndParent);
1119 hWndParent = PsGetWin32Thread()->Desktop->DesktopWindow;
1120 ParentWindow = IntGetWindowObject(hWndParent);
1123 /* Check the class. */
1124 Status = ClassReferenceClassByNameOrAtom(&ClassObject, lpClassName->Buffer);
1125 if (!NT_SUCCESS(Status))
1127 RtlFreeUnicodeString(&WindowName);
1128 IntReleaseWindowObject(ParentWindow);
1132 /* Check the window station. */
1133 DPRINT("IoGetCurrentProcess() %X\n", IoGetCurrentProcess());
1134 DPRINT("PROCESS_WINDOW_STATION %X\n", PROCESS_WINDOW_STATION());
1135 Status = ValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
1139 if (!NT_SUCCESS(Status))
1141 RtlFreeUnicodeString(&WindowName);
1142 ObmDereferenceObject(ClassObject);
1143 IntReleaseWindowObject(ParentWindow);
1144 DPRINT("Validation of window station handle (0x%X) failed\n",
1145 PROCESS_WINDOW_STATION());
1149 /* Create the window object. */
1150 WindowObject = (PWINDOW_OBJECT)
1151 ObmCreateObject(PsGetWin32Process()->WindowStation->HandleTable, &Handle,
1152 otWindow, sizeof(WINDOW_OBJECT) + ClassObject->cbWndExtra
1155 DPRINT("Created object with handle %X\n", Handle);
1158 ObDereferenceObject(WinStaObject);
1159 ObmDereferenceObject(ClassObject);
1160 RtlFreeUnicodeString(&WindowName);
1161 IntReleaseWindowObject(ParentWindow);
1162 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
1165 ObDereferenceObject(WinStaObject);
1168 * Fill out the structure describing it.
1170 WindowObject->Class = ClassObject;
1171 WindowObject->ExStyle = dwExStyle;
1172 WindowObject->Style = dwStyle & ~WS_VISIBLE;
1173 DPRINT("1: Style is now %d\n", WindowObject->Style);
1175 SystemMenu = IntGetSystemMenu(WindowObject, TRUE, TRUE);
1177 WindowObject->x = x;
1178 WindowObject->y = y;
1179 WindowObject->Width = nWidth;
1180 WindowObject->Height = nHeight;
1181 WindowObject->ContextHelpId = 0;
1182 WindowObject->ParentHandle = hWndParent;
1183 WindowObject->IDMenu = (UINT)hMenu;
1185 WindowObject->SystemMenu = SystemMenu->Self;
1187 WindowObject->SystemMenu = (HMENU)0;
1188 WindowObject->Instance = hInstance;
1189 WindowObject->Parameters = lpParam;
1190 WindowObject->Self = Handle;
1191 WindowObject->MessageQueue = PsGetWin32Thread()->MessageQueue;
1192 WindowObject->Parent = ParentWindow;
1193 WindowObject->UserData = 0;
1194 WindowObject->Unicode = ClassObject->Unicode;
1195 WindowObject->WndProcA = ClassObject->lpfnWndProcA;
1196 WindowObject->WndProcW = ClassObject->lpfnWndProcW;
1197 WindowObject->OwnerThread = PsGetCurrentThread();
1198 WindowObject->FirstChild = NULL;
1199 WindowObject->LastChild = NULL;
1200 WindowObject->PrevSibling = NULL;
1201 WindowObject->NextSibling = NULL;
1203 /* extra window data */
1204 if (ClassObject->cbWndExtra != 0)
1206 WindowObject->ExtraData = (PULONG)(WindowObject + 1);
1207 WindowObject->ExtraDataSize = ClassObject->cbWndExtra;
1208 RtlZeroMemory(WindowObject->ExtraData, WindowObject->ExtraDataSize);
1212 WindowObject->ExtraData = NULL;
1213 WindowObject->ExtraDataSize = 0;
1216 InitializeListHead(&WindowObject->PropListHead);
1217 ExInitializeFastMutex(&WindowObject->ChildrenListLock);
1219 RtlInitUnicodeString(&WindowObject->WindowName, WindowName.Buffer);
1220 RtlFreeUnicodeString(&WindowName);
1223 /* Correct the window style. */
1224 if (!(dwStyle & WS_CHILD))
1226 WindowObject->Style |= WS_CLIPSIBLINGS;
1227 DPRINT("3: Style is now %d\n", WindowObject->Style);
1228 if (!(dwStyle & WS_POPUP))
1230 WindowObject->Style |= WS_CAPTION;
1231 WindowObject->Flags |= WINDOWOBJECT_NEED_SIZE;
1232 DPRINT("4: Style is now %d\n", WindowObject->Style);
1233 /* FIXME: Note the window needs a size. */
1237 /* Insert the window into the thread's window list. */
1238 ExAcquireFastMutexUnsafe (&PsGetWin32Thread()->WindowListLock);
1239 InsertTailList (&PsGetWin32Thread()->WindowListHead,
1240 &WindowObject->ThreadListEntry);
1241 ExReleaseFastMutexUnsafe (&PsGetWin32Thread()->WindowListLock);
1243 /* Allocate a DCE for this window. */
1244 if (dwStyle & CS_OWNDC) WindowObject->Dce = DceAllocDCE(WindowObject->Self,DCE_WINDOW_DC);
1245 /* FIXME: Handle "CS_CLASSDC" */
1247 /* Initialize the window dimensions. */
1248 WindowObject->WindowRect.left = x;
1249 WindowObject->WindowRect.top = y;
1250 WindowObject->WindowRect.right = x + nWidth;
1251 WindowObject->WindowRect.bottom = y + nHeight;
1252 WindowObject->ClientRect = WindowObject->WindowRect;
1255 * Get the size and position of the window.
1257 if ((dwStyle & WS_THICKFRAME) || !(dwStyle & (WS_POPUP | WS_CHILD)))
1259 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1260 WinPosGetMinMaxInfo(WindowObject, &MaxSize, &MaxPos, &MinTrack,
1262 x = min(MaxSize.x, y);
1263 y = min(MaxSize.y, y);
1264 x = max(MinTrack.x, x);
1265 y = max(MinTrack.y, y);
1268 WindowObject->WindowRect.left = x;
1269 WindowObject->WindowRect.top = y;
1270 WindowObject->WindowRect.right = x + nWidth;
1271 WindowObject->WindowRect.bottom = y + nHeight;
1272 WindowObject->ClientRect = WindowObject->WindowRect;
1274 /* FIXME: Initialize the window menu. */
1276 /* Initialize the window's scrollbars */
1277 if (dwStyle & WS_VSCROLL)
1278 IntCreateScrollBar(WindowObject, SB_VERT);
1279 if (dwStyle & WS_HSCROLL)
1280 IntCreateScrollBar(WindowObject, SB_HORZ);
1282 /* Send a NCCREATE message. */
1283 Cs.lpCreateParams = lpParam;
1284 Cs.hInstance = hInstance;
1286 Cs.hwndParent = hWndParent;
1292 Cs.lpszName = lpWindowName->Buffer;
1293 Cs.lpszClass = lpClassName->Buffer;
1294 Cs.dwExStyle = dwExStyle;
1296 // AG: For some reason these don't get set already. This might need moving
1297 // elsewhere... What is actually done with WindowObject anyway, to retain
1299 DPRINT("[win32k.window] NtUserCreateWindowEx style %d, exstyle %d, parent %d\n", Cs.style, Cs.dwExStyle, Cs.hwndParent);
1300 // NtUserSetWindowLong(Handle, GWL_STYLE, WindowObject->Style, TRUE);
1301 // NtUserSetWindowLong(Handle, GWL_EXSTYLE, WindowObject->ExStyle, TRUE);
1304 DPRINT("NtUserCreateWindowEx(): About to send NCCREATE message.\n");
1305 Result = IntSendNCCREATEMessage(WindowObject->Self, &Cs);
1308 /* FIXME: Cleanup. */
1309 IntReleaseWindowObject(ParentWindow);
1310 DPRINT("NtUserCreateWindowEx(): NCCREATE message failed.\n");
1314 /* Calculate the non-client size. */
1315 MaxPos.x = WindowObject->WindowRect.left;
1316 MaxPos.y = WindowObject->WindowRect.top;
1317 DPRINT("NtUserCreateWindowEx(): About to get non-client size.\n");
1318 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1319 Result = WinPosGetNonClientSize(WindowObject->Self,
1320 &WindowObject->WindowRect,
1321 &WindowObject->ClientRect);
1322 NtGdiOffsetRect(&WindowObject->WindowRect,
1323 MaxPos.x - WindowObject->WindowRect.left,
1324 MaxPos.y - WindowObject->WindowRect.top);
1327 /* link the window into the parent's child list */
1328 ExAcquireFastMutexUnsafe(&ParentWindow->ChildrenListLock);
1329 if ((dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
1331 /* link window as bottom sibling */
1332 IntLinkWindow(WindowObject, ParentWindow, ParentWindow->LastChild /*prev sibling*/);
1336 /* link window as top sibling */
1337 IntLinkWindow(WindowObject, ParentWindow, NULL /*prev sibling*/);
1339 ExReleaseFastMutexUnsafe(&ParentWindow->ChildrenListLock);
1341 /* Send the WM_CREATE message. */
1342 DPRINT("NtUserCreateWindowEx(): about to send CREATE message.\n");
1343 Result = IntSendCREATEMessage(WindowObject->Self, &Cs);
1344 if (Result == (LRESULT)-1)
1346 /* FIXME: Cleanup. */
1347 IntReleaseWindowObject(ParentWindow);
1348 DPRINT("NtUserCreateWindowEx(): send CREATE message failed.\n");
1352 /* Send move and size messages. */
1353 if (!(WindowObject->Flags & WINDOWOBJECT_NEED_SIZE))
1357 DPRINT("NtUserCreateWindow(): About to send WM_SIZE\n");
1359 if ((WindowObject->ClientRect.right - WindowObject->ClientRect.left) < 0 ||
1360 (WindowObject->ClientRect.bottom - WindowObject->ClientRect.top) < 0)
1361 DPRINT("Sending bogus WM_SIZE\n");
1363 lParam = MAKE_LONG(WindowObject->ClientRect.right -
1364 WindowObject->ClientRect.left,
1365 WindowObject->ClientRect.bottom -
1366 WindowObject->ClientRect.top);
1367 IntCallWindowProc(NULL, WindowObject->Self, WM_SIZE, SIZE_RESTORED,
1370 DPRINT("NtUserCreateWindow(): About to send WM_MOVE\n");
1372 lParam = MAKE_LONG(WindowObject->ClientRect.left,
1373 WindowObject->ClientRect.top);
1374 IntCallWindowProc(NULL, WindowObject->Self, WM_MOVE, 0, lParam);
1377 /* Move from parent-client to screen coordinates */
1378 if (0 != (WindowObject->Style & WS_CHILD))
1380 NtGdiOffsetRect(&WindowObject->WindowRect,
1381 ParentWindow->ClientRect.left,
1382 ParentWindow->ClientRect.top);
1383 NtGdiOffsetRect(&WindowObject->ClientRect,
1384 ParentWindow->ClientRect.left,
1385 ParentWindow->ClientRect.top);
1388 /* Show or maybe minimize or maximize the window. */
1389 if (WindowObject->Style & (WS_MINIMIZE | WS_MAXIMIZE))
1394 SwFlag = (WindowObject->Style & WS_MINIMIZE) ? SW_MINIMIZE :
1396 WinPosMinMaximize(WindowObject, SwFlag, &NewPos);
1398 ((WindowObject->Style & WS_CHILD) || IntGetActiveWindow()) ?
1399 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED :
1400 SWP_NOZORDER | SWP_FRAMECHANGED;
1401 DPRINT("NtUserCreateWindow(): About to minimize/maximize\n");
1402 WinPosSetWindowPos(WindowObject->Self, 0, NewPos.left, NewPos.top,
1403 NewPos.right, NewPos.bottom, SwFlag);
1406 /* Notify the parent window of a new child. */
1407 if ((WindowObject->Style & WS_CHILD) ||
1408 (!(WindowObject->ExStyle & WS_EX_NOPARENTNOTIFY)))
1410 DPRINT("NtUserCreateWindow(): About to notify parent\n");
1411 IntCallWindowProc(NULL, WindowObject->Parent->Self,
1413 MAKEWPARAM(WM_CREATE, WindowObject->IDMenu),
1414 (LPARAM)WindowObject->Self);
1417 if (dwStyle & WS_VISIBLE)
1419 DPRINT("NtUserCreateWindow(): About to show window\n");
1420 WinPosShowWindow(WindowObject->Self, dwShowMode);
1422 /* FIXME: Should code be reworked to accomodate the following line? */
1423 DPRINT("Setting Active Window to %d\n\n\n",WindowObject->Self);
1424 NtUserSetActiveWindow(WindowObject->Self);
1425 DPRINT("NtUserCreateWindow(): = %X\n", Handle);
1426 DPRINT("WindowObject->SystemMenu = 0x%x\n", WindowObject->SystemMenu);
1427 return((HWND)Handle);
1435 NtUserDeferWindowPos(HDWP WinPosInfo,
1437 HWND WndInsertAfter,
1454 NtUserDestroyWindow(HWND Wnd)
1456 PWINDOW_OBJECT Window;
1460 Window = IntGetWindowObject(Wnd);
1466 /* Check for desktop window (has NULL parent) */
1467 if (NULL == Window->Parent)
1469 IntReleaseWindowObject(Window);
1470 SetLastWin32Error(ERROR_ACCESS_DENIED);
1474 /* Look whether the focus is within the tree of windows we will
1477 hWndFocus = IntGetFocusWindow();
1478 if (hWndFocus == Wnd || IntIsChildWindow(Wnd, hWndFocus))
1480 HWND Parent = NtUserGetAncestor(Wnd, GA_PARENT);
1481 if (Parent == IntGetDesktopWindow())
1485 IntSetFocusWindow(Parent);
1490 if (HOOK_CallHooks(WH_CBT, HCBT_DESTROYWND, (WPARAM) hwnd, 0, TRUE))
1496 isChild = (0 != (Window->Style & WS_CHILD));
1501 if (! USER_IsExitingThread(GetCurrentThreadId()))
1503 send_parent_notify(hwnd, WM_DESTROY);
1506 else if (NULL != GetWindow(Wnd, GW_OWNER))
1508 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1509 /* FIXME: clean up palette - see "Internals" p.352 */
1512 if (! IsWindow(Wnd))
1518 /* Hide the window */
1519 if (! WinPosShowWindow(Wnd, SW_HIDE ))
1522 if (hwnd == GetActiveWindow())
1524 WINPOS_ActivateOtherWindow( hwnd );
1530 if (! IsWindow(Wnd))
1536 /* Recursively destroy owned windows */
1543 BOOL GotOne = FALSE;
1544 HWND *list = WIN_ListChildren(GetDesktopWindow());
1547 for (i = 0; list[i]; i++)
1549 if (GetWindow(list[i], GW_OWNER) != Wnd)
1553 if (WIN_IsCurrentThread(list[i]))
1555 DestroyWindow(list[i]);
1559 WIN_SetOwner(list[i], NULL);
1561 HeapFree(GetProcessHeap(), 0, list);
1571 /* Send destroy messages */
1572 IntSendDestroyMsg(Wnd);
1581 /* Unlink now so we won't bother with the children later on */
1583 WIN_UnlinkWindow( hwnd );
1586 /* Destroy the window storage */
1587 IntDestroyWindow(Window, PsGetWin32Process(), PsGetWin32Thread(), TRUE);
1598 NtUserDrawMenuBarTemp(
1605 /* we'll use this function just for caching the menu bar */
1615 NtUserEndDeferWindowPosEx(DWORD Unknown0,
1628 NtUserFillWindow(DWORD Unknown0,
1641 * Searches a window's children for a window with the specified
1644 * hwndParent = The window whose childs are to be searched.
1647 * hwndChildAfter = Search starts after this child window.
1648 * NULL = start from beginning
1650 * ucClassName = Class name to search for
1651 * Reguired parameter.
1653 * ucWindowName = Window name
1654 * ->Buffer == NULL = don't care
1657 * The HWND of the window if it was found, otherwise NULL
1660 * Should use MmCopyFromCaller, we don't want an access violation in here
1667 NtUserFindWindowEx(HWND hwndParent,
1668 HWND hwndChildAfter,
1669 PUNICODE_STRING ucClassName,
1670 PUNICODE_STRING ucWindowName)
1674 PWINDOW_OBJECT ParentWindow, WndChildAfter, WndChild;
1675 PWNDCLASS_OBJECT classObject;
1677 // Get a pointer to the class
1678 status = ClassReferenceClassByNameOrAtom(&classObject, ucClassName->Buffer);
1679 if (!NT_SUCCESS(status))
1684 // If hwndParent==NULL use the desktop window instead
1686 hwndParent = PsGetWin32Thread()->Desktop->DesktopWindow;
1689 ParentWindow = IntGetWindowObject(hwndParent);
1693 ObmDereferenceObject(classObject);
1697 ExAcquireFastMutexUnsafe (&ParentWindow->ChildrenListLock);
1701 if (!(WndChildAfter = IntGetWindowObject(hwndChildAfter)))
1703 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
1707 /* must be a direct child (not a decendant child)*/
1708 if (WndChildAfter->Parent != ParentWindow)
1710 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1714 WndChild = WndChildAfter->NextSibling;
1718 WndChild = ParentWindow->FirstChild;
1723 if (classObject == WndChild->Class && (ucWindowName->Buffer==NULL ||
1724 RtlCompareUnicodeString (ucWindowName, &WndChild->WindowName, TRUE) == 0))
1726 windowHandle = WndChild->Self;
1728 ExReleaseFastMutexUnsafe (&ParentWindow->ChildrenListLock);
1729 IntReleaseWindowObject(ParentWindow);
1730 ObmDereferenceObject (classObject);
1732 return windowHandle;
1735 WndChild = WndChild->NextSibling;
1738 ExReleaseFastMutexUnsafe (&ParentWindow->ChildrenListLock);
1740 IntReleaseWindowObject(ParentWindow);
1741 ObmDereferenceObject (classObject);
1751 NtUserFlashWindowEx(DWORD Unknown0)
1763 NtUserGetAncestor(HWND hWnd, UINT Type)
1765 PWINDOW_OBJECT Wnd, WndAncestor;
1766 HWND hWndAncestor = NULL;
1768 IntAcquireWinLockShared();
1770 if (!(Wnd = IntGetWindowObject(hWnd)))
1772 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
1776 WndAncestor = IntGetAncestor(Wnd, Type);
1777 if (WndAncestor) hWndAncestor = WndAncestor->Self;
1779 IntReleaseWinLock();
1781 return hWndAncestor;
1790 NtUserGetCapture(VOID)
1792 PWINDOW_OBJECT Window;
1793 Window = IntGetCaptureWindow();
1796 return(Window->Self);
1806 * Returns client window rectangle relative to the upper-left corner of client area.
1808 * \param hWnd window handle.
1809 * \param Rect pointer to the buffer where the coordinates are returned.
1816 NtUserGetClientRect(HWND hWnd, LPRECT Rect)
1818 PWINDOW_OBJECT WindowObject;
1821 IntAcquireWinLockShared();
1822 if (!(WindowObject = IntGetWindowObject(hWnd)))
1824 IntReleaseWinLock();
1825 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
1829 IntGetClientRect(WindowObject, &SafeRect);
1830 IntReleaseWinLock();
1832 if (! NT_SUCCESS(MmCopyToCaller(Rect, &SafeRect, sizeof(RECT))))
1846 NtUserGetDesktopWindow()
1848 return IntGetDesktopWindow();
1856 NtUserGetForegroundWindow(VOID)
1868 NtUserGetInternalWindowPos(DWORD Unknown0,
1883 NtUserGetLastActivePopup(HWND hWnd)
1888 IntAcquireWinLockShared();
1890 if (!(Wnd = IntGetWindowObject(hWnd)))
1892 IntReleaseWinLock();
1893 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
1897 hWndLastPopup = Wnd->hWndLastPopup;
1899 IntReleaseWinLock();
1901 return hWndLastPopup;
1909 NtUserGetOpenClipboardWindow(VOID)
1921 NtUserGetParent(HWND hWnd)
1923 PWINDOW_OBJECT Wnd, WndParent;
1924 HWND hWndParent = NULL;
1926 IntAcquireWinLockShared();
1928 if (!(Wnd = IntGetWindowObject(hWnd)))
1930 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
1934 WndParent = IntGetParent(Wnd);
1935 if (WndParent) hWndParent = WndParent->Self;
1937 IntReleaseWinLock();
1947 NtUserGetShellWindow()
1949 return hwndShellWindow;
1958 NtUserGetSystemMenu(
1962 HMENU res = (HMENU)0;
1963 PWINDOW_OBJECT WindowObject;
1964 WindowObject = IntGetWindowObject((HWND)hWnd);
1967 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
1971 res = IntGetSystemMenu(WindowObject, bRevert, FALSE);
1973 IntReleaseWindowObject(WindowObject);
1983 NtUserGetWindow(HWND hWnd, UINT Relationship)
1986 HWND hWndResult = NULL;
1988 IntAcquireWinLockShared();
1990 if (!(Wnd = IntGetWindowObject(hWnd)))
1992 IntReleaseWinLock();
1993 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
1997 switch (Relationship)
2000 if (Wnd->Parent && Wnd->Parent->FirstChild)
2002 hWndResult = Wnd->Parent->FirstChild->Self;
2006 if (Wnd->Parent && Wnd->Parent->LastChild)
2008 hWndResult = Wnd->Parent->LastChild->Self;
2012 if (Wnd->Parent && Wnd->NextSibling)
2014 hWndResult = Wnd->NextSibling->Self;
2018 if (Wnd->Parent && Wnd->PrevSibling)
2020 hWndResult = Wnd->PrevSibling->Self;
2026 hWndResult = Wnd->hWndOwner;
2030 if (Wnd->FirstChild)
2032 hWndResult = Wnd->FirstChild->Self;
2037 IntReleaseWinLock();
2047 NtUserGetWindowDC(HWND hWnd)
2049 return (DWORD) NtUserGetDCEx( hWnd, 0, DCX_USESTYLE | DCX_WINDOW );
2057 NtUserGetWindowLong(HWND hWnd, DWORD Index, BOOL Ansi)
2059 PWINDOW_OBJECT WindowObject;
2064 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
2067 (PVOID*)&WindowObject);
2068 if (!NT_SUCCESS(Status))
2070 SetLastWin32Error(ERROR_INVALID_HANDLE);
2074 if (0 <= (int) Index)
2076 if (WindowObject->ExtraDataSize - sizeof(LONG) < Index ||
2077 0 != Index % sizeof(LONG))
2079 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2082 Result = WindowObject->ExtraData[Index / sizeof(LONG)];
2089 Result = WindowObject->ExStyle;
2093 Result = WindowObject->Style;
2098 Result = (LONG) WindowObject->WndProcA;
2102 Result = (LONG) WindowObject->WndProcW;
2107 Result = (LONG) WindowObject->Instance;
2110 case GWL_HWNDPARENT:
2111 Result = (LONG) WindowObject->ParentHandle;
2115 Result = (LONG) WindowObject->IDMenu;
2119 Result = WindowObject->UserData;
2123 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index);
2124 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2130 ObmDereferenceObject(WindowObject);
2140 NtUserGetWindowPlacement(DWORD Unknown0,
2150 * Return the dimension of the window in the screen coordinates.
2151 * \param hWnd window handle.
2152 * \param Rect pointer to the buffer where the coordinates are returned.
2158 NtUserGetWindowRect(HWND hWnd, LPRECT Rect)
2163 IntAcquireWinLockShared();
2164 if (!(Wnd = IntGetWindowObject(hWnd)))
2166 IntReleaseWinLock();
2167 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2171 SafeRect = Wnd->WindowRect;
2172 IntReleaseWinLock();
2174 if (! NT_SUCCESS(MmCopyToCaller(Rect, &SafeRect, sizeof(RECT))))
2187 NtUserGetWindowThreadProcessId(HWND hWnd, LPDWORD UnsafePid)
2192 IntAcquireWinLockShared();
2194 if (!(Wnd = IntGetWindowObject(hWnd)))
2196 IntReleaseWinLock();
2197 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2201 tid = IntGetWindowThreadProcessId(Wnd, &pid);
2202 IntReleaseWinLock();
2204 if (UnsafePid) MmCopyToCaller(UnsafePid, &pid, sizeof(DWORD));
2214 NtUserInternalGetWindowText(HWND hWnd,
2219 PWINDOW_OBJECT WindowObject;
2221 IntAcquireWinLockShared(); /* ??? */
2222 WindowObject = IntGetWindowObject(hWnd);
2225 IntReleaseWinLock(); /* ??? */
2226 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2232 /* FIXME - Window text is currently stored
2233 in the Atom 'USER32!WindowTextAtomA' */
2238 /* FIXME - return length of window text */
2241 IntReleaseWindowObject(WindowObject);
2243 IntReleaseWinLock(); /* ??? */
2252 NtUserLockWindowUpdate(DWORD Unknown0)
2272 UINT flags = SWP_NOZORDER | SWP_NOACTIVATE;
2275 flags |= SWP_NOREDRAW;
2276 return NtUserSetWindowPos(hWnd, 0, X, Y, nWidth, nHeight, flags);
2280 QueryWindow based on KJK::Hyperion and James Tabor.
2282 0 = QWUniqueProcessId
2283 1 = QWUniqueThreadId
2284 4 = QWIsHung Implements IsHungAppWindow found
2287 9 = QWKillWindow When I called this with hWnd ==
2288 DesktopWindow, it shutdown the system
2295 NtUserQueryWindow(HWND hWnd, DWORD Index)
2298 PWINDOW_OBJECT Window = IntGetWindowObject(hWnd);
2300 if(Window == NULL) return((DWORD)NULL);
2302 IntReleaseWindowObject(Window);
2307 return((DWORD)Window->OwnerThread->ThreadsProcess->UniqueProcessId);
2310 return((DWORD)Window->OwnerThread->Cid.UniqueThread);
2313 return((DWORD)NULL);
2323 NtUserRealChildWindowFromPoint(DWORD Unknown0,
2341 CONST RECT *lprcUpdate,
2346 RECT SafeUpdateRect;
2350 if (!(Wnd = IntGetWindowObject(hWnd)))
2352 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2356 if(NULL != lprcUpdate)
2358 Status = MmCopyFromCaller(&SafeUpdateRect, (PRECT)lprcUpdate, sizeof(RECT));
2360 if(!NT_SUCCESS(Status))
2362 /* FIXME: set last error */
2368 Status = PaintRedrawWindow
2371 NULL == lprcUpdate ? NULL : &SafeUpdateRect,
2378 if(!NT_SUCCESS(Status))
2380 /* FIXME: set last error */
2392 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe)
2394 PLIST_ENTRY Current;
2395 PREGISTERED_MESSAGE NewMsg, RegMsg;
2396 UINT Msg = REGISTERED_MESSAGE_MIN;
2397 UNICODE_STRING MessageName;
2400 Status = MmCopyFromCaller(&MessageName, MessageNameUnsafe, sizeof(UNICODE_STRING));
2401 if (! NT_SUCCESS(Status))
2403 SetLastNtError(Status);
2407 NewMsg = ExAllocatePoolWithTag(PagedPool,
2408 sizeof(REGISTERED_MESSAGE) +
2413 SetLastNtError(STATUS_NO_MEMORY);
2417 Status = MmCopyFromCaller(NewMsg->MessageName, MessageName.Buffer, MessageName.Length);
2418 if (! NT_SUCCESS(Status))
2421 SetLastNtError(Status);
2424 NewMsg->MessageName[MessageName.Length / sizeof(WCHAR)] = L'\0';
2425 if (wcslen(NewMsg->MessageName) != MessageName.Length / sizeof(WCHAR))
2428 SetLastNtError(STATUS_INVALID_PARAMETER);
2432 Current = RegisteredMessageListHead.Flink;
2433 while (Current != &RegisteredMessageListHead)
2435 RegMsg = CONTAINING_RECORD(Current, REGISTERED_MESSAGE, ListEntry);
2436 if (0 == wcscmp(NewMsg->MessageName, RegMsg->MessageName))
2442 Current = Current->Flink;
2445 if (REGISTERED_MESSAGE_MAX < Msg)
2448 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
2452 InsertTailList(&RegisteredMessageListHead, &(NewMsg->ListEntry));
2462 NtUserScrollWindowEx(DWORD Unknown0,
2481 NtUserSetCapture(HWND Wnd)
2483 PWINDOW_OBJECT Window;
2484 PWINDOW_OBJECT Prev;
2486 Prev = IntGetCaptureWindow();
2490 IntSendMessage(Prev->Self, WM_CAPTURECHANGED, 0L, (LPARAM)Wnd, FALSE);
2495 IntSetCaptureWindow(NULL);
2499 Window = IntGetWindowObject(Wnd);
2500 IntSetCaptureWindow(Window);
2501 IntReleaseWindowObject(Window);
2518 NtUserSetImeOwnerWindow(DWORD Unknown0,
2531 NtUserSetInternalWindowPos(DWORD Unknown0,
2547 NtUserSetLayeredWindowAttributes(DWORD Unknown0,
2562 NtUserSetLogonNotifyWindow(DWORD Unknown0)
2579 PWINDOW_OBJECT WindowObject;
2580 PMENU_OBJECT MenuObject;
2581 WindowObject = IntGetWindowObject((HWND)hWnd);
2584 SetLastWin32Error(ERROR_INVALID_HANDLE);
2590 /* assign new menu handle */
2591 MenuObject = IntGetMenuObject((HWND)hMenu);
2594 IntReleaseWindowObject(WindowObject);
2595 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
2599 WindowObject->IDMenu = (UINT)hMenu;
2601 IntReleaseMenuObject(MenuObject);
2605 /* remove the menu handle */
2606 WindowObject->IDMenu = 0;
2609 IntReleaseWindowObject(WindowObject);
2611 /* FIXME (from wine)
2614 if (IsWindowVisible(hWnd))
2615 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
2616 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
2629 NtUserSetParent(HWND hWndChild, HWND hWndNewParent)
2631 PWINDOW_OBJECT Wnd = NULL, WndParent = NULL, WndOldParent;
2634 if (IntIsBroadcastHwnd(hWndChild) || IntIsBroadcastHwnd(hWndNewParent))
2636 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2640 IntAcquireWinLockExclusive();
2643 if (!(WndParent = IntGetWindowObject(hWndNewParent)))
2645 IntReleaseWinLock();
2646 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2651 if (!(Wnd = IntGetWindowObject(hWndNewParent)))
2653 IntReleaseWinLock();
2654 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2658 WndOldParent = IntSetParent(Wnd, WndParent);
2659 if (WndOldParent) hWndOldParent = WndOldParent->Self;
2661 IntReleaseWinLock();
2663 return hWndOldParent;
2671 NtUserSetShellWindowEx(HWND hwndShell, HWND hwndShellListView)
2673 PEPROCESS my_current = IoGetCurrentProcess();
2675 /* test if we are permitted to change the shell window */
2676 if (pidShellWindow && my_current->UniqueProcessId!=pidShellWindow)
2679 hwndShellWindow = hwndShell;
2680 hwndShellListView = hwndShellListView;
2683 pidShellWindow = my_current->UniqueProcessId; /* request shell window for the calling process */
2685 pidShellWindow = 0; /* shell window is now free for other processes. */
2695 NtUserSetSystemMenu(
2700 PWINDOW_OBJECT WindowObject;
2701 PMENU_OBJECT MenuObject;
2702 WindowObject = IntGetWindowObject((HWND)hWnd);
2705 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2711 /* assign new menu handle */
2712 MenuObject = IntGetMenuObject(hMenu);
2715 IntReleaseWindowObject(WindowObject);
2716 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
2720 res = IntSetSystemMenu(WindowObject, MenuObject);
2722 IntReleaseMenuObject(MenuObject);
2725 IntReleaseWindowObject(WindowObject);
2734 NtUserSetWindowFNID(DWORD Unknown0,
2747 NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
2749 PWINDOW_OBJECT WindowObject;
2755 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
2758 (PVOID*)&WindowObject);
2759 if (!NT_SUCCESS(Status))
2761 SetLastWin32Error(ERROR_INVALID_HANDLE);
2765 if (0 <= (int) Index)
2767 if (WindowObject->ExtraDataSize - sizeof(LONG) < Index ||
2768 0 != Index % sizeof(LONG))
2770 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2773 OldValue = WindowObject->ExtraData[Index / sizeof(LONG)];
2774 WindowObject->ExtraData[Index / sizeof(LONG)] = NewValue;
2781 OldValue = (LONG) WindowObject->ExStyle;
2782 Style.styleOld = OldValue;
2783 Style.styleNew = NewValue;
2784 IntSendSTYLECHANGINGMessage(hWnd, GWL_EXSTYLE, &Style);
2785 WindowObject->ExStyle = (DWORD)Style.styleNew;
2786 IntSendSTYLECHANGEDMessage(hWnd, GWL_EXSTYLE, &Style);
2790 OldValue = (LONG) WindowObject->Style;
2791 Style.styleOld = OldValue;
2792 Style.styleNew = NewValue;
2793 IntSendSTYLECHANGINGMessage(hWnd, GWL_STYLE, &Style);
2794 WindowObject->Style = (DWORD)Style.styleNew;
2795 IntSendSTYLECHANGEDMessage(hWnd, GWL_STYLE, &Style);
2799 /* FIXME: should check if window belongs to current process */
2802 OldValue = (LONG) WindowObject->WndProcA;
2803 WindowObject->WndProcA = (WNDPROC) NewValue;
2804 WindowObject->WndProcW = (WNDPROC) NewValue+0x80000000;
2805 WindowObject->Unicode = FALSE;
2809 OldValue = (LONG) WindowObject->WndProcW;
2810 WindowObject->WndProcW = (WNDPROC) NewValue;
2811 WindowObject->WndProcA = (WNDPROC) NewValue+0x80000000;
2812 WindowObject->Unicode = TRUE;
2817 OldValue = (LONG) WindowObject->Instance;
2818 WindowObject->Instance = (HINSTANCE) NewValue;
2821 case GWL_HWNDPARENT:
2822 OldValue = (LONG) WindowObject->ParentHandle;
2823 WindowObject->ParentHandle = (HWND) NewValue;
2824 /* FIXME: Need to update window lists of old and new parent */
2829 OldValue = (LONG) WindowObject->IDMenu;
2830 WindowObject->IDMenu = (UINT) NewValue;
2834 OldValue = WindowObject->UserData;
2835 WindowObject->UserData = NewValue;
2839 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index);
2840 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2846 ObmDereferenceObject(WindowObject);
2855 NtUserSetWindowPlacement(DWORD Unknown0,
2870 HWND hWndInsertAfter,
2877 return WinPosSetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
2885 NtUserSetWindowRgn(DWORD Unknown0,
2899 NtUserSetWindowWord(HWND hWnd, INT Index, WORD NewVal)
2910 NtUserShowWindow(HWND hWnd,
2913 return(WinPosShowWindow(hWnd, nCmdShow));
2921 NtUserShowWindowAsync(DWORD Unknown0,
2934 NtUserUpdateWindow(HWND hWnd)
2936 PWINDOW_OBJECT pWindow = IntGetWindowObject( hWnd);
2940 if (pWindow->UpdateRegion)
2941 NtUserSendMessage( hWnd, WM_PAINT,0,0);
2942 IntReleaseWindowObject(pWindow);
2951 NtUserUpdateLayeredWindow(DWORD Unknown0,
2971 NtUserValidateRect(HWND hWnd, const RECT* Rect)
2973 return (VOID)NtUserRedrawWindow(hWnd, Rect, 0, RDW_VALIDATE | RDW_NOCHILDREN);
2981 NtUserWindowFromPoint(DWORD Unknown0,