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.
19 * $Id: desktop.c,v 1.23 2004/11/06 22:28:11 gvg Exp $
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 /* INITALIZATION FUNCTIONS ****************************************************/
58 return STATUS_SUCCESS
;
62 CleanupDesktopImpl(VOID
)
64 return STATUS_SUCCESS
;
67 /* PRIVATE FUNCTIONS **********************************************************/
70 * IntValidateDesktopHandle
72 * Validates the desktop handle.
75 * If the function succeeds, the handle remains referenced. If the
76 * fucntion fails, last error is set.
80 IntValidateDesktopHandle(
82 KPROCESSOR_MODE AccessMode
,
83 ACCESS_MASK DesiredAccess
,
84 PDESKTOP_OBJECT
*Object
)
88 Status
= ObReferenceObjectByHandle(
96 if (!NT_SUCCESS(Status
))
97 SetLastNtError(Status
);
103 IntGetDesktopWorkArea(PDESKTOP_OBJECT Desktop
, PRECT Rect
)
109 Ret
= &Desktop
->WorkArea
;
110 if((Ret
->right
== -1) && ScreenDeviceContext
)
113 BITMAPOBJ
*BitmapObj
;
114 dc
= DC_LockDc(ScreenDeviceContext
);
115 BitmapObj
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
118 Ret
->right
= BitmapObj
->SurfObj
.sizlBitmap
.cx
;
119 Ret
->bottom
= BitmapObj
->SurfObj
.sizlBitmap
.cy
;
120 BITMAPOBJ_UnlockBitmap(dc
->w
.hBitmap
);
122 DC_UnlockDc(ScreenDeviceContext
);
131 PDESKTOP_OBJECT FASTCALL
132 IntGetActiveDesktop(VOID
)
138 * returns or creates a handle to the desktop object
141 IntGetDesktopObjectHandle(PDESKTOP_OBJECT DesktopObject
)
146 ASSERT(DesktopObject
);
148 Status
= ObFindHandleForObject(PsGetCurrentProcess(),
154 if(!NT_SUCCESS(Status
))
156 Status
= ObOpenObjectByPointer(DesktopObject
,
163 if(!NT_SUCCESS(Status
))
165 /* unable to create a handle */
166 DPRINT1("Unable to create a desktop handle\n");
174 PUSER_MESSAGE_QUEUE FASTCALL
175 IntGetFocusMessageQueue(VOID
)
177 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
180 DPRINT("No active desktop\n");
183 return (PUSER_MESSAGE_QUEUE
)pdo
->ActiveMessageQueue
;
187 IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue
)
189 PUSER_MESSAGE_QUEUE Old
;
190 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
193 DPRINT("No active desktop\n");
198 if(NewQueue
->Desktop
!= NULL
)
200 DPRINT("Message Queue already attached to another desktop!\n");
203 IntReferenceMessageQueue(NewQueue
);
204 InterlockedExchange((LONG
*)&NewQueue
->Desktop
, (LONG
)pdo
);
206 Old
= (PUSER_MESSAGE_QUEUE
)InterlockedExchange((LONG
*)&pdo
->ActiveMessageQueue
, (LONG
)NewQueue
);
209 InterlockedExchange((LONG
*)&Old
->Desktop
, 0);
210 IntDereferenceMessageQueue(Old
);
214 HWND FASTCALL
IntGetDesktopWindow(VOID
)
216 PDESKTOP_OBJECT pdo
= IntGetActiveDesktop();
219 DPRINT("No active desktop\n");
222 return pdo
->DesktopWindow
;
225 HWND FASTCALL
IntGetCurrentThreadDesktopWindow(VOID
)
227 PDESKTOP_OBJECT pdo
= PsGetWin32Thread()->Desktop
;
230 DPRINT1("Thread doesn't have a desktop\n");
233 return pdo
->DesktopWindow
;
236 /* PUBLIC FUNCTIONS ***********************************************************/
239 IntShowDesktop(PDESKTOP_OBJECT Desktop
, ULONG Width
, ULONG Height
)
241 CSRSS_API_REQUEST Request
;
242 CSRSS_API_REPLY Reply
;
244 Request
.Type
= CSRSS_SHOW_DESKTOP
;
245 Request
.Data
.ShowDesktopRequest
.DesktopWindow
= Desktop
->DesktopWindow
;
246 Request
.Data
.ShowDesktopRequest
.Width
= Width
;
247 Request
.Data
.ShowDesktopRequest
.Height
= Height
;
249 return CsrNotify(&Request
, &Reply
);
253 IntHideDesktop(PDESKTOP_OBJECT Desktop
)
256 CSRSS_API_REQUEST Request
;
257 CSRSS_API_REPLY Reply
;
259 Request
.Type
= CSRSS_HIDE_DESKTOP
;
260 Request
.Data
.HideDesktopRequest
.DesktopWindow
= Desktop
->DesktopWindow
;
262 return NotifyCsrss(&Request
, &Reply
);
264 PWINDOW_OBJECT DesktopWindow
;
266 DesktopWindow
= IntGetWindowObject(Desktop
->DesktopWindow
);
269 return ERROR_INVALID_WINDOW_HANDLE
;
271 DesktopWindow
->Style
&= ~WS_VISIBLE
;
273 return STATUS_SUCCESS
;
278 * NtUserCreateDesktop
280 * Creates a new desktop.
284 * Name of the new desktop.
290 * Requested type of access.
293 * Security descriptor.
296 * Handle to window station on which to create the desktop.
299 * If the function succeeds, the return value is a handle to the newly
300 * created desktop. If the specified desktop already exists, the function
301 * succeeds and returns a handle to the existing desktop. When you are
302 * finished using the handle, call the CloseDesktop function to close it.
303 * If the function fails, the return value is NULL.
311 PUNICODE_STRING lpszDesktopName
,
313 ACCESS_MASK dwDesiredAccess
,
314 LPSECURITY_ATTRIBUTES lpSecurity
,
315 HWINSTA hWindowStation
)
317 OBJECT_ATTRIBUTES ObjectAttributes
;
318 PWINSTATION_OBJECT WinStaObject
;
319 PDESKTOP_OBJECT DesktopObject
;
320 UNICODE_STRING DesktopName
;
323 CSRSS_API_REQUEST Request
;
324 CSRSS_API_REPLY Reply
;
326 Status
= IntValidateWindowStationHandle(
332 if (! NT_SUCCESS(Status
))
334 DPRINT1("Failed validation of window station handle (0x%X)\n",
336 SetLastNtError(Status
);
340 if (! IntGetFullWindowStationName(&DesktopName
, &WinStaObject
->Name
,
343 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
344 ObDereferenceObject(WinStaObject
);
348 ObDereferenceObject(WinStaObject
);
351 * Try to open already existing desktop
354 DPRINT("Trying to open desktop (%wZ)\n", &DesktopName
);
356 /* Initialize ObjectAttributes for the desktop object */
357 InitializeObjectAttributes(
364 Status
= ObOpenObjectByName(
373 if (NT_SUCCESS(Status
))
375 DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName
);
376 ExFreePool(DesktopName
.Buffer
);
381 * No existing desktop found, try to create new one
384 Status
= ObCreateObject(
390 sizeof(DESKTOP_OBJECT
),
393 (PVOID
*)&DesktopObject
);
395 if (! NT_SUCCESS(Status
))
397 DPRINT1("Failed creating desktop (%wZ)\n", &DesktopName
);
398 ExFreePool(DesktopName
.Buffer
);
399 SetLastNtError(STATUS_UNSUCCESSFUL
);
404 DesktopObject
->WorkArea
.left
= 0;
405 DesktopObject
->WorkArea
.top
= 0;
406 DesktopObject
->WorkArea
.right
= -1;
407 DesktopObject
->WorkArea
.bottom
= -1;
408 IntGetDesktopWorkArea(DesktopObject
, NULL
);
410 /* Initialize some local (to win32k) desktop state. */
411 DesktopObject
->ActiveMessageQueue
= NULL
;
413 Status
= ObInsertObject(
414 (PVOID
)DesktopObject
,
416 STANDARD_RIGHTS_REQUIRED
,
421 ObDereferenceObject(DesktopObject
);
422 ExFreePool(DesktopName
.Buffer
);
424 if (! NT_SUCCESS(Status
))
426 DPRINT1("Failed to create desktop handle\n");
427 SetLastNtError(Status
);
431 Request
.Type
= CSRSS_CREATE_DESKTOP
;
432 memcpy(Request
.Data
.CreateDesktopRequest
.DesktopName
, lpszDesktopName
->Buffer
,
433 lpszDesktopName
->Length
);
434 Request
.Data
.CreateDesktopRequest
.DesktopName
[lpszDesktopName
->Length
/ sizeof(WCHAR
)] = L
'\0';
436 Status
= CsrNotify(&Request
, &Reply
);
437 if (! NT_SUCCESS(Status
))
439 DPRINT1("Failed to notify CSRSS about new desktop\n");
441 SetLastNtError(Status
);
451 * Opens an existing desktop.
455 * Name of the existing desktop.
461 * Requested type of access.
464 * Handle to the desktop or zero on failure.
472 PUNICODE_STRING lpszDesktopName
,
474 ACCESS_MASK dwDesiredAccess
)
476 OBJECT_ATTRIBUTES ObjectAttributes
;
477 PWINSTATION_OBJECT WinStaObject
;
478 UNICODE_STRING DesktopName
;
483 * Validate the window station handle and compose the fully
484 * qualified desktop name
487 Status
= IntValidateWindowStationHandle(
488 PROCESS_WINDOW_STATION(),
493 if (!NT_SUCCESS(Status
))
495 DPRINT("Failed validation of window station handle (0x%X)\n",
496 PROCESS_WINDOW_STATION());
497 SetLastNtError(Status
);
501 if (!IntGetFullWindowStationName(&DesktopName
, &WinStaObject
->Name
,
504 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
505 ObDereferenceObject(WinStaObject
);
509 ObDereferenceObject(WinStaObject
);
511 DPRINT("Trying to open desktop station (%wZ)\n", &DesktopName
);
513 /* Initialize ObjectAttributes for the desktop object */
514 InitializeObjectAttributes(
521 Status
= ObOpenObjectByName(
530 if (!NT_SUCCESS(Status
))
532 SetLastNtError(Status
);
533 ExFreePool(DesktopName
.Buffer
);
537 DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName
);
538 ExFreePool(DesktopName
.Buffer
);
544 * NtUserOpenInputDesktop
546 * Opens the input (interactive) desktop.
553 * Inheritance option.
556 * Requested type of access.
559 * Handle to the input desktop or zero on failure.
566 NtUserOpenInputDesktop(
569 ACCESS_MASK dwDesiredAccess
)
571 PDESKTOP_OBJECT Object
;
575 DPRINT("About to open input desktop\n");
577 /* Get a pointer to the desktop object */
579 Status
= IntValidateDesktopHandle(
585 if (!NT_SUCCESS(Status
))
587 DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop
);
591 /* Create a new handle to the object */
593 Status
= ObOpenObjectByPointer(
602 ObDereferenceObject(Object
);
604 if (NT_SUCCESS(Status
))
606 DPRINT("Successfully opened input desktop\n");
607 return (HDESK
)Desktop
;
610 SetLastNtError(Status
);
617 * Closes a desktop handle.
621 * Handle to the desktop.
627 * The desktop handle can be created with NtUserCreateDesktop or
628 * NtUserOpenDesktop. This function will fail if any thread in the calling
629 * process is using the specified desktop handle or if the handle refers
630 * to the initial desktop of the calling process.
637 NtUserCloseDesktop(HDESK hDesktop
)
639 PDESKTOP_OBJECT Object
;
642 DPRINT("About to close desktop handle (0x%X)\n", hDesktop
);
644 Status
= IntValidateDesktopHandle(
650 if (!NT_SUCCESS(Status
))
652 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop
);
656 ObDereferenceObject(Object
);
658 DPRINT("Closing desktop handle (0x%X)\n", hDesktop
);
660 Status
= ZwClose(hDesktop
);
661 if (!NT_SUCCESS(Status
))
663 SetLastNtError(Status
);
671 static int GetSystemVersionString(LPWSTR buffer
)
673 RTL_OSVERSIONINFOEXW versionInfo
;
676 versionInfo
.dwOSVersionInfoSize
= sizeof(RTL_OSVERSIONINFOEXW
);
678 if (!NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW
)&versionInfo
)))
681 if (versionInfo
.dwMajorVersion
<= 4)
682 len
= swprintf(buffer
,
683 L
"ReactOS Version %d.%d %s Build %d",
684 versionInfo
.dwMajorVersion
, versionInfo
.dwMinorVersion
,
685 versionInfo
.szCSDVersion
, versionInfo
.dwBuildNumber
&0xFFFF);
687 len
= swprintf(buffer
,
688 L
"ReactOS %s (Build %d)",
689 versionInfo
.szCSDVersion
, versionInfo
.dwBuildNumber
&0xFFFF);
694 static NTSTATUS STDCALL
PaintDesktopVersionCallback(
695 IN PWSTR ValueName
, IN ULONG ValueType
,
696 IN PVOID ValueData
, IN ULONG ValueLength
,
697 IN PVOID Context
, IN PVOID EntryContext
700 DPRINT("PaintDesktopVersionCallback ValueType=%d ValueLength=%d\n", ValueType
, ValueLength
);
702 if (ValueType
==REG_DWORD
&& ValueLength
==sizeof(DWORD
))
703 *((DWORD
*)EntryContext
) = *(DWORD
*)ValueData
;
705 return STATUS_SUCCESS
;
711 * The NtUserPaintDesktop function fills the clipping region in the
712 * specified device context with the desktop pattern or wallpaper. The
713 * function is provided primarily for shell desktops.
717 * Handle to the device context.
724 NtUserPaintDesktop(HDC hDC
)
727 HBRUSH DesktopBrush
, PreviousBrush
;
729 BOOL doPatBlt
= TRUE
;
731 RTL_QUERY_REGISTRY_TABLE queryTable
[2];
732 DWORD displayVersion
;
736 PWINSTATION_OBJECT WinSta
= PsGetWin32Thread()->Desktop
->WindowStation
;
738 IntGdiGetClipBox(hDC
, &Rect
);
740 hWndDesktop
= IntGetDesktopWindow();
741 DesktopBrush
= (HBRUSH
)NtUserGetClassLong(hWndDesktop
, GCL_HBRBACKGROUND
, FALSE
);
744 * Paint desktop background
747 if(WinSta
->hbmWallpaper
!= NULL
)
749 PWINDOW_OBJECT DeskWin
;
751 if((DeskWin
= IntGetWindowObject(hWndDesktop
)))
757 sz
.cx
= DeskWin
->WindowRect
.right
- DeskWin
->WindowRect
.left
;
758 sz
.cy
= DeskWin
->WindowRect
.bottom
- DeskWin
->WindowRect
.top
;
759 IntReleaseWindowObject(DeskWin
);
761 x
= (sz
.cx
/ 2) - (WinSta
->cxWallpaper
/ 2);
762 y
= (sz
.cy
/ 2) - (WinSta
->cyWallpaper
/ 2);
764 hWallpaperDC
= NtGdiCreateCompatableDC(hDC
);
765 if(hWallpaperDC
!= NULL
)
771 /* FIXME - clip out the bitmap */
772 PreviousBrush
= NtGdiSelectObject(hDC
, DesktopBrush
);
773 NtGdiPatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
, Rect
.bottom
, PATCOPY
);
774 NtGdiSelectObject(hDC
, PreviousBrush
);
779 hOldBitmap
= NtGdiSelectObject(hWallpaperDC
, WinSta
->hbmWallpaper
);
780 NtGdiBitBlt(hDC
, x
, y
, WinSta
->cxWallpaper
, WinSta
->cyWallpaper
, hWallpaperDC
, 0, 0, SRCCOPY
);
781 NtGdiSelectObject(hWallpaperDC
, hOldBitmap
);
783 NtGdiDeleteDC(hWallpaperDC
);
789 PreviousBrush
= NtGdiSelectObject(hDC
, DesktopBrush
);
790 NtGdiPatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
, Rect
.bottom
, PATCOPY
);
791 NtGdiSelectObject(hDC
, PreviousBrush
);
795 * Display system version on the desktop background
798 RtlZeroMemory(queryTable
, sizeof(queryTable
));
800 queryTable
[0].QueryRoutine
= PaintDesktopVersionCallback
;
801 queryTable
[0].Name
= L
"PaintDesktopVersion";
802 queryTable
[0].EntryContext
= &displayVersion
;
804 /* query the "PaintDesktopVersion" flag in the "Control Panel\Desktop" key */
805 status
= RtlQueryRegistryValues(RTL_REGISTRY_USER
, L
"Control Panel\\Desktop", queryTable
, NULL
, NULL
);
807 if (!NT_SUCCESS(status
)) {
808 DPRINT1("RtlQueryRegistryValues failed for PaintDesktopVersion: status=%x\n", status
);
811 DPRINT("PaintDesktopVersion=%d\n", displayVersion
);
813 if (displayVersion
) {
814 static WCHAR s_wszVersion
[256] = {0};
818 len
= wcslen(s_wszVersion
);
820 len
= GetSystemVersionString(s_wszVersion
);
823 if (!NtUserSystemParametersInfo(SPI_GETWORKAREA
, 0, &rect
, 0)) {
824 rect
.right
= NtUserGetSystemMetrics(SM_CXSCREEN
);
825 rect
.bottom
= NtUserGetSystemMetrics(SM_CYSCREEN
);
828 COLORREF color_old
= NtGdiSetTextColor(hDC
, RGB(255,255,255));
829 UINT align_old
= NtGdiSetTextAlign(hDC
, TA_RIGHT
);
830 int mode_old
= NtGdiSetBkMode(hDC
, TRANSPARENT
);
832 NtGdiTextOut(hDC
, rect
.right
-16, rect
.bottom
-48, s_wszVersion
, len
);
834 NtGdiSetBkMode(hDC
, mode_old
);
835 NtGdiSetTextAlign(hDC
, align_old
);
836 NtGdiSetTextColor(hDC
, color_old
);
845 * NtUserSwitchDesktop
847 * Sets the current input (interactive) desktop.
861 NtUserSwitchDesktop(HDESK hDesktop
)
863 PDESKTOP_OBJECT DesktopObject
;
866 DPRINT("About to switch desktop (0x%X)\n", hDesktop
);
868 Status
= IntValidateDesktopHandle(
874 if (!NT_SUCCESS(Status
))
876 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop
);
881 * Don't allow applications switch the desktop if it's locked, unless the caller
882 * is the logon application itself
884 if((DesktopObject
->WindowStation
->Flags
& WSS_LOCKED
) &&
885 LogonProcess
!= NULL
&& LogonProcess
!= PsGetWin32Process())
887 ObDereferenceObject(DesktopObject
);
888 DPRINT1("Switching desktop 0x%x denied because the work station is locked!\n", hDesktop
);
892 /* FIXME: Fail if the desktop belong to an invisible window station */
893 /* FIXME: Fail if the process is associated with a secured
894 desktop such as Winlogon or Screen-Saver */
895 /* FIXME: Connect to input device */
897 /* Set the active desktop in the desktop's window station. */
898 DesktopObject
->WindowStation
->ActiveDesktop
= DesktopObject
;
900 /* Set the global state. */
901 InputDesktop
= DesktopObject
;
902 InputDesktopHandle
= hDesktop
;
903 InputWindowStation
= DesktopObject
->WindowStation
;
905 ObDereferenceObject(DesktopObject
);
911 * NtUserResolveDesktopForWOW
918 NtUserResolveDesktopForWOW(DWORD Unknown0
)
925 * NtUserGetThreadDesktop
932 NtUserGetThreadDesktop(DWORD dwThreadId
, DWORD Unknown1
)
936 PDESKTOP_OBJECT DesktopObject
;
937 HDESK Ret
, hThreadDesktop
;
938 OBJECT_HANDLE_INFORMATION HandleInformation
;
942 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
946 Status
= PsLookupThreadByThreadId((PVOID
)dwThreadId
, &Thread
);
947 if(!NT_SUCCESS(Status
))
949 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
953 if(Thread
->ThreadsProcess
== PsGetCurrentProcess())
955 /* just return the handle, we queried the desktop handle of a thread running
956 in the same context */
957 Ret
= Thread
->Tcb
.Win32Thread
->hDesktop
;
958 ObDereferenceObject(Thread
);
962 /* get the desktop handle and the desktop of the thread */
963 if(!(hThreadDesktop
= Thread
->Tcb
.Win32Thread
->hDesktop
) ||
964 !(DesktopObject
= Thread
->Tcb
.Win32Thread
->Desktop
))
966 ObDereferenceObject(Thread
);
967 DPRINT1("Desktop information of thread 0x%x broken!?\n", dwThreadId
);
971 /* we could just use DesktopObject instead of looking up the handle, but latter
972 may be a bit safer (e.g. when the desktop is being destroyed */
973 /* switch into the context of the thread we're trying to get the desktop from,
974 so we can use the handle */
975 KeAttachProcess(Thread
->ThreadsProcess
);
976 Status
= ObReferenceObjectByHandle(hThreadDesktop
,
980 (PVOID
*)&DesktopObject
,
984 /* the handle couldn't be found, there's nothing to get... */
985 if(!NT_SUCCESS(Status
))
987 ObDereferenceObject(Thread
);
991 /* lookup our handle table if we can find a handle to the desktop object,
992 if not, create one */
993 Ret
= IntGetDesktopObjectHandle(DesktopObject
);
995 /* all done, we got a valid handle to the desktop */
996 ObDereferenceObject(DesktopObject
);
997 ObDereferenceObject(Thread
);
1002 * NtUserSetThreadDesktop
1009 NtUserSetThreadDesktop(HDESK hDesktop
)
1011 PW32THREAD W32Thread
;
1012 PDESKTOP_OBJECT DesktopObject
;
1015 /* Validate the new desktop. */
1016 Status
= IntValidateDesktopHandle(
1022 if (!NT_SUCCESS(Status
))
1024 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop
);
1028 W32Thread
= PsGetWin32Thread();
1029 /* Check for setting the same desktop as before. */
1030 if (DesktopObject
== W32Thread
->Desktop
)
1032 W32Thread
->hDesktop
= hDesktop
;
1033 ObDereferenceObject(DesktopObject
);
1037 /* FIXME: Should check here to see if the thread has any windows. */
1039 if (W32Thread
->Desktop
!= NULL
)
1041 ObDereferenceObject(W32Thread
->Desktop
);
1044 W32Thread
->Desktop
= DesktopObject
;
1045 W32Thread
->hDesktop
= hDesktop
;