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.
|
|
|
|
*
|
2005-01-06 13:58:04 +00:00
|
|
|
* $Id$
|
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 ******************************************************************/
|
2005-06-29 07:09:25 +00:00
|
|
|
|
2004-05-10 17:07:20 +00:00
|
|
|
#include <w32k.h>
|
2003-12-07 19:29:33 +00:00
|
|
|
|
2005-06-29 07:09:25 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
|
|
|
|
/* Currently active desktop */
|
|
|
|
PDESKTOP_OBJECT InputDesktop = NULL;
|
2005-05-08 02:11:54 +00:00
|
|
|
HDESK InputDesktopHandle = NULL;
|
2003-12-07 19:29:33 +00:00
|
|
|
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 ****************************************************/
|
|
|
|
|
2005-06-26 21:42:30 +00:00
|
|
|
static GENERIC_MAPPING IntDesktopMapping =
|
2005-09-07 21:25:42 +00:00
|
|
|
{
|
|
|
|
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
|
|
|
|
};
|
2005-06-26 21:42:30 +00:00
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
NTSTATUS FASTCALL
|
|
|
|
InitDesktopImpl(VOID)
|
|
|
|
{
|
2005-06-26 04:49:10 +00:00
|
|
|
/* Set Desktop Object Attributes */
|
|
|
|
ExDesktopObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(DESKTOP_OBJECT);
|
2005-06-26 21:42:30 +00:00
|
|
|
ExDesktopObjectType->TypeInfo.GenericMapping = IntDesktopMapping;
|
2005-09-07 21:25:42 +00:00
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS FASTCALL
|
|
|
|
CleanupDesktopImpl(VOID)
|
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
return STATUS_SUCCESS;
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
2005-03-12 14:15:49 +00:00
|
|
|
/* OBJECT CALLBACKS **********************************************************/
|
|
|
|
|
|
|
|
NTSTATUS STDCALL
|
|
|
|
IntDesktopObjectCreate(PVOID ObjectBody,
|
2005-09-07 21:25:42 +00:00
|
|
|
PVOID Parent,
|
|
|
|
PWSTR RemainingPath,
|
|
|
|
struct _OBJECT_ATTRIBUTES* ObjectAttributes)
|
2005-03-12 14:15:49 +00:00
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)ObjectBody;
|
|
|
|
UNICODE_STRING UnicodeString;
|
2005-03-12 14:15:49 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
DPRINT("Creating desktop (0x%X) Name (%S)\n", Desktop, RemainingPath);
|
|
|
|
if (RemainingPath == NULL)
|
|
|
|
{
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2005-03-12 14:15:49 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
if (wcschr((RemainingPath + 1), '\\') != NULL)
|
|
|
|
{
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
2005-03-12 14:15:49 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
RtlInitUnicodeString(&UnicodeString, (RemainingPath + 1));
|
2005-03-12 14:15:49 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
InitializeListHead(&Desktop->ShellHookWindows);
|
2005-03-12 14:15:49 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
Desktop->WindowStation = (PWINSTATION_OBJECT)Parent;
|
2005-03-12 14:15:49 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
/* Put the desktop on the window station's list of associcated desktops */
|
2005-09-24 02:50:02 +00:00
|
|
|
// ExInterlocked
|
|
|
|
InsertTailList(
|
2005-09-07 21:25:42 +00:00
|
|
|
&Desktop->WindowStation->DesktopListHead,
|
2005-09-24 02:50:02 +00:00
|
|
|
&Desktop->ListEntry);//,
|
|
|
|
// &Desktop->WindowStation->Lock);
|
2005-09-07 21:25:42 +00:00
|
|
|
|
|
|
|
return RtlCreateUnicodeString(&Desktop->Name, UnicodeString.Buffer);
|
2005-03-12 14:15:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID STDCALL
|
|
|
|
IntDesktopObjectDelete(PVOID DeletedObject)
|
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)DeletedObject;
|
2005-03-12 14:15:49 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
DPRINT("Deleting desktop (0x%X)\n", Desktop);
|
2005-03-12 14:15:49 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
/* Remove the desktop from the window station's list of associcated desktops */
|
|
|
|
RemoveEntryList(&Desktop->ListEntry);
|
2005-03-12 14:15:49 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
RtlFreeUnicodeString(&Desktop->Name);
|
2005-03-12 14:15:49 +00:00
|
|
|
}
|
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
/* PRIVATE FUNCTIONS **********************************************************/
|
|
|
|
|
2005-09-24 02:50:02 +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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-20 16:46:06 +00:00
|
|
|
NTSTATUS FASTCALL
|
|
|
|
IntParseDesktopPath(PEPROCESS Process,
|
|
|
|
PUNICODE_STRING DesktopPath,
|
|
|
|
HWINSTA *hWinSta,
|
|
|
|
HDESK *hDesktop)
|
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
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)
|
2004-11-20 16:46:06 +00:00
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
if(*c == L'\\')
|
|
|
|
{
|
|
|
|
wl = (ULONG_PTR)c - (ULONG_PTR)DesktopPath->Buffer;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
l -= sizeof(WCHAR);
|
|
|
|
c++;
|
2004-11-20 16:46:06 +00:00
|
|
|
}
|
2005-09-07 21:25:42 +00:00
|
|
|
|
|
|
|
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,
|
2004-11-20 16:46:06 +00:00
|
|
|
NULL,
|
2005-09-07 21:25:42 +00:00
|
|
|
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,
|
2004-11-20 16:46:06 +00:00
|
|
|
NULL,
|
2005-09-07 21:25:42 +00:00
|
|
|
NULL);
|
2004-11-20 16:46:06 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
Status = ObOpenObjectByName(&ObjectAttributes,
|
|
|
|
ExDesktopObjectType,
|
|
|
|
NULL,
|
|
|
|
KernelMode,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
(HANDLE*)hDesktop);
|
2005-05-08 02:11:54 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2005-05-08 02:11:54 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
return STATUS_SUCCESS;
|
2004-11-20 16:46:06 +00:00
|
|
|
}
|
|
|
|
|
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(
|
2005-09-07 21:25:42 +00:00
|
|
|
Desktop,
|
|
|
|
DesiredAccess,
|
|
|
|
ExDesktopObjectType,
|
|
|
|
AccessMode,
|
|
|
|
(PVOID*)Object,
|
|
|
|
NULL);
|
2003-12-07 19:29:33 +00:00
|
|
|
|
|
|
|
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
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
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;
|
|
|
|
}
|
2003-12-26 00:58:33 +00:00
|
|
|
}
|
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
PDESKTOP_OBJECT FASTCALL
|
|
|
|
IntGetActiveDesktop(VOID)
|
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
return InputDesktop;
|
2004-05-05 22:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* returns or creates a handle to the desktop object
|
|
|
|
*/
|
|
|
|
HDESK FASTCALL
|
|
|
|
IntGetDesktopObjectHandle(PDESKTOP_OBJECT DesktopObject)
|
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
HDESK Ret;
|
2005-05-08 02:11:54 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
ASSERT(DesktopObject);
|
2005-05-08 02:11:54 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
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)
|
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
DPRINT("Message Queue already attached to another desktop!\n");
|
|
|
|
return;
|
2004-08-08 17:57:34 +00:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
2005-09-07 21:25:42 +00:00
|
|
|
return pdo->DesktopWindow;
|
2003-12-12 18:18:21 +00:00
|
|
|
}
|
|
|
|
|
2005-09-05 21:19:23 +00:00
|
|
|
PWINDOW_OBJECT FASTCALL UserGetDesktopWindow(VOID)
|
|
|
|
{
|
|
|
|
PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
|
2005-09-07 21:25:42 +00:00
|
|
|
|
2005-09-05 21:19:23 +00:00
|
|
|
if (!pdo)
|
|
|
|
{
|
|
|
|
DPRINT("No active desktop\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-09-07 21:25:42 +00:00
|
|
|
|
2005-09-11 14:48:32 +00:00
|
|
|
return UserGetWindowObject(pdo->DesktopWindow);
|
2005-09-05 21:19:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-07-09 20:57:38 +00:00
|
|
|
HWND FASTCALL IntGetCurrentThreadDesktopWindow(VOID)
|
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
PDESKTOP_OBJECT pdo = PsGetWin32Thread()->Desktop;
|
|
|
|
if (NULL == pdo)
|
|
|
|
{
|
2004-07-09 20:57:38 +00:00
|
|
|
DPRINT1("Thread doesn't have a desktop\n");
|
|
|
|
return NULL;
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
|
|
|
return pdo->DesktopWindow;
|
2004-07-09 20:57:38 +00:00
|
|
|
}
|
|
|
|
|
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 */
|
2005-05-08 02:11:54 +00:00
|
|
|
Status = RtlQueryRegistryValues(RTL_REGISTRY_USER,
|
2004-12-10 16:52:04 +00:00
|
|
|
L"Control Panel\\Desktop",
|
|
|
|
QueryTable, NULL, NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("RtlQueryRegistryValues failed for PaintDesktopVersion (%x)\n",
|
|
|
|
Status);
|
|
|
|
g_PaintDesktopVersion = FALSE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-08 02:11:54 +00:00
|
|
|
|
2004-12-10 16:52:04 +00:00
|
|
|
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
|
2005-09-05 21:19:23 +00:00
|
|
|
co_IntShowDesktop(PDESKTOP_OBJECT Desktop, ULONG Width, ULONG Height)
|
2003-12-07 23:02:57 +00:00
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
CSR_API_MESSAGE Request;
|
2003-12-07 23:02:57 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
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;
|
2003-12-07 23:02:57 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
return co_CsrNotify(&Request);
|
2003-12-07 23:02:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS FASTCALL
|
|
|
|
IntHideDesktop(PDESKTOP_OBJECT Desktop)
|
|
|
|
{
|
2004-12-24 17:45:59 +00:00
|
|
|
#if 0
|
2005-09-07 21:25:42 +00:00
|
|
|
CSRSS_API_REQUEST Request;
|
|
|
|
CSRSS_API_REPLY Reply;
|
2003-12-07 23:02:57 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
Request.Type = CSRSS_HIDE_DESKTOP;
|
|
|
|
Request.Data.HideDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
|
2004-12-24 17:45:59 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
return NotifyCsrss(&Request, &Reply);
|
2004-12-24 17:45:59 +00:00
|
|
|
#else
|
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
PWINDOW_OBJECT DesktopWindow;
|
|
|
|
|
|
|
|
DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow);
|
|
|
|
if (! DesktopWindow)
|
|
|
|
{
|
2004-12-24 17:45:59 +00:00
|
|
|
return ERROR_INVALID_WINDOW_HANDLE;
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
|
|
|
DesktopWindow->Style &= ~WS_VISIBLE;
|
2004-12-24 17:45:59 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
return STATUS_SUCCESS;
|
2004-12-24 17:45:59 +00:00
|
|
|
#endif
|
2003-12-07 23:02:57 +00:00
|
|
|
}
|
|
|
|
|
2005-09-24 02:50:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2005-03-13 23:08:51 +00:00
|
|
|
/*
|
|
|
|
* Send the Message to the windows registered for ShellHook
|
|
|
|
* notifications. The lParam contents depend on the Message. See
|
|
|
|
* MSDN for more details (RegisterShellHookWindow)
|
|
|
|
*/
|
2005-09-05 21:19:23 +00:00
|
|
|
VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam)
|
2005-03-13 23:08:51 +00:00
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
PDESKTOP_OBJECT Desktop = IntGetActiveDesktop();
|
2005-09-24 02:50:02 +00:00
|
|
|
HWND* HwndList;
|
2005-03-13 23:08:51 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
static UINT MsgType = 0;
|
2005-03-13 23:08:51 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
if (!MsgType)
|
|
|
|
{
|
2005-03-13 23:08:51 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
/* Too bad, this doesn't work.*/
|
2005-03-13 23:08:51 +00:00
|
|
|
#if 0
|
2005-09-07 21:25:42 +00:00
|
|
|
UNICODE_STRING Str;
|
|
|
|
RtlInitUnicodeString(&Str, L"SHELLHOOK");
|
|
|
|
MsgType = UserRegisterWindowMessage(&Str);
|
2005-03-13 23:08:51 +00:00
|
|
|
#endif
|
2005-09-07 21:25:42 +00:00
|
|
|
|
|
|
|
MsgType = IntAddAtom(L"SHELLHOOK");
|
|
|
|
|
|
|
|
DPRINT("MsgType = %x\n", MsgType);
|
|
|
|
if (!MsgType)
|
|
|
|
DPRINT1("LastError: %x\n", GetLastNtError());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Desktop)
|
|
|
|
{
|
|
|
|
DPRINT1("IntShellHookNotify: No desktop!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-09-24 02:50:02 +00:00
|
|
|
HwndList = UserBuildShellHookHwndList(Desktop);
|
|
|
|
if (HwndList)
|
2005-09-07 21:25:42 +00:00
|
|
|
{
|
2005-09-24 02:50:02 +00:00
|
|
|
HWND* cursor = HwndList;
|
|
|
|
|
|
|
|
for (; *cursor; cursor++)
|
2005-09-07 21:25:42 +00:00
|
|
|
{
|
2005-09-24 02:50:02 +00:00
|
|
|
DPRINT("Sending notify\n");
|
|
|
|
co_IntPostOrSendMessage(*cursor,
|
|
|
|
MsgType,
|
|
|
|
Message,
|
|
|
|
lParam);
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
|
|
|
|
2005-09-24 02:50:02 +00:00
|
|
|
ExFreePool(HwndList);
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
2005-09-24 02:50:02 +00:00
|
|
|
|
2005-03-13 23:08:51 +00:00
|
|
|
}
|
2005-05-08 02:11:54 +00:00
|
|
|
|
2005-03-13 23:08:51 +00:00
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
|
|
|
|
PSHELL_HOOK_WINDOW Entry;
|
2005-03-13 23:08:51 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
DPRINT("IntRegisterShellHookWindow\n");
|
2005-03-13 23:08:51 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
/* First deregister the window, so we can be sure it's never twice in the
|
|
|
|
* list.
|
|
|
|
*/
|
|
|
|
IntDeRegisterShellHookWindow(hWnd);
|
2005-03-13 23:08:51 +00:00
|
|
|
|
2005-09-24 02:50:02 +00:00
|
|
|
Entry = ExAllocatePoolWithTag(PagedPool,
|
2005-09-07 21:25:42 +00:00
|
|
|
sizeof(SHELL_HOOK_WINDOW),
|
|
|
|
TAG_WINSTA);
|
2005-03-13 23:08:51 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
if (!Entry)
|
|
|
|
return FALSE;
|
2005-03-13 23:08:51 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
Entry->hWnd = hWnd;
|
2005-03-13 23:08:51 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
InsertTailList(&Desktop->ShellHookWindows, &Entry->ListEntry);
|
2005-03-13 23:08:51 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
return TRUE;
|
2005-03-13 23:08:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
|
|
|
|
PSHELL_HOOK_WINDOW Current;
|
2005-03-13 23:08:51 +00:00
|
|
|
|
2005-09-24 02:50:02 +00:00
|
|
|
LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
|
2005-09-07 21:25:42 +00:00
|
|
|
{
|
|
|
|
if (Current->hWnd == hWnd)
|
|
|
|
{
|
2005-09-24 02:50:02 +00:00
|
|
|
RemoveEntryList(&Current->ListEntry);
|
|
|
|
ExFreePool(Current);
|
2005-09-07 21:25:42 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
2005-03-13 23:08:51 +00:00
|
|
|
}
|
|
|
|
|
2005-09-24 02:50:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* SYSCALLS *******************************************************************/
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
PWINSTATION_OBJECT WinStaObject;
|
|
|
|
PDESKTOP_OBJECT DesktopObject;
|
|
|
|
UNICODE_STRING DesktopName;
|
|
|
|
NTSTATUS Status;
|
|
|
|
HDESK Desktop;
|
|
|
|
CSR_API_MESSAGE Request;
|
|
|
|
DECLARE_RETURN(HDESK);
|
|
|
|
|
2005-09-24 02:50:02 +00:00
|
|
|
DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName);
|
2005-09-07 21:25:42 +00:00
|
|
|
UserEnterExclusive();
|
|
|
|
|
|
|
|
Status = IntValidateWindowStationHandle(
|
|
|
|
hWindowStation,
|
|
|
|
KernelMode,
|
|
|
|
0, /* FIXME - WINSTA_CREATEDESKTOP */
|
|
|
|
&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",
|
2005-09-07 21:25:42 +00:00
|
|
|
hWindowStation, lpszDesktopName);
|
2003-12-07 19:29:33 +00:00
|
|
|
SetLastNtError(Status);
|
2005-09-05 21:19:23 +00:00
|
|
|
RETURN( NULL);
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
2005-05-08 02:11:54 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
if (! IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
|
|
|
|
lpszDesktopName))
|
|
|
|
{
|
2003-12-07 19:29:33 +00:00
|
|
|
SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
ObDereferenceObject(WinStaObject);
|
2005-09-05 21:19:23 +00:00
|
|
|
RETURN( NULL);
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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))
|
|
|
|
{
|
2003-12-07 19:29:33 +00:00
|
|
|
DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
|
|
|
|
ExFreePool(DesktopName.Buffer);
|
2005-09-05 21:19:23 +00:00
|
|
|
RETURN( Desktop);
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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))
|
|
|
|
{
|
2003-12-07 23:02:57 +00:00
|
|
|
DPRINT1("Failed creating desktop (%wZ)\n", &DesktopName);
|
2003-12-07 19:29:33 +00:00
|
|
|
ExFreePool(DesktopName.Buffer);
|
|
|
|
SetLastNtError(STATUS_UNSUCCESSFUL);
|
2005-09-05 21:19:23 +00:00
|
|
|
RETURN( NULL);
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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))
|
|
|
|
{
|
2003-12-07 23:02:57 +00:00
|
|
|
DPRINT1("Failed to create desktop handle\n");
|
|
|
|
SetLastNtError(Status);
|
2005-09-05 21:19:23 +00:00
|
|
|
RETURN( NULL);
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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))
|
|
|
|
{
|
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);
|
2005-09-05 21:19:23 +00:00
|
|
|
RETURN( NULL);
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RETURN( Desktop);
|
2003-12-07 19:29:33 +00:00
|
|
|
|
2005-09-05 21:19:23 +00:00
|
|
|
CLEANUP:
|
2005-09-07 21:25:42 +00:00
|
|
|
DPRINT("Leave NtUserCreateDesktop, ret=%i\n",_ret_);
|
|
|
|
UserLeave();
|
|
|
|
END_CLEANUP;
|
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;
|
2005-09-05 21:19:23 +00:00
|
|
|
DECLARE_RETURN(HDESK);
|
2005-09-07 21:25:42 +00:00
|
|
|
|
2005-09-05 21:19:23 +00:00
|
|
|
DPRINT("Enter NtUserOpenDesktop: %wZ\n", lpszDesktopName);
|
|
|
|
UserEnterExclusive();
|
2005-09-07 21:25:42 +00:00
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
/*
|
|
|
|
* Validate the window station handle and compose the fully
|
|
|
|
* qualified desktop name
|
|
|
|
*/
|
|
|
|
|
|
|
|
Status = IntValidateWindowStationHandle(
|
2005-09-07 21:25:42 +00:00
|
|
|
PsGetCurrentProcess()->Win32WindowStation,
|
|
|
|
KernelMode,
|
|
|
|
0,
|
|
|
|
&WinStaObject);
|
2003-12-07 19:29:33 +00:00
|
|
|
|
|
|
|
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);
|
2005-09-05 21:19:23 +00:00
|
|
|
RETURN( 0);
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
|
2005-09-07 21:25:42 +00:00
|
|
|
lpszDesktopName))
|
2003-12-07 19:29:33 +00:00
|
|
|
{
|
|
|
|
SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
ObDereferenceObject(WinStaObject);
|
2005-09-05 21:19:23 +00:00
|
|
|
RETURN( 0);
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
2005-05-08 02:11:54 +00:00
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
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(
|
2005-09-07 21:25:42 +00:00
|
|
|
&ObjectAttributes,
|
|
|
|
ExDesktopObjectType,
|
|
|
|
NULL,
|
|
|
|
UserMode,
|
|
|
|
dwDesiredAccess,
|
|
|
|
NULL,
|
|
|
|
(HANDLE*)&Desktop);
|
2003-12-07 19:29:33 +00:00
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastNtError(Status);
|
|
|
|
ExFreePool(DesktopName.Buffer);
|
2005-09-05 21:19:23 +00:00
|
|
|
RETURN( 0);
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
|
|
|
|
ExFreePool(DesktopName.Buffer);
|
|
|
|
|
2005-09-05 21:19:23 +00:00
|
|
|
RETURN( Desktop);
|
2005-09-07 21:25:42 +00:00
|
|
|
|
2005-09-05 21:19:23 +00:00
|
|
|
CLEANUP:
|
|
|
|
DPRINT("Leave NtUserOpenDesktop, ret=%i\n",_ret_);
|
|
|
|
UserLeave();
|
|
|
|
END_CLEANUP;
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NtUserOpenInputDesktop
|
|
|
|
*
|
|
|
|
* Opens the input (interactive) desktop.
|
|
|
|
*
|
|
|
|
* Parameters
|
|
|
|
* dwFlags
|
|
|
|
* Interaction flags.
|
|
|
|
*
|
|
|
|
* fInherit
|
|
|
|
* Inheritance option.
|
|
|
|
*
|
|
|
|
* dwDesiredAccess
|
|
|
|
* Requested type of access.
|
2005-05-08 02:11:54 +00:00
|
|
|
*
|
2003-12-07 19:29:33 +00:00
|
|
|
* Return Value
|
|
|
|
* Handle to the input desktop or zero on failure.
|
|
|
|
*
|
|
|
|
* Status
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
|
|
|
|
HDESK STDCALL
|
|
|
|
NtUserOpenInputDesktop(
|
|
|
|
DWORD dwFlags,
|
|
|
|
BOOL fInherit,
|
|
|
|
ACCESS_MASK dwDesiredAccess)
|
|
|
|
{
|
2004-12-24 17:45:59 +00:00
|
|
|
PDESKTOP_OBJECT Object;
|
2003-12-07 19:29:33 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
HDESK Desktop;
|
2005-09-24 02:50:02 +00:00
|
|
|
DECLARE_RETURN(HDESK);
|
|
|
|
|
|
|
|
DPRINT("Enter NtUserOpenInputDesktop\n");
|
|
|
|
UserEnterExclusive();
|
2003-12-07 19:29:33 +00:00
|
|
|
|
|
|
|
DPRINT("About to open input desktop\n");
|
|
|
|
|
2004-12-24 17:45:59 +00:00
|
|
|
/* Get a pointer to the desktop object */
|
|
|
|
|
|
|
|
Status = IntValidateDesktopHandle(
|
2005-09-07 21:25:42 +00:00
|
|
|
InputDesktopHandle,
|
|
|
|
UserMode,
|
|
|
|
0,
|
|
|
|
&Object);
|
2004-12-24 17:45:59 +00:00
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop);
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN((HDESK)0);
|
2004-12-24 17:45:59 +00:00
|
|
|
}
|
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
/* Create a new handle to the object */
|
|
|
|
|
|
|
|
Status = ObOpenObjectByPointer(
|
2005-09-07 21:25:42 +00:00
|
|
|
Object,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
dwDesiredAccess,
|
|
|
|
ExDesktopObjectType,
|
|
|
|
UserMode,
|
|
|
|
(HANDLE*)&Desktop);
|
2003-12-07 19:29:33 +00:00
|
|
|
|
2004-12-24 17:45:59 +00:00
|
|
|
ObDereferenceObject(Object);
|
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("Successfully opened input desktop\n");
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN((HDESK)Desktop);
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SetLastNtError(Status);
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN((HDESK)0);
|
|
|
|
|
|
|
|
CLEANUP:
|
|
|
|
DPRINT("Leave NtUserOpenInputDesktop, ret=%i\n",_ret_);
|
|
|
|
UserLeave();
|
|
|
|
END_CLEANUP;
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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;
|
2005-09-24 02:50:02 +00:00
|
|
|
DECLARE_RETURN(BOOL);
|
|
|
|
|
|
|
|
DPRINT("Enter NtUserCloseDesktop\n");
|
|
|
|
UserEnterExclusive();
|
2005-09-07 21:25:42 +00:00
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
DPRINT("About to close desktop handle (0x%X)\n", hDesktop);
|
|
|
|
|
|
|
|
Status = IntValidateDesktopHandle(
|
2005-09-07 21:25:42 +00:00
|
|
|
hDesktop,
|
|
|
|
UserMode,
|
|
|
|
0,
|
|
|
|
&Object);
|
2003-12-07 19:29:33 +00:00
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN(FALSE);
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ObDereferenceObject(Object);
|
|
|
|
|
|
|
|
DPRINT("Closing desktop handle (0x%X)\n", hDesktop);
|
|
|
|
|
|
|
|
Status = ZwClose(hDesktop);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastNtError(Status);
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN(FALSE);
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN(TRUE);
|
2004-09-15 20:53:43 +00:00
|
|
|
|
2005-09-24 02:50:02 +00:00
|
|
|
CLEANUP:
|
|
|
|
DPRINT("Leave NtUserCloseDesktop, ret=%i\n",_ret_);
|
|
|
|
UserLeave();
|
|
|
|
END_CLEANUP;
|
|
|
|
}
|
2004-09-15 20:53:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
2005-05-08 02:11:54 +00:00
|
|
|
* hDC
|
|
|
|
* Handle to the device context.
|
2003-12-07 19:29:33 +00:00
|
|
|
*
|
|
|
|
* Status
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
|
|
|
|
BOOL STDCALL
|
|
|
|
NtUserPaintDesktop(HDC hDC)
|
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
RECT Rect;
|
|
|
|
HBRUSH DesktopBrush, PreviousBrush;
|
|
|
|
HWND hWndDesktop;
|
|
|
|
BOOL doPatBlt = TRUE;
|
|
|
|
PWINDOW_OBJECT WndDesktop;
|
|
|
|
int len;
|
2005-09-24 02:50:02 +00:00
|
|
|
DECLARE_RETURN(BOOL);
|
|
|
|
|
|
|
|
UserEnterExclusive();
|
|
|
|
DPRINT("Enter NtUserPaintDesktop\n");
|
2005-09-07 21:25:42 +00:00
|
|
|
|
|
|
|
PWINSTATION_OBJECT WinSta = PsGetWin32Thread()->Desktop->WindowStation;
|
|
|
|
|
|
|
|
IntGdiGetClipBox(hDC, &Rect);
|
|
|
|
|
|
|
|
hWndDesktop = IntGetDesktopWindow();
|
2005-09-11 14:48:32 +00:00
|
|
|
if (!(WndDesktop = UserGetWindowObject(hWndDesktop)))
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN(FALSE);
|
2005-09-07 21:25:42 +00:00
|
|
|
|
|
|
|
DesktopBrush = (HBRUSH)IntGetClassLong(WndDesktop, GCL_HBRBACKGROUND, FALSE); //fixme: verify retval
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Paint desktop background
|
|
|
|
*/
|
|
|
|
|
|
|
|
if(WinSta->hbmWallpaper != NULL)
|
|
|
|
{
|
|
|
|
PWINDOW_OBJECT DeskWin;
|
|
|
|
|
2005-09-11 14:48:32 +00:00
|
|
|
if((DeskWin = UserGetWindowObject(hWndDesktop)))
|
2005-09-07 21:25:42 +00:00
|
|
|
{
|
|
|
|
SIZE sz;
|
|
|
|
int x, y;
|
|
|
|
HDC hWallpaperDC;
|
|
|
|
|
|
|
|
sz.cx = DeskWin->WindowRect.right - DeskWin->WindowRect.left;
|
|
|
|
sz.cy = DeskWin->WindowRect.bottom - DeskWin->WindowRect.top;
|
2005-11-28 01:09:27 +00:00
|
|
|
|
|
|
|
if(WinSta->WallpaperMode == wmStretch ||
|
|
|
|
WinSta->WallpaperMode == wmTile)
|
|
|
|
{
|
|
|
|
x = 0;
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x = (sz.cx / 2) - (WinSta->cxWallpaper / 2);
|
|
|
|
y = (sz.cy / 2) - (WinSta->cyWallpaper / 2);
|
|
|
|
}
|
|
|
|
|
2005-09-24 19:30:12 +00:00
|
|
|
hWallpaperDC = NtGdiCreateCompatibleDC(hDC);
|
2005-09-07 21:25:42 +00:00
|
|
|
if(hWallpaperDC != NULL)
|
|
|
|
{
|
|
|
|
HBITMAP hOldBitmap;
|
2005-11-28 01:09:27 +00:00
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
if(x > 0 || y > 0)
|
|
|
|
{
|
2005-11-28 01:09:27 +00:00
|
|
|
/* 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);
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
2005-11-28 01:09:27 +00:00
|
|
|
|
|
|
|
//Do not fill the background after it is painted no matter the size of the picture
|
|
|
|
doPatBlt = FALSE;
|
|
|
|
|
2005-09-07 21:25:42 +00:00
|
|
|
hOldBitmap = NtGdiSelectObject(hWallpaperDC, WinSta->hbmWallpaper);
|
2005-11-28 01:09:27 +00:00
|
|
|
|
|
|
|
if(WinSta->WallpaperMode == wmStretch)
|
|
|
|
{
|
|
|
|
#if 0 //Broken Stretch Code
|
|
|
|
/* Fix me, stretch the bitmap to fit the screen. I'm not smart enough to do this :( */
|
|
|
|
BITMAPINFO bmINFO;
|
|
|
|
LPVOID pBits;
|
|
|
|
bmINFO.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
|
|
/* Get bits */
|
|
|
|
NtGdiGetDIBits(hDC,
|
|
|
|
WinSta->hbmWallpaper,
|
|
|
|
0,
|
|
|
|
WinSta->cyWallpaper,
|
|
|
|
NULL, // what goes here?
|
|
|
|
&bmINFO,
|
|
|
|
DIB_RGB_COLORS);
|
|
|
|
|
|
|
|
bmINFO.bmiHeader.biCompression = BI_RGB;
|
|
|
|
|
|
|
|
pBits = ExAllocatePool(PagedPool,bmINFO.bmiHeader.biSizeImage);
|
|
|
|
|
|
|
|
if(pBits == NULL)
|
|
|
|
{
|
|
|
|
doPatBlt = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
NtGdiGetDIBits(hDC,
|
|
|
|
WinSta->hbmWallpaper,
|
|
|
|
0,
|
|
|
|
WinSta->cyWallpaper,
|
|
|
|
(LPVOID)pBits, // what goes here?
|
|
|
|
&bmINFO,
|
|
|
|
DIB_RGB_COLORS);
|
|
|
|
DPRINT1("Before Draw\n");
|
|
|
|
|
|
|
|
/* Stretch it to fit the screen */
|
|
|
|
NtGdiStretchDIBits(hDC,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
Rect.right,
|
|
|
|
Rect.bottom,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
WinSta->cxWallpaper,
|
|
|
|
WinSta->cyWallpaper,
|
|
|
|
(LPVOID)pBits, // get this from NtGdiGetDiBits?
|
|
|
|
&bmINFO, // get this from NtGdiGetDiBits?
|
|
|
|
DIB_RGB_COLORS,
|
|
|
|
SRCCOPY);
|
|
|
|
ExFreePool(pBits);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
/* Draw nothing */
|
|
|
|
doPatBlt = TRUE;
|
|
|
|
#endif //Broken Stretch Code
|
|
|
|
}
|
|
|
|
else if(WinSta->WallpaperMode == wmTile)
|
|
|
|
{
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NtGdiBitBlt(hDC, x, y, WinSta->cxWallpaper, WinSta->cyWallpaper, hWallpaperDC, 0, 0, SRCCOPY);
|
|
|
|
}
|
|
|
|
NtGdiSelectObject(hWallpaperDC, hOldBitmap);
|
2005-09-07 21:25:42 +00:00
|
|
|
NtGdiDeleteDC(hWallpaperDC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-28 01:09:27 +00:00
|
|
|
/* Back ground is set to none, clear the screen */
|
2005-09-07 21:25:42 +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
|
|
|
|
*/
|
|
|
|
|
|
|
|
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)
|
2004-08-17 21:47:36 +00:00
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
if (!UserSystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0))
|
|
|
|
{
|
|
|
|
rect.right = UserGetSystemMetrics(SM_CXSCREEN);
|
|
|
|
rect.bottom = UserGetSystemMetrics(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);
|
2004-08-17 21:47:36 +00:00
|
|
|
}
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
|
|
|
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN(TRUE);
|
|
|
|
|
|
|
|
CLEANUP:
|
|
|
|
DPRINT("Leave NtUserPaintDesktop, ret=%i\n",_ret_);
|
|
|
|
UserLeave();
|
|
|
|
END_CLEANUP;
|
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-24 17:45:59 +00:00
|
|
|
PDESKTOP_OBJECT DesktopObject;
|
2003-12-07 19:29:33 +00:00
|
|
|
NTSTATUS Status;
|
2005-09-24 02:50:02 +00:00
|
|
|
DECLARE_RETURN(BOOL);
|
|
|
|
|
|
|
|
UserEnterExclusive();
|
|
|
|
DPRINT("Enter NtUserSwitchDesktop\n");
|
2003-12-07 19:29:33 +00:00
|
|
|
|
|
|
|
DPRINT("About to switch desktop (0x%X)\n", hDesktop);
|
|
|
|
|
|
|
|
Status = IntValidateDesktopHandle(
|
2005-09-07 21:25:42 +00:00
|
|
|
hDesktop,
|
|
|
|
UserMode,
|
|
|
|
0,
|
|
|
|
&DesktopObject);
|
2003-12-07 19:29:33 +00:00
|
|
|
|
2005-05-08 02:11:54 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2003-12-07 19:29:33 +00:00
|
|
|
{
|
|
|
|
DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN(FALSE);
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
2005-05-08 02:11:54 +00:00
|
|
|
|
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) &&
|
2005-09-07 21:25:42 +00:00
|
|
|
LogonProcess != NULL && LogonProcess != PsGetWin32Process())
|
2004-05-01 16:43:15 +00:00
|
|
|
{
|
|
|
|
ObDereferenceObject(DesktopObject);
|
|
|
|
DPRINT1("Switching desktop 0x%x denied because the work station is locked!\n", hDesktop);
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN(FALSE);
|
2004-05-01 16:43:15 +00:00
|
|
|
}
|
2005-05-08 02:11:54 +00:00
|
|
|
|
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-24 17:45:59 +00:00
|
|
|
DesktopObject->WindowStation->ActiveDesktop = DesktopObject;
|
2003-12-07 19:29:33 +00:00
|
|
|
|
2004-12-24 17:45:59 +00:00
|
|
|
/* Set the global state. */
|
|
|
|
InputDesktop = DesktopObject;
|
|
|
|
InputDesktopHandle = hDesktop;
|
|
|
|
InputWindowStation = DesktopObject->WindowStation;
|
2003-12-07 19:29:33 +00:00
|
|
|
|
|
|
|
ObDereferenceObject(DesktopObject);
|
|
|
|
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN(TRUE);
|
|
|
|
|
|
|
|
CLEANUP:
|
|
|
|
DPRINT("Leave NtUserSwitchDesktop, ret=%i\n",_ret_);
|
|
|
|
UserLeave();
|
|
|
|
END_CLEANUP;
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
{
|
2005-09-07 21:25:42 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
PETHREAD Thread;
|
|
|
|
PDESKTOP_OBJECT DesktopObject;
|
|
|
|
HDESK Ret, hThreadDesktop;
|
|
|
|
OBJECT_HANDLE_INFORMATION HandleInformation;
|
2005-09-24 02:50:02 +00:00
|
|
|
DECLARE_RETURN(HDESK);
|
|
|
|
|
|
|
|
UserEnterExclusive();
|
|
|
|
DPRINT("Enter NtUserGetThreadDesktop\n");
|
2005-09-07 21:25:42 +00:00
|
|
|
|
|
|
|
if(!dwThreadId)
|
|
|
|
{
|
|
|
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN(0);
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN(0);
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(Thread->ThreadsProcess == PsGetCurrentProcess())
|
|
|
|
{
|
|
|
|
/* just return the handle, we queried the desktop handle of a thread running
|
|
|
|
in the same context */
|
2005-11-08 08:56:41 +00:00
|
|
|
Ret = ((PW32THREAD)Thread->Tcb.Win32Thread)->hDesktop;
|
2005-09-07 21:25:42 +00:00
|
|
|
ObDereferenceObject(Thread);
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN(Ret);
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* get the desktop handle and the desktop of the thread */
|
2005-11-08 08:56:41 +00:00
|
|
|
if(!(hThreadDesktop = ((PW32THREAD)Thread->Tcb.Win32Thread)->hDesktop) ||
|
|
|
|
!(DesktopObject = ((PW32THREAD)Thread->Tcb.Win32Thread)->Desktop))
|
2005-09-07 21:25:42 +00:00
|
|
|
{
|
|
|
|
ObDereferenceObject(Thread);
|
|
|
|
DPRINT1("Desktop information of thread 0x%x broken!?\n", dwThreadId);
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN(NULL);
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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);
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN(NULL);
|
2005-09-07 21:25:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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);
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN(Ret);
|
|
|
|
|
|
|
|
CLEANUP:
|
|
|
|
DPRINT("Leave NtUserGetThreadDesktop, ret=%i\n",_ret_);
|
|
|
|
UserLeave();
|
|
|
|
END_CLEANUP;
|
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;
|
2005-09-24 02:50:02 +00:00
|
|
|
DECLARE_RETURN(BOOL);
|
|
|
|
|
|
|
|
UserEnterExclusive();
|
|
|
|
DPRINT("Enter NtUserSetThreadDesktop\n");
|
|
|
|
|
2003-12-07 19:29:33 +00:00
|
|
|
/* Validate the new desktop. */
|
|
|
|
Status = IntValidateDesktopHandle(
|
2005-09-07 21:25:42 +00:00
|
|
|
hDesktop,
|
|
|
|
UserMode,
|
|
|
|
0,
|
|
|
|
&DesktopObject);
|
2003-12-07 19:29:33 +00:00
|
|
|
|
2005-05-08 02:11:54 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2003-12-07 19:29:33 +00:00
|
|
|
{
|
|
|
|
DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN(FALSE);
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2005-09-24 02:50:02 +00:00
|
|
|
RETURN(TRUE);
|
|
|
|
|
|
|
|
CLEANUP:
|
|
|
|
DPRINT("Leave NtUserSetThreadDesktop, ret=%i\n",_ret_);
|
|
|
|
UserLeave();
|
|
|
|
END_CLEANUP;
|
2003-12-07 19:29:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|