+++ /dev/null
-/*
- * ReactOS W32 Subsystem
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- *
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * PURPOSE: Desktops
- * FILE: subsys/win32k/ntuser/desktop.c
- * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
- * REVISION HISTORY:
- * 06-06-2001 CSH Created
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <w32k.h>
-
-#define NDEBUG
-#include <debug.h>
-
-/* GLOBALS *******************************************************************/
-
-/* Currently active desktop */
-PDESKTOP_OBJECT InputDesktop = NULL;
-HDESK InputDesktopHandle = NULL;
-HDC ScreenDeviceContext = NULL;
-
-BOOL g_PaintDesktopVersion = FALSE;
-
-/* INITALIZATION FUNCTIONS ****************************************************/
-
-static GENERIC_MAPPING IntDesktopMapping =
- {
- STANDARD_RIGHTS_READ | DESKTOP_ENUMERATE | DESKTOP_READOBJECTS,
- STANDARD_RIGHTS_WRITE | DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_HOOKCONTROL |
- DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD | DESKTOP_WRITEOBJECTS,
- STANDARD_RIGHTS_EXECUTE | DESKTOP_SWITCHDESKTOP,
- STANDARD_RIGHTS_REQUIRED | DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE |
- DESKTOP_HOOKCONTROL | DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD |
- DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS
- };
-
-NTSTATUS FASTCALL
-InitDesktopImpl(VOID)
-{
- /* Set Desktop Object Attributes */
- ExDesktopObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(DESKTOP_OBJECT);
- ExDesktopObjectType->TypeInfo.GenericMapping = IntDesktopMapping;
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS FASTCALL
-CleanupDesktopImpl(VOID)
-{
- return STATUS_SUCCESS;
-}
-
-/* OBJECT CALLBACKS **********************************************************/
-
-NTSTATUS STDCALL
-IntDesktopObjectCreate(PVOID ObjectBody,
- PVOID Parent,
- PWSTR RemainingPath,
- struct _OBJECT_ATTRIBUTES* ObjectAttributes)
-{
- PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)ObjectBody;
- UNICODE_STRING UnicodeString;
-
- DPRINT("Creating desktop (0x%X) Name (%S)\n", Desktop, RemainingPath);
- if (RemainingPath == NULL)
- {
- return STATUS_SUCCESS;
- }
-
- if (wcschr((RemainingPath + 1), '\\') != NULL)
- {
- return STATUS_UNSUCCESSFUL;
- }
-
- RtlInitUnicodeString(&UnicodeString, (RemainingPath + 1));
-
- InitializeListHead(&Desktop->ShellHookWindows);
-
- Desktop->WindowStation = (PWINSTATION_OBJECT)Parent;
-
- /* Put the desktop on the window station's list of associcated desktops */
-// ExInterlocked
- InsertTailList(
- &Desktop->WindowStation->DesktopListHead,
- &Desktop->ListEntry);//,
-// &Desktop->WindowStation->Lock);
-
- return RtlCreateUnicodeString(&Desktop->Name, UnicodeString.Buffer);
-}
-
-VOID STDCALL
-IntDesktopObjectDelete(PVOID DeletedObject)
-{
- PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)DeletedObject;
-
- DPRINT("Deleting desktop (0x%X)\n", Desktop);
-
- /* Remove the desktop from the window station's list of associcated desktops */
- RemoveEntryList(&Desktop->ListEntry);
-
- RtlFreeUnicodeString(&Desktop->Name);
-}
-
-/* PRIVATE FUNCTIONS **********************************************************/
-
-static int GetSystemVersionString(LPWSTR buffer)
-{
- RTL_OSVERSIONINFOEXW versionInfo;
- int len;
-
- versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
-
- if (!NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&versionInfo)))
- return 0;
-
- if (versionInfo.dwMajorVersion <= 4)
- len = swprintf(buffer,
- L"ReactOS Version %d.%d %s Build %d",
- versionInfo.dwMajorVersion, versionInfo.dwMinorVersion,
- versionInfo.szCSDVersion, versionInfo.dwBuildNumber&0xFFFF);
- else
- len = swprintf(buffer,
- L"ReactOS %s (Build %d)",
- versionInfo.szCSDVersion, versionInfo.dwBuildNumber&0xFFFF);
-
- return len;
-}
-
-
-NTSTATUS FASTCALL
-IntParseDesktopPath(PEPROCESS Process,
- PUNICODE_STRING DesktopPath,
- HWINSTA *hWinSta,
- HDESK *hDesktop)
-{
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING WinSta, Desktop, FullName;
- BOOL DesktopPresent = FALSE;
- BOOL WinStaPresent = FALSE;
- NTSTATUS Status;
-
- ASSERT(hWinSta);
-
- *hWinSta = NULL;
-
- if(hDesktop != NULL)
- {
- *hDesktop = NULL;
- }
-
- RtlInitUnicodeString(&WinSta, NULL);
- RtlInitUnicodeString(&Desktop, NULL);
-
- if(DesktopPath != NULL && DesktopPath->Buffer != NULL && DesktopPath->Length > sizeof(WCHAR))
- {
- PWCHAR c = DesktopPath->Buffer;
- USHORT wl = 0;
- USHORT l = DesktopPath->Length;
-
- /*
- * Parse the desktop path string which can be in the form "WinSta\Desktop"
- * or just "Desktop". In latter case WinSta0 will be used.
- */
-
- while(l > 0)
- {
- if(*c == L'\\')
- {
- wl = (ULONG_PTR)c - (ULONG_PTR)DesktopPath->Buffer;
- break;
- }
- l -= sizeof(WCHAR);
- c++;
- }
-
- if(wl > 0)
- {
- WinSta.Length = wl;
- WinSta.MaximumLength = wl + sizeof(WCHAR);
- WinSta.Buffer = DesktopPath->Buffer;
-
- WinStaPresent = TRUE;
- c++;
- }
-
- Desktop.Length = DesktopPath->Length - wl;
- if(wl > 0)
- {
- Desktop.Length -= sizeof(WCHAR);
- }
- if(Desktop.Length > 0)
- {
- Desktop.MaximumLength = Desktop.Length + sizeof(WCHAR);
- Desktop.Buffer = ((wl > 0) ? c : DesktopPath->Buffer);
- DesktopPresent = TRUE;
- }
- }
-
- if(!WinStaPresent)
- {
- /* search the process handle table for (inherited) window station
- handles, use a more appropriate one than WinSta0 if possible. */
- Status = ObFindHandleForObject(Process,
- NULL,
- ExWindowStationObjectType,
- NULL,
- (PHANDLE)hWinSta);
- if(!NT_SUCCESS(Status))
- {
- /* we had no luck searching for opened handles, use WinSta0 now */
- RtlInitUnicodeString(&WinSta, L"WinSta0");
- }
- }
-
- if(!DesktopPresent && hDesktop != NULL)
- {
- /* search the process handle table for (inherited) desktop
- handles, use a more appropriate one than Default if possible. */
- Status = ObFindHandleForObject(Process,
- NULL,
- ExDesktopObjectType,
- NULL,
- (PHANDLE)hDesktop);
- if(!NT_SUCCESS(Status))
- {
- /* we had no luck searching for opened handles, use Desktop now */
- RtlInitUnicodeString(&Desktop, L"Default");
- }
- }
-
- if(*hWinSta == NULL)
- {
- if(!IntGetFullWindowStationName(&FullName, &WinSta, NULL))
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- /* open the window station */
- InitializeObjectAttributes(&ObjectAttributes,
- &FullName,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = ObOpenObjectByName(&ObjectAttributes,
- ExWindowStationObjectType,
- NULL,
- KernelMode,
- 0,
- NULL,
- (HANDLE*)hWinSta);
-
- RtlFreeUnicodeString(&FullName);
-
- if(!NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- DPRINT("Failed to reference window station %wZ PID: %d!\n", &WinSta, PsGetCurrentProcessId());
- return Status;
- }
- }
-
- if(hDesktop != NULL && *hDesktop == NULL)
- {
- if(!IntGetFullWindowStationName(&FullName, &WinSta, &Desktop))
- {
- NtClose(*hWinSta);
- *hWinSta = NULL;
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- /* open the desktop object */
- InitializeObjectAttributes(&ObjectAttributes,
- &FullName,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = ObOpenObjectByName(&ObjectAttributes,
- ExDesktopObjectType,
- NULL,
- KernelMode,
- 0,
- NULL,
- (HANDLE*)hDesktop);
-
- RtlFreeUnicodeString(&FullName);
-
- if(!NT_SUCCESS(Status))
- {
- *hDesktop = NULL;
- NtClose(*hWinSta);
- *hWinSta = NULL;
- SetLastNtError(Status);
- DPRINT("Failed to reference desktop %wZ PID: %d!\n", &Desktop, PsGetCurrentProcessId());
- return Status;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-/*
- * IntValidateDesktopHandle
- *
- * Validates the desktop handle.
- *
- * Remarks
- * If the function succeeds, the handle remains referenced. If the
- * fucntion fails, last error is set.
- */
-
-NTSTATUS FASTCALL
-IntValidateDesktopHandle(
- HDESK Desktop,
- KPROCESSOR_MODE AccessMode,
- ACCESS_MASK DesiredAccess,
- PDESKTOP_OBJECT *Object)
-{
- NTSTATUS Status;
-
- Status = ObReferenceObjectByHandle(
- Desktop,
- DesiredAccess,
- ExDesktopObjectType,
- AccessMode,
- (PVOID*)Object,
- NULL);
-
- if (!NT_SUCCESS(Status))
- SetLastNtError(Status);
-
- return Status;
-}
-
-VOID FASTCALL
-IntGetDesktopWorkArea(PDESKTOP_OBJECT Desktop, PRECT Rect)
-{
- PRECT Ret;
-
- ASSERT(Desktop);
-
- Ret = &Desktop->WorkArea;
- if((Ret->right == -1) && ScreenDeviceContext)
- {
- PDC dc;
- BITMAPOBJ *BitmapObj;
- dc = DC_LockDc(ScreenDeviceContext);
- /* FIXME - Handle dc == NULL!!!! */
- BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
- if(BitmapObj)
- {
- Ret->right = BitmapObj->SurfObj.sizlBitmap.cx;
- Ret->bottom = BitmapObj->SurfObj.sizlBitmap.cy;
- BITMAPOBJ_UnlockBitmap(BitmapObj);
- }
- DC_UnlockDc(dc);
- }
-
- if(Rect)
- {
- *Rect = *Ret;
- }
-}
-
-PDESKTOP_OBJECT FASTCALL
-IntGetActiveDesktop(VOID)
-{
- return InputDesktop;
-}
-
-/*
- * returns or creates a handle to the desktop object
- */
-HDESK FASTCALL
-IntGetDesktopObjectHandle(PDESKTOP_OBJECT DesktopObject)
-{
- NTSTATUS Status;
- HDESK Ret;
-
- ASSERT(DesktopObject);
-
- Status = ObFindHandleForObject(PsGetCurrentProcess(),
- DesktopObject,
- ExDesktopObjectType,
- NULL,
- (PHANDLE)&Ret);
-
- if(!NT_SUCCESS(Status))
- {
- Status = ObOpenObjectByPointer(DesktopObject,
- 0,
- NULL,
- 0,
- ExDesktopObjectType,
- UserMode,
- (PHANDLE)&Ret);
- if(!NT_SUCCESS(Status))
- {
- /* unable to create a handle */
- DPRINT1("Unable to create a desktop handle\n");
- return NULL;
- }
- }
-
- return Ret;
-}
-
-PUSER_MESSAGE_QUEUE FASTCALL
-IntGetFocusMessageQueue(VOID)
-{
- PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
- if (!pdo)
- {
- DPRINT("No active desktop\n");
- return(NULL);
- }
- return (PUSER_MESSAGE_QUEUE)pdo->ActiveMessageQueue;
-}
-
-VOID FASTCALL
-IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue)
-{
- PUSER_MESSAGE_QUEUE Old;
- PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
- if (!pdo)
- {
- DPRINT("No active desktop\n");
- return;
- }
- if(NewQueue != NULL)
- {
- if(NewQueue->Desktop != NULL)
- {
- DPRINT("Message Queue already attached to another desktop!\n");
- return;
- }
- IntReferenceMessageQueue(NewQueue);
- InterlockedExchange((LONG*)&NewQueue->Desktop, (LONG)pdo);
- }
- Old = (PUSER_MESSAGE_QUEUE)InterlockedExchange((LONG*)&pdo->ActiveMessageQueue, (LONG)NewQueue);
- if(Old != NULL)
- {
- InterlockedExchange((LONG*)&Old->Desktop, 0);
- IntDereferenceMessageQueue(Old);
- }
-}
-
-HWND FASTCALL IntGetDesktopWindow(VOID)
-{
- PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
- if (!pdo)
- {
- DPRINT("No active desktop\n");
- return NULL;
- }
- return pdo->DesktopWindow;
-}
-
-PWINDOW_OBJECT FASTCALL UserGetDesktopWindow(VOID)
-{
- PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
-
- if (!pdo)
- {
- DPRINT("No active desktop\n");
- return NULL;
- }
-
- return UserGetWindowObject(pdo->DesktopWindow);
-}
-
-
-HWND FASTCALL IntGetCurrentThreadDesktopWindow(VOID)
-{
- PDESKTOP_OBJECT pdo = PsGetWin32Thread()->Desktop;
- if (NULL == pdo)
- {
- DPRINT1("Thread doesn't have a desktop\n");
- return NULL;
- }
- return pdo->DesktopWindow;
-}
-
-BOOL FASTCALL IntDesktopUpdatePerUserSettings(BOOL bEnable)
-{
- if (bEnable)
- {
- RTL_QUERY_REGISTRY_TABLE QueryTable[2];
- NTSTATUS Status;
-
- RtlZeroMemory(QueryTable, sizeof(QueryTable));
-
- QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
- QueryTable[0].Name = L"PaintDesktopVersion";
- QueryTable[0].EntryContext = &g_PaintDesktopVersion;
-
- /* Query the "PaintDesktopVersion" flag in the "Control Panel\Desktop" key */
- Status = RtlQueryRegistryValues(RTL_REGISTRY_USER,
- L"Control Panel\\Desktop",
- QueryTable, NULL, NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("RtlQueryRegistryValues failed for PaintDesktopVersion (%x)\n",
- Status);
- g_PaintDesktopVersion = FALSE;
- return FALSE;
- }
-
- DPRINT("PaintDesktopVersion = %d\n", g_PaintDesktopVersion);
-
- return TRUE;
- }
- else
- {
- g_PaintDesktopVersion = FALSE;
- return TRUE;
- }
-}
-
-/* PUBLIC FUNCTIONS ***********************************************************/
-
-NTSTATUS FASTCALL
-co_IntShowDesktop(PDESKTOP_OBJECT Desktop, ULONG Width, ULONG Height)
-{
- CSR_API_MESSAGE Request;
-
- Request.Type = MAKE_CSR_API(SHOW_DESKTOP, CSR_GUI);
- Request.Data.ShowDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
- Request.Data.ShowDesktopRequest.Width = Width;
- Request.Data.ShowDesktopRequest.Height = Height;
-
- return co_CsrNotify(&Request);
-}
-
-NTSTATUS FASTCALL
-IntHideDesktop(PDESKTOP_OBJECT Desktop)
-{
-#if 0
- CSRSS_API_REQUEST Request;
- CSRSS_API_REPLY Reply;
-
- Request.Type = CSRSS_HIDE_DESKTOP;
- Request.Data.HideDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
-
- return NotifyCsrss(&Request, &Reply);
-#else
-
- PWINDOW_OBJECT DesktopWindow;
-
- DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow);
- if (! DesktopWindow)
- {
- return ERROR_INVALID_WINDOW_HANDLE;
- }
- DesktopWindow->Style &= ~WS_VISIBLE;
-
- return STATUS_SUCCESS;
-#endif
-}
-
-
-
-
-static
-HWND* FASTCALL
-UserBuildShellHookHwndList(PDESKTOP_OBJECT Desktop)
-{
- ULONG entries=0;
- PSHELL_HOOK_WINDOW Current;
- HWND* list;
-
- /* fixme: if we save nb elements in desktop, we dont have to loop to find nb entries */
- LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
- entries++;
-
- if (!entries) return NULL;
-
- list = ExAllocatePool(PagedPool, sizeof(HWND) * (entries + 1)); /* alloc one extra for nullterm */
- if (list)
- {
- HWND* cursor = list;
-
- LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
- *cursor++ = Current->hWnd;
-
- *cursor = NULL; /* nullterm list */
- }
-
- return list;
-}
-
-/*
- * Send the Message to the windows registered for ShellHook
- * notifications. The lParam contents depend on the Message. See
- * MSDN for more details (RegisterShellHookWindow)
- */
-VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam)
-{
- PDESKTOP_OBJECT Desktop = IntGetActiveDesktop();
- HWND* HwndList;
-
- static UINT MsgType = 0;
-
- if (!MsgType)
- {
-
- /* Too bad, this doesn't work.*/
-#if 0
- UNICODE_STRING Str;
- RtlInitUnicodeString(&Str, L"SHELLHOOK");
- MsgType = UserRegisterWindowMessage(&Str);
-#endif
-
- MsgType = IntAddAtom(L"SHELLHOOK");
-
- DPRINT("MsgType = %x\n", MsgType);
- if (!MsgType)
- DPRINT1("LastError: %x\n", GetLastNtError());
- }
-
- if (!Desktop)
- {
- DPRINT1("IntShellHookNotify: No desktop!\n");
- return;
- }
-
- HwndList = UserBuildShellHookHwndList(Desktop);
- if (HwndList)
- {
- HWND* cursor = HwndList;
-
- for (; *cursor; cursor++)
- {
- DPRINT("Sending notify\n");
- co_IntPostOrSendMessage(*cursor,
- MsgType,
- Message,
- lParam);
- }
-
- ExFreePool(HwndList);
- }
-
-}
-
-/*
- * Add the window to the ShellHookWindows list. The windows
- * on that list get notifications that are important to shell
- * type applications.
- *
- * TODO: Validate the window? I'm not sure if sending these messages to
- * an unsuspecting application that is not your own is a nice thing to do.
- */
-BOOL IntRegisterShellHookWindow(HWND hWnd)
-{
- PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
- PSHELL_HOOK_WINDOW Entry;
-
- DPRINT("IntRegisterShellHookWindow\n");
-
- /* First deregister the window, so we can be sure it's never twice in the
- * list.
- */
- IntDeRegisterShellHookWindow(hWnd);
-
- Entry = ExAllocatePoolWithTag(PagedPool,
- sizeof(SHELL_HOOK_WINDOW),
- TAG_WINSTA);
-
- if (!Entry)
- return FALSE;
-
- Entry->hWnd = hWnd;
-
- InsertTailList(&Desktop->ShellHookWindows, &Entry->ListEntry);
-
- return TRUE;
-}
-
-/*
- * Remove the window from the ShellHookWindows list. The windows
- * on that list get notifications that are important to shell
- * type applications.
- */
-BOOL IntDeRegisterShellHookWindow(HWND hWnd)
-{
- PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
- PSHELL_HOOK_WINDOW Current;
-
- LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
- {
- if (Current->hWnd == hWnd)
- {
- RemoveEntryList(&Current->ListEntry);
- ExFreePool(Current);
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-
-
-
-/* SYSCALLS *******************************************************************/
-
-
-/*
- * NtUserCreateDesktop
- *
- * Creates a new desktop.
- *
- * Parameters
- * lpszDesktopName
- * Name of the new desktop.
- *
- * dwFlags
- * Interaction flags.
- *
- * dwDesiredAccess
- * Requested type of access.
- *
- * lpSecurity
- * Security descriptor.
- *
- * hWindowStation
- * Handle to window station on which to create the desktop.
- *
- * Return Value
- * If the function succeeds, the return value is a handle to the newly
- * created desktop. If the specified desktop already exists, the function
- * succeeds and returns a handle to the existing desktop. When you are
- * finished using the handle, call the CloseDesktop function to close it.
- * If the function fails, the return value is NULL.
- *
- * Status
- * @implemented
- */
-
-HDESK STDCALL
-NtUserCreateDesktop(
- PUNICODE_STRING lpszDesktopName,
- DWORD dwFlags,
- ACCESS_MASK dwDesiredAccess,
- LPSECURITY_ATTRIBUTES lpSecurity,
- HWINSTA hWindowStation)
-{
- OBJECT_ATTRIBUTES ObjectAttributes;
- PWINSTATION_OBJECT WinStaObject;
- PDESKTOP_OBJECT DesktopObject;
- UNICODE_STRING DesktopName;
- NTSTATUS Status;
- HDESK Desktop;
- CSR_API_MESSAGE Request;
- DECLARE_RETURN(HDESK);
-
- DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName);
- UserEnterExclusive();
-
- Status = IntValidateWindowStationHandle(
- hWindowStation,
- KernelMode,
- 0, /* FIXME - WINSTA_CREATEDESKTOP */
- &WinStaObject);
-
- if (! NT_SUCCESS(Status))
- {
- DPRINT1("Failed validation of window station handle (0x%X), cannot create desktop %wZ\n",
- hWindowStation, lpszDesktopName);
- SetLastNtError(Status);
- RETURN( NULL);
- }
-
- if (! IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
- lpszDesktopName))
- {
- SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
- ObDereferenceObject(WinStaObject);
- RETURN( NULL);
- }
-
- ObDereferenceObject(WinStaObject);
-
- /*
- * Try to open already existing desktop
- */
-
- DPRINT1("Trying to open desktop (%wZ)\n", &DesktopName);
-
- /* Initialize ObjectAttributes for the desktop object */
- InitializeObjectAttributes(
- &ObjectAttributes,
- &DesktopName,
- 0,
- NULL,
- NULL);
-
- Status = ObOpenObjectByName(
- &ObjectAttributes,
- ExDesktopObjectType,
- NULL,
- KernelMode,
- dwDesiredAccess,
- NULL,
- (HANDLE*)&Desktop);
-
- if (NT_SUCCESS(Status))
- {
- DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
- ExFreePool(DesktopName.Buffer);
- RETURN( Desktop);
- }
-
- /*
- * No existing desktop found, try to create new one
- */
-
- Status = ObCreateObject(
- KernelMode,
- ExDesktopObjectType,
- &ObjectAttributes,
- ExGetPreviousMode(),
- NULL,
- sizeof(DESKTOP_OBJECT),
- 0,
- 0,
- (PVOID*)&DesktopObject);
-
- if (! NT_SUCCESS(Status))
- {
- DPRINT1("Failed creating desktop (%wZ)\n", &DesktopName);
- ExFreePool(DesktopName.Buffer);
- SetLastNtError(STATUS_UNSUCCESSFUL);
- RETURN( NULL);
- }
-
- // init desktop area
- DesktopObject->WorkArea.left = 0;
- DesktopObject->WorkArea.top = 0;
- DesktopObject->WorkArea.right = -1;
- DesktopObject->WorkArea.bottom = -1;
- IntGetDesktopWorkArea(DesktopObject, NULL);
-
- /* Initialize some local (to win32k) desktop state. */
- DesktopObject->ActiveMessageQueue = NULL;
-
- Status = ObInsertObject(
- (PVOID)DesktopObject,
- NULL,
- STANDARD_RIGHTS_REQUIRED,
- 0,
- NULL,
- (HANDLE*)&Desktop);
-
- ObDereferenceObject(DesktopObject);
- ExFreePool(DesktopName.Buffer);
-
- if (! NT_SUCCESS(Status))
- {
- DPRINT1("Failed to create desktop handle\n");
- SetLastNtError(Status);
- RETURN( NULL);
- }
-
- /*
- * Create a handle for CSRSS and notify CSRSS
- */
- Request.Type = MAKE_CSR_API(CREATE_DESKTOP, CSR_GUI);
- Status = CsrInsertObject(Desktop,
- GENERIC_ALL,
- (HANDLE*)&Request.Data.CreateDesktopRequest.DesktopHandle);
- if (! NT_SUCCESS(Status))
- {
- DPRINT1("Failed to create desktop handle for CSRSS\n");
- ZwClose(Desktop);
- SetLastNtError(Status);
- RETURN( NULL);
- }
-
- Status = co_CsrNotify(&Request);
- if (! NT_SUCCESS(Status))
- {
- CsrCloseHandle(Request.Data.CreateDesktopRequest.DesktopHandle);
- DPRINT1("Failed to notify CSRSS about new desktop\n");
- ZwClose(Desktop);
- SetLastNtError(Status);
- RETURN( NULL);
- }
-
- RETURN( Desktop);
-
-CLEANUP:
- DPRINT("Leave NtUserCreateDesktop, ret=%i\n",_ret_);
- UserLeave();
- END_CLEANUP;
-}
-
-/*
- * NtUserOpenDesktop
- *
- * Opens an existing desktop.
- *
- * Parameters
- * lpszDesktopName
- * Name of the existing desktop.
- *
- * dwFlags
- * Interaction flags.
- *
- * dwDesiredAccess
- * Requested type of access.
- *
- * Return Value
- * Handle to the desktop or zero on failure.
- *
- * Status
- * @implemented
- */
-
-HDESK STDCALL
-NtUserOpenDesktop(
- PUNICODE_STRING lpszDesktopName,
- DWORD dwFlags,
- ACCESS_MASK dwDesiredAccess)
-{
- OBJECT_ATTRIBUTES ObjectAttributes;
- HWINSTA WinSta;
- PWINSTATION_OBJECT WinStaObject;
- UNICODE_STRING DesktopName;
- NTSTATUS Status;
- HDESK Desktop;
- DECLARE_RETURN(HDESK);
-
- DPRINT("Enter NtUserOpenDesktop: %wZ\n", lpszDesktopName);
- UserEnterExclusive();
-
- /*
- * Validate the window station handle and compose the fully
- * qualified desktop name
- */
-
- WinSta = UserGetProcessWindowStation();
- Status = IntValidateWindowStationHandle(
- WinSta,
- KernelMode,
- 0,
- &WinStaObject);
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed validation of window station handle (0x%X)\n", WinSta);
- SetLastNtError(Status);
- RETURN( 0);
- }
-
- if (!IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
- lpszDesktopName))
- {
- SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
- ObDereferenceObject(WinStaObject);
- RETURN( 0);
- }
-
- ObDereferenceObject(WinStaObject);
-
- DPRINT("Trying to open desktop (%wZ)\n", &DesktopName);
-
- /* Initialize ObjectAttributes for the desktop object */
- InitializeObjectAttributes(
- &ObjectAttributes,
- &DesktopName,
- 0,
- NULL,
- NULL);
-
- Status = ObOpenObjectByName(
- &ObjectAttributes,
- ExDesktopObjectType,
- NULL,
- KernelMode,
- dwDesiredAccess,
- NULL,
- (HANDLE*)&Desktop);
-
- if (!NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- ExFreePool(DesktopName.Buffer);
- RETURN( 0);
- }
-
- DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
- ExFreePool(DesktopName.Buffer);
-
- RETURN( Desktop);
-
-CLEANUP:
- DPRINT("Leave NtUserOpenDesktop, ret=%i\n",_ret_);
- UserLeave();
- END_CLEANUP;
-}
-
-/*
- * NtUserOpenInputDesktop
- *
- * Opens the input (interactive) desktop.
- *
- * Parameters
- * dwFlags
- * Interaction flags.
- *
- * fInherit
- * Inheritance option.
- *
- * dwDesiredAccess
- * Requested type of access.
- *
- * Return Value
- * Handle to the input desktop or zero on failure.
- *
- * Status
- * @implemented
- */
-
-HDESK STDCALL
-NtUserOpenInputDesktop(
- DWORD dwFlags,
- BOOL fInherit,
- ACCESS_MASK dwDesiredAccess)
-{
- PDESKTOP_OBJECT Object;
- NTSTATUS Status;
- HDESK Desktop;
- DECLARE_RETURN(HDESK);
-
- DPRINT("Enter NtUserOpenInputDesktop\n");
- UserEnterExclusive();
-
- DPRINT("About to open input desktop\n");
-
- /* Get a pointer to the desktop object */
-
- Status = IntValidateDesktopHandle(
- InputDesktopHandle,
- UserMode,
- 0,
- &Object);
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop);
- RETURN((HDESK)0);
- }
-
- /* Create a new handle to the object */
-
- Status = ObOpenObjectByPointer(
- Object,
- 0,
- NULL,
- dwDesiredAccess,
- ExDesktopObjectType,
- UserMode,
- (HANDLE*)&Desktop);
-
- ObDereferenceObject(Object);
-
- if (NT_SUCCESS(Status))
- {
- DPRINT("Successfully opened input desktop\n");
- RETURN((HDESK)Desktop);
- }
-
- SetLastNtError(Status);
- RETURN((HDESK)0);
-
-CLEANUP:
- DPRINT("Leave NtUserOpenInputDesktop, ret=%i\n",_ret_);
- UserLeave();
- END_CLEANUP;
-}
-
-/*
- * NtUserCloseDesktop
- *
- * Closes a desktop handle.
- *
- * Parameters
- * hDesktop
- * Handle to the desktop.
- *
- * Return Value
- * Status
- *
- * Remarks
- * The desktop handle can be created with NtUserCreateDesktop or
- * NtUserOpenDesktop. This function will fail if any thread in the calling
- * process is using the specified desktop handle or if the handle refers
- * to the initial desktop of the calling process.
- *
- * Status
- * @implemented
- */
-
-BOOL STDCALL
-NtUserCloseDesktop(HDESK hDesktop)
-{
- PDESKTOP_OBJECT Object;
- NTSTATUS Status;
- DECLARE_RETURN(BOOL);
-
- DPRINT("Enter NtUserCloseDesktop\n");
- UserEnterExclusive();
-
- DPRINT("About to close desktop handle (0x%X)\n", hDesktop);
-
- Status = IntValidateDesktopHandle(
- hDesktop,
- UserMode,
- 0,
- &Object);
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
- RETURN(FALSE);
- }
-
- ObDereferenceObject(Object);
-
- DPRINT("Closing desktop handle (0x%X)\n", hDesktop);
-
- Status = ZwClose(hDesktop);
- if (!NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- RETURN(FALSE);
- }
-
- RETURN(TRUE);
-
-CLEANUP:
- DPRINT("Leave NtUserCloseDesktop, ret=%i\n",_ret_);
- UserLeave();
- END_CLEANUP;
-}
-
-
-
-
-/*
- * NtUserPaintDesktop
- *
- * The NtUserPaintDesktop function fills the clipping region in the
- * specified device context with the desktop pattern or wallpaper. The
- * function is provided primarily for shell desktops.
- *
- * Parameters
- * hDC
- * Handle to the device context.
- *
- * Status
- * @implemented
- */
-
-BOOL STDCALL
-NtUserPaintDesktop(HDC hDC)
-{
- RECT Rect;
- HBRUSH DesktopBrush, PreviousBrush;
- HWND hWndDesktop;
- BOOL doPatBlt = TRUE;
- PWINDOW_OBJECT WndDesktop;
- int len;
- COLORREF color_old;
- UINT align_old;
- int mode_old;
- PWINSTATION_OBJECT WinSta = PsGetWin32Thread()->Desktop->WindowStation;
- DECLARE_RETURN(BOOL);
-
- UserEnterExclusive();
- DPRINT("Enter NtUserPaintDesktop\n");
-
-
- IntGdiGetClipBox(hDC, &Rect);
-
- hWndDesktop = IntGetDesktopWindow();
-
- WndDesktop = UserGetWindowObject(hWndDesktop);
- if (!WndDesktop)
- {
- RETURN(FALSE);
- }
-
- DesktopBrush = (HBRUSH)IntGetClassLong(WndDesktop, GCL_HBRBACKGROUND, FALSE); //fixme: verify retval
-
-
- /*
- * Paint desktop background
- */
-
- if (WinSta->hbmWallpaper != NULL)
- {
- PWINDOW_OBJECT DeskWin;
-
- DeskWin = UserGetWindowObject(hWndDesktop);
-
- if (DeskWin)
- {
- SIZE sz;
- int x, y;
- HDC hWallpaperDC;
-
- sz.cx = DeskWin->WindowRect.right - DeskWin->WindowRect.left;
- sz.cy = DeskWin->WindowRect.bottom - DeskWin->WindowRect.top;
-
- if (WinSta->WallpaperMode == wmStretch ||
- WinSta->WallpaperMode == wmTile)
- {
- x = 0;
- y = 0;
- }
- else
- {
- /* Find the upper left corner, can be negtive if the bitmap is bigger then the screen */
- x = (sz.cx / 2) - (WinSta->cxWallpaper / 2);
- y = (sz.cy / 2) - (WinSta->cyWallpaper / 2);
- }
-
- hWallpaperDC = NtGdiCreateCompatibleDC(hDC);
- if(hWallpaperDC != NULL)
- {
- HBITMAP hOldBitmap;
-
- /* fill in the area that the bitmap is not going to cover */
- if (x > 0 || y > 0)
- {
- /* FIXME - clip out the bitmap
- can be replaced with "NtGdiPatBlt(hDC, x, y, WinSta->cxWallpaper, WinSta->cyWallpaper, PATCOPY | DSTINVERT);"
- once we support DSTINVERT */
- PreviousBrush = NtGdiSelectObject(hDC, DesktopBrush);
- NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
- NtGdiSelectObject(hDC, PreviousBrush);
- }
-
- /*Do not fill the background after it is painted no matter the size of the picture */
- doPatBlt = FALSE;
-
- hOldBitmap = NtGdiSelectObject(hWallpaperDC, WinSta->hbmWallpaper);
-
- if (WinSta->WallpaperMode == wmStretch)
- {
- if(Rect.right && Rect.bottom)
- NtGdiStretchBlt(hDC,
- x,
- y,
- sz.cx,
- sz.cy,
- hWallpaperDC,
- 0,
- 0,
- WinSta->cxWallpaper,
- WinSta->cyWallpaper,
- SRCCOPY,
- 0);
-
- }
- else if (WinSta->WallpaperMode == wmTile)
- {
- /* paint the bitmap across the screen then down */
- for(y = 0; y < Rect.bottom; y += WinSta->cyWallpaper)
- {
- for(x = 0; x < Rect.right; x += WinSta->cxWallpaper)
- {
- NtGdiBitBlt(hDC,
- x,
- y,
- WinSta->cxWallpaper,
- WinSta->cyWallpaper,
- hWallpaperDC,
- 0,
- 0,
- SRCCOPY,
- 0,
- 0);
- }
- }
- }
- else
- {
- NtGdiBitBlt(hDC,
- x,
- y,
- WinSta->cxWallpaper,
- WinSta->cyWallpaper,
- hWallpaperDC,
- 0,
- 0,
- SRCCOPY,
- 0,
- 0);
- }
- NtGdiSelectObject(hWallpaperDC, hOldBitmap);
- NtGdiDeleteObjectApp(hWallpaperDC);
- }
- }
- }
-
- /* Back ground is set to none, clear the screen */
- if (doPatBlt)
- {
- PreviousBrush = NtGdiSelectObject(hDC, DesktopBrush);
- NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
- NtGdiSelectObject(hDC, PreviousBrush);
- }
-
- /*
- * Display system version on the desktop background
- */
-
- if (g_PaintDesktopVersion)
- {
- static WCHAR s_wszVersion[256] = {0};
- RECT rect;
-
- if (*s_wszVersion)
- {
- len = wcslen(s_wszVersion);
- }
- else
- {
- len = GetSystemVersionString(s_wszVersion);
- }
-
- if (len)
- {
- if (!UserSystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0))
- {
- rect.right = UserGetSystemMetrics(SM_CXSCREEN);
- rect.bottom = UserGetSystemMetrics(SM_CYSCREEN);
- }
-
- color_old = NtGdiSetTextColor(hDC, RGB(255,255,255));
- align_old = NtGdiSetTextAlign(hDC, TA_RIGHT);
- mode_old = NtGdiSetBkMode(hDC, TRANSPARENT);
-
- NtGdiTextOut(hDC, rect.right-16, rect.bottom-48, s_wszVersion, len);
-
- NtGdiSetBkMode(hDC, mode_old);
- NtGdiSetTextAlign(hDC, align_old);
- NtGdiSetTextColor(hDC, color_old);
- }
- }
-
- RETURN(TRUE);
-
-CLEANUP:
- DPRINT("Leave NtUserPaintDesktop, ret=%i\n",_ret_);
- UserLeave();
- END_CLEANUP;
-}
-
-
-/*
- * NtUserSwitchDesktop
- *
- * Sets the current input (interactive) desktop.
- *
- * Parameters
- * hDesktop
- * Handle to desktop.
- *
- * Return Value
- * Status
- *
- * Status
- * @unimplemented
- */
-
-BOOL STDCALL
-NtUserSwitchDesktop(HDESK hDesktop)
-{
- PDESKTOP_OBJECT DesktopObject;
- NTSTATUS Status;
- DECLARE_RETURN(BOOL);
-
- UserEnterExclusive();
- DPRINT("Enter NtUserSwitchDesktop\n");
-
- DPRINT("About to switch desktop (0x%X)\n", hDesktop);
-
- Status = IntValidateDesktopHandle(
- hDesktop,
- UserMode,
- 0,
- &DesktopObject);
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
- RETURN(FALSE);
- }
-
- /*
- * Don't allow applications switch the desktop if it's locked, unless the caller
- * is the logon application itself
- */
- if((DesktopObject->WindowStation->Flags & WSS_LOCKED) &&
- LogonProcess != NULL && LogonProcess != PsGetWin32Process())
- {
- ObDereferenceObject(DesktopObject);
- DPRINT1("Switching desktop 0x%x denied because the work station is locked!\n", hDesktop);
- RETURN(FALSE);
- }
-
- /* FIXME: Fail if the desktop belong to an invisible window station */
- /* FIXME: Fail if the process is associated with a secured
- desktop such as Winlogon or Screen-Saver */
- /* FIXME: Connect to input device */
-
- /* Set the active desktop in the desktop's window station. */
- DesktopObject->WindowStation->ActiveDesktop = DesktopObject;
-
- /* Set the global state. */
- InputDesktop = DesktopObject;
- InputDesktopHandle = hDesktop;
- InputWindowStation = DesktopObject->WindowStation;
-
- ObDereferenceObject(DesktopObject);
-
- RETURN(TRUE);
-
-CLEANUP:
- DPRINT("Leave NtUserSwitchDesktop, ret=%i\n",_ret_);
- UserLeave();
- END_CLEANUP;
-}
-
-/*
- * NtUserResolveDesktopForWOW
- *
- * Status
- * @unimplemented
- */
-
-DWORD STDCALL
-NtUserResolveDesktopForWOW(DWORD Unknown0)
-{
- UNIMPLEMENTED
- return 0;
-}
-
-/*
- * NtUserGetThreadDesktop
- *
- * Status
- * @implemented
- */
-
-HDESK STDCALL
-NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1)
-{
- NTSTATUS Status;
- PETHREAD Thread;
- PDESKTOP_OBJECT DesktopObject;
- HDESK Ret, hThreadDesktop;
- OBJECT_HANDLE_INFORMATION HandleInformation;
- DECLARE_RETURN(HDESK);
-
- UserEnterExclusive();
- DPRINT("Enter NtUserGetThreadDesktop\n");
-
- if(!dwThreadId)
- {
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- RETURN(0);
- }
-
- Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);
- if(!NT_SUCCESS(Status))
- {
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- RETURN(0);
- }
-
- if(Thread->ThreadsProcess == PsGetCurrentProcess())
- {
- /* just return the handle, we queried the desktop handle of a thread running
- in the same context */
- Ret = ((PW32THREAD)Thread->Tcb.Win32Thread)->hDesktop;
- ObDereferenceObject(Thread);
- RETURN(Ret);
- }
-
- /* get the desktop handle and the desktop of the thread */
- if(!(hThreadDesktop = ((PW32THREAD)Thread->Tcb.Win32Thread)->hDesktop) ||
- !(DesktopObject = ((PW32THREAD)Thread->Tcb.Win32Thread)->Desktop))
- {
- ObDereferenceObject(Thread);
- DPRINT1("Desktop information of thread 0x%x broken!?\n", dwThreadId);
- RETURN(NULL);
- }
-
- /* we could just use DesktopObject instead of looking up the handle, but latter
- may be a bit safer (e.g. when the desktop is being destroyed */
- /* switch into the context of the thread we're trying to get the desktop from,
- so we can use the handle */
- KeAttachProcess(&Thread->ThreadsProcess->Pcb);
- Status = ObReferenceObjectByHandle(hThreadDesktop,
- GENERIC_ALL,
- ExDesktopObjectType,
- UserMode,
- (PVOID*)&DesktopObject,
- &HandleInformation);
- KeDetachProcess();
-
- /* the handle couldn't be found, there's nothing to get... */
- if(!NT_SUCCESS(Status))
- {
- ObDereferenceObject(Thread);
- RETURN(NULL);
- }
-
- /* lookup our handle table if we can find a handle to the desktop object,
- if not, create one */
- Ret = IntGetDesktopObjectHandle(DesktopObject);
-
- /* all done, we got a valid handle to the desktop */
- ObDereferenceObject(DesktopObject);
- ObDereferenceObject(Thread);
- RETURN(Ret);
-
-CLEANUP:
- DPRINT("Leave NtUserGetThreadDesktop, ret=%i\n",_ret_);
- UserLeave();
- END_CLEANUP;
-}
-
-/*
- * NtUserSetThreadDesktop
- *
- * Status
- * @implemented
- */
-
-BOOL STDCALL
-NtUserSetThreadDesktop(HDESK hDesktop)
-{
- PW32THREAD W32Thread;
- PDESKTOP_OBJECT DesktopObject;
- NTSTATUS Status;
- DECLARE_RETURN(BOOL);
-
- UserEnterExclusive();
- DPRINT("Enter NtUserSetThreadDesktop\n");
-
- /* Validate the new desktop. */
- Status = IntValidateDesktopHandle(
- hDesktop,
- UserMode,
- 0,
- &DesktopObject);
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
- RETURN(FALSE);
- }
-
- W32Thread = PsGetWin32Thread();
-
- /* FIXME: Should check here to see if the thread has any windows. */
-
- if (W32Thread->Desktop != NULL)
- {
- ObDereferenceObject(W32Thread->Desktop);
- }
-
- W32Thread->Desktop = DesktopObject;
- W32Thread->hDesktop = hDesktop;
-
- RETURN(TRUE);
-
-CLEANUP:
- DPRINT("Leave NtUserSetThreadDesktop, ret=%i\n",_ret_);
- UserLeave();
- END_CLEANUP;
-}
-
-/* EOF */