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/desktop.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
27 * 06-06-2001 CSH Created
30 /* INCLUDES ******************************************************************/
34 /* not yet defined in w32api... */
36 ObFindHandleForObject(IN PEPROCESS Process
,
38 IN POBJECT_TYPE ObjectType
,
39 IN POBJECT_HANDLE_INFORMATION HandleInformation
,
42 #define ObFindHandleForObject(Process, Object, ObjectType, HandleInformation, Handle) \
46 /* GLOBALS *******************************************************************/
48 /* Currently active desktop */
49 PDESKTOP_OBJECT InputDesktop
= NULL
;
50 HDESK InputDesktopHandle
= NULL
;
51 HDC ScreenDeviceContext
= NULL
;
53 BOOL g_PaintDesktopVersion
= FALSE
;
55 /* INITALIZATION FUNCTIONS ****************************************************/
60 return STATUS_SUCCESS
;
64 CleanupDesktopImpl(VOID
)
66 return STATUS_SUCCESS
;
69 /* PRIVATE FUNCTIONS **********************************************************/
72 IntParseDesktopPath(PEPROCESS Process
,
73 PUNICODE_STRING DesktopPath
,
77 OBJECT_ATTRIBUTES ObjectAttributes
;
78 UNICODE_STRING WinSta
, Desktop
, FullName
;
79 BOOL DesktopPresent
= FALSE
;
80 BOOL WinStaPresent
= FALSE
;
92 RtlInitUnicodeString(&WinSta
, NULL
);
93 RtlInitUnicodeString(&Desktop
, NULL
);
95 if(DesktopPath
!= NULL
&& DesktopPath
->Buffer
!= NULL
&& DesktopPath
->Length
> sizeof(WCHAR
))
97 PWCHAR c
= DesktopPath
->Buffer
;
99 USHORT l
= DesktopPath
->Length
;
102 * Parse the desktop path string which can be in the form "WinSta\Desktop"
103 * or just "Desktop". In latter case WinSta0 will be used.
110 wl
= (ULONG_PTR
)c
- (ULONG_PTR
)DesktopPath
->Buffer
;
120 WinSta
.MaximumLength
= wl
+ sizeof(WCHAR
);
121 WinSta
.Buffer
= DesktopPath
->Buffer
;
123 WinStaPresent
= TRUE
;
127 Desktop
.Length
= DesktopPath
->Length
- wl
;
130 Desktop
.Length
-= sizeof(WCHAR
);
132 if(Desktop
.Length
> 0)
134 Desktop
.MaximumLength
= Desktop
.Length
+ sizeof(WCHAR
);
135 Desktop
.Buffer
= ((wl
> 0) ? c
: DesktopPath
->Buffer
);
136 DesktopPresent
= TRUE
;
142 /* search the process handle table for (inherited) window station
143 handles, use a more appropriate one than WinSta0 if possible. */
144 Status
= ObFindHandleForObject(Process
,
146 ExWindowStationObjectType
,
149 if(!NT_SUCCESS(Status
))
151 /* we had no luck searching for opened handles, use WinSta0 now */
152 RtlInitUnicodeString(&WinSta
, L
"WinSta0");
156 if(!DesktopPresent
&& hDesktop
!= NULL
)
158 /* search the process handle table for (inherited) desktop
159 handles, use a more appropriate one than Default if possible. */
160 Status
= ObFindHandleForObject(Process
,
165 if(!NT_SUCCESS(Status
))
167 /* we had no luck searching for opened handles, use Desktop now */
168 RtlInitUnicodeString(&Desktop
, L
"Default");
174 if(!IntGetFullWindowStationName(&FullName
, &WinSta
, NULL
))
176 return STATUS_INSUFFICIENT_RESOURCES
;
179 /* open the window station */
180 InitializeObjectAttributes(&ObjectAttributes
,
182 OBJ_CASE_INSENSITIVE
,
186 Status
= ObOpenObjectByName(&ObjectAttributes
,
187 ExWindowStationObjectType
,
194 RtlFreeUnicodeString(&FullName
);
196 if(!NT_SUCCESS(Status
))
198 SetLastNtError(Status
);
199 DPRINT("Failed to reference window station %wZ PID: %d!\n", &WinSta
, PsGetCurrentProcessId());
204 if(hDesktop
!= NULL
&& *hDesktop
== NULL
)
206 if(!IntGetFullWindowStationName(&FullName
, &WinSta
, &Desktop
))
210 return STATUS_INSUFFICIENT_RESOURCES
;
213 /* open the desktop object */
214 InitializeObjectAttributes(&ObjectAttributes
,
216 OBJ_CASE_INSENSITIVE
,
220 Status
= ObOpenObjectByName(&ObjectAttributes
,
228 RtlFreeUnicodeString(&FullName
);
230 if(!NT_SUCCESS(Status
))
235 SetLastNtError(Status
);
236 DPRINT("Failed to reference desktop %wZ PID: %d!\n", &Desktop
, PsGetCurrentProcessId());
241 return STATUS_SUCCESS
;
245 * IntValidateDesktopHandle
247 * Validates the desktop handle.
250 * If the function succeeds, the handle remains referenced. If the
251 * fucntion fails, last error is set.
255 IntValidateDesktopHandle(
257 KPROCESSOR_MODE AccessMode
,
258 ACCESS_MASK DesiredAccess
,
259 PDESKTOP_OBJECT
*Object
)
263 Status
= ObReferenceObjectByHandle(
271 if (!NT_SUCCESS(Status
))
272 SetLastNtError(Status
);
278 IntGetDesktopWorkArea(PDESKTOP_OBJECT Desktop
, PRECT Rect
)
284 Ret
= &Desktop
->WorkArea
;
285 if((Ret
->right
== -1) && ScreenDeviceContext
)
288 BITMAPOBJ
*BitmapObj
;
289 dc
= DC_LockDc(ScreenDeviceContext
);
290 /* FIXME - Handle dc == NULL!!!! */
291 BitmapObj
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
294 Ret
->right
= BitmapObj
->SurfObj
.sizlBitmap
.cx
;
295 Ret
->bottom
= BitmapObj
->SurfObj
.sizlBitmap
.cy
;
296 BITMAPOBJ_UnlockBitmap(dc
->w
.hBitmap
);
298 DC_UnlockDc(ScreenDeviceContext
);
307 PDESKTOP_OBJECT FASTCALL
308 IntGetActiveDesktop(VOID
)
314 * returns or creates a handle to the desktop object
317 IntGetDesktopObjectHandle(PDESKTOP_OBJECT DesktopObject
)
322 ASSERT(DesktopObject
);
324 Status
= ObFindHandleForObject(PsGetCurrentProcess(),
330 if(!NT_SUCCESS(Status
))
332 Status
= ObOpenObjectByPointer(DesktopObject
,
339 if(!NT_SUCCESS(Status
))
341 /* unable to create a handle */
342 DPRINT1("Unable to create a desktop handle\n");
350 PUSER_MESSAGE_QUEUE FASTCALL
351 IntGetFocusMessageQueue(VOID
)
353 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
356 DPRINT("No active desktop\n");
359 return (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
363 IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue
)
365 PUSER_MESSAGE_QUEUE Old
;
366 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
369 DPRINT("No active desktop\n");
374 if(NewQueue
->Desktop
!= NULL
)
376 DPRINT("Message Queue already attached to another desktop!\n");
379 IntReferenceMessageQueue(NewQueue
);
380 InterlockedExchange((LONG
*)&NewQueue
->Desktop
, (LONG
)pdo
);
382 Old
= (PUSER_MESSAGE_QUEUE
)InterlockedExchange((LONG
*)&pdo
->ActiveMessageQueue
, (LONG
)NewQueue
);
385 InterlockedExchange((LONG
*)&Old
->Desktop
, 0);
386 IntDereferenceMessageQueue(Old
);
390 HWND FASTCALL
IntGetDesktopWindow(VOID
)
392 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
395 DPRINT("No active desktop\n");
398 return pdo
->DesktopWindow
;
401 HWND FASTCALL
IntGetCurrentThreadDesktopWindow(VOID
)
403 PDESKTOP_OBJECT pdo
= PsGetWin32Thread()->Desktop
;
406 DPRINT1("Thread doesn't have a desktop\n");
409 return pdo
->DesktopWindow
;
412 BOOL FASTCALL
IntDesktopUpdatePerUserSettings(BOOL bEnable
)
416 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
419 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
421 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
422 QueryTable
[0].Name
= L
"PaintDesktopVersion";
423 QueryTable
[0].EntryContext
= &g_PaintDesktopVersion
;
425 /* Query the "PaintDesktopVersion" flag in the "Control Panel\Desktop" key */
426 Status
= RtlQueryRegistryValues(RTL_REGISTRY_USER
,
427 L
"Control Panel\\Desktop",
428 QueryTable
, NULL
, NULL
);
429 if (!NT_SUCCESS(Status
))
431 DPRINT1("RtlQueryRegistryValues failed for PaintDesktopVersion (%x)\n",
433 g_PaintDesktopVersion
= FALSE
;
437 DPRINT("PaintDesktopVersion = %d\n", g_PaintDesktopVersion
);
443 g_PaintDesktopVersion
= FALSE
;
448 /* PUBLIC FUNCTIONS ***********************************************************/
451 IntShowDesktop(PDESKTOP_OBJECT Desktop
, ULONG Width
, ULONG Height
)
453 CSRSS_API_REQUEST Request
;
454 CSRSS_API_REPLY Reply
;
456 Request
.Type
= CSRSS_SHOW_DESKTOP
;
457 Request
.Data
.ShowDesktopRequest
.DesktopWindow
= Desktop
->DesktopWindow
;
458 Request
.Data
.ShowDesktopRequest
.Width
= Width
;
459 Request
.Data
.ShowDesktopRequest
.Height
= Height
;
461 return CsrNotify(&Request
, &Reply
);
465 IntHideDesktop(PDESKTOP_OBJECT Desktop
)
468 CSRSS_API_REQUEST Request
;
469 CSRSS_API_REPLY Reply
;
471 Request
.Type
= CSRSS_HIDE_DESKTOP
;
472 Request
.Data
.HideDesktopRequest
.DesktopWindow
= Desktop
->DesktopWindow
;
474 return NotifyCsrss(&Request
, &Reply
);
476 PWINDOW_OBJECT DesktopWindow
;
478 DesktopWindow
= IntGetWindowObject(Desktop
->DesktopWindow
);
481 return ERROR_INVALID_WINDOW_HANDLE
;
483 DesktopWindow
->Style
&= ~WS_VISIBLE
;
485 return STATUS_SUCCESS
;
490 * NtUserCreateDesktop
492 * Creates a new desktop.
496 * Name of the new desktop.
502 * Requested type of access.
505 * Security descriptor.
508 * Handle to window station on which to create the desktop.
511 * If the function succeeds, the return value is a handle to the newly
512 * created desktop. If the specified desktop already exists, the function
513 * succeeds and returns a handle to the existing desktop. When you are
514 * finished using the handle, call the CloseDesktop function to close it.
515 * If the function fails, the return value is NULL.
523 PUNICODE_STRING lpszDesktopName
,
525 ACCESS_MASK dwDesiredAccess
,
526 LPSECURITY_ATTRIBUTES lpSecurity
,
527 HWINSTA hWindowStation
)
529 OBJECT_ATTRIBUTES ObjectAttributes
;
530 PWINSTATION_OBJECT WinStaObject
;
531 PDESKTOP_OBJECT DesktopObject
;
532 UNICODE_STRING DesktopName
;
535 CSRSS_API_REQUEST Request
;
536 CSRSS_API_REPLY Reply
;
538 DPRINT("CreateDesktop: %wZ\n", lpszDesktopName
);
540 Status
= IntValidateWindowStationHandle(
543 0, /* FIXME - WINSTA_CREATEDESKTOP */
546 if (! NT_SUCCESS(Status
))
548 DPRINT1("Failed validation of window station handle (0x%X), cannot create desktop %wZ\n",
549 hWindowStation
, lpszDesktopName
);
550 SetLastNtError(Status
);
554 if (! IntGetFullWindowStationName(&DesktopName
, &WinStaObject
->Name
,
557 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
558 ObDereferenceObject(WinStaObject
);
562 ObDereferenceObject(WinStaObject
);
565 * Try to open already existing desktop
568 DPRINT("Trying to open desktop (%wZ)\n", &DesktopName
);
570 /* Initialize ObjectAttributes for the desktop object */
571 InitializeObjectAttributes(
578 Status
= ObOpenObjectByName(
587 if (NT_SUCCESS(Status
))
589 DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName
);
590 ExFreePool(DesktopName
.Buffer
);
595 * No existing desktop found, try to create new one
598 Status
= ObCreateObject(
604 sizeof(DESKTOP_OBJECT
),
607 (PVOID
*)&DesktopObject
);
609 if (! NT_SUCCESS(Status
))
611 DPRINT1("Failed creating desktop (%wZ)\n", &DesktopName
);
612 ExFreePool(DesktopName
.Buffer
);
613 SetLastNtError(STATUS_UNSUCCESSFUL
);
618 DesktopObject
->WorkArea
.left
= 0;
619 DesktopObject
->WorkArea
.top
= 0;
620 DesktopObject
->WorkArea
.right
= -1;
621 DesktopObject
->WorkArea
.bottom
= -1;
622 IntGetDesktopWorkArea(DesktopObject
, NULL
);
624 /* Initialize some local (to win32k) desktop state. */
625 DesktopObject
->ActiveMessageQueue
= NULL
;
627 Status
= ObInsertObject(
628 (PVOID
)DesktopObject
,
630 STANDARD_RIGHTS_REQUIRED
,
635 ObDereferenceObject(DesktopObject
);
636 ExFreePool(DesktopName
.Buffer
);
638 if (! NT_SUCCESS(Status
))
640 DPRINT1("Failed to create desktop handle\n");
641 SetLastNtError(Status
);
646 * Create a handle for CSRSS and notify CSRSS
648 Request
.Type
= CSRSS_CREATE_DESKTOP
;
649 Status
= CsrInsertObject((PVOID
)DesktopObject
,
654 (HANDLE
*)&Request
.Data
.CreateDesktopRequest
.DesktopHandle
);
655 if (! NT_SUCCESS(Status
))
657 DPRINT1("Failed to create desktop handle for CSRSS\n");
659 SetLastNtError(Status
);
663 Status
= CsrNotify(&Request
, &Reply
);
664 if (! NT_SUCCESS(Status
))
666 CsrCloseHandle(Request
.Data
.CreateDesktopRequest
.DesktopHandle
);
667 DPRINT1("Failed to notify CSRSS about new desktop\n");
669 SetLastNtError(Status
);
679 * Opens an existing desktop.
683 * Name of the existing desktop.
689 * Requested type of access.
692 * Handle to the desktop or zero on failure.
700 PUNICODE_STRING lpszDesktopName
,
702 ACCESS_MASK dwDesiredAccess
)
704 OBJECT_ATTRIBUTES ObjectAttributes
;
705 PWINSTATION_OBJECT WinStaObject
;
706 UNICODE_STRING DesktopName
;
711 * Validate the window station handle and compose the fully
712 * qualified desktop name
715 Status
= IntValidateWindowStationHandle(
716 PsGetCurrentProcess()->Win32WindowStation
,
721 if (!NT_SUCCESS(Status
))
723 DPRINT1("Failed validation of window station handle (0x%X)\n",
724 PsGetCurrentProcess()->Win32WindowStation
);
725 SetLastNtError(Status
);
729 if (!IntGetFullWindowStationName(&DesktopName
, &WinStaObject
->Name
,
732 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
733 ObDereferenceObject(WinStaObject
);
737 ObDereferenceObject(WinStaObject
);
739 DPRINT1("Trying to open desktop (%wZ)\n", &DesktopName
);
741 /* Initialize ObjectAttributes for the desktop object */
742 InitializeObjectAttributes(
749 Status
= ObOpenObjectByName(
758 if (!NT_SUCCESS(Status
))
760 SetLastNtError(Status
);
761 ExFreePool(DesktopName
.Buffer
);
765 DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName
);
766 ExFreePool(DesktopName
.Buffer
);
772 * NtUserOpenInputDesktop
774 * Opens the input (interactive) desktop.
781 * Inheritance option.
784 * Requested type of access.
787 * Handle to the input desktop or zero on failure.
794 NtUserOpenInputDesktop(
797 ACCESS_MASK dwDesiredAccess
)
799 PDESKTOP_OBJECT Object
;
803 DPRINT("About to open input desktop\n");
805 /* Get a pointer to the desktop object */
807 Status
= IntValidateDesktopHandle(
813 if (!NT_SUCCESS(Status
))
815 DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop
);
819 /* Create a new handle to the object */
821 Status
= ObOpenObjectByPointer(
830 ObDereferenceObject(Object
);
832 if (NT_SUCCESS(Status
))
834 DPRINT("Successfully opened input desktop\n");
835 return (HDESK
)Desktop
;
838 SetLastNtError(Status
);
845 * Closes a desktop handle.
849 * Handle to the desktop.
855 * The desktop handle can be created with NtUserCreateDesktop or
856 * NtUserOpenDesktop. This function will fail if any thread in the calling
857 * process is using the specified desktop handle or if the handle refers
858 * to the initial desktop of the calling process.
865 NtUserCloseDesktop(HDESK hDesktop
)
867 PDESKTOP_OBJECT Object
;
870 DPRINT("About to close desktop handle (0x%X)\n", hDesktop
);
872 Status
= IntValidateDesktopHandle(
878 if (!NT_SUCCESS(Status
))
880 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop
);
884 ObDereferenceObject(Object
);
886 DPRINT("Closing desktop handle (0x%X)\n", hDesktop
);
888 Status
= ZwClose(hDesktop
);
889 if (!NT_SUCCESS(Status
))
891 SetLastNtError(Status
);
899 static int GetSystemVersionString(LPWSTR buffer
)
901 RTL_OSVERSIONINFOEXW versionInfo
;
904 versionInfo
.dwOSVersionInfoSize
= sizeof(RTL_OSVERSIONINFOEXW
);
906 if (!NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW
)&versionInfo
)))
909 if (versionInfo
.dwMajorVersion
<= 4)
910 len
= swprintf(buffer
,
911 L
"ReactOS Version %d.%d %s Build %d",
912 versionInfo
.dwMajorVersion
, versionInfo
.dwMinorVersion
,
913 versionInfo
.szCSDVersion
, versionInfo
.dwBuildNumber
&0xFFFF);
915 len
= swprintf(buffer
,
916 L
"ReactOS %s (Build %d)",
917 versionInfo
.szCSDVersion
, versionInfo
.dwBuildNumber
&0xFFFF);
925 * The NtUserPaintDesktop function fills the clipping region in the
926 * specified device context with the desktop pattern or wallpaper. The
927 * function is provided primarily for shell desktops.
931 * Handle to the device context.
938 NtUserPaintDesktop(HDC hDC
)
941 HBRUSH DesktopBrush
, PreviousBrush
;
943 BOOL doPatBlt
= TRUE
;
946 PWINSTATION_OBJECT WinSta
= PsGetWin32Thread()->Desktop
->WindowStation
;
948 IntGdiGetClipBox(hDC
, &Rect
);
950 hWndDesktop
= IntGetDesktopWindow();
951 DesktopBrush
= (HBRUSH
)NtUserGetClassLong(hWndDesktop
, GCL_HBRBACKGROUND
, FALSE
);
954 * Paint desktop background
957 if(WinSta
->hbmWallpaper
!= NULL
)
959 PWINDOW_OBJECT DeskWin
;
961 if((DeskWin
= IntGetWindowObject(hWndDesktop
)))
967 sz
.cx
= DeskWin
->WindowRect
.right
- DeskWin
->WindowRect
.left
;
968 sz
.cy
= DeskWin
->WindowRect
.bottom
- DeskWin
->WindowRect
.top
;
969 IntReleaseWindowObject(DeskWin
);
971 x
= (sz
.cx
/ 2) - (WinSta
->cxWallpaper
/ 2);
972 y
= (sz
.cy
/ 2) - (WinSta
->cyWallpaper
/ 2);
974 hWallpaperDC
= NtGdiCreateCompatableDC(hDC
);
975 if(hWallpaperDC
!= NULL
)
981 /* FIXME - clip out the bitmap */
982 PreviousBrush
= NtGdiSelectObject(hDC
, DesktopBrush
);
983 NtGdiPatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
, Rect
.bottom
, PATCOPY
);
984 NtGdiSelectObject(hDC
, PreviousBrush
);
989 hOldBitmap
= NtGdiSelectObject(hWallpaperDC
, WinSta
->hbmWallpaper
);
990 NtGdiBitBlt(hDC
, x
, y
, WinSta
->cxWallpaper
, WinSta
->cyWallpaper
, hWallpaperDC
, 0, 0, SRCCOPY
);
991 NtGdiSelectObject(hWallpaperDC
, hOldBitmap
);
993 NtGdiDeleteDC(hWallpaperDC
);
999 PreviousBrush
= NtGdiSelectObject(hDC
, DesktopBrush
);
1000 NtGdiPatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
, Rect
.bottom
, PATCOPY
);
1001 NtGdiSelectObject(hDC
, PreviousBrush
);
1005 * Display system version on the desktop background
1008 if (g_PaintDesktopVersion
) {
1009 static WCHAR s_wszVersion
[256] = {0};
1013 len
= wcslen(s_wszVersion
);
1015 len
= GetSystemVersionString(s_wszVersion
);
1018 if (!NtUserSystemParametersInfo(SPI_GETWORKAREA
, 0, &rect
, 0)) {
1019 rect
.right
= NtUserGetSystemMetrics(SM_CXSCREEN
);
1020 rect
.bottom
= NtUserGetSystemMetrics(SM_CYSCREEN
);
1023 COLORREF color_old
= NtGdiSetTextColor(hDC
, RGB(255,255,255));
1024 UINT align_old
= NtGdiSetTextAlign(hDC
, TA_RIGHT
);
1025 int mode_old
= NtGdiSetBkMode(hDC
, TRANSPARENT
);
1027 NtGdiTextOut(hDC
, rect
.right
-16, rect
.bottom
-48, s_wszVersion
, len
);
1029 NtGdiSetBkMode(hDC
, mode_old
);
1030 NtGdiSetTextAlign(hDC
, align_old
);
1031 NtGdiSetTextColor(hDC
, color_old
);
1040 * NtUserSwitchDesktop
1042 * Sets the current input (interactive) desktop.
1046 * Handle to desktop.
1056 NtUserSwitchDesktop(HDESK hDesktop
)
1058 PDESKTOP_OBJECT DesktopObject
;
1061 DPRINT("About to switch desktop (0x%X)\n", hDesktop
);
1063 Status
= IntValidateDesktopHandle(
1069 if (!NT_SUCCESS(Status
))
1071 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop
);
1076 * Don't allow applications switch the desktop if it's locked, unless the caller
1077 * is the logon application itself
1079 if((DesktopObject
->WindowStation
->Flags
& WSS_LOCKED
) &&
1080 LogonProcess
!= NULL
&& LogonProcess
!= PsGetWin32Process())
1082 ObDereferenceObject(DesktopObject
);
1083 DPRINT1("Switching desktop 0x%x denied because the work station is locked!\n", hDesktop
);
1087 /* FIXME: Fail if the desktop belong to an invisible window station */
1088 /* FIXME: Fail if the process is associated with a secured
1089 desktop such as Winlogon or Screen-Saver */
1090 /* FIXME: Connect to input device */
1092 /* Set the active desktop in the desktop's window station. */
1093 DesktopObject
->WindowStation
->ActiveDesktop
= DesktopObject
;
1095 /* Set the global state. */
1096 InputDesktop
= DesktopObject
;
1097 InputDesktopHandle
= hDesktop
;
1098 InputWindowStation
= DesktopObject
->WindowStation
;
1100 ObDereferenceObject(DesktopObject
);
1106 * NtUserResolveDesktopForWOW
1113 NtUserResolveDesktopForWOW(DWORD Unknown0
)
1120 * NtUserGetThreadDesktop
1127 NtUserGetThreadDesktop(DWORD dwThreadId
, DWORD Unknown1
)
1131 PDESKTOP_OBJECT DesktopObject
;
1132 HDESK Ret
, hThreadDesktop
;
1133 OBJECT_HANDLE_INFORMATION HandleInformation
;
1137 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1141 Status
= PsLookupThreadByThreadId((HANDLE
)dwThreadId
, &Thread
);
1142 if(!NT_SUCCESS(Status
))
1144 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1148 if(Thread
->ThreadsProcess
== PsGetCurrentProcess())
1150 /* just return the handle, we queried the desktop handle of a thread running
1151 in the same context */
1152 Ret
= Thread
->Tcb
.Win32Thread
->hDesktop
;
1153 ObDereferenceObject(Thread
);
1157 /* get the desktop handle and the desktop of the thread */
1158 if(!(hThreadDesktop
= Thread
->Tcb
.Win32Thread
->hDesktop
) ||
1159 !(DesktopObject
= Thread
->Tcb
.Win32Thread
->Desktop
))
1161 ObDereferenceObject(Thread
);
1162 DPRINT1("Desktop information of thread 0x%x broken!?\n", dwThreadId
);
1166 /* we could just use DesktopObject instead of looking up the handle, but latter
1167 may be a bit safer (e.g. when the desktop is being destroyed */
1168 /* switch into the context of the thread we're trying to get the desktop from,
1169 so we can use the handle */
1170 KeAttachProcess(Thread
->ThreadsProcess
);
1171 Status
= ObReferenceObjectByHandle(hThreadDesktop
,
1173 ExDesktopObjectType
,
1175 (PVOID
*)&DesktopObject
,
1176 &HandleInformation
);
1179 /* the handle couldn't be found, there's nothing to get... */
1180 if(!NT_SUCCESS(Status
))
1182 ObDereferenceObject(Thread
);
1186 /* lookup our handle table if we can find a handle to the desktop object,
1187 if not, create one */
1188 Ret
= IntGetDesktopObjectHandle(DesktopObject
);
1190 /* all done, we got a valid handle to the desktop */
1191 ObDereferenceObject(DesktopObject
);
1192 ObDereferenceObject(Thread
);
1197 * NtUserSetThreadDesktop
1204 NtUserSetThreadDesktop(HDESK hDesktop
)
1206 PW32THREAD W32Thread
;
1207 PDESKTOP_OBJECT DesktopObject
;
1210 /* Validate the new desktop. */
1211 Status
= IntValidateDesktopHandle(
1217 if (!NT_SUCCESS(Status
))
1219 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop
);
1223 W32Thread
= PsGetWin32Thread();
1225 /* FIXME: Should check here to see if the thread has any windows. */
1227 if (W32Thread
->Desktop
!= NULL
)
1229 ObDereferenceObject(W32Thread
->Desktop
);
1232 W32Thread
->Desktop
= DesktopObject
;
1233 W32Thread
->hDesktop
= hDesktop
;