2003-12-07 19:29:33 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*
|
2004-12-21 21:38:27 +00:00
|
|
|
* $Id: desktop.c,v 1.29 2004/12/21 21:38:27 weiden Exp $
|
2003-12-07 19:29:33 +00:00
|
|
|
*
|
|
|
|
* 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 ******************************************************************/
|
2004-05-10 17:07:20 +00:00
|
|
|
#include <w32k.h>
|
2003-12-07 19:29:33 +00:00
|
|
|
|
2004-05-05 22:47:06 +00:00
|
|
|
#if 0
|
|
|
|
/* not yet defined in w32api... */
|
|
|
|
NTSTATUS STDCALL
|
|
|
|
ObFindHandleForObject(IN PEPROCESS Process,
|
|
|
|
IN PVOID Object,
|
|
|
|
IN POBJECT_TYPE ObjectType,
|
|
|
|
IN POBJECT_HANDLE_INFORMATION HandleInformation,
|
|
|
|
OUT PHANDLE Handle);
|
|
|
|
#else
|
|
|
|
#define ObFindHandleForObject(Process, Object, ObjectType, HandleInformation, Handle) \
|
|
|
|
(STATUS_UNSUCCESSFUL)
|
|
|
|
#endif
|
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
|
|
|
|
/* Currently active desktop */
|
|
|
|
PDESKTOP_OBJECT InputDesktop = NULL;
|
|
|
|
HDC ScreenDeviceContext = NULL;
|
|
|
|
|
2004-12-06 02:23:05 +00:00
|
|
|
BOOL g_PaintDesktopVersion = FALSE;
|
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
/* INITALIZATION FUNCTIONS ****************************************************/
|
|
|
|
|
|
|
|
NTSTATUS FASTCALL
|
|
|
|
InitDesktopImpl(VOID)
|
|
|
|
{
|
2003-12-07 23:02:57 +00:00
|
|
|
return STATUS_SUCCESS;
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS FASTCALL
|
|
|
|
CleanupDesktopImpl(VOID)
|
|
|
|
{
|
2003-12-07 23:02:57 +00:00
|
|
|
return STATUS_SUCCESS;
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* PRIVATE FUNCTIONS **********************************************************/
|
|
|
|
|
2004-11-20 16:46:06 +00:00
|
|
|
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,
|
|
|
|
UserMode,
|
|
|
|
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,
|
|
|
|
UserMode,
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
2004-05-08 12:42:46 +00:00
|
|
|
VOID FASTCALL
|
|
|
|
IntGetDesktopWorkArea(PDESKTOP_OBJECT Desktop, PRECT Rect)
|
2003-12-26 00:58:33 +00:00
|
|
|
{
|
|
|
|
PRECT Ret;
|
|
|
|
|
2004-05-08 12:42:46 +00:00
|
|
|
ASSERT(Desktop);
|
|
|
|
|
2003-12-26 00:58:33 +00:00
|
|
|
Ret = &Desktop->WorkArea;
|
|
|
|
if((Ret->right == -1) && ScreenDeviceContext)
|
|
|
|
{
|
|
|
|
PDC dc;
|
2004-07-03 13:55:37 +00:00
|
|
|
BITMAPOBJ *BitmapObj;
|
2003-12-26 00:58:33 +00:00
|
|
|
dc = DC_LockDc(ScreenDeviceContext);
|
2004-12-12 01:40:39 +00:00
|
|
|
/* FIXME - Handle dc == NULL!!!! */
|
2004-07-03 13:55:37 +00:00
|
|
|
BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
|
|
|
|
if(BitmapObj)
|
2003-12-26 00:58:33 +00:00
|
|
|
{
|
2004-07-03 13:55:37 +00:00
|
|
|
Ret->right = BitmapObj->SurfObj.sizlBitmap.cx;
|
|
|
|
Ret->bottom = BitmapObj->SurfObj.sizlBitmap.cy;
|
|
|
|
BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
|
2003-12-26 00:58:33 +00:00
|
|
|
}
|
|
|
|
DC_UnlockDc(ScreenDeviceContext);
|
|
|
|
}
|
|
|
|
|
2004-05-08 12:42:46 +00:00
|
|
|
if(Rect)
|
|
|
|
{
|
|
|
|
*Rect = *Ret;
|
|
|
|
}
|
2003-12-26 00:58:33 +00:00
|
|
|
}
|
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
PDESKTOP_OBJECT FASTCALL
|
|
|
|
IntGetActiveDesktop(VOID)
|
|
|
|
{
|
2004-05-05 22:47:06 +00:00
|
|
|
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;
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2004-08-08 17:57:34 +00:00
|
|
|
PUSER_MESSAGE_QUEUE Old;
|
2003-12-07 19:29:33 +00:00
|
|
|
PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
|
|
|
|
if (!pdo)
|
|
|
|
{
|
|
|
|
DPRINT("No active desktop\n");
|
|
|
|
return;
|
|
|
|
}
|
2004-08-08 17:57:34 +00:00
|
|
|
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);
|
|
|
|
}
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
2003-12-12 18:18:21 +00:00
|
|
|
HWND FASTCALL IntGetDesktopWindow(VOID)
|
|
|
|
{
|
|
|
|
PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
|
|
|
|
if (!pdo)
|
|
|
|
{
|
|
|
|
DPRINT("No active desktop\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return pdo->DesktopWindow;
|
|
|
|
}
|
|
|
|
|
2004-07-09 20:57:38 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2004-12-10 16:52:04 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
|
|
|
|
2003-12-07 23:02:57 +00:00
|
|
|
NTSTATUS FASTCALL
|
2004-12-21 21:38:27 +00:00
|
|
|
IntShowDesktop(PDESKTOP_OBJECT Desktop)
|
2003-12-07 23:02:57 +00:00
|
|
|
{
|
|
|
|
CSRSS_API_REQUEST Request;
|
|
|
|
CSRSS_API_REPLY Reply;
|
2004-12-21 21:38:27 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
SIZEL DesktopSize;
|
|
|
|
PDC dc;
|
|
|
|
HDC hDC;
|
|
|
|
|
|
|
|
IntGraphicsCheck(TRUE);
|
|
|
|
|
|
|
|
hDC = IntGetScreenDC();
|
|
|
|
if(hDC != NULL && (dc = DC_LockDc(hDC)))
|
|
|
|
{
|
|
|
|
BITMAPOBJ *BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
|
|
|
|
if(BitmapObj != NULL)
|
|
|
|
{
|
|
|
|
DesktopSize.cx = BitmapObj->SurfObj.sizlBitmap.cx;
|
|
|
|
DesktopSize.cy = BitmapObj->SurfObj.sizlBitmap.cy;
|
|
|
|
BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
|
|
|
|
}
|
|
|
|
DC_UnlockDc(hDC);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to query screen size!\n");
|
|
|
|
IntGraphicsCheck(FALSE);
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT1("IntShowDesktop: 0x%x, %d, %d\n", Desktop->DesktopWindow, DesktopSize.cx, DesktopSize.cy);
|
|
|
|
|
|
|
|
Status = CsrInsertObject((PVOID)Desktop,
|
|
|
|
NULL,
|
|
|
|
GENERIC_ALL,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
(HANDLE*)&Request.Data.ShowDesktopRequest.hDesktop);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
Request.Type = CSRSS_SHOW_DESKTOP;
|
|
|
|
Request.Data.ShowDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
|
|
|
|
Request.Data.ShowDesktopRequest.Width = DesktopSize.cx;
|
|
|
|
Request.Data.ShowDesktopRequest.Height = DesktopSize.cy;
|
2003-12-07 23:02:57 +00:00
|
|
|
|
2004-12-21 21:38:27 +00:00
|
|
|
Status = CsrNotify(&Request, &Reply);
|
|
|
|
|
|
|
|
CsrCloseHandle(Request.Data.ShowDesktopRequest.hDesktop);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("IntShowDesktop: Failed to notify CSRSS!\n");
|
|
|
|
IntGraphicsCheck(FALSE);
|
|
|
|
}
|
2003-12-07 23:02:57 +00:00
|
|
|
|
2004-12-21 21:38:27 +00:00
|
|
|
return Status;
|
2003-12-07 23:02:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS FASTCALL
|
|
|
|
IntHideDesktop(PDESKTOP_OBJECT Desktop)
|
|
|
|
{
|
|
|
|
CSRSS_API_REQUEST Request;
|
|
|
|
CSRSS_API_REPLY Reply;
|
2004-12-21 21:38:27 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = CsrInsertObject((PVOID)Desktop,
|
|
|
|
NULL,
|
|
|
|
GENERIC_ALL,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
(HANDLE*)&Request.Data.HideDesktopRequest.hDesktop);
|
|
|
|
if(NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
Request.Type = CSRSS_HIDE_DESKTOP;
|
|
|
|
Request.Data.HideDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
|
2003-12-07 23:02:57 +00:00
|
|
|
|
2004-12-21 21:38:27 +00:00
|
|
|
Status = CsrNotify(&Request, &Reply);
|
|
|
|
|
|
|
|
CsrCloseHandle(Request.Data.HideDesktopRequest.hDesktop);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
IntGraphicsCheck(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
2003-12-07 23:02:57 +00:00
|
|
|
}
|
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
{
|
2003-12-07 23:02:57 +00:00
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
PWINSTATION_OBJECT WinStaObject;
|
|
|
|
PDESKTOP_OBJECT DesktopObject;
|
|
|
|
UNICODE_STRING DesktopName;
|
|
|
|
NTSTATUS Status;
|
|
|
|
HDESK Desktop;
|
|
|
|
CSRSS_API_REQUEST Request;
|
|
|
|
CSRSS_API_REPLY Reply;
|
2004-11-20 16:46:06 +00:00
|
|
|
|
2004-12-05 00:20:41 +00:00
|
|
|
DPRINT("CreateDesktop: %wZ\n", lpszDesktopName);
|
2003-12-07 23:02:57 +00:00
|
|
|
|
|
|
|
Status = IntValidateWindowStationHandle(
|
|
|
|
hWindowStation,
|
|
|
|
KernelMode,
|
2004-11-20 16:46:06 +00:00
|
|
|
0, /* FIXME - WINSTA_CREATEDESKTOP */
|
2003-12-07 23:02:57 +00:00
|
|
|
&WinStaObject);
|
|
|
|
|
|
|
|
if (! NT_SUCCESS(Status))
|
|
|
|
{
|
2004-11-20 16:46:06 +00:00
|
|
|
DPRINT1("Failed validation of window station handle (0x%X), cannot create desktop %wZ\n",
|
|
|
|
hWindowStation, lpszDesktopName);
|
2003-12-07 19:29:33 +00:00
|
|
|
SetLastNtError(Status);
|
2003-12-07 23:02:57 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2003-12-07 19:29:33 +00:00
|
|
|
|
2003-12-07 23:02:57 +00:00
|
|
|
if (! IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
|
|
|
|
lpszDesktopName))
|
|
|
|
{
|
2003-12-07 19:29:33 +00:00
|
|
|
SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
ObDereferenceObject(WinStaObject);
|
2003-12-07 23:02:57 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObDereferenceObject(WinStaObject);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Try to open already existing desktop
|
|
|
|
*/
|
|
|
|
|
|
|
|
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,
|
|
|
|
UserMode,
|
|
|
|
dwDesiredAccess,
|
|
|
|
NULL,
|
2004-04-09 20:03:21 +00:00
|
|
|
(HANDLE*)&Desktop);
|
2003-12-07 23:02:57 +00:00
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
2003-12-07 19:29:33 +00:00
|
|
|
DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
|
|
|
|
ExFreePool(DesktopName.Buffer);
|
|
|
|
return Desktop;
|
2003-12-07 23:02:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No existing desktop found, try to create new one
|
|
|
|
*/
|
|
|
|
|
|
|
|
Status = ObCreateObject(
|
|
|
|
ExGetPreviousMode(),
|
|
|
|
ExDesktopObjectType,
|
|
|
|
&ObjectAttributes,
|
|
|
|
ExGetPreviousMode(),
|
|
|
|
NULL,
|
|
|
|
sizeof(DESKTOP_OBJECT),
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
(PVOID*)&DesktopObject);
|
|
|
|
|
|
|
|
if (! NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed creating desktop (%wZ)\n", &DesktopName);
|
2003-12-07 19:29:33 +00:00
|
|
|
ExFreePool(DesktopName.Buffer);
|
|
|
|
SetLastNtError(STATUS_UNSUCCESSFUL);
|
2003-12-07 23:02:57 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2003-12-07 19:29:33 +00:00
|
|
|
|
2003-12-26 00:58:33 +00:00
|
|
|
// init desktop area
|
2003-12-07 23:02:57 +00:00
|
|
|
DesktopObject->WorkArea.left = 0;
|
|
|
|
DesktopObject->WorkArea.top = 0;
|
2003-12-26 00:47:18 +00:00
|
|
|
DesktopObject->WorkArea.right = -1;
|
|
|
|
DesktopObject->WorkArea.bottom = -1;
|
2004-05-08 12:42:46 +00:00
|
|
|
IntGetDesktopWorkArea(DesktopObject, NULL);
|
2003-12-07 23:02:57 +00:00
|
|
|
|
|
|
|
/* Initialize some local (to win32k) desktop state. */
|
|
|
|
DesktopObject->ActiveMessageQueue = NULL;
|
|
|
|
|
|
|
|
Status = ObInsertObject(
|
|
|
|
(PVOID)DesktopObject,
|
|
|
|
NULL,
|
|
|
|
STANDARD_RIGHTS_REQUIRED,
|
|
|
|
0,
|
|
|
|
NULL,
|
2004-04-09 20:03:21 +00:00
|
|
|
(HANDLE*)&Desktop);
|
2003-12-12 20:44:52 +00:00
|
|
|
|
2003-12-07 23:02:57 +00:00
|
|
|
ObDereferenceObject(DesktopObject);
|
|
|
|
ExFreePool(DesktopName.Buffer);
|
|
|
|
|
|
|
|
if (! NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to create desktop handle\n");
|
|
|
|
SetLastNtError(Status);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2004-11-20 16:46:06 +00:00
|
|
|
/*
|
|
|
|
* Create a handle for CSRSS and notify CSRSS
|
|
|
|
*/
|
2003-12-07 23:02:57 +00:00
|
|
|
Request.Type = CSRSS_CREATE_DESKTOP;
|
2004-11-20 16:46:06 +00:00
|
|
|
Status = CsrInsertObject((PVOID)DesktopObject,
|
|
|
|
NULL,
|
|
|
|
GENERIC_ALL,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
(HANDLE*)&Request.Data.CreateDesktopRequest.DesktopHandle);
|
|
|
|
if (! NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to create desktop handle for CSRSS\n");
|
|
|
|
ZwClose(Desktop);
|
|
|
|
SetLastNtError(Status);
|
|
|
|
return NULL;
|
|
|
|
}
|
2003-12-07 23:02:57 +00:00
|
|
|
|
2004-05-28 21:33:41 +00:00
|
|
|
Status = CsrNotify(&Request, &Reply);
|
2003-12-07 23:02:57 +00:00
|
|
|
if (! NT_SUCCESS(Status))
|
|
|
|
{
|
2004-11-20 16:46:06 +00:00
|
|
|
CsrCloseHandle(Request.Data.CreateDesktopRequest.DesktopHandle);
|
2003-12-07 23:02:57 +00:00
|
|
|
DPRINT1("Failed to notify CSRSS about new desktop\n");
|
|
|
|
ZwClose(Desktop);
|
|
|
|
SetLastNtError(Status);
|
|
|
|
return NULL;
|
|
|
|
}
|
2003-12-07 19:29:33 +00:00
|
|
|
|
2003-12-07 23:02:57 +00:00
|
|
|
return Desktop;
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
PWINSTATION_OBJECT WinStaObject;
|
|
|
|
UNICODE_STRING DesktopName;
|
|
|
|
NTSTATUS Status;
|
|
|
|
HDESK Desktop;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Validate the window station handle and compose the fully
|
|
|
|
* qualified desktop name
|
|
|
|
*/
|
|
|
|
|
|
|
|
Status = IntValidateWindowStationHandle(
|
2004-11-20 16:46:06 +00:00
|
|
|
PsGetCurrentProcess()->Win32WindowStation,
|
2003-12-07 19:29:33 +00:00
|
|
|
KernelMode,
|
|
|
|
0,
|
|
|
|
&WinStaObject);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2004-11-20 16:46:06 +00:00
|
|
|
DPRINT1("Failed validation of window station handle (0x%X)\n",
|
|
|
|
PsGetCurrentProcess()->Win32WindowStation);
|
2003-12-07 19:29:33 +00:00
|
|
|
SetLastNtError(Status);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
|
|
|
|
lpszDesktopName))
|
|
|
|
{
|
|
|
|
SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
ObDereferenceObject(WinStaObject);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObDereferenceObject(WinStaObject);
|
|
|
|
|
2004-11-20 16:46:06 +00:00
|
|
|
DPRINT1("Trying to open desktop (%wZ)\n", &DesktopName);
|
2003-12-07 19:29:33 +00:00
|
|
|
|
|
|
|
/* Initialize ObjectAttributes for the desktop object */
|
|
|
|
InitializeObjectAttributes(
|
|
|
|
&ObjectAttributes,
|
|
|
|
&DesktopName,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = ObOpenObjectByName(
|
|
|
|
&ObjectAttributes,
|
|
|
|
ExDesktopObjectType,
|
|
|
|
NULL,
|
|
|
|
UserMode,
|
|
|
|
dwDesiredAccess,
|
|
|
|
NULL,
|
2004-04-09 20:03:21 +00:00
|
|
|
(HANDLE*)&Desktop);
|
2003-12-07 19:29:33 +00:00
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastNtError(Status);
|
|
|
|
ExFreePool(DesktopName.Buffer);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
|
|
|
|
ExFreePool(DesktopName.Buffer);
|
|
|
|
|
|
|
|
return Desktop;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
HDESK Desktop;
|
|
|
|
|
|
|
|
DPRINT("About to open input desktop\n");
|
|
|
|
|
|
|
|
/* Create a new handle to the object */
|
|
|
|
|
|
|
|
Status = ObOpenObjectByPointer(
|
2004-12-21 21:38:27 +00:00
|
|
|
InputDesktop,
|
2003-12-07 19:29:33 +00:00
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
dwDesiredAccess,
|
|
|
|
ExDesktopObjectType,
|
|
|
|
UserMode,
|
2004-04-09 20:03:21 +00:00
|
|
|
(HANDLE*)&Desktop);
|
2003-12-07 19:29:33 +00:00
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("Successfully opened input desktop\n");
|
|
|
|
return (HDESK)Desktop;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetLastNtError(Status);
|
|
|
|
return (HDESK)0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
|
|
|
|
DPRINT("About to close desktop handle (0x%X)\n", hDesktop);
|
|
|
|
|
|
|
|
Status = IntValidateDesktopHandle(
|
|
|
|
hDesktop,
|
2003-12-12 20:44:52 +00:00
|
|
|
UserMode,
|
2003-12-07 19:29:33 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2004-09-15 20:53:43 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
/*
|
|
|
|
* 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
|
2004-09-15 20:53:43 +00:00
|
|
|
* hDC
|
2003-12-07 19:29:33 +00:00
|
|
|
* Handle to the device context.
|
|
|
|
*
|
|
|
|
* Status
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
|
|
|
|
BOOL STDCALL
|
|
|
|
NtUserPaintDesktop(HDC hDC)
|
|
|
|
{
|
2003-12-13 18:40:34 +00:00
|
|
|
RECT Rect;
|
2003-12-22 15:30:21 +00:00
|
|
|
HBRUSH DesktopBrush, PreviousBrush;
|
|
|
|
HWND hWndDesktop;
|
2004-09-15 20:53:43 +00:00
|
|
|
BOOL doPatBlt = TRUE;
|
|
|
|
int len;
|
|
|
|
|
2004-08-17 21:47:36 +00:00
|
|
|
PWINSTATION_OBJECT WinSta = PsGetWin32Thread()->Desktop->WindowStation;
|
2003-12-07 19:29:33 +00:00
|
|
|
|
2003-12-13 18:40:34 +00:00
|
|
|
IntGdiGetClipBox(hDC, &Rect);
|
2003-12-07 19:29:33 +00:00
|
|
|
|
2003-12-22 15:30:21 +00:00
|
|
|
hWndDesktop = IntGetDesktopWindow();
|
|
|
|
DesktopBrush = (HBRUSH)NtUserGetClassLong(hWndDesktop, GCL_HBRBACKGROUND, FALSE);
|
|
|
|
|
2003-12-13 18:40:34 +00:00
|
|
|
/*
|
|
|
|
* Paint desktop background
|
|
|
|
*/
|
2003-12-07 19:29:33 +00:00
|
|
|
|
2004-08-17 21:47:36 +00:00
|
|
|
if(WinSta->hbmWallpaper != NULL)
|
|
|
|
{
|
|
|
|
PWINDOW_OBJECT DeskWin;
|
2004-08-17 21:52:17 +00:00
|
|
|
|
2004-08-17 21:47:36 +00:00
|
|
|
if((DeskWin = IntGetWindowObject(hWndDesktop)))
|
|
|
|
{
|
|
|
|
SIZE sz;
|
|
|
|
int x, y;
|
|
|
|
HDC hWallpaperDC;
|
|
|
|
|
|
|
|
sz.cx = DeskWin->WindowRect.right - DeskWin->WindowRect.left;
|
|
|
|
sz.cy = DeskWin->WindowRect.bottom - DeskWin->WindowRect.top;
|
|
|
|
IntReleaseWindowObject(DeskWin);
|
2004-08-17 21:52:17 +00:00
|
|
|
|
2004-08-17 21:47:36 +00:00
|
|
|
x = (sz.cx / 2) - (WinSta->cxWallpaper / 2);
|
|
|
|
y = (sz.cy / 2) - (WinSta->cyWallpaper / 2);
|
|
|
|
|
|
|
|
hWallpaperDC = NtGdiCreateCompatableDC(hDC);
|
|
|
|
if(hWallpaperDC != NULL)
|
|
|
|
{
|
|
|
|
HBITMAP hOldBitmap;
|
2004-08-17 21:52:17 +00:00
|
|
|
|
2004-08-17 21:47:36 +00:00
|
|
|
if(x > 0 || y > 0)
|
|
|
|
{
|
|
|
|
/* FIXME - clip out the bitmap */
|
|
|
|
PreviousBrush = NtGdiSelectObject(hDC, DesktopBrush);
|
|
|
|
NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
|
|
|
|
NtGdiSelectObject(hDC, PreviousBrush);
|
|
|
|
}
|
2004-09-15 20:53:43 +00:00
|
|
|
else
|
|
|
|
doPatBlt = FALSE;
|
|
|
|
|
2004-08-17 21:47:36 +00:00
|
|
|
hOldBitmap = NtGdiSelectObject(hWallpaperDC, WinSta->hbmWallpaper);
|
|
|
|
NtGdiBitBlt(hDC, x, y, WinSta->cxWallpaper, WinSta->cyWallpaper, hWallpaperDC, 0, 0, SRCCOPY);
|
|
|
|
NtGdiSelectObject(hWallpaperDC, hOldBitmap);
|
|
|
|
|
|
|
|
NtGdiDeleteDC(hWallpaperDC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-15 20:53:43 +00:00
|
|
|
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
|
|
|
|
*/
|
|
|
|
|
2004-12-06 02:23:05 +00:00
|
|
|
if (g_PaintDesktopVersion) {
|
2004-09-15 20:53:43 +00:00
|
|
|
static WCHAR s_wszVersion[256] = {0};
|
|
|
|
RECT rect;
|
|
|
|
|
|
|
|
if (*s_wszVersion)
|
|
|
|
len = wcslen(s_wszVersion);
|
|
|
|
else
|
|
|
|
len = GetSystemVersionString(s_wszVersion);
|
|
|
|
|
|
|
|
if (len) {
|
|
|
|
if (!NtUserSystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0)) {
|
|
|
|
rect.right = NtUserGetSystemMetrics(SM_CXSCREEN);
|
|
|
|
rect.bottom = NtUserGetSystemMetrics(SM_CYSCREEN);
|
|
|
|
}
|
|
|
|
|
|
|
|
COLORREF color_old = NtGdiSetTextColor(hDC, RGB(255,255,255));
|
|
|
|
UINT align_old = NtGdiSetTextAlign(hDC, TA_RIGHT);
|
|
|
|
int 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);
|
|
|
|
}
|
|
|
|
}
|
2003-12-07 19:29:33 +00:00
|
|
|
|
2003-12-13 18:40:34 +00:00
|
|
|
return TRUE;
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
2004-09-15 20:53:43 +00:00
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
/*
|
|
|
|
* NtUserSwitchDesktop
|
|
|
|
*
|
|
|
|
* Sets the current input (interactive) desktop.
|
|
|
|
*
|
|
|
|
* Parameters
|
|
|
|
* hDesktop
|
|
|
|
* Handle to desktop.
|
|
|
|
*
|
|
|
|
* Return Value
|
|
|
|
* Status
|
|
|
|
*
|
|
|
|
* Status
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
|
|
|
|
BOOL STDCALL
|
|
|
|
NtUserSwitchDesktop(HDESK hDesktop)
|
|
|
|
{
|
2004-12-21 21:38:27 +00:00
|
|
|
PDESKTOP_OBJECT DesktopObject, PreviousDesktop;
|
2003-12-07 19:29:33 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
DPRINT("About to switch desktop (0x%X)\n", hDesktop);
|
|
|
|
|
|
|
|
Status = IntValidateDesktopHandle(
|
|
|
|
hDesktop,
|
2003-12-12 18:18:21 +00:00
|
|
|
UserMode,
|
2003-12-07 19:29:33 +00:00
|
|
|
0,
|
|
|
|
&DesktopObject);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-05-01 16:43:15 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
/* 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. */
|
2004-12-21 21:38:27 +00:00
|
|
|
PreviousDesktop = InterlockedExchangePointer(&DesktopObject->WindowStation->ActiveDesktop, DesktopObject);
|
|
|
|
if(PreviousDesktop != DesktopObject)
|
|
|
|
{
|
|
|
|
/* FIXME - nasty hack... */
|
|
|
|
|
|
|
|
if(PreviousDesktop != NULL)
|
|
|
|
{
|
|
|
|
IntHideDesktop(PreviousDesktop);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the global state. */
|
|
|
|
InputDesktop = DesktopObject;
|
|
|
|
InputWindowStation = DesktopObject->WindowStation;
|
2003-12-07 19:29:33 +00:00
|
|
|
|
2004-12-21 21:38:27 +00:00
|
|
|
/* FIXME - HACK! This is only because we want GUI on demand! */
|
|
|
|
if(IntIsGUIActive())
|
|
|
|
{
|
|
|
|
IntShowDesktop(DesktopObject);
|
|
|
|
}
|
|
|
|
}
|
2003-12-07 19:29:33 +00:00
|
|
|
|
|
|
|
ObDereferenceObject(DesktopObject);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NtUserResolveDesktopForWOW
|
|
|
|
*
|
|
|
|
* Status
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
|
|
|
|
DWORD STDCALL
|
|
|
|
NtUserResolveDesktopForWOW(DWORD Unknown0)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NtUserGetThreadDesktop
|
|
|
|
*
|
|
|
|
* Status
|
2003-12-12 20:44:52 +00:00
|
|
|
* @implemented
|
2003-12-07 19:29:33 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
HDESK STDCALL
|
|
|
|
NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1)
|
|
|
|
{
|
2003-12-12 20:44:52 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
PETHREAD Thread;
|
2004-05-05 22:47:06 +00:00
|
|
|
PDESKTOP_OBJECT DesktopObject;
|
|
|
|
HDESK Ret, hThreadDesktop;
|
|
|
|
OBJECT_HANDLE_INFORMATION HandleInformation;
|
2003-12-12 20:44:52 +00:00
|
|
|
|
|
|
|
if(!dwThreadId)
|
|
|
|
{
|
|
|
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = PsLookupThreadByThreadId((PVOID)dwThreadId, &Thread);
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-05-05 22:47:06 +00:00
|
|
|
if(Thread->ThreadsProcess == PsGetCurrentProcess())
|
2003-12-12 20:44:52 +00:00
|
|
|
{
|
2004-05-05 22:47:06 +00:00
|
|
|
/* just return the handle, we queried the desktop handle of a thread running
|
|
|
|
in the same context */
|
2004-09-28 15:02:31 +00:00
|
|
|
Ret = Thread->Tcb.Win32Thread->hDesktop;
|
2004-05-05 22:47:06 +00:00
|
|
|
ObDereferenceObject(Thread);
|
2003-12-12 20:44:52 +00:00
|
|
|
return Ret;
|
|
|
|
}
|
|
|
|
|
2004-05-05 22:47:06 +00:00
|
|
|
/* get the desktop handle and the desktop of the thread */
|
2004-09-28 15:02:31 +00:00
|
|
|
if(!(hThreadDesktop = Thread->Tcb.Win32Thread->hDesktop) ||
|
|
|
|
!(DesktopObject = Thread->Tcb.Win32Thread->Desktop))
|
2004-05-05 22:47:06 +00:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
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;
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NtUserSetThreadDesktop
|
|
|
|
*
|
|
|
|
* Status
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
|
|
|
|
BOOL STDCALL
|
|
|
|
NtUserSetThreadDesktop(HDESK hDesktop)
|
|
|
|
{
|
2004-05-05 22:47:06 +00:00
|
|
|
PW32THREAD W32Thread;
|
2003-12-07 19:29:33 +00:00
|
|
|
PDESKTOP_OBJECT DesktopObject;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
/* Validate the new desktop. */
|
|
|
|
Status = IntValidateDesktopHandle(
|
|
|
|
hDesktop,
|
2003-12-12 20:44:52 +00:00
|
|
|
UserMode,
|
2003-12-07 19:29:33 +00:00
|
|
|
0,
|
|
|
|
&DesktopObject);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2004-05-05 22:47:06 +00:00
|
|
|
W32Thread = PsGetWin32Thread();
|
2003-12-07 19:29:33 +00:00
|
|
|
|
|
|
|
/* FIXME: Should check here to see if the thread has any windows. */
|
|
|
|
|
2004-05-05 22:47:06 +00:00
|
|
|
if (W32Thread->Desktop != NULL)
|
2003-12-07 19:29:33 +00:00
|
|
|
{
|
2004-05-05 22:47:06 +00:00
|
|
|
ObDereferenceObject(W32Thread->Desktop);
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
2004-05-05 22:47:06 +00:00
|
|
|
W32Thread->Desktop = DesktopObject;
|
|
|
|
W32Thread->hDesktop = hDesktop;
|
2003-12-07 19:29:33 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|