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
->rpwinstaParent
= (PWINSTATION_OBJECT
)ParseObject
;
149 /* Put the desktop on the window station's list of associated desktops */
150 InsertTailList(&Desktop
->rpwinstaParent
->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 **********************************************************/
176 InitDesktopImpl(VOID
)
178 /* Set Desktop Object Attributes */
179 ExDesktopObjectType
->TypeInfo
.DefaultNonPagedPoolCharge
= sizeof(DESKTOP
);
180 ExDesktopObjectType
->TypeInfo
.GenericMapping
= IntDesktopMapping
;
181 return STATUS_SUCCESS
;
186 CleanupDesktopImpl(VOID
)
188 return STATUS_SUCCESS
;
191 static int GetSystemVersionString(LPWSTR buffer
)
193 RTL_OSVERSIONINFOEXW versionInfo
;
196 versionInfo
.dwOSVersionInfoSize
= sizeof(RTL_OSVERSIONINFOEXW
);
198 if (!NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW
)&versionInfo
)))
201 if (versionInfo
.dwMajorVersion
<= 4)
202 len
= swprintf(buffer
,
203 L
"ReactOS Version %d.%d %s Build %d",
204 versionInfo
.dwMajorVersion
, versionInfo
.dwMinorVersion
,
205 versionInfo
.szCSDVersion
, versionInfo
.dwBuildNumber
&0xFFFF);
207 len
= swprintf(buffer
,
208 L
"ReactOS %s (Build %d)",
209 versionInfo
.szCSDVersion
, versionInfo
.dwBuildNumber
&0xFFFF);
216 IntParseDesktopPath(PEPROCESS Process
,
217 PUNICODE_STRING DesktopPath
,
221 OBJECT_ATTRIBUTES ObjectAttributes
;
222 UNICODE_STRING WinSta
, Desktop
, FullName
;
223 BOOL DesktopPresent
= FALSE
;
224 BOOL WinStaPresent
= FALSE
;
236 RtlInitUnicodeString(&WinSta
, NULL
);
237 RtlInitUnicodeString(&Desktop
, NULL
);
239 if(DesktopPath
!= NULL
&& DesktopPath
->Buffer
!= NULL
&& DesktopPath
->Length
> sizeof(WCHAR
))
241 PWCHAR c
= DesktopPath
->Buffer
;
243 USHORT l
= DesktopPath
->Length
;
246 * Parse the desktop path string which can be in the form "WinSta\Desktop"
247 * or just "Desktop". In latter case WinSta0 will be used.
254 wl
= (ULONG_PTR
)c
- (ULONG_PTR
)DesktopPath
->Buffer
;
264 WinSta
.MaximumLength
= wl
+ sizeof(WCHAR
);
265 WinSta
.Buffer
= DesktopPath
->Buffer
;
267 WinStaPresent
= TRUE
;
271 Desktop
.Length
= DesktopPath
->Length
- wl
;
274 Desktop
.Length
-= sizeof(WCHAR
);
276 if(Desktop
.Length
> 0)
278 Desktop
.MaximumLength
= Desktop
.Length
+ sizeof(WCHAR
);
279 Desktop
.Buffer
= ((wl
> 0) ? c
: DesktopPath
->Buffer
);
280 DesktopPresent
= TRUE
;
287 /* search the process handle table for (inherited) window station
288 handles, use a more appropriate one than WinSta0 if possible. */
289 if (!ObFindHandleForObject(Process
,
291 ExWindowStationObjectType
,
296 /* we had no luck searching for opened handles, use WinSta0 now */
297 RtlInitUnicodeString(&WinSta
, L
"WinSta0");
301 if(!DesktopPresent
&& hDesktop
!= NULL
)
304 /* search the process handle table for (inherited) desktop
305 handles, use a more appropriate one than Default if possible. */
306 if (!ObFindHandleForObject(Process
,
313 /* we had no luck searching for opened handles, use Desktop now */
314 RtlInitUnicodeString(&Desktop
, L
"Default");
320 if(!IntGetFullWindowStationName(&FullName
, &WinSta
, NULL
))
322 return STATUS_INSUFFICIENT_RESOURCES
;
325 /* open the window station */
326 InitializeObjectAttributes(&ObjectAttributes
,
328 OBJ_CASE_INSENSITIVE
,
332 Status
= ObOpenObjectByName(&ObjectAttributes
,
333 ExWindowStationObjectType
,
340 ExFreePoolWithTag(FullName
.Buffer
, TAG_STRING
);
342 if(!NT_SUCCESS(Status
))
344 SetLastNtError(Status
);
345 DPRINT("Failed to reference window station %wZ PID: %d!\n", &WinSta
, PsGetCurrentProcessId());
350 if(hDesktop
!= NULL
&& *hDesktop
== NULL
)
352 if(!IntGetFullWindowStationName(&FullName
, &WinSta
, &Desktop
))
356 return STATUS_INSUFFICIENT_RESOURCES
;
359 /* open the desktop object */
360 InitializeObjectAttributes(&ObjectAttributes
,
362 OBJ_CASE_INSENSITIVE
,
366 Status
= ObOpenObjectByName(&ObjectAttributes
,
374 ExFreePoolWithTag(FullName
.Buffer
, TAG_STRING
);
376 if(!NT_SUCCESS(Status
))
381 SetLastNtError(Status
);
382 DPRINT("Failed to reference desktop %wZ PID: %d!\n", &Desktop
, PsGetCurrentProcessId());
387 return STATUS_SUCCESS
;
391 * IntValidateDesktopHandle
393 * Validates the desktop handle.
396 * If the function succeeds, the handle remains referenced. If the
397 * fucntion fails, last error is set.
401 IntValidateDesktopHandle(
403 KPROCESSOR_MODE AccessMode
,
404 ACCESS_MASK DesiredAccess
,
409 Status
= ObReferenceObjectByHandle(
417 if (!NT_SUCCESS(Status
))
418 SetLastNtError(Status
);
424 IntGetActiveDesktop(VOID
)
430 * returns or creates a handle to the desktop object
433 IntGetDesktopObjectHandle(PDESKTOP DesktopObject
)
438 ASSERT(DesktopObject
);
440 if (!ObFindHandleForObject(PsGetCurrentProcess(),
446 Status
= ObOpenObjectByPointer(DesktopObject
,
453 if(!NT_SUCCESS(Status
))
455 /* unable to create a handle */
456 DPRINT1("Unable to create a desktop handle\n");
462 DPRINT1("Got handle: %lx\n", Ret
);
468 PUSER_MESSAGE_QUEUE FASTCALL
469 IntGetFocusMessageQueue(VOID
)
471 PDESKTOP pdo
= IntGetActiveDesktop();
474 DPRINT("No active desktop\n");
477 return (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
481 IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue
)
483 PUSER_MESSAGE_QUEUE Old
;
484 PDESKTOP pdo
= IntGetActiveDesktop();
487 DPRINT("No active desktop\n");
492 if(NewQueue
->Desktop
!= NULL
)
494 DPRINT("Message Queue already attached to another desktop!\n");
497 IntReferenceMessageQueue(NewQueue
);
498 (void)InterlockedExchangePointer((PVOID
*)&NewQueue
->Desktop
, pdo
);
500 Old
= (PUSER_MESSAGE_QUEUE
)InterlockedExchangePointer((PVOID
*)&pdo
->ActiveMessageQueue
, NewQueue
);
503 (void)InterlockedExchangePointer((PVOID
*)&Old
->Desktop
, 0);
504 IntDereferenceMessageQueue(Old
);
508 HWND FASTCALL
IntGetDesktopWindow(VOID
)
510 PDESKTOP pdo
= IntGetActiveDesktop();
513 DPRINT("No active desktop\n");
516 return pdo
->DesktopWindow
;
519 PWND FASTCALL
UserGetDesktopWindow(VOID
)
521 PDESKTOP pdo
= IntGetActiveDesktop();
525 DPRINT("No active desktop\n");
529 return UserGetWindowObject(pdo
->DesktopWindow
);
532 HWND FASTCALL
IntGetMessageWindow(VOID
)
534 PDESKTOP pdo
= IntGetActiveDesktop();
538 DPRINT("No active desktop\n");
541 return pdo
->spwndMessage
->head
.h
;
544 HWND FASTCALL
IntGetCurrentThreadDesktopWindow(VOID
)
546 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
547 PDESKTOP pdo
= pti
->rpdesk
;
550 DPRINT1("Thread doesn't have a desktop\n");
553 return pdo
->DesktopWindow
;
556 BOOL FASTCALL
IntDesktopUpdatePerUserSettings(BOOL bEnable
)
560 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
563 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
565 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
566 QueryTable
[0].Name
= L
"PaintDesktopVersion";
567 QueryTable
[0].EntryContext
= &g_PaintDesktopVersion
;
569 /* Query the "PaintDesktopVersion" flag in the "Control Panel\Desktop" key */
570 Status
= RtlQueryRegistryValues(RTL_REGISTRY_USER
,
571 L
"Control Panel\\Desktop",
572 QueryTable
, NULL
, NULL
);
573 if (!NT_SUCCESS(Status
))
575 DPRINT1("RtlQueryRegistryValues failed for PaintDesktopVersion (%x)\n",
577 g_PaintDesktopVersion
= FALSE
;
581 DPRINT("PaintDesktopVersion = %d\n", g_PaintDesktopVersion
);
587 g_PaintDesktopVersion
= FALSE
;
592 /* PUBLIC FUNCTIONS ***********************************************************/
595 UserGetDesktopDC(ULONG DcType
, BOOL EmptyDC
, BOOL ValidatehWnd
)
597 PWND DesktopObject
= 0;
600 if (DcType
== DC_TYPE_DIRECT
)
602 DesktopObject
= UserGetDesktopWindow();
603 DesktopHDC
= (HDC
)UserGetWindowDC(DesktopObject
);
608 hDev
= (HDEV
)pPrimarySurface
;
609 DesktopHDC
= IntGdiCreateDisplayDC(hDev
, DcType
, EmptyDC
);
620 Window
= UserGetDesktopWindow();
622 IntInvalidateWindows( Window
,
632 co_IntShowDesktop(PDESKTOP Desktop
, ULONG Width
, ULONG Height
)
634 CSR_API_MESSAGE Request
;
636 Request
.Type
= MAKE_CSR_API(SHOW_DESKTOP
, CSR_GUI
);
637 Request
.Data
.ShowDesktopRequest
.DesktopWindow
= Desktop
->DesktopWindow
;
638 Request
.Data
.ShowDesktopRequest
.Width
= Width
;
639 Request
.Data
.ShowDesktopRequest
.Height
= Height
;
641 return co_CsrNotify(&Request
);
645 IntHideDesktop(PDESKTOP Desktop
)
648 CSRSS_API_REQUEST Request
;
649 CSRSS_API_REPLY Reply
;
651 Request
.Type
= CSRSS_HIDE_DESKTOP
;
652 Request
.Data
.HideDesktopRequest
.DesktopWindow
= Desktop
->DesktopWindow
;
654 return NotifyCsrss(&Request
, &Reply
);
659 DesktopWnd
= IntGetWindowObject(Desktop
->DesktopWindow
);
662 return ERROR_INVALID_WINDOW_HANDLE
;
664 DesktopWnd
->style
&= ~WS_VISIBLE
;
666 return STATUS_SUCCESS
;
675 UserBuildShellHookHwndList(PDESKTOP Desktop
)
678 PSHELL_HOOK_WINDOW Current
;
681 /* fixme: if we save nb elements in desktop, we dont have to loop to find nb entries */
682 LIST_FOR_EACH(Current
, &Desktop
->ShellHookWindows
, SHELL_HOOK_WINDOW
, ListEntry
)
685 if (!entries
) return NULL
;
687 list
= ExAllocatePoolWithTag(PagedPool
, sizeof(HWND
) * (entries
+ 1), USERTAG_WINDOWLIST
); /* alloc one extra for nullterm */
692 LIST_FOR_EACH(Current
, &Desktop
->ShellHookWindows
, SHELL_HOOK_WINDOW
, ListEntry
)
693 *cursor
++ = Current
->hWnd
;
695 *cursor
= NULL
; /* nullterm list */
702 * Send the Message to the windows registered for ShellHook
703 * notifications. The lParam contents depend on the Message. See
704 * MSDN for more details (RegisterShellHookWindow)
706 VOID
co_IntShellHookNotify(WPARAM Message
, LPARAM lParam
)
708 PDESKTOP Desktop
= IntGetActiveDesktop();
711 static UINT MsgType
= 0;
716 /* Too bad, this doesn't work.*/
719 RtlInitUnicodeString(&Str
, L
"SHELLHOOK");
720 MsgType
= UserRegisterWindowMessage(&Str
);
723 MsgType
= IntAddAtom(L
"SHELLHOOK");
725 DPRINT("MsgType = %x\n", MsgType
);
727 DPRINT1("LastError: %x\n", GetLastNtError());
732 DPRINT("IntShellHookNotify: No desktop!\n");
736 HwndList
= UserBuildShellHookHwndList(Desktop
);
739 HWND
* cursor
= HwndList
;
741 for (; *cursor
; cursor
++)
743 DPRINT("Sending notify\n");
744 co_IntPostOrSendMessage(*cursor
,
750 ExFreePool(HwndList
);
756 * Add the window to the ShellHookWindows list. The windows
757 * on that list get notifications that are important to shell
760 * TODO: Validate the window? I'm not sure if sending these messages to
761 * an unsuspecting application that is not your own is a nice thing to do.
763 BOOL
IntRegisterShellHookWindow(HWND hWnd
)
765 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
766 PDESKTOP Desktop
= pti
->rpdesk
;
767 PSHELL_HOOK_WINDOW Entry
;
769 DPRINT("IntRegisterShellHookWindow\n");
771 /* First deregister the window, so we can be sure it's never twice in the
774 IntDeRegisterShellHookWindow(hWnd
);
776 Entry
= ExAllocatePoolWithTag(PagedPool
,
777 sizeof(SHELL_HOOK_WINDOW
),
785 InsertTailList(&Desktop
->ShellHookWindows
, &Entry
->ListEntry
);
791 * Remove the window from the ShellHookWindows list. The windows
792 * on that list get notifications that are important to shell
795 BOOL
IntDeRegisterShellHookWindow(HWND hWnd
)
797 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
798 PDESKTOP Desktop
= pti
->rpdesk
;
799 PSHELL_HOOK_WINDOW Current
;
801 LIST_FOR_EACH(Current
, &Desktop
->ShellHookWindows
, SHELL_HOOK_WINDOW
, ListEntry
)
803 if (Current
->hWnd
== hWnd
)
805 RemoveEntryList(&Current
->ListEntry
);
815 IntFreeDesktopHeap(IN OUT PDESKTOP Desktop
)
817 if (Desktop
->hsectionDesktop
!= NULL
)
819 ObDereferenceObject(Desktop
->hsectionDesktop
);
820 Desktop
->hsectionDesktop
= NULL
;
823 /* SYSCALLS *******************************************************************/
826 * NtUserCreateDesktop
828 * Creates a new desktop.
835 * Name of the device.
844 * Requested type of access.
848 * If the function succeeds, the return value is a handle to the newly
849 * created desktop. If the specified desktop already exists, the function
850 * succeeds and returns a handle to the existing desktop. When you are
851 * finished using the handle, call the CloseDesktop function to close it.
852 * If the function fails, the return value is NULL.
860 POBJECT_ATTRIBUTES poa
,
861 PUNICODE_STRING lpszDesktopDevice
,
864 ACCESS_MASK dwDesiredAccess
)
866 OBJECT_ATTRIBUTES ObjectAttributes
;
867 PTHREADINFO W32Thread
;
868 PWINSTATION_OBJECT WinStaObject
;
869 PDESKTOP DesktopObject
;
870 UNICODE_STRING DesktopName
;
871 NTSTATUS Status
= STATUS_SUCCESS
;
873 CSR_API_MESSAGE Request
;
874 PVOID DesktopHeapSystemBase
= NULL
;
875 SIZE_T DesktopInfoSize
;
876 UNICODE_STRING SafeDesktopName
;
878 ULONG_PTR HeapSize
= 4 * 1024 * 1024; /* FIXME */
879 HWINSTA hWindowStation
= NULL
;
880 PUNICODE_STRING lpszDesktopName
= NULL
;
881 UNICODE_STRING ClassName
, MenuName
;
882 LARGE_STRING WindowName
;
883 BOOL NoHooks
= FALSE
;
887 PTHREADINFO ptiCurrent
;
888 DECLARE_RETURN(HDESK
);
890 DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName
);
891 UserEnterExclusive();
893 ptiCurrent
= PsGetCurrentThreadWin32Thread();
896 /* Turn off hooks when calling any CreateWindowEx from inside win32k. */
897 NoHooks
= (ptiCurrent
->TIF_flags
& TIF_DISABLEHOOKS
);
898 ptiCurrent
->TIF_flags
|= TIF_DISABLEHOOKS
;
904 sizeof(OBJECT_ATTRIBUTES
),
907 hWindowStation
= poa
->RootDirectory
;
908 lpszDesktopName
= poa
->ObjectName
;
910 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
912 Status
=_SEH2_GetExceptionCode();
916 if (! NT_SUCCESS(Status
))
918 DPRINT1("Failed reading Object Attributes from user space.\n");
919 SetLastNtError(Status
);
923 Status
= IntValidateWindowStationHandle(
926 0, /* FIXME - WINSTA_CREATEDESKTOP */
929 if (! NT_SUCCESS(Status
))
931 DPRINT1("Failed validation of window station handle (0x%X), cannot create desktop %wZ\n",
932 hWindowStation
, lpszDesktopName
);
933 SetLastNtError(Status
);
936 if(lpszDesktopName
!= NULL
)
938 Status
= IntSafeCopyUnicodeString(&SafeDesktopName
, lpszDesktopName
);
939 if(!NT_SUCCESS(Status
))
941 SetLastNtError(Status
);
947 RtlInitUnicodeString(&SafeDesktopName
, NULL
);
950 if (! IntGetFullWindowStationName(&DesktopName
, &WinStaObject
->Name
,
953 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
954 ObDereferenceObject(WinStaObject
);
956 ExFreePoolWithTag(SafeDesktopName
.Buffer
, TAG_STRING
);
960 ExFreePoolWithTag(SafeDesktopName
.Buffer
, TAG_STRING
);
961 ObDereferenceObject(WinStaObject
);
964 * Try to open already existing desktop
967 DPRINT("Trying to open desktop (%wZ)\n", &DesktopName
);
969 /* Initialize ObjectAttributes for the desktop object */
970 InitializeObjectAttributes(
977 Status
= ObOpenObjectByName(
983 (PVOID
)&DummyContext
,
985 if (!NT_SUCCESS(Status
)) RETURN(NULL
);
986 if (Status
== STATUS_OBJECT_NAME_EXISTS
)
988 ExFreePoolWithTag(DesktopName
.Buffer
, TAG_STRING
);
992 /* Reference the desktop */
993 Status
= ObReferenceObjectByHandle(Desktop
,
997 (PVOID
)&DesktopObject
,
999 if (!NT_SUCCESS(Status
)) RETURN(NULL
);
1001 DesktopObject
->hsectionDesktop
= NULL
;
1002 DesktopObject
->pheapDesktop
= UserCreateHeap(&DesktopObject
->hsectionDesktop
,
1003 &DesktopHeapSystemBase
,
1005 if (DesktopObject
->pheapDesktop
== NULL
)
1007 ObDereferenceObject(DesktopObject
);
1008 DPRINT1("Failed to create desktop heap!\n");
1012 DesktopInfoSize
= FIELD_OFFSET(DESKTOPINFO
,
1013 szDesktopName
[(lpszDesktopName
->Length
/ sizeof(WCHAR
)) + 1]);
1015 DesktopObject
->pDeskInfo
= RtlAllocateHeap(DesktopObject
->pheapDesktop
,
1019 if (DesktopObject
->pDeskInfo
== NULL
)
1021 ObDereferenceObject(DesktopObject
);
1022 DPRINT1("Failed to create the DESKTOP structure!\n");
1026 RtlZeroMemory(DesktopObject
->pDeskInfo
,
1029 DesktopObject
->pDeskInfo
->pvDesktopBase
= DesktopHeapSystemBase
;
1030 DesktopObject
->pDeskInfo
->pvDesktopLimit
= (PVOID
)((ULONG_PTR
)DesktopHeapSystemBase
+ HeapSize
);
1031 RtlCopyMemory(DesktopObject
->pDeskInfo
->szDesktopName
,
1032 lpszDesktopName
->Buffer
,
1033 lpszDesktopName
->Length
);
1035 /* Initialize some local (to win32k) desktop state. */
1036 InitializeListHead(&DesktopObject
->PtiList
);
1037 DesktopObject
->ActiveMessageQueue
= NULL
;
1038 /* Setup Global Hooks. */
1039 for (i
= 0; i
< NB_HOOKS
; i
++)
1041 InitializeListHead(&DesktopObject
->pDeskInfo
->aphkStart
[i
]);
1043 ExFreePoolWithTag(DesktopName
.Buffer
, TAG_STRING
);
1045 if (! NT_SUCCESS(Status
))
1047 DPRINT1("Failed to create desktop handle\n");
1048 SetLastNtError(Status
);
1053 * Create a handle for CSRSS and notify CSRSS for Creating Desktop Window.
1055 * Honestly, I believe this is a cleverly written hack that allowed ReactOS
1056 * to function at the beginning of the project by ramroding the GUI into
1057 * operation and making the desktop window work from user space.
1060 Request
.Type
= MAKE_CSR_API(CREATE_DESKTOP
, CSR_GUI
);
1061 Status
= CsrInsertObject(Desktop
,
1063 (HANDLE
*)&Request
.Data
.CreateDesktopRequest
.DesktopHandle
);
1064 if (! NT_SUCCESS(Status
))
1066 DPRINT1("Failed to create desktop handle for CSRSS\n");
1068 SetLastNtError(Status
);
1072 Status
= co_CsrNotify(&Request
);
1073 if (! NT_SUCCESS(Status
))
1075 CsrCloseHandle(Request
.Data
.CreateDesktopRequest
.DesktopHandle
);
1076 DPRINT1("Failed to notify CSRSS about new desktop\n");
1078 SetLastNtError(Status
);
1082 W32Thread
= PsGetCurrentThreadWin32Thread();
1084 if (!W32Thread
->rpdesk
) IntSetThreadDesktop(DesktopObject
,FALSE
);
1087 Based on wine/server/window.c in get_desktop_window.
1090 ClassName
.Buffer
= ((PWSTR
)((ULONG_PTR
)(WORD
)(gpsi
->atomSysClass
[ICLS_HWNDMESSAGE
])));
1091 ClassName
.Length
= 0;
1092 RtlZeroMemory(&MenuName
, sizeof(MenuName
));
1093 RtlZeroMemory(&WindowName
, sizeof(WindowName
));
1095 RtlZeroMemory(&Cs
, sizeof(Cs
));
1096 Cs
.cx
= Cs
.cy
= 100;
1097 Cs
.style
= WS_POPUP
|WS_CLIPCHILDREN
;
1098 Cs
.hInstance
= hModClient
;
1099 Cs
.lpszName
= (LPCWSTR
) &WindowName
;
1100 Cs
.lpszClass
= (LPCWSTR
) &ClassName
;
1102 pWnd
= co_UserCreateWindowEx(&Cs
, &ClassName
, &WindowName
);
1105 DPRINT1("Failed to create Message window handle\n");
1109 DesktopObject
->spwndMessage
= pWnd
;
1115 if (!NoHooks
&& ptiCurrent
) ptiCurrent
->TIF_flags
&= ~TIF_DISABLEHOOKS
;
1116 DPRINT("Leave NtUserCreateDesktop, ret=%i\n",_ret_
);
1124 * Opens an existing desktop.
1128 * Name of the existing desktop.
1131 * Interaction flags.
1134 * Requested type of access.
1137 * Handle to the desktop or zero on failure.
1145 PUNICODE_STRING lpszDesktopName
,
1147 ACCESS_MASK dwDesiredAccess
)
1149 OBJECT_ATTRIBUTES ObjectAttributes
;
1151 PWINSTATION_OBJECT WinStaObject
;
1152 UNICODE_STRING DesktopName
;
1153 UNICODE_STRING SafeDesktopName
;
1157 DECLARE_RETURN(HDESK
);
1159 DPRINT("Enter NtUserOpenDesktop: %wZ\n", lpszDesktopName
);
1160 UserEnterExclusive();
1163 * Validate the window station handle and compose the fully
1164 * qualified desktop name
1167 WinSta
= UserGetProcessWindowStation();
1168 Status
= IntValidateWindowStationHandle(
1174 if (!NT_SUCCESS(Status
))
1176 DPRINT1("Failed validation of window station handle (0x%X)\n", WinSta
);
1177 SetLastNtError(Status
);
1181 if(lpszDesktopName
!= NULL
)
1183 Status
= IntSafeCopyUnicodeString(&SafeDesktopName
, lpszDesktopName
);
1184 if(!NT_SUCCESS(Status
))
1186 SetLastNtError(Status
);
1192 RtlInitUnicodeString(&SafeDesktopName
, NULL
);
1195 Result
= IntGetFullWindowStationName(&DesktopName
, &WinStaObject
->Name
,
1198 if (lpszDesktopName
)
1199 ExFreePoolWithTag(SafeDesktopName
.Buffer
, TAG_STRING
);
1200 ObDereferenceObject(WinStaObject
);
1205 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
1210 DPRINT("Trying to open desktop (%wZ)\n", &DesktopName
);
1212 /* Initialize ObjectAttributes for the desktop object */
1213 InitializeObjectAttributes(
1220 Status
= ObOpenObjectByName(
1222 ExDesktopObjectType
,
1229 if (!NT_SUCCESS(Status
))
1231 SetLastNtError(Status
);
1232 ExFreePool(DesktopName
.Buffer
);
1236 DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName
);
1237 ExFreePool(DesktopName
.Buffer
);
1242 DPRINT("Leave NtUserOpenDesktop, ret=%i\n",_ret_
);
1248 * NtUserOpenInputDesktop
1250 * Opens the input (interactive) desktop.
1254 * Interaction flags.
1257 * Inheritance option.
1260 * Requested type of access.
1263 * Handle to the input desktop or zero on failure.
1270 NtUserOpenInputDesktop(
1273 ACCESS_MASK dwDesiredAccess
)
1278 DECLARE_RETURN(HDESK
);
1280 DPRINT("Enter NtUserOpenInputDesktop\n");
1281 UserEnterExclusive();
1283 DPRINT("About to open input desktop\n");
1285 /* Get a pointer to the desktop object */
1287 Status
= IntValidateDesktopHandle(
1293 if (!NT_SUCCESS(Status
))
1295 DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop
);
1299 /* Create a new handle to the object */
1301 Status
= ObOpenObjectByPointer(
1306 ExDesktopObjectType
,
1310 ObDereferenceObject(Object
);
1312 if (NT_SUCCESS(Status
))
1314 DPRINT("Successfully opened input desktop\n");
1315 RETURN((HDESK
)Desktop
);
1318 SetLastNtError(Status
);
1322 DPRINT("Leave NtUserOpenInputDesktop, ret=%i\n",_ret_
);
1328 * NtUserCloseDesktop
1330 * Closes a desktop handle.
1334 * Handle to the desktop.
1340 * The desktop handle can be created with NtUserCreateDesktop or
1341 * NtUserOpenDesktop. This function will fail if any thread in the calling
1342 * process is using the specified desktop handle or if the handle refers
1343 * to the initial desktop of the calling process.
1350 NtUserCloseDesktop(HDESK hDesktop
)
1354 DECLARE_RETURN(BOOL
);
1356 DPRINT("Enter NtUserCloseDesktop\n");
1357 UserEnterExclusive();
1359 DPRINT("About to close desktop handle (0x%X)\n", hDesktop
);
1361 Status
= IntValidateDesktopHandle(
1367 if (!NT_SUCCESS(Status
))
1369 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop
);
1373 ObDereferenceObject(Object
);
1375 DPRINT("Closing desktop handle (0x%X)\n", hDesktop
);
1377 Status
= ZwClose(hDesktop
);
1378 if (!NT_SUCCESS(Status
))
1380 SetLastNtError(Status
);
1387 DPRINT("Leave NtUserCloseDesktop, ret=%i\n",_ret_
);
1396 * NtUserPaintDesktop
1398 * The NtUserPaintDesktop function fills the clipping region in the
1399 * specified device context with the desktop pattern or wallpaper. The
1400 * function is provided primarily for shell desktops.
1404 * Handle to the device context.
1411 NtUserPaintDesktop(HDC hDC
)
1414 HBRUSH DesktopBrush
, PreviousBrush
;
1416 BOOL doPatBlt
= TRUE
;
1422 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1423 PWINSTATION_OBJECT WinSta
= pti
->rpdesk
->rpwinstaParent
;
1424 DECLARE_RETURN(BOOL
);
1426 UserEnterExclusive();
1427 DPRINT("Enter NtUserPaintDesktop\n");
1429 GdiGetClipBox(hDC
, &Rect
);
1431 hWndDesktop
= IntGetDesktopWindow();
1433 WndDesktop
= UserGetWindowObject(hWndDesktop
);
1439 DesktopBrush
= (HBRUSH
)WndDesktop
->pcls
->hbrBackground
;
1443 * Paint desktop background
1446 if (WinSta
->hbmWallpaper
!= NULL
)
1450 DeskWin
= UserGetWindowObject(hWndDesktop
);
1458 sz
.cx
= DeskWin
->rcWindow
.right
- DeskWin
->rcWindow
.left
;
1459 sz
.cy
= DeskWin
->rcWindow
.bottom
- DeskWin
->rcWindow
.top
;
1461 if (WinSta
->WallpaperMode
== wmStretch
||
1462 WinSta
->WallpaperMode
== wmTile
)
1469 /* Find the upper left corner, can be negtive if the bitmap is bigger then the screen */
1470 x
= (sz
.cx
/ 2) - (WinSta
->cxWallpaper
/ 2);
1471 y
= (sz
.cy
/ 2) - (WinSta
->cyWallpaper
/ 2);
1474 hWallpaperDC
= NtGdiCreateCompatibleDC(hDC
);
1475 if(hWallpaperDC
!= NULL
)
1479 /* fill in the area that the bitmap is not going to cover */
1482 /* FIXME - clip out the bitmap
1483 can be replaced with "NtGdiPatBlt(hDC, x, y, WinSta->cxWallpaper, WinSta->cyWallpaper, PATCOPY | DSTINVERT);"
1484 once we support DSTINVERT */
1485 PreviousBrush
= NtGdiSelectBrush(hDC
, DesktopBrush
);
1486 NtGdiPatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
, Rect
.bottom
, PATCOPY
);
1487 NtGdiSelectBrush(hDC
, PreviousBrush
);
1490 /*Do not fill the background after it is painted no matter the size of the picture */
1493 hOldBitmap
= NtGdiSelectBitmap(hWallpaperDC
, WinSta
->hbmWallpaper
);
1495 if (WinSta
->WallpaperMode
== wmStretch
)
1497 if(Rect
.right
&& Rect
.bottom
)
1498 NtGdiStretchBlt(hDC
,
1506 WinSta
->cxWallpaper
,
1507 WinSta
->cyWallpaper
,
1512 else if (WinSta
->WallpaperMode
== wmTile
)
1514 /* paint the bitmap across the screen then down */
1515 for(y
= 0; y
< Rect
.bottom
; y
+= WinSta
->cyWallpaper
)
1517 for(x
= 0; x
< Rect
.right
; x
+= WinSta
->cxWallpaper
)
1522 WinSta
->cxWallpaper
,
1523 WinSta
->cyWallpaper
,
1538 WinSta
->cxWallpaper
,
1539 WinSta
->cyWallpaper
,
1547 NtGdiSelectBitmap(hWallpaperDC
, hOldBitmap
);
1548 NtGdiDeleteObjectApp(hWallpaperDC
);
1553 /* Back ground is set to none, clear the screen */
1556 PreviousBrush
= NtGdiSelectBrush(hDC
, DesktopBrush
);
1557 NtGdiPatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
, Rect
.bottom
, PATCOPY
);
1558 NtGdiSelectBrush(hDC
, PreviousBrush
);
1562 * Display system version on the desktop background
1565 if (g_PaintDesktopVersion
)
1567 static WCHAR s_wszVersion
[256] = {0};
1572 len
= wcslen(s_wszVersion
);
1576 len
= GetSystemVersionString(s_wszVersion
);
1581 if (!UserSystemParametersInfo(SPI_GETWORKAREA
, 0, &rect
, 0))
1583 rect
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
1584 rect
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
1587 color_old
= IntGdiSetTextColor(hDC
, RGB(255,255,255));
1588 align_old
= IntGdiSetTextAlign(hDC
, TA_RIGHT
);
1589 mode_old
= IntGdiSetBkMode(hDC
, TRANSPARENT
);
1591 GreExtTextOutW(hDC
, rect
.right
-16, rect
.bottom
-48, 0, NULL
, s_wszVersion
, len
, NULL
, 0);
1593 IntGdiSetBkMode(hDC
, mode_old
);
1594 IntGdiSetTextAlign(hDC
, align_old
);
1595 IntGdiSetTextColor(hDC
, color_old
);
1602 DPRINT("Leave NtUserPaintDesktop, ret=%i\n",_ret_
);
1609 * NtUserSwitchDesktop
1611 * Sets the current input (interactive) desktop.
1615 * Handle to desktop.
1625 NtUserSwitchDesktop(HDESK hDesktop
)
1627 PDESKTOP DesktopObject
;
1629 DECLARE_RETURN(BOOL
);
1631 UserEnterExclusive();
1632 DPRINT("Enter NtUserSwitchDesktop\n");
1634 DPRINT("About to switch desktop (0x%X)\n", hDesktop
);
1636 Status
= IntValidateDesktopHandle(
1642 if (!NT_SUCCESS(Status
))
1644 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop
);
1649 * Don't allow applications switch the desktop if it's locked, unless the caller
1650 * is the logon application itself
1652 if((DesktopObject
->rpwinstaParent
->Flags
& WSS_LOCKED
) &&
1653 LogonProcess
!= NULL
&& LogonProcess
!= PsGetCurrentProcessWin32Process())
1655 ObDereferenceObject(DesktopObject
);
1656 DPRINT1("Switching desktop 0x%x denied because the work station is locked!\n", hDesktop
);
1660 if(DesktopObject
->rpwinstaParent
!= InputWindowStation
)
1662 ObDereferenceObject(DesktopObject
);
1663 DPRINT1("Switching desktop 0x%x denied because desktop doesn't belong to the interactive winsta!\n", hDesktop
);
1667 /* FIXME: Fail if the process is associated with a secured
1668 desktop such as Winlogon or Screen-Saver */
1669 /* FIXME: Connect to input device */
1671 /* Set the active desktop in the desktop's window station. */
1672 InputWindowStation
->ActiveDesktop
= DesktopObject
;
1674 /* Set the global state. */
1675 InputDesktop
= DesktopObject
;
1676 InputDesktopHandle
= hDesktop
;
1678 ObDereferenceObject(DesktopObject
);
1683 DPRINT("Leave NtUserSwitchDesktop, ret=%i\n",_ret_
);
1689 * NtUserResolveDesktopForWOW
1696 NtUserResolveDesktopForWOW(DWORD Unknown0
)
1703 * NtUserGetThreadDesktop
1710 NtUserGetThreadDesktop(DWORD dwThreadId
, DWORD Unknown1
)
1714 PDESKTOP DesktopObject
;
1715 HDESK Ret
, hThreadDesktop
;
1716 OBJECT_HANDLE_INFORMATION HandleInformation
;
1717 DECLARE_RETURN(HDESK
);
1719 UserEnterExclusive();
1720 DPRINT("Enter NtUserGetThreadDesktop\n");
1724 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1728 Status
= PsLookupThreadByThreadId((HANDLE
)(DWORD_PTR
)dwThreadId
, &Thread
);
1729 if(!NT_SUCCESS(Status
))
1731 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1735 if(Thread
->ThreadsProcess
== PsGetCurrentProcess())
1737 /* just return the handle, we queried the desktop handle of a thread running
1738 in the same context */
1739 Ret
= ((PTHREADINFO
)Thread
->Tcb
.Win32Thread
)->hdesk
;
1740 ObDereferenceObject(Thread
);
1744 /* get the desktop handle and the desktop of the thread */
1745 if(!(hThreadDesktop
= ((PTHREADINFO
)Thread
->Tcb
.Win32Thread
)->hdesk
) ||
1746 !(DesktopObject
= ((PTHREADINFO
)Thread
->Tcb
.Win32Thread
)->rpdesk
))
1748 ObDereferenceObject(Thread
);
1749 DPRINT1("Desktop information of thread 0x%x broken!?\n", dwThreadId
);
1753 /* we could just use DesktopObject instead of looking up the handle, but latter
1754 may be a bit safer (e.g. when the desktop is being destroyed */
1755 /* switch into the context of the thread we're trying to get the desktop from,
1756 so we can use the handle */
1757 KeAttachProcess(&Thread
->ThreadsProcess
->Pcb
);
1758 Status
= ObReferenceObjectByHandle(hThreadDesktop
,
1760 ExDesktopObjectType
,
1762 (PVOID
*)&DesktopObject
,
1763 &HandleInformation
);
1766 /* the handle couldn't be found, there's nothing to get... */
1767 if(!NT_SUCCESS(Status
))
1769 ObDereferenceObject(Thread
);
1773 /* lookup our handle table if we can find a handle to the desktop object,
1774 if not, create one */
1775 Ret
= IntGetDesktopObjectHandle(DesktopObject
);
1777 /* all done, we got a valid handle to the desktop */
1778 ObDereferenceObject(DesktopObject
);
1779 ObDereferenceObject(Thread
);
1783 DPRINT("Leave NtUserGetThreadDesktop, ret=%i\n",_ret_
);
1789 IntUnmapDesktopView(IN PDESKTOP DesktopObject
)
1792 PPROCESSINFO CurrentWin32Process
;
1793 PW32HEAP_USER_MAPPING HeapMapping
, *PrevLink
;
1794 NTSTATUS Status
= STATUS_SUCCESS
;
1798 CurrentWin32Process
= PsGetCurrentProcessWin32Process();
1799 PrevLink
= &CurrentWin32Process
->HeapMappings
.Next
;
1801 /* unmap if we're the last thread using the desktop */
1802 HeapMapping
= *PrevLink
;
1803 while (HeapMapping
!= NULL
)
1805 if (HeapMapping
->KernelMapping
== (PVOID
)DesktopObject
->pheapDesktop
)
1807 if (--HeapMapping
->Count
== 0)
1809 *PrevLink
= HeapMapping
->Next
;
1811 Status
= MmUnmapViewOfSection(PsGetCurrentProcess(),
1812 HeapMapping
->UserMapping
);
1814 ObDereferenceObject(DesktopObject
);
1816 UserHeapFree(HeapMapping
);
1821 PrevLink
= &HeapMapping
->Next
;
1822 HeapMapping
= HeapMapping
->Next
;
1825 ti
= GetW32ThreadInfo();
1828 GetWin32ClientInfo()->pDeskInfo
= NULL
;
1830 GetWin32ClientInfo()->ulClientDelta
= 0;
1836 IntMapDesktopView(IN PDESKTOP DesktopObject
)
1839 PPROCESSINFO CurrentWin32Process
;
1840 PW32HEAP_USER_MAPPING HeapMapping
, *PrevLink
;
1841 PVOID UserBase
= NULL
;
1842 SIZE_T ViewSize
= 0;
1843 LARGE_INTEGER Offset
;
1846 CurrentWin32Process
= PsGetCurrentProcessWin32Process();
1847 PrevLink
= &CurrentWin32Process
->HeapMappings
.Next
;
1849 /* find out if another thread already mapped the desktop heap */
1850 HeapMapping
= *PrevLink
;
1851 while (HeapMapping
!= NULL
)
1853 if (HeapMapping
->KernelMapping
== (PVOID
)DesktopObject
->pheapDesktop
)
1855 HeapMapping
->Count
++;
1856 return STATUS_SUCCESS
;
1859 PrevLink
= &HeapMapping
->Next
;
1860 HeapMapping
= HeapMapping
->Next
;
1863 /* we're the first, map the heap */
1864 DPRINT("Noone mapped the desktop heap %p yet, so - map it!\n", DesktopObject
->pheapDesktop
);
1865 Offset
.QuadPart
= 0;
1866 Status
= MmMapViewOfSection(DesktopObject
->hsectionDesktop
,
1867 PsGetCurrentProcess(),
1875 PAGE_EXECUTE_READ
); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
1876 if (!NT_SUCCESS(Status
))
1878 DPRINT1("Failed to map desktop\n");
1882 /* add the mapping */
1883 HeapMapping
= UserHeapAlloc(sizeof(W32HEAP_USER_MAPPING
));
1884 if (HeapMapping
== NULL
)
1886 MmUnmapViewOfSection(PsGetCurrentProcess(),
1888 DPRINT1("UserHeapAlloc() failed!\n");
1889 return STATUS_NO_MEMORY
;
1892 HeapMapping
->Next
= NULL
;
1893 HeapMapping
->KernelMapping
= (PVOID
)DesktopObject
->pheapDesktop
;
1894 HeapMapping
->UserMapping
= UserBase
;
1895 HeapMapping
->Limit
= ViewSize
;
1896 HeapMapping
->Count
= 1;
1897 *PrevLink
= HeapMapping
;
1899 ObReferenceObject(DesktopObject
);
1901 /* create a W32THREADINFO structure if not already done, or update it */
1902 ti
= GetW32ThreadInfo();
1903 GetWin32ClientInfo()->ulClientDelta
= DesktopHeapGetUserDelta();
1906 if (GetWin32ClientInfo()->pDeskInfo
== NULL
)
1908 GetWin32ClientInfo()->pDeskInfo
=
1909 (PVOID
)((ULONG_PTR
)DesktopObject
->pDeskInfo
-
1910 GetWin32ClientInfo()->ulClientDelta
);
1914 return STATUS_SUCCESS
;
1918 IntSetThreadDesktop(IN PDESKTOP DesktopObject
,
1919 IN BOOL FreeOnFailure
)
1921 PDESKTOP OldDesktop
;
1922 PTHREADINFO W32Thread
;
1926 DPRINT("IntSetThreadDesktop() DO=%p, FOF=%d\n", DesktopObject
, FreeOnFailure
);
1927 MapHeap
= (PsGetCurrentProcess() != PsInitialSystemProcess
);
1928 W32Thread
= PsGetCurrentThreadWin32Thread();
1930 if (W32Thread
->rpdesk
!= DesktopObject
)
1932 OldDesktop
= W32Thread
->rpdesk
;
1934 if (!IsListEmpty(&W32Thread
->WindowListHead
))
1936 DPRINT1("Attempted to change thread desktop although the thread has windows!\n");
1937 SetLastWin32Error(ERROR_BUSY
);
1941 W32Thread
->rpdesk
= DesktopObject
;
1943 if (MapHeap
&& DesktopObject
!= NULL
)
1945 Status
= IntMapDesktopView(DesktopObject
);
1946 if (!NT_SUCCESS(Status
))
1948 SetLastNtError(Status
);
1953 /* Hack for system threads */
1956 PCLIENTINFO pci
= GetWin32ClientInfo();
1957 pci
->ulClientDelta
= DesktopHeapGetUserDelta();
1960 pci
->pDeskInfo
= (PVOID
)((ULONG_PTR
)DesktopObject
->pDeskInfo
- pci
->ulClientDelta
);
1964 if (OldDesktop
!= NULL
&&
1965 !IntCheckProcessDesktopClasses(OldDesktop
,
1968 DPRINT1("Failed to move process classes to shared heap!\n");
1970 /* failed to move desktop classes to the shared heap,
1971 unmap the view and return the error */
1972 if (MapHeap
&& DesktopObject
!= NULL
)
1973 IntUnmapDesktopView(DesktopObject
);
1978 /* Remove the thread from the old desktop's list */
1979 RemoveEntryList(&W32Thread
->PtiLink
);
1981 if (DesktopObject
!= NULL
)
1983 ObReferenceObject(DesktopObject
);
1984 /* Insert into new desktop's list */
1985 InsertTailList(&DesktopObject
->PtiList
, &W32Thread
->PtiLink
);
1988 if (OldDesktop
!= NULL
)
1992 IntUnmapDesktopView(OldDesktop
);
1995 ObDereferenceObject(OldDesktop
);
2003 * NtUserSetThreadDesktop
2010 NtUserSetThreadDesktop(HDESK hDesktop
)
2012 PDESKTOP DesktopObject
;
2014 DECLARE_RETURN(BOOL
);
2016 UserEnterExclusive();
2017 DPRINT("Enter NtUserSetThreadDesktop\n");
2019 /* Validate the new desktop. */
2020 Status
= IntValidateDesktopHandle(
2026 if (!NT_SUCCESS(Status
))
2028 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop
);
2032 /* FIXME: Should check here to see if the thread has any windows. */
2034 if (!IntSetThreadDesktop(DesktopObject
,
2043 DPRINT("Leave NtUserSetThreadDesktop, ret=%i\n",_ret_
);