2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
5 * FILE: subsystems/win32/win32k/ntuser/desktop.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * 06-06-2001 CSH Created
11 /* INCLUDES ******************************************************************/
24 IN OUT PDESKTOP Desktop
27 /* GLOBALS *******************************************************************/
29 /* Currently active desktop */
30 PDESKTOP InputDesktop
= NULL
;
31 HDESK InputDesktopHandle
= NULL
;
32 HDC ScreenDeviceContext
= NULL
;
33 BOOL g_PaintDesktopVersion
= FALSE
;
35 GENERIC_MAPPING IntDesktopMapping
=
37 STANDARD_RIGHTS_READ
| DESKTOP_ENUMERATE
|
39 STANDARD_RIGHTS_WRITE
| DESKTOP_CREATEMENU
|
40 DESKTOP_CREATEWINDOW
|
42 DESKTOP_JOURNALPLAYBACK
|
43 DESKTOP_JOURNALRECORD
|
45 STANDARD_RIGHTS_EXECUTE
| DESKTOP_SWITCHDESKTOP
,
46 STANDARD_RIGHTS_REQUIRED
| DESKTOP_CREATEMENU
|
47 DESKTOP_CREATEWINDOW
|
50 DESKTOP_JOURNALPLAYBACK
|
51 DESKTOP_JOURNALRECORD
|
53 DESKTOP_SWITCHDESKTOP
|
57 /* OBJECT CALLBACKS **********************************************************/
61 IntDesktopObjectParse(IN PVOID ParseObject
,
63 IN OUT PACCESS_STATE AccessState
,
64 IN KPROCESSOR_MODE AccessMode
,
66 IN OUT PUNICODE_STRING CompleteName
,
67 IN OUT PUNICODE_STRING RemainingName
,
68 IN OUT PVOID Context OPTIONAL
,
69 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL
,
74 OBJECT_ATTRIBUTES ObjectAttributes
;
75 PLIST_ENTRY NextEntry
, ListHead
;
76 PWINSTATION_OBJECT WinStaObject
= (PWINSTATION_OBJECT
)ParseObject
;
77 PUNICODE_STRING DesktopName
;
79 /* Set the list pointers and loop the window station */
80 ListHead
= &WinStaObject
->DesktopListHead
;
81 NextEntry
= ListHead
->Flink
;
82 while (NextEntry
!= ListHead
)
84 /* Get the current desktop */
85 Desktop
= CONTAINING_RECORD(NextEntry
, DESKTOP
, ListEntry
);
88 DesktopName
= GET_DESKTOP_NAME(Desktop
);
91 /* Compare the name */
92 if (RtlEqualUnicodeString(RemainingName
,
94 (Attributes
& OBJ_CASE_INSENSITIVE
)))
96 /* We found a match. Did this come from a create? */
99 /* Unless OPEN_IF was given, fail with an error */
100 if (!(Attributes
& OBJ_OPENIF
))
103 return STATUS_OBJECT_NAME_COLLISION
;
107 /* Otherwise, return with a warning only */
108 Status
= STATUS_OBJECT_NAME_EXISTS
;
113 /* This was a real open, so this is OK */
114 Status
= STATUS_SUCCESS
;
117 /* Reference the desktop and return it */
118 ObReferenceObject(Desktop
);
124 /* Go to the next desktop */
125 NextEntry
= NextEntry
->Flink
;
128 /* If we got here but this isn't a create, then fail */
129 if (!Context
) return STATUS_OBJECT_NAME_NOT_FOUND
;
131 /* Create the desktop object */
132 InitializeObjectAttributes(&ObjectAttributes
, RemainingName
, 0, NULL
, NULL
);
133 Status
= ObCreateObject(KernelMode
,
142 if (!NT_SUCCESS(Status
)) return Status
;
144 /* Initialize shell hook window list and set the parent */
145 RtlZeroMemory(Desktop
, sizeof(DESKTOP
));
146 InitializeListHead(&Desktop
->ShellHookWindows
);
147 Desktop
->WindowStation
= (PWINSTATION_OBJECT
)ParseObject
;
149 /* Put the desktop on the window station's list of associated desktops */
150 InsertTailList(&Desktop
->WindowStation
->DesktopListHead
,
151 &Desktop
->ListEntry
);
153 /* Set the desktop object and return success */
155 return STATUS_SUCCESS
;
159 IntDesktopObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters
)
161 PDESKTOP Desktop
= (PDESKTOP
)Parameters
->Object
;
163 DPRINT("Deleting desktop (0x%X)\n", Desktop
);
165 /* Remove the desktop from the window station's list of associcated desktops */
166 RemoveEntryList(&Desktop
->ListEntry
);
168 IntFreeDesktopHeap(Desktop
);
171 /* PRIVATE FUNCTIONS **********************************************************/
175 InitDesktopImpl(VOID
)
177 /* Set Desktop Object Attributes */
178 ExDesktopObjectType
->TypeInfo
.DefaultNonPagedPoolCharge
= sizeof(DESKTOP
);
179 ExDesktopObjectType
->TypeInfo
.GenericMapping
= IntDesktopMapping
;
180 return STATUS_SUCCESS
;
185 CleanupDesktopImpl(VOID
)
187 return STATUS_SUCCESS
;
190 static int GetSystemVersionString(LPWSTR buffer
)
192 RTL_OSVERSIONINFOEXW versionInfo
;
195 versionInfo
.dwOSVersionInfoSize
= sizeof(RTL_OSVERSIONINFOEXW
);
197 if (!NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW
)&versionInfo
)))
200 if (versionInfo
.dwMajorVersion
<= 4)
201 len
= swprintf(buffer
,
202 L
"ReactOS Version %d.%d %s Build %d",
203 versionInfo
.dwMajorVersion
, versionInfo
.dwMinorVersion
,
204 versionInfo
.szCSDVersion
, versionInfo
.dwBuildNumber
&0xFFFF);
206 len
= swprintf(buffer
,
207 L
"ReactOS %s (Build %d)",
208 versionInfo
.szCSDVersion
, versionInfo
.dwBuildNumber
&0xFFFF);
215 IntParseDesktopPath(PEPROCESS Process
,
216 PUNICODE_STRING DesktopPath
,
220 OBJECT_ATTRIBUTES ObjectAttributes
;
221 UNICODE_STRING WinSta
, Desktop
, FullName
;
222 BOOL DesktopPresent
= FALSE
;
223 BOOL WinStaPresent
= FALSE
;
235 RtlInitUnicodeString(&WinSta
, NULL
);
236 RtlInitUnicodeString(&Desktop
, NULL
);
238 if(DesktopPath
!= NULL
&& DesktopPath
->Buffer
!= NULL
&& DesktopPath
->Length
> sizeof(WCHAR
))
240 PWCHAR c
= DesktopPath
->Buffer
;
242 USHORT l
= DesktopPath
->Length
;
245 * Parse the desktop path string which can be in the form "WinSta\Desktop"
246 * or just "Desktop". In latter case WinSta0 will be used.
253 wl
= (ULONG_PTR
)c
- (ULONG_PTR
)DesktopPath
->Buffer
;
263 WinSta
.MaximumLength
= wl
+ sizeof(WCHAR
);
264 WinSta
.Buffer
= DesktopPath
->Buffer
;
266 WinStaPresent
= TRUE
;
270 Desktop
.Length
= DesktopPath
->Length
- wl
;
273 Desktop
.Length
-= sizeof(WCHAR
);
275 if(Desktop
.Length
> 0)
277 Desktop
.MaximumLength
= Desktop
.Length
+ sizeof(WCHAR
);
278 Desktop
.Buffer
= ((wl
> 0) ? c
: DesktopPath
->Buffer
);
279 DesktopPresent
= TRUE
;
286 /* search the process handle table for (inherited) window station
287 handles, use a more appropriate one than WinSta0 if possible. */
288 if (!ObFindHandleForObject(Process
,
290 ExWindowStationObjectType
,
295 /* we had no luck searching for opened handles, use WinSta0 now */
296 RtlInitUnicodeString(&WinSta
, L
"WinSta0");
300 if(!DesktopPresent
&& hDesktop
!= NULL
)
303 /* search the process handle table for (inherited) desktop
304 handles, use a more appropriate one than Default if possible. */
305 if (!ObFindHandleForObject(Process
,
312 /* we had no luck searching for opened handles, use Desktop now */
313 RtlInitUnicodeString(&Desktop
, L
"Default");
319 if(!IntGetFullWindowStationName(&FullName
, &WinSta
, NULL
))
321 return STATUS_INSUFFICIENT_RESOURCES
;
324 /* open the window station */
325 InitializeObjectAttributes(&ObjectAttributes
,
327 OBJ_CASE_INSENSITIVE
,
331 Status
= ObOpenObjectByName(&ObjectAttributes
,
332 ExWindowStationObjectType
,
339 ExFreePoolWithTag(FullName
.Buffer
, TAG_STRING
);
341 if(!NT_SUCCESS(Status
))
343 SetLastNtError(Status
);
344 DPRINT("Failed to reference window station %wZ PID: %d!\n", &WinSta
, PsGetCurrentProcessId());
349 if(hDesktop
!= NULL
&& *hDesktop
== NULL
)
351 if(!IntGetFullWindowStationName(&FullName
, &WinSta
, &Desktop
))
355 return STATUS_INSUFFICIENT_RESOURCES
;
358 /* open the desktop object */
359 InitializeObjectAttributes(&ObjectAttributes
,
361 OBJ_CASE_INSENSITIVE
,
365 Status
= ObOpenObjectByName(&ObjectAttributes
,
373 ExFreePoolWithTag(FullName
.Buffer
, TAG_STRING
);
375 if(!NT_SUCCESS(Status
))
380 SetLastNtError(Status
);
381 DPRINT("Failed to reference desktop %wZ PID: %d!\n", &Desktop
, PsGetCurrentProcessId());
386 return STATUS_SUCCESS
;
390 * IntValidateDesktopHandle
392 * Validates the desktop handle.
395 * If the function succeeds, the handle remains referenced. If the
396 * fucntion fails, last error is set.
400 IntValidateDesktopHandle(
402 KPROCESSOR_MODE AccessMode
,
403 ACCESS_MASK DesiredAccess
,
408 Status
= ObReferenceObjectByHandle(
416 if (!NT_SUCCESS(Status
))
417 SetLastNtError(Status
);
423 IntGetDesktopWorkArea(PDESKTOP Desktop
, RECTL
*Rect
)
429 Ret
= &Desktop
->WorkArea
;
430 if((Ret
->right
== -1) && ScreenDeviceContext
)
434 dc
= DC_LockDc(ScreenDeviceContext
);
435 /* FIXME - Handle dc == NULL!!!! */
436 psurf
= dc
->dclevel
.pSurface
;
439 Ret
->right
= psurf
->SurfObj
.sizlBitmap
.cx
;
440 Ret
->bottom
= psurf
->SurfObj
.sizlBitmap
.cy
;
452 IntGetActiveDesktop(VOID
)
458 * returns or creates a handle to the desktop object
461 IntGetDesktopObjectHandle(PDESKTOP DesktopObject
)
466 ASSERT(DesktopObject
);
468 if (!ObFindHandleForObject(PsGetCurrentProcess(),
474 Status
= ObOpenObjectByPointer(DesktopObject
,
481 if(!NT_SUCCESS(Status
))
483 /* unable to create a handle */
484 DPRINT1("Unable to create a desktop handle\n");
490 DPRINT1("Got handle: %lx\n", Ret
);
496 PUSER_MESSAGE_QUEUE FASTCALL
497 IntGetFocusMessageQueue(VOID
)
499 PDESKTOP pdo
= IntGetActiveDesktop();
502 DPRINT("No active desktop\n");
505 return (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
509 IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue
)
511 PUSER_MESSAGE_QUEUE Old
;
512 PDESKTOP pdo
= IntGetActiveDesktop();
515 DPRINT("No active desktop\n");
520 if(NewQueue
->Desktop
!= NULL
)
522 DPRINT("Message Queue already attached to another desktop!\n");
525 IntReferenceMessageQueue(NewQueue
);
526 (void)InterlockedExchangePointer((PVOID
*)&NewQueue
->Desktop
, pdo
);
528 Old
= (PUSER_MESSAGE_QUEUE
)InterlockedExchangePointer((PVOID
*)&pdo
->ActiveMessageQueue
, NewQueue
);
531 (void)InterlockedExchangePointer((PVOID
*)&Old
->Desktop
, 0);
532 IntDereferenceMessageQueue(Old
);
536 HWND FASTCALL
IntGetDesktopWindow(VOID
)
538 PDESKTOP pdo
= IntGetActiveDesktop();
541 DPRINT("No active desktop\n");
544 return pdo
->DesktopWindow
;
547 PWINDOW_OBJECT FASTCALL
UserGetDesktopWindow(VOID
)
549 PDESKTOP pdo
= IntGetActiveDesktop();
553 DPRINT("No active desktop\n");
557 return UserGetWindowObject(pdo
->DesktopWindow
);
560 HWND FASTCALL
IntGetMessageWindow(VOID
)
562 PDESKTOP pdo
= IntGetActiveDesktop();
566 DPRINT("No active desktop\n");
569 return pdo
->spwndMessage
->head
.h
;
572 HWND FASTCALL
IntGetCurrentThreadDesktopWindow(VOID
)
574 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
575 PDESKTOP pdo
= pti
->Desktop
;
578 DPRINT1("Thread doesn't have a desktop\n");
581 return pdo
->DesktopWindow
;
584 BOOL FASTCALL
IntDesktopUpdatePerUserSettings(BOOL bEnable
)
588 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
591 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
593 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
594 QueryTable
[0].Name
= L
"PaintDesktopVersion";
595 QueryTable
[0].EntryContext
= &g_PaintDesktopVersion
;
597 /* Query the "PaintDesktopVersion" flag in the "Control Panel\Desktop" key */
598 Status
= RtlQueryRegistryValues(RTL_REGISTRY_USER
,
599 L
"Control Panel\\Desktop",
600 QueryTable
, NULL
, NULL
);
601 if (!NT_SUCCESS(Status
))
603 DPRINT1("RtlQueryRegistryValues failed for PaintDesktopVersion (%x)\n",
605 g_PaintDesktopVersion
= FALSE
;
609 DPRINT("PaintDesktopVersion = %d\n", g_PaintDesktopVersion
);
615 g_PaintDesktopVersion
= FALSE
;
620 /* PUBLIC FUNCTIONS ***********************************************************/
623 UserGetDesktopDC(ULONG DcType
, BOOL EmptyDC
, BOOL ValidatehWnd
)
625 PWINDOW_OBJECT DesktopObject
= 0;
628 if (DcType
== DC_TYPE_DIRECT
)
630 DesktopObject
= UserGetDesktopWindow();
631 DesktopHDC
= (HDC
)UserGetWindowDC(DesktopObject
);
636 hDev
= (HDEV
)pPrimarySurface
;
637 DesktopHDC
= IntGdiCreateDisplayDC(hDev
, DcType
, EmptyDC
);
646 PWINDOW_OBJECT Window
= NULL
;
648 UserEnterExclusive();
650 Window
= UserGetDesktopWindow();
652 IntInvalidateWindows( Window
,
653 Window
->UpdateRegion
,
663 co_IntShowDesktop(PDESKTOP Desktop
, ULONG Width
, ULONG Height
)
665 CSR_API_MESSAGE Request
;
667 Request
.Type
= MAKE_CSR_API(SHOW_DESKTOP
, CSR_GUI
);
668 Request
.Data
.ShowDesktopRequest
.DesktopWindow
= Desktop
->DesktopWindow
;
669 Request
.Data
.ShowDesktopRequest
.Width
= Width
;
670 Request
.Data
.ShowDesktopRequest
.Height
= Height
;
672 return co_CsrNotify(&Request
);
676 IntHideDesktop(PDESKTOP Desktop
)
679 CSRSS_API_REQUEST Request
;
680 CSRSS_API_REPLY Reply
;
682 Request
.Type
= CSRSS_HIDE_DESKTOP
;
683 Request
.Data
.HideDesktopRequest
.DesktopWindow
= Desktop
->DesktopWindow
;
685 return NotifyCsrss(&Request
, &Reply
);
688 PWINDOW_OBJECT DesktopWindow
;
691 DesktopWindow
= IntGetWindowObject(Desktop
->DesktopWindow
);
694 return ERROR_INVALID_WINDOW_HANDLE
;
696 DesktopWnd
= DesktopWindow
->Wnd
;
697 DesktopWnd
->style
&= ~WS_VISIBLE
;
699 return STATUS_SUCCESS
;
708 UserBuildShellHookHwndList(PDESKTOP Desktop
)
711 PSHELL_HOOK_WINDOW Current
;
714 /* fixme: if we save nb elements in desktop, we dont have to loop to find nb entries */
715 LIST_FOR_EACH(Current
, &Desktop
->ShellHookWindows
, SHELL_HOOK_WINDOW
, ListEntry
)
718 if (!entries
) return NULL
;
720 list
= ExAllocatePool(PagedPool
, sizeof(HWND
) * (entries
+ 1)); /* alloc one extra for nullterm */
725 LIST_FOR_EACH(Current
, &Desktop
->ShellHookWindows
, SHELL_HOOK_WINDOW
, ListEntry
)
726 *cursor
++ = Current
->hWnd
;
728 *cursor
= NULL
; /* nullterm list */
735 * Send the Message to the windows registered for ShellHook
736 * notifications. The lParam contents depend on the Message. See
737 * MSDN for more details (RegisterShellHookWindow)
739 VOID
co_IntShellHookNotify(WPARAM Message
, LPARAM lParam
)
741 PDESKTOP Desktop
= IntGetActiveDesktop();
744 static UINT MsgType
= 0;
749 /* Too bad, this doesn't work.*/
752 RtlInitUnicodeString(&Str
, L
"SHELLHOOK");
753 MsgType
= UserRegisterWindowMessage(&Str
);
756 MsgType
= IntAddAtom(L
"SHELLHOOK");
758 DPRINT("MsgType = %x\n", MsgType
);
760 DPRINT1("LastError: %x\n", GetLastNtError());
765 DPRINT("IntShellHookNotify: No desktop!\n");
769 HwndList
= UserBuildShellHookHwndList(Desktop
);
772 HWND
* cursor
= HwndList
;
774 for (; *cursor
; cursor
++)
776 DPRINT("Sending notify\n");
777 co_IntPostOrSendMessage(*cursor
,
783 ExFreePool(HwndList
);
789 * Add the window to the ShellHookWindows list. The windows
790 * on that list get notifications that are important to shell
793 * TODO: Validate the window? I'm not sure if sending these messages to
794 * an unsuspecting application that is not your own is a nice thing to do.
796 BOOL
IntRegisterShellHookWindow(HWND hWnd
)
798 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
799 PDESKTOP Desktop
= pti
->Desktop
;
800 PSHELL_HOOK_WINDOW Entry
;
802 DPRINT("IntRegisterShellHookWindow\n");
804 /* First deregister the window, so we can be sure it's never twice in the
807 IntDeRegisterShellHookWindow(hWnd
);
809 Entry
= ExAllocatePoolWithTag(PagedPool
,
810 sizeof(SHELL_HOOK_WINDOW
),
818 InsertTailList(&Desktop
->ShellHookWindows
, &Entry
->ListEntry
);
824 * Remove the window from the ShellHookWindows list. The windows
825 * on that list get notifications that are important to shell
828 BOOL
IntDeRegisterShellHookWindow(HWND hWnd
)
830 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
831 PDESKTOP Desktop
= pti
->Desktop
;
832 PSHELL_HOOK_WINDOW Current
;
834 LIST_FOR_EACH(Current
, &Desktop
->ShellHookWindows
, SHELL_HOOK_WINDOW
, ListEntry
)
836 if (Current
->hWnd
== hWnd
)
838 RemoveEntryList(&Current
->ListEntry
);
848 IntFreeDesktopHeap(IN OUT PDESKTOP Desktop
)
850 if (Desktop
->DesktopHeapSection
!= NULL
)
852 ObDereferenceObject(Desktop
->DesktopHeapSection
);
853 Desktop
->DesktopHeapSection
= NULL
;
856 /* SYSCALLS *******************************************************************/
859 * NtUserCreateDesktop
861 * Creates a new desktop.
868 * Name of the device.
877 * Requested type of access.
881 * If the function succeeds, the return value is a handle to the newly
882 * created desktop. If the specified desktop already exists, the function
883 * succeeds and returns a handle to the existing desktop. When you are
884 * finished using the handle, call the CloseDesktop function to close it.
885 * If the function fails, the return value is NULL.
893 POBJECT_ATTRIBUTES poa
,
894 PUNICODE_STRING lpszDesktopDevice
,
897 ACCESS_MASK dwDesiredAccess
)
899 OBJECT_ATTRIBUTES ObjectAttributes
;
900 PTHREADINFO W32Thread
;
901 PWINSTATION_OBJECT WinStaObject
;
902 PDESKTOP DesktopObject
;
903 UNICODE_STRING DesktopName
;
904 NTSTATUS Status
= STATUS_SUCCESS
;
906 CSR_API_MESSAGE Request
;
907 PVOID DesktopHeapSystemBase
= NULL
;
908 SIZE_T DesktopInfoSize
;
909 UNICODE_STRING SafeDesktopName
;
911 ULONG_PTR HeapSize
= 4 * 1024 * 1024; /* FIXME */
912 HWINSTA hWindowStation
= NULL
;
913 PUNICODE_STRING lpszDesktopName
= NULL
;
914 UNICODE_STRING ClassName
, WindowName
, MenuName
;
915 PPROCESSINFO pi
= GetW32ProcessInfo();
919 DECLARE_RETURN(HDESK
);
921 DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName
);
922 UserEnterExclusive();
927 sizeof(OBJECT_ATTRIBUTES
),
930 hWindowStation
= poa
->RootDirectory
;
931 lpszDesktopName
= poa
->ObjectName
;
933 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
935 Status
=_SEH2_GetExceptionCode();
939 if (! NT_SUCCESS(Status
))
941 DPRINT1("Failed reading Object Attributes from user space.\n");
942 SetLastNtError(Status
);
946 Status
= IntValidateWindowStationHandle(
949 0, /* FIXME - WINSTA_CREATEDESKTOP */
952 if (! NT_SUCCESS(Status
))
954 DPRINT1("Failed validation of window station handle (0x%X), cannot create desktop %wZ\n",
955 hWindowStation
, lpszDesktopName
);
956 SetLastNtError(Status
);
959 if(lpszDesktopName
!= NULL
)
961 Status
= IntSafeCopyUnicodeString(&SafeDesktopName
, lpszDesktopName
);
962 if(!NT_SUCCESS(Status
))
964 SetLastNtError(Status
);
970 RtlInitUnicodeString(&SafeDesktopName
, NULL
);
973 if (! IntGetFullWindowStationName(&DesktopName
, &WinStaObject
->Name
,
976 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
977 ObDereferenceObject(WinStaObject
);
979 ExFreePoolWithTag(SafeDesktopName
.Buffer
, TAG_STRING
);
983 ExFreePoolWithTag(SafeDesktopName
.Buffer
, TAG_STRING
);
984 ObDereferenceObject(WinStaObject
);
987 * Try to open already existing desktop
990 DPRINT("Trying to open desktop (%wZ)\n", &DesktopName
);
992 /* Initialize ObjectAttributes for the desktop object */
993 InitializeObjectAttributes(
1000 Status
= ObOpenObjectByName(
1002 ExDesktopObjectType
,
1006 (PVOID
)&DummyContext
,
1008 if (!NT_SUCCESS(Status
)) RETURN(NULL
);
1009 if (Status
== STATUS_OBJECT_NAME_EXISTS
)
1011 ExFreePoolWithTag(DesktopName
.Buffer
, TAG_STRING
);
1015 /* Reference the desktop */
1016 Status
= ObReferenceObjectByHandle(Desktop
,
1018 ExDesktopObjectType
,
1020 (PVOID
)&DesktopObject
,
1022 if (!NT_SUCCESS(Status
)) RETURN(NULL
);
1024 DesktopObject
->DesktopHeapSection
= NULL
;
1025 DesktopObject
->pheapDesktop
= UserCreateHeap(&DesktopObject
->DesktopHeapSection
,
1026 &DesktopHeapSystemBase
,
1028 if (DesktopObject
->pheapDesktop
== NULL
)
1030 ObDereferenceObject(DesktopObject
);
1031 DPRINT1("Failed to create desktop heap!\n");
1035 DesktopInfoSize
= FIELD_OFFSET(DESKTOPINFO
,
1036 szDesktopName
[(lpszDesktopName
->Length
/ sizeof(WCHAR
)) + 1]);
1038 DesktopObject
->DesktopInfo
= RtlAllocateHeap(DesktopObject
->pheapDesktop
,
1042 if (DesktopObject
->DesktopInfo
== NULL
)
1044 ObDereferenceObject(DesktopObject
);
1045 DPRINT1("Failed to create the DESKTOP structure!\n");
1049 RtlZeroMemory(DesktopObject
->DesktopInfo
,
1052 DesktopObject
->DesktopInfo
->pvDesktopBase
= DesktopHeapSystemBase
;
1053 DesktopObject
->DesktopInfo
->pvDesktopLimit
= (PVOID
)((ULONG_PTR
)DesktopHeapSystemBase
+ HeapSize
);
1054 RtlCopyMemory(DesktopObject
->DesktopInfo
->szDesktopName
,
1055 lpszDesktopName
->Buffer
,
1056 lpszDesktopName
->Length
);
1058 // init desktop area
1059 DesktopObject
->WorkArea
.left
= 0;
1060 DesktopObject
->WorkArea
.top
= 0;
1061 DesktopObject
->WorkArea
.right
= -1;
1062 DesktopObject
->WorkArea
.bottom
= -1;
1063 IntGetDesktopWorkArea(DesktopObject
, NULL
);
1065 /* Initialize some local (to win32k) desktop state. */
1066 InitializeListHead(&DesktopObject
->PtiList
);
1067 DesktopObject
->ActiveMessageQueue
= NULL
;
1068 ExFreePoolWithTag(DesktopName
.Buffer
, TAG_STRING
);
1070 if (! NT_SUCCESS(Status
))
1072 DPRINT1("Failed to create desktop handle\n");
1073 SetLastNtError(Status
);
1078 * Create a handle for CSRSS and notify CSRSS for Creating Desktop Window.
1080 * Honestly, I believe this is a cleverly written hack that allowed ReactOS
1081 * to function at the beginning of the project by ramroding the GUI into
1082 * operation and making the desktop window work from user space.
1085 Request
.Type
= MAKE_CSR_API(CREATE_DESKTOP
, CSR_GUI
);
1086 Status
= CsrInsertObject(Desktop
,
1088 (HANDLE
*)&Request
.Data
.CreateDesktopRequest
.DesktopHandle
);
1089 if (! NT_SUCCESS(Status
))
1091 DPRINT1("Failed to create desktop handle for CSRSS\n");
1093 SetLastNtError(Status
);
1097 Status
= co_CsrNotify(&Request
);
1098 if (! NT_SUCCESS(Status
))
1100 CsrCloseHandle(Request
.Data
.CreateDesktopRequest
.DesktopHandle
);
1101 DPRINT1("Failed to notify CSRSS about new desktop\n");
1103 SetLastNtError(Status
);
1107 W32Thread
= PsGetCurrentThreadWin32Thread();
1109 if (!W32Thread
->Desktop
) IntSetThreadDesktop(DesktopObject
,FALSE
);
1112 Based on wine/server/window.c in get_desktop_window.
1115 ClassName
.Buffer
= ((PWSTR
)((ULONG_PTR
)(WORD
)(AtomMessage
)));
1116 ClassName
.Length
= 0;
1117 RtlZeroMemory(&MenuName
, sizeof(MenuName
));
1118 RtlZeroMemory(&WindowName
, sizeof(WindowName
));
1120 wc
.cbSize
= sizeof(wc
);
1122 wc
.lpfnWndProc
= gpsi
->apfnClientW
.pfnMessageWindowProc
;
1125 wc
.hInstance
= hModClient
;
1128 wc
.hbrBackground
= 0;
1129 wc
.lpszMenuName
= NULL
;
1130 wc
.lpszClassName
= ClassName
.Buffer
;
1133 Class
= IntCreateClass( &wc
,
1143 ASSERT(Class
->System
);
1144 Class
->pclsNext
= SystemClassList
;
1145 (void)InterlockedExchangePointer((PVOID
*)&SystemClassList
,
1150 DPRINT1("!!! Registering Message system class failed!\n");
1153 pWnd
= co_IntCreateWindowEx( 0,
1156 (WS_POPUP
|WS_CLIPCHILDREN
),
1169 DPRINT1("Failed to create Message window handle\n");
1173 DesktopObject
->spwndMessage
= pWnd
;
1179 DPRINT("Leave NtUserCreateDesktop, ret=%i\n",_ret_
);
1187 * Opens an existing desktop.
1191 * Name of the existing desktop.
1194 * Interaction flags.
1197 * Requested type of access.
1200 * Handle to the desktop or zero on failure.
1208 PUNICODE_STRING lpszDesktopName
,
1210 ACCESS_MASK dwDesiredAccess
)
1212 OBJECT_ATTRIBUTES ObjectAttributes
;
1214 PWINSTATION_OBJECT WinStaObject
;
1215 UNICODE_STRING DesktopName
;
1216 UNICODE_STRING SafeDesktopName
;
1220 DECLARE_RETURN(HDESK
);
1222 DPRINT("Enter NtUserOpenDesktop: %wZ\n", lpszDesktopName
);
1223 UserEnterExclusive();
1226 * Validate the window station handle and compose the fully
1227 * qualified desktop name
1230 WinSta
= UserGetProcessWindowStation();
1231 Status
= IntValidateWindowStationHandle(
1237 if (!NT_SUCCESS(Status
))
1239 DPRINT1("Failed validation of window station handle (0x%X)\n", WinSta
);
1240 SetLastNtError(Status
);
1244 if(lpszDesktopName
!= NULL
)
1246 Status
= IntSafeCopyUnicodeString(&SafeDesktopName
, lpszDesktopName
);
1247 if(!NT_SUCCESS(Status
))
1249 SetLastNtError(Status
);
1255 RtlInitUnicodeString(&SafeDesktopName
, NULL
);
1258 Result
= IntGetFullWindowStationName(&DesktopName
, &WinStaObject
->Name
,
1261 if (lpszDesktopName
)
1262 ExFreePoolWithTag(SafeDesktopName
.Buffer
, TAG_STRING
);
1263 ObDereferenceObject(WinStaObject
);
1268 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1273 DPRINT("Trying to open desktop (%wZ)\n", &DesktopName
);
1275 /* Initialize ObjectAttributes for the desktop object */
1276 InitializeObjectAttributes(
1283 Status
= ObOpenObjectByName(
1285 ExDesktopObjectType
,
1292 if (!NT_SUCCESS(Status
))
1294 SetLastNtError(Status
);
1295 ExFreePool(DesktopName
.Buffer
);
1299 DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName
);
1300 ExFreePool(DesktopName
.Buffer
);
1305 DPRINT("Leave NtUserOpenDesktop, ret=%i\n",_ret_
);
1311 * NtUserOpenInputDesktop
1313 * Opens the input (interactive) desktop.
1317 * Interaction flags.
1320 * Inheritance option.
1323 * Requested type of access.
1326 * Handle to the input desktop or zero on failure.
1333 NtUserOpenInputDesktop(
1336 ACCESS_MASK dwDesiredAccess
)
1341 DECLARE_RETURN(HDESK
);
1343 DPRINT("Enter NtUserOpenInputDesktop\n");
1344 UserEnterExclusive();
1346 DPRINT("About to open input desktop\n");
1348 /* Get a pointer to the desktop object */
1350 Status
= IntValidateDesktopHandle(
1356 if (!NT_SUCCESS(Status
))
1358 DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop
);
1362 /* Create a new handle to the object */
1364 Status
= ObOpenObjectByPointer(
1369 ExDesktopObjectType
,
1373 ObDereferenceObject(Object
);
1375 if (NT_SUCCESS(Status
))
1377 DPRINT("Successfully opened input desktop\n");
1378 RETURN((HDESK
)Desktop
);
1381 SetLastNtError(Status
);
1385 DPRINT("Leave NtUserOpenInputDesktop, ret=%i\n",_ret_
);
1391 * NtUserCloseDesktop
1393 * Closes a desktop handle.
1397 * Handle to the desktop.
1403 * The desktop handle can be created with NtUserCreateDesktop or
1404 * NtUserOpenDesktop. This function will fail if any thread in the calling
1405 * process is using the specified desktop handle or if the handle refers
1406 * to the initial desktop of the calling process.
1413 NtUserCloseDesktop(HDESK hDesktop
)
1417 DECLARE_RETURN(BOOL
);
1419 DPRINT("Enter NtUserCloseDesktop\n");
1420 UserEnterExclusive();
1422 DPRINT("About to close desktop handle (0x%X)\n", hDesktop
);
1424 Status
= IntValidateDesktopHandle(
1430 if (!NT_SUCCESS(Status
))
1432 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop
);
1436 ObDereferenceObject(Object
);
1438 DPRINT("Closing desktop handle (0x%X)\n", hDesktop
);
1440 Status
= ZwClose(hDesktop
);
1441 if (!NT_SUCCESS(Status
))
1443 SetLastNtError(Status
);
1450 DPRINT("Leave NtUserCloseDesktop, ret=%i\n",_ret_
);
1459 * NtUserPaintDesktop
1461 * The NtUserPaintDesktop function fills the clipping region in the
1462 * specified device context with the desktop pattern or wallpaper. The
1463 * function is provided primarily for shell desktops.
1467 * Handle to the device context.
1474 NtUserPaintDesktop(HDC hDC
)
1477 HBRUSH DesktopBrush
, PreviousBrush
;
1479 BOOL doPatBlt
= TRUE
;
1480 PWINDOW_OBJECT WndDesktop
;
1485 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1486 PWINSTATION_OBJECT WinSta
= pti
->Desktop
->WindowStation
;
1487 DECLARE_RETURN(BOOL
);
1489 UserEnterExclusive();
1490 DPRINT("Enter NtUserPaintDesktop\n");
1492 GdiGetClipBox(hDC
, &Rect
);
1494 hWndDesktop
= IntGetDesktopWindow();
1496 WndDesktop
= UserGetWindowObject(hWndDesktop
);
1502 DesktopBrush
= (HBRUSH
)UserGetClassLongPtr(WndDesktop
->Wnd
->pcls
, GCL_HBRBACKGROUND
, FALSE
);
1506 * Paint desktop background
1509 if (WinSta
->hbmWallpaper
!= NULL
)
1511 PWINDOW_OBJECT DeskWin
;
1513 DeskWin
= UserGetWindowObject(hWndDesktop
);
1521 sz
.cx
= DeskWin
->Wnd
->rcWindow
.right
- DeskWin
->Wnd
->rcWindow
.left
;
1522 sz
.cy
= DeskWin
->Wnd
->rcWindow
.bottom
- DeskWin
->Wnd
->rcWindow
.top
;
1524 if (WinSta
->WallpaperMode
== wmStretch
||
1525 WinSta
->WallpaperMode
== wmTile
)
1532 /* Find the upper left corner, can be negtive if the bitmap is bigger then the screen */
1533 x
= (sz
.cx
/ 2) - (WinSta
->cxWallpaper
/ 2);
1534 y
= (sz
.cy
/ 2) - (WinSta
->cyWallpaper
/ 2);
1537 hWallpaperDC
= NtGdiCreateCompatibleDC(hDC
);
1538 if(hWallpaperDC
!= NULL
)
1542 /* fill in the area that the bitmap is not going to cover */
1545 /* FIXME - clip out the bitmap
1546 can be replaced with "NtGdiPatBlt(hDC, x, y, WinSta->cxWallpaper, WinSta->cyWallpaper, PATCOPY | DSTINVERT);"
1547 once we support DSTINVERT */
1548 PreviousBrush
= NtGdiSelectBrush(hDC
, DesktopBrush
);
1549 NtGdiPatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
, Rect
.bottom
, PATCOPY
);
1550 NtGdiSelectBrush(hDC
, PreviousBrush
);
1553 /*Do not fill the background after it is painted no matter the size of the picture */
1556 hOldBitmap
= NtGdiSelectBitmap(hWallpaperDC
, WinSta
->hbmWallpaper
);
1558 if (WinSta
->WallpaperMode
== wmStretch
)
1560 if(Rect
.right
&& Rect
.bottom
)
1561 NtGdiStretchBlt(hDC
,
1569 WinSta
->cxWallpaper
,
1570 WinSta
->cyWallpaper
,
1575 else if (WinSta
->WallpaperMode
== wmTile
)
1577 /* paint the bitmap across the screen then down */
1578 for(y
= 0; y
< Rect
.bottom
; y
+= WinSta
->cyWallpaper
)
1580 for(x
= 0; x
< Rect
.right
; x
+= WinSta
->cxWallpaper
)
1585 WinSta
->cxWallpaper
,
1586 WinSta
->cyWallpaper
,
1601 WinSta
->cxWallpaper
,
1602 WinSta
->cyWallpaper
,
1610 NtGdiSelectBitmap(hWallpaperDC
, hOldBitmap
);
1611 NtGdiDeleteObjectApp(hWallpaperDC
);
1616 /* Back ground is set to none, clear the screen */
1619 PreviousBrush
= NtGdiSelectBrush(hDC
, DesktopBrush
);
1620 NtGdiPatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
, Rect
.bottom
, PATCOPY
);
1621 NtGdiSelectBrush(hDC
, PreviousBrush
);
1625 * Display system version on the desktop background
1628 if (g_PaintDesktopVersion
)
1630 static WCHAR s_wszVersion
[256] = {0};
1635 len
= wcslen(s_wszVersion
);
1639 len
= GetSystemVersionString(s_wszVersion
);
1644 if (!UserSystemParametersInfo(SPI_GETWORKAREA
, 0, &rect
, 0))
1646 rect
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
1647 rect
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
1650 color_old
= IntGdiSetTextColor(hDC
, RGB(255,255,255));
1651 align_old
= IntGdiSetTextAlign(hDC
, TA_RIGHT
);
1652 mode_old
= IntGdiSetBkMode(hDC
, TRANSPARENT
);
1654 GreExtTextOutW(hDC
, rect
.right
-16, rect
.bottom
-48, 0, NULL
, s_wszVersion
, len
, NULL
, 0);
1656 IntGdiSetBkMode(hDC
, mode_old
);
1657 IntGdiSetTextAlign(hDC
, align_old
);
1658 IntGdiSetTextColor(hDC
, color_old
);
1665 DPRINT("Leave NtUserPaintDesktop, ret=%i\n",_ret_
);
1672 * NtUserSwitchDesktop
1674 * Sets the current input (interactive) desktop.
1678 * Handle to desktop.
1688 NtUserSwitchDesktop(HDESK hDesktop
)
1690 PDESKTOP DesktopObject
;
1692 DECLARE_RETURN(BOOL
);
1694 UserEnterExclusive();
1695 DPRINT("Enter NtUserSwitchDesktop\n");
1697 DPRINT("About to switch desktop (0x%X)\n", hDesktop
);
1699 Status
= IntValidateDesktopHandle(
1705 if (!NT_SUCCESS(Status
))
1707 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop
);
1712 * Don't allow applications switch the desktop if it's locked, unless the caller
1713 * is the logon application itself
1715 if((DesktopObject
->WindowStation
->Flags
& WSS_LOCKED
) &&
1716 LogonProcess
!= NULL
&& LogonProcess
!= PsGetCurrentProcessWin32Process())
1718 ObDereferenceObject(DesktopObject
);
1719 DPRINT1("Switching desktop 0x%x denied because the work station is locked!\n", hDesktop
);
1723 /* FIXME: Fail if the desktop belong to an invisible window station */
1724 /* FIXME: Fail if the process is associated with a secured
1725 desktop such as Winlogon or Screen-Saver */
1726 /* FIXME: Connect to input device */
1728 /* Set the active desktop in the desktop's window station. */
1729 DesktopObject
->WindowStation
->ActiveDesktop
= DesktopObject
;
1731 /* Set the global state. */
1732 InputDesktop
= DesktopObject
;
1733 InputDesktopHandle
= hDesktop
;
1734 InputWindowStation
= DesktopObject
->WindowStation
;
1736 ObDereferenceObject(DesktopObject
);
1741 DPRINT("Leave NtUserSwitchDesktop, ret=%i\n",_ret_
);
1747 * NtUserResolveDesktopForWOW
1754 NtUserResolveDesktopForWOW(DWORD Unknown0
)
1761 * NtUserGetThreadDesktop
1768 NtUserGetThreadDesktop(DWORD dwThreadId
, DWORD Unknown1
)
1772 PDESKTOP DesktopObject
;
1773 HDESK Ret
, hThreadDesktop
;
1774 OBJECT_HANDLE_INFORMATION HandleInformation
;
1775 DECLARE_RETURN(HDESK
);
1777 UserEnterExclusive();
1778 DPRINT("Enter NtUserGetThreadDesktop\n");
1782 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1786 Status
= PsLookupThreadByThreadId((HANDLE
)(DWORD_PTR
)dwThreadId
, &Thread
);
1787 if(!NT_SUCCESS(Status
))
1789 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1793 if(Thread
->ThreadsProcess
== PsGetCurrentProcess())
1795 /* just return the handle, we queried the desktop handle of a thread running
1796 in the same context */
1797 Ret
= ((PTHREADINFO
)Thread
->Tcb
.Win32Thread
)->hDesktop
;
1798 ObDereferenceObject(Thread
);
1802 /* get the desktop handle and the desktop of the thread */
1803 if(!(hThreadDesktop
= ((PTHREADINFO
)Thread
->Tcb
.Win32Thread
)->hDesktop
) ||
1804 !(DesktopObject
= ((PTHREADINFO
)Thread
->Tcb
.Win32Thread
)->Desktop
))
1806 ObDereferenceObject(Thread
);
1807 DPRINT1("Desktop information of thread 0x%x broken!?\n", dwThreadId
);
1811 /* we could just use DesktopObject instead of looking up the handle, but latter
1812 may be a bit safer (e.g. when the desktop is being destroyed */
1813 /* switch into the context of the thread we're trying to get the desktop from,
1814 so we can use the handle */
1815 KeAttachProcess(&Thread
->ThreadsProcess
->Pcb
);
1816 Status
= ObReferenceObjectByHandle(hThreadDesktop
,
1818 ExDesktopObjectType
,
1820 (PVOID
*)&DesktopObject
,
1821 &HandleInformation
);
1824 /* the handle couldn't be found, there's nothing to get... */
1825 if(!NT_SUCCESS(Status
))
1827 ObDereferenceObject(Thread
);
1831 /* lookup our handle table if we can find a handle to the desktop object,
1832 if not, create one */
1833 Ret
= IntGetDesktopObjectHandle(DesktopObject
);
1835 /* all done, we got a valid handle to the desktop */
1836 ObDereferenceObject(DesktopObject
);
1837 ObDereferenceObject(Thread
);
1841 DPRINT("Leave NtUserGetThreadDesktop, ret=%i\n",_ret_
);
1847 IntUnmapDesktopView(IN PDESKTOP DesktopObject
)
1850 PPROCESSINFO CurrentWin32Process
;
1851 PW32HEAP_USER_MAPPING HeapMapping
, *PrevLink
;
1852 NTSTATUS Status
= STATUS_SUCCESS
;
1856 CurrentWin32Process
= PsGetCurrentProcessWin32Process();
1857 PrevLink
= &CurrentWin32Process
->HeapMappings
.Next
;
1859 /* unmap if we're the last thread using the desktop */
1860 HeapMapping
= *PrevLink
;
1861 while (HeapMapping
!= NULL
)
1863 if (HeapMapping
->KernelMapping
== (PVOID
)DesktopObject
->pheapDesktop
)
1865 if (--HeapMapping
->Count
== 0)
1867 *PrevLink
= HeapMapping
->Next
;
1869 Status
= MmUnmapViewOfSection(PsGetCurrentProcess(),
1870 HeapMapping
->UserMapping
);
1872 ObDereferenceObject(DesktopObject
);
1874 UserHeapFree(HeapMapping
);
1879 PrevLink
= &HeapMapping
->Next
;
1880 HeapMapping
= HeapMapping
->Next
;
1883 ti
= GetW32ThreadInfo();
1886 GetWin32ClientInfo()->pDeskInfo
= NULL
;
1888 GetWin32ClientInfo()->ulClientDelta
= 0;
1894 IntMapDesktopView(IN PDESKTOP DesktopObject
)
1897 PPROCESSINFO CurrentWin32Process
;
1898 PW32HEAP_USER_MAPPING HeapMapping
, *PrevLink
;
1899 PVOID UserBase
= NULL
;
1900 SIZE_T ViewSize
= 0;
1901 LARGE_INTEGER Offset
;
1904 CurrentWin32Process
= PsGetCurrentProcessWin32Process();
1905 PrevLink
= &CurrentWin32Process
->HeapMappings
.Next
;
1907 /* find out if another thread already mapped the desktop heap */
1908 HeapMapping
= *PrevLink
;
1909 while (HeapMapping
!= NULL
)
1911 if (HeapMapping
->KernelMapping
== (PVOID
)DesktopObject
->pheapDesktop
)
1913 HeapMapping
->Count
++;
1914 return STATUS_SUCCESS
;
1917 PrevLink
= &HeapMapping
->Next
;
1918 HeapMapping
= HeapMapping
->Next
;
1921 /* we're the first, map the heap */
1922 DPRINT("Noone mapped the desktop heap %p yet, so - map it!\n", DesktopObject
->pheapDesktop
);
1923 Offset
.QuadPart
= 0;
1924 Status
= MmMapViewOfSection(DesktopObject
->DesktopHeapSection
,
1925 PsGetCurrentProcess(),
1933 PAGE_EXECUTE_READ
); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
1934 if (!NT_SUCCESS(Status
))
1936 DPRINT1("Failed to map desktop\n");
1940 /* add the mapping */
1941 HeapMapping
= UserHeapAlloc(sizeof(W32HEAP_USER_MAPPING
));
1942 if (HeapMapping
== NULL
)
1944 MmUnmapViewOfSection(PsGetCurrentProcess(),
1946 DPRINT1("UserHeapAlloc() failed!\n");
1947 return STATUS_NO_MEMORY
;
1950 HeapMapping
->Next
= NULL
;
1951 HeapMapping
->KernelMapping
= (PVOID
)DesktopObject
->pheapDesktop
;
1952 HeapMapping
->UserMapping
= UserBase
;
1953 HeapMapping
->Limit
= ViewSize
;
1954 HeapMapping
->Count
= 1;
1955 *PrevLink
= HeapMapping
;
1957 ObReferenceObject(DesktopObject
);
1959 /* create a W32THREADINFO structure if not already done, or update it */
1960 ti
= GetW32ThreadInfo();
1961 GetWin32ClientInfo()->ulClientDelta
= DesktopHeapGetUserDelta();
1964 if (GetWin32ClientInfo()->pDeskInfo
== NULL
)
1966 GetWin32ClientInfo()->pDeskInfo
=
1967 (PVOID
)((ULONG_PTR
)DesktopObject
->DesktopInfo
-
1968 GetWin32ClientInfo()->ulClientDelta
);
1972 return STATUS_SUCCESS
;
1976 IntSetThreadDesktop(IN PDESKTOP DesktopObject
,
1977 IN BOOL FreeOnFailure
)
1979 PDESKTOP OldDesktop
;
1980 PTHREADINFO W32Thread
;
1984 DPRINT("IntSetThreadDesktop() DO=%p, FOF=%d\n", DesktopObject
, FreeOnFailure
);
1985 MapHeap
= (PsGetCurrentProcess() != PsInitialSystemProcess
);
1986 W32Thread
= PsGetCurrentThreadWin32Thread();
1988 if (W32Thread
->Desktop
!= DesktopObject
)
1990 OldDesktop
= W32Thread
->Desktop
;
1992 if (!IsListEmpty(&W32Thread
->WindowListHead
))
1994 DPRINT1("Attempted to change thread desktop although the thread has windows!\n");
1995 SetLastWin32Error(ERROR_BUSY
);
1999 W32Thread
->Desktop
= DesktopObject
;
2001 if (MapHeap
&& DesktopObject
!= NULL
)
2003 Status
= IntMapDesktopView(DesktopObject
);
2004 if (!NT_SUCCESS(Status
))
2006 SetLastNtError(Status
);
2011 /* Hack for system threads */
2014 PCLIENTINFO pci
= GetWin32ClientInfo();
2015 pci
->ulClientDelta
= DesktopHeapGetUserDelta();
2018 pci
->pDeskInfo
= (PVOID
)((ULONG_PTR
)DesktopObject
->DesktopInfo
- pci
->ulClientDelta
);
2022 if (OldDesktop
!= NULL
&&
2023 !IntCheckProcessDesktopClasses(OldDesktop
,
2026 DPRINT1("Failed to move process classes to shared heap!\n");
2028 /* failed to move desktop classes to the shared heap,
2029 unmap the view and return the error */
2030 if (MapHeap
&& DesktopObject
!= NULL
)
2031 IntUnmapDesktopView(DesktopObject
);
2036 /* Remove the thread from the old desktop's list */
2037 RemoveEntryList(&W32Thread
->PtiLink
);
2039 if (DesktopObject
!= NULL
)
2041 ObReferenceObject(DesktopObject
);
2042 /* Insert into new desktop's list */
2043 InsertTailList(&DesktopObject
->PtiList
, &W32Thread
->PtiLink
);
2046 if (OldDesktop
!= NULL
)
2050 IntUnmapDesktopView(OldDesktop
);
2053 ObDereferenceObject(OldDesktop
);
2061 * NtUserSetThreadDesktop
2068 NtUserSetThreadDesktop(HDESK hDesktop
)
2070 PDESKTOP DesktopObject
;
2072 DECLARE_RETURN(BOOL
);
2074 UserEnterExclusive();
2075 DPRINT("Enter NtUserSetThreadDesktop\n");
2077 /* Validate the new desktop. */
2078 Status
= IntValidateDesktopHandle(
2084 if (!NT_SUCCESS(Status
))
2086 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop
);
2090 /* FIXME: Should check here to see if the thread has any windows. */
2092 if (!IntSetThreadDesktop(DesktopObject
,
2101 DPRINT("Leave NtUserSetThreadDesktop, ret=%i\n",_ret_
);