- Rewrite Desktop/WindowsStation parsing to follow the NT Object Model, with some minor hacks to respect ROS's current parsing semantics.

- Thanks to this, the long-lasting ExpDesktopCreate hack is gone, and so is OB_ROS_FIND_METHOD and OB_ROS_CREATE_METHOD in win32k. Next patch can fully remove WIN32_CALLOUT_DATA and use the NT type instead.
- Add official OBJECT_ macros in obtypes.h

svn path=/trunk/; revision=22041
This commit is contained in:
Alex Ionescu 2006-05-25 19:30:09 +00:00
parent befa307429
commit cf356e801d
11 changed files with 257 additions and 263 deletions

View file

@ -87,6 +87,22 @@ Author:
#define OB_FLAG_SECURITY 0x20
#define OB_FLAG_SINGLE_PROCESS 0x40
#define OBJECT_TO_OBJECT_HEADER(o) \
CONTAINING_RECORD((o), OBJECT_HEADER, Body)
#define OBJECT_HEADER_TO_NAME_INFO(h) \
((POBJECT_HEADER_NAME_INFO)(!(h)->NameInfoOffset ? \
NULL: ((PCHAR)(h) - (h)->NameInfoOffset)))
#define OBJECT_HEADER_TO_HANDLE_INFO(h) \
((POBJECT_HEADER_HANDLE_INFO)(!(h)->HandleInfoOffset ? \
NULL: ((PCHAR)(h) - (h)->HandleInfoOffset)))
#define OBJECT_HEADER_TO_CREATOR_INFO(h) \
((POBJECT_HEADER_CREATOR_INFO)(!((h)->Flags & \
OB_FLAG_CREATOR_INFO) ? NULL: ((PCHAR)(h) - \
sizeof(OBJECT_HEADER_CREATOR_INFO))))
//
// Reasons for Open Callback
//

View file

@ -12,8 +12,7 @@ typedef struct _W32_CALLOUT_DATA
OB_DELETE_METHOD WinStaDelete;
OB_PARSE_METHOD WinStaParse;
OB_OPEN_METHOD WinStaOpen;
OB_ROS_FIND_METHOD WinStaFind;
OB_ROS_CREATE_METHOD DesktopCreate;
OB_PARSE_METHOD DesktopParse;
} W32_CALLOUT_DATA, *PW32_CALLOUT_DATA;
#endif

View file

@ -38,8 +38,7 @@ static GENERIC_MAPPING ExpDesktopMapping =
OB_OPEN_METHOD ExpWindowStationObjectOpen = NULL;
OB_PARSE_METHOD ExpWindowStationObjectParse = NULL;
OB_DELETE_METHOD ExpWindowStationObjectDelete = NULL;
OB_ROS_FIND_METHOD ExpWindowStationObjectFind = NULL;
OB_ROS_CREATE_METHOD ExpDesktopObjectCreate = NULL;
OB_PARSE_METHOD ExpDesktopObjectParse = NULL;
OB_DELETE_METHOD ExpDesktopObjectDelete = NULL;
/* FUNCTIONS ****************************************************************/
@ -47,17 +46,17 @@ OB_DELETE_METHOD ExpDesktopObjectDelete = NULL;
NTSTATUS
STDCALL
ExpWinStaObjectOpen(OB_OPEN_REASON Reason,
PVOID ObjectBody,
PEPROCESS Process,
ULONG HandleCount,
ACCESS_MASK GrantedAccess)
PVOID ObjectBody,
ACCESS_MASK GrantedAccess,
ULONG HandleCount)
{
/* Call the Registered Callback */
return ExpWindowStationObjectOpen(Reason,
ObjectBody,
Process,
HandleCount,
GrantedAccess);
ObjectBody,
GrantedAccess,
HandleCount);
}
VOID
@ -68,18 +67,6 @@ ExpWinStaObjectDelete(PVOID DeletedObject)
ExpWindowStationObjectDelete(DeletedObject);
}
PVOID
STDCALL
ExpWinStaObjectFind(PVOID WinStaObject,
PWSTR Name,
ULONG Attributes)
{
/* Call the Registered Callback */
return ExpWindowStationObjectFind(WinStaObject,
Name,
Attributes);
}
NTSTATUS
STDCALL
ExpWinStaObjectParse(IN PVOID ParseObject,
@ -105,21 +92,6 @@ ExpWinStaObjectParse(IN PVOID ParseObject,
SecurityQos,
Object);
}
NTSTATUS
STDCALL
ExpDesktopCreate(PVOID ObjectBody,
PVOID Parent,
PWSTR RemainingPath,
POBJECT_ATTRIBUTES ObjectAttributes)
{
/* Call the Registered Callback */
return ExpDesktopObjectCreate(ObjectBody,
Parent,
RemainingPath,
ObjectAttributes);
}
VOID
STDCALL
ExpDesktopDelete(PVOID DeletedObject)
@ -143,9 +115,9 @@ ExpWin32kInit(VOID)
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
ObjectTypeInitializer.GenericMapping = ExpWindowStationMapping;
ObjectTypeInitializer.PoolType = NonPagedPool;
ObjectTypeInitializer.OpenProcedure = (OB_OPEN_METHOD)ExpWinStaObjectOpen;
ObjectTypeInitializer.OpenProcedure = ExpWinStaObjectOpen;
ObjectTypeInitializer.DeleteProcedure = ExpWinStaObjectDelete;
ObjectTypeInitializer.ParseProcedure = (OB_PARSE_METHOD)ExpWinStaObjectParse;
ObjectTypeInitializer.ParseProcedure = ExpWinStaObjectParse;
ObpCreateTypeObject(&ObjectTypeInitializer,
&Name,
&ExWindowStationObjectType);

View file

@ -53,13 +53,6 @@ typedef NTSTATUS
struct _OBJECT_ATTRIBUTES* ObjectAttributes
);
typedef PVOID
(NTAPI *OB_ROS_FIND_METHOD)(
PVOID WinStaObject,
PWSTR Name,
ULONG Attributes
);
BOOLEAN
NTAPI
ObpDeleteEntryDirectory(POBP_LOOKUP_CONTEXT Context);

View file

@ -19,14 +19,6 @@
PHANDLE_TABLE ObpKernelHandleTable = NULL;
/* TEMPORARY HACK. DO NOT REMOVE -- Alex */
NTSTATUS
STDCALL
ExpDesktopCreate(PVOID ObjectBody,
PVOID Parent,
PWSTR RemainingPath,
POBJECT_CREATE_INFORMATION ObjectCreateInformation);
/* PRIVATE FUNCTIONS *********************************************************/
/*++
@ -1012,7 +1004,6 @@ ObInsertObject(IN PVOID Object,
}
if ((Header->Type == IoFileObjectType) ||
(Header->Type == ExDesktopObjectType) ||
(Header->Type->TypeInfo.OpenProcedure != NULL))
{
DPRINT("About to call Open Routine\n");
@ -1027,15 +1018,6 @@ ObInsertObject(IN PVOID Object,
DPRINT("Called IopCreateFile: %x\n", Status);
}
else if (Header->Type == ExDesktopObjectType)
{
/* TEMPORARY HACK. DO NOT TOUCH -- Alex */
DPRINT("Calling ExpDesktopCreate\n");
Status = ExpDesktopCreate(&Header->Body,
FoundObject,
RemainingPath.Buffer,
ObjectCreateInfo);
}
else if (Header->Type->TypeInfo.OpenProcedure != NULL)
{
DPRINT("Calling %x\n", Header->Type->TypeInfo.OpenProcedure);

View file

@ -176,13 +176,13 @@ Next:
RtlInitUnicodeString(&CurrentUs, current);
Status = CurrentHeader->Type->TypeInfo.ParseProcedure(CurrentObject,
CurrentHeader->Type,
NULL,
ExGetPreviousMode(),
AccessState,
ExGetPreviousMode(), // fixme: should be a parameter, since caller decides.
Attributes,
&PathString,
&CurrentUs,
NULL,
NULL,
ParseContext,
NULL, // fixme: where do we get this from? captured OBP?
&NextObject);
current = CurrentUs.Buffer;
if (Status == STATUS_REPARSE)

View file

@ -23,8 +23,7 @@ static PKWIN32_THREAD_CALLOUT PspWin32ThreadCallback = NULL;
extern OB_OPEN_METHOD ExpWindowStationObjectOpen;
extern OB_PARSE_METHOD ExpWindowStationObjectParse;
extern OB_DELETE_METHOD ExpWindowStationObjectDelete;
extern OB_ROS_FIND_METHOD ExpWindowStationObjectFind;
extern OB_ROS_CREATE_METHOD ExpDesktopObjectCreate;
extern OB_PARSE_METHOD ExpDesktopObjectParse;
extern OB_DELETE_METHOD ExpDesktopObjectDelete;
#ifndef ALEX_CB_REWRITE
@ -64,8 +63,7 @@ PsEstablishWin32Callouts(PWIN32_CALLOUTS_FPNS calloutData)
ExpWindowStationObjectOpen = CalloutData->WinStaOpen;
ExpWindowStationObjectParse = CalloutData->WinStaParse;
ExpWindowStationObjectDelete = CalloutData->WinStaDelete;
ExpWindowStationObjectFind = CalloutData->WinStaFind;
ExpDesktopObjectCreate = CalloutData->DesktopCreate;
ExpDesktopObjectParse = CalloutData->DesktopParse;
ExpDesktopObjectDelete = CalloutData->DesktopDelete;
}

View file

@ -10,7 +10,6 @@ typedef struct _DESKTOP_OBJECT
CSHORT Size;
LIST_ENTRY ListEntry;
UNICODE_STRING Name;
/* Pointer to the associated window station. */
struct _WINSTATION_OBJECT *WindowStation;
/* Pointer to the active queue. */
@ -48,11 +47,18 @@ InitDesktopImpl(VOID);
NTSTATUS FASTCALL
CleanupDesktopImpl(VOID);
NTSTATUS STDCALL
IntDesktopObjectCreate(PVOID ObjectBody,
PVOID Parent,
PWSTR RemainingPath,
struct _OBJECT_ATTRIBUTES* ObjectAttributes);
NTSTATUS
STDCALL
IntDesktopObjectParse(IN PVOID ParseObject,
IN PVOID ObjectType,
IN OUT PACCESS_STATE AccessState,
IN KPROCESSOR_MODE AccessMode,
IN ULONG Attributes,
IN OUT PUNICODE_STRING CompleteName,
IN OUT PUNICODE_STRING RemainingName,
IN OUT PVOID Context OPTIONAL,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
OUT PVOID *Object);
VOID STDCALL
IntDesktopObjectDelete(PVOID DeletedObject);
@ -120,6 +126,12 @@ VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam);
#define IntIsActiveDesktop(Desktop) \
((Desktop)->WindowStation->ActiveDesktop == (Desktop))
#define GET_DESKTOP_NAME(d) \
OBJECT_HEADER_TO_NAME_INFO(OBJECT_TO_OBJECT_HEADER(d)) ? \
&(OBJECT_HEADER_TO_NAME_INFO(OBJECT_TO_OBJECT_HEADER(d))->Name) : \
NULL
static __inline PVOID
DesktopHeapAlloc(IN PDESKTOP Desktop,
IN SIZE_T Bytes)

View file

@ -384,8 +384,7 @@ DriverEntry (
CalloutData.WinStaOpen = IntWinStaObjectOpen;
CalloutData.WinStaParse = IntWinStaObjectParse;
CalloutData.WinStaDelete = IntWinStaObjectDelete;
CalloutData.WinStaFind = IntWinStaObjectFind;
CalloutData.DesktopCreate = IntDesktopObjectCreate;
CalloutData.DesktopParse = IntDesktopObjectParse;
CalloutData.DesktopDelete = IntDesktopObjectDelete;
CalloutData.W32ProcessCallout = Win32kProcessCallback;
CalloutData.W32ThreadCallout = Win32kThreadCallback;

View file

@ -34,82 +34,143 @@
#define NDEBUG
#include <debug.h>
static
VOID
IntFreeDesktopHeap(
IN OUT PDESKTOP_OBJECT Desktop
);
/* GLOBALS *******************************************************************/
/* Currently active desktop */
PDESKTOP_OBJECT InputDesktop = NULL;
HDESK InputDesktopHandle = NULL;
HDC ScreenDeviceContext = NULL;
BOOL g_PaintDesktopVersion = FALSE;
static VOID IntFreeDesktopHeap(IN OUT PDESKTOP_OBJECT Desktop);
/* INITALIZATION FUNCTIONS ****************************************************/
static GENERIC_MAPPING IntDesktopMapping =
{
STANDARD_RIGHTS_READ | DESKTOP_ENUMERATE | DESKTOP_READOBJECTS,
STANDARD_RIGHTS_WRITE | DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_HOOKCONTROL |
DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD | DESKTOP_WRITEOBJECTS,
GENERIC_MAPPING IntDesktopMapping =
{
STANDARD_RIGHTS_READ | DESKTOP_ENUMERATE |
DESKTOP_READOBJECTS,
STANDARD_RIGHTS_WRITE | DESKTOP_CREATEMENU |
DESKTOP_CREATEWINDOW |
DESKTOP_HOOKCONTROL |
DESKTOP_JOURNALPLAYBACK |
DESKTOP_JOURNALRECORD |
DESKTOP_WRITEOBJECTS,
STANDARD_RIGHTS_EXECUTE | DESKTOP_SWITCHDESKTOP,
STANDARD_RIGHTS_REQUIRED | DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE |
DESKTOP_HOOKCONTROL | DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD |
DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS
};
NTSTATUS FASTCALL
InitDesktopImpl(VOID)
{
/* Set Desktop Object Attributes */
ExDesktopObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(DESKTOP_OBJECT);
ExDesktopObjectType->TypeInfo.GenericMapping = IntDesktopMapping;
return STATUS_SUCCESS;
}
NTSTATUS FASTCALL
CleanupDesktopImpl(VOID)
{
return STATUS_SUCCESS;
}
STANDARD_RIGHTS_REQUIRED | DESKTOP_CREATEMENU |
DESKTOP_CREATEWINDOW |
DESKTOP_ENUMERATE |
DESKTOP_HOOKCONTROL |
DESKTOP_JOURNALPLAYBACK |
DESKTOP_JOURNALRECORD |
DESKTOP_READOBJECTS |
DESKTOP_SWITCHDESKTOP |
DESKTOP_WRITEOBJECTS
};
/* OBJECT CALLBACKS **********************************************************/
NTSTATUS STDCALL
IntDesktopObjectCreate(PVOID ObjectBody,
PVOID Parent,
PWSTR RemainingPath,
struct _OBJECT_ATTRIBUTES* ObjectAttributes)
NTSTATUS
NTAPI
IntDesktopObjectParse(IN PVOID ParseObject,
IN PVOID ObjectType,
IN OUT PACCESS_STATE AccessState,
IN KPROCESSOR_MODE AccessMode,
IN ULONG Attributes,
IN OUT PUNICODE_STRING CompleteName,
IN OUT PUNICODE_STRING RemainingName,
IN OUT PVOID Context OPTIONAL,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
OUT PVOID *Object)
{
PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)ObjectBody;
UNICODE_STRING UnicodeString;
NTSTATUS Status;
PDESKTOP_OBJECT Desktop;
OBJECT_ATTRIBUTES ObjectAttributes;
PLIST_ENTRY NextEntry, ListHead;
PWINSTATION_OBJECT WinStaObject = (PWINSTATION_OBJECT)ParseObject;
PUNICODE_STRING DesktopName;
DPRINT("Creating desktop (0x%X) Name (%S)\n", Desktop, RemainingPath);
if (RemainingPath == NULL)
{
return STATUS_SUCCESS;
}
/* Set the list pointers and loop the window station */
DPRINT1("Creating desktop(%wZ)\n", RemainingName);
ListHead = &WinStaObject->DesktopListHead;
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
/* Get the current desktop */
Desktop = CONTAINING_RECORD(NextEntry, DESKTOP_OBJECT, ListEntry);
if (wcschr((RemainingPath + 1), '\\') != NULL)
{
return STATUS_UNSUCCESSFUL;
}
/* Get its name */
DesktopName = GET_DESKTOP_NAME(Desktop);
if (DesktopName)
{
/* Compare the name */
if (RtlEqualUnicodeString(RemainingName,
DesktopName,
(Attributes & OBJ_CASE_INSENSITIVE)))
{
/* We found a match. Did this come from a create? */
if (Context)
{
/* Unless OPEN_IF was given, fail with an error */
if (!(Attributes & OBJ_OPENIF))
{
/* Name collision */
return STATUS_OBJECT_NAME_COLLISION;
}
else
{
/* Otherwise, return with a warning only */
Status = STATUS_OBJECT_NAME_EXISTS;
}
}
else
{
/* This was a real open, so this is OK */
Status = STATUS_SUCCESS;
}
RtlInitUnicodeString(&UnicodeString, (RemainingPath + 1));
/* Reference the desktop and return it */
ObReferenceObject(Desktop);
*Object = Desktop;
RemainingName->Buffer = NULL; // => ROS Parse routines need to do this
return Status;
}
}
InitializeListHead(&Desktop->ShellHookWindows);
/* Go to the next desktop */
NextEntry = NextEntry->Flink;
}
Desktop->WindowStation = (PWINSTATION_OBJECT)Parent;
/* If we got here but this isn't a create, then fail */
if (!Context) return STATUS_OBJECT_NAME_NOT_FOUND;
/* Put the desktop on the window station's list of associcated desktops */
// ExInterlocked
InsertTailList(
&Desktop->WindowStation->DesktopListHead,
&Desktop->ListEntry);//,
// &Desktop->WindowStation->Lock);
/* Create the desktop object */
InitializeObjectAttributes(&ObjectAttributes, RemainingName, 0, NULL, NULL);
Status = ObCreateObject(KernelMode,
ExDesktopObjectType,
&ObjectAttributes,
UserMode,
NULL,
sizeof(DESKTOP_OBJECT),
0,
0,
(PVOID)&Desktop);
if (!NT_SUCCESS(Status)) return Status;
return RtlCreateUnicodeString(&Desktop->Name, UnicodeString.Buffer);
/* Initialize shell hook window list and set the parent */
InitializeListHead(&Desktop->ShellHookWindows);
Desktop->WindowStation = (PWINSTATION_OBJECT)ParseObject;
/* Put the desktop on the window station's list of associated desktops */
InsertTailList(&Desktop->WindowStation->DesktopListHead,
&Desktop->ListEntry);
/* Set the desktop object and return success */
*Object = Desktop;
RemainingName->Buffer = NULL; // => ROS Parse routines need to do this
return STATUS_SUCCESS;
}
VOID STDCALL
@ -122,13 +183,28 @@ IntDesktopObjectDelete(PVOID DeletedObject)
/* Remove the desktop from the window station's list of associcated desktops */
RemoveEntryList(&Desktop->ListEntry);
RtlFreeUnicodeString(&Desktop->Name);
IntFreeDesktopHeap(Desktop);
}
/* PRIVATE FUNCTIONS **********************************************************/
NTSTATUS
FASTCALL
InitDesktopImpl(VOID)
{
/* Set Desktop Object Attributes */
ExDesktopObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(DESKTOP_OBJECT);
ExDesktopObjectType->TypeInfo.GenericMapping = IntDesktopMapping;
return STATUS_SUCCESS;
}
NTSTATUS
FASTCALL
CleanupDesktopImpl(VOID)
{
return STATUS_SUCCESS;
}
static int GetSystemVersionString(LPWSTR buffer)
{
RTL_OSVERSIONINFOEXW versionInfo;
@ -736,8 +812,6 @@ IntFreeDesktopHeap(IN OUT PDESKTOP_OBJECT Desktop)
Desktop->DesktopHeapSection = NULL;
}
}
/* SYSCALLS *******************************************************************/
@ -791,6 +865,7 @@ NtUserCreateDesktop(
PVOID DesktopHeapSystemBase = NULL;
SIZE_T DesktopInfoSize;
UNICODE_STRING SafeDesktopName;
ULONG DummyContext;
DECLARE_RETURN(HDESK);
@ -839,7 +914,7 @@ NtUserCreateDesktop(
* Try to open already existing desktop
*/
DPRINT1("Trying to open desktop (%wZ)\n", &DesktopName);
DPRINT("Trying to open desktop (%wZ)\n", &DesktopName);
/* Initialize ObjectAttributes for the desktop object */
InitializeObjectAttributes(
@ -852,41 +927,26 @@ NtUserCreateDesktop(
Status = ObOpenObjectByName(
&ObjectAttributes,
ExDesktopObjectType,
NULL,
(PVOID)&DummyContext,
KernelMode,
dwDesiredAccess,
NULL,
(HANDLE*)&Desktop);
if (NT_SUCCESS(Status))
if (!NT_SUCCESS(Status)) RETURN(NULL);
if (Status == STATUS_OBJECT_NAME_EXISTS)
{
DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
ExFreePool(DesktopName.Buffer);
RETURN( Desktop);
}
/*
* No existing desktop found, try to create new one
*/
Status = ObCreateObject(
KernelMode,
ExDesktopObjectType,
&ObjectAttributes,
ExGetPreviousMode(),
NULL,
sizeof(DESKTOP_OBJECT),
0,
0,
(PVOID*)&DesktopObject);
if (! NT_SUCCESS(Status))
{
DPRINT1("Failed creating desktop (%wZ)\n", &DesktopName);
ExFreePool(DesktopName.Buffer);
SetLastNtError(STATUS_UNSUCCESSFUL);
RETURN( NULL);
}
/* Reference the desktop */
Status = ObReferenceObjectByHandle(Desktop,
0,
ExDesktopObjectType,
KernelMode,
(PVOID)&DesktopObject,
NULL);
if (!NT_SUCCESS(Status)) RETURN(NULL);
DesktopObject->DesktopHeapSection = NULL;
DesktopObject->hDesktopHeap = UserCreateHeap(&DesktopObject->DesktopHeapSection,
@ -930,16 +990,6 @@ NtUserCreateDesktop(
/* 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))

View file

@ -105,7 +105,6 @@ IntWinStaObjectOpen(OB_OPEN_REASON Reason,
PWINSTATION_OBJECT WinSta = (PWINSTATION_OBJECT)ObjectBody;
NTSTATUS Status;
DPRINT1("IntWinStaObjectOpen\n");
if (Reason == ObCreateHandle)
{
@ -115,10 +114,8 @@ DPRINT1("IntWinStaObjectOpen\n");
InitializeListHead(&WinSta->DesktopListHead);
DPRINT1("Create winsta atomtable\n");
WinSta->AtomTable = NULL;
Status = RtlCreateAtomTable(37, &WinSta->AtomTable);
if (!NT_SUCCESS(Status)) DPRINT1("Error creating atom table\n");
WinSta->SystemMenuTemplate = (HANDLE)0;
DPRINT("Window station successfully created.\n");
@ -139,51 +136,6 @@ IntWinStaObjectDelete(PVOID DeletedObject)
RtlFreeUnicodeString(&WinSta->Name);
}
PVOID STDCALL
IntWinStaObjectFind(PVOID Object,
PWSTR Name,
ULONG Attributes)
{
PLIST_ENTRY Current;
PDESKTOP_OBJECT CurrentObject;
PWINSTATION_OBJECT WinStaObject = (PWINSTATION_OBJECT)Object;
DPRINT("WinStaObject (0x%X) Name (%wS)\n", WinStaObject, Name);
if (Name[0] == 0)
{
return NULL;
}
Current = WinStaObject->DesktopListHead.Flink;
while (Current != &WinStaObject->DesktopListHead)
{
CurrentObject = CONTAINING_RECORD(Current, DESKTOP_OBJECT, ListEntry);
DPRINT("Scanning %wZ for %wS\n", &CurrentObject->Name, Name);
if (Attributes & OBJ_CASE_INSENSITIVE)
{
if (_wcsicmp(CurrentObject->Name.Buffer, Name) == 0)
{
DPRINT("Found desktop at (0x%X)\n", CurrentObject);
return CurrentObject;
}
}
else
{
if (wcscmp(CurrentObject->Name.Buffer, Name) == 0)
{
DPRINT("Found desktop at (0x%X)\n", CurrentObject);
return CurrentObject;
}
}
Current = Current->Flink;
}
DPRINT("Returning NULL\n");
return NULL;
}
NTSTATUS
STDCALL
IntWinStaObjectParse(IN PVOID Object,
@ -197,44 +149,65 @@ IntWinStaObjectParse(IN PVOID Object,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
OUT PVOID *NextObject)
{
PWSTR *Path = &RemainingName->Buffer;
PVOID FoundObject;
NTSTATUS Status;
PWSTR End;
DPRINT("Object (0x%X) Path (0x%X) *Path (%wZ)\n", Object, RemainingName, RemainingName);
DPRINT("Object (0x%X) Path (0x%X) *Path (%wS)\n", Object, Path, *Path);
/* Assume we don't find anything */
*NextObject = NULL;
*NextObject = NULL;
/* Check for an empty name */
if (!RemainingName->Length)
{
/* Make sure this is a window station, can't parse a desktop now */
if (ObjectType != ExWindowStationObjectType)
{
/* Fail */
return STATUS_OBJECT_TYPE_MISMATCH;
}
if ((Path == NULL) || ((*Path) == NULL))
{
return STATUS_SUCCESS;
}
/* Reference the window station and return */
//ObReferenceObject(Object);
//*NextObject = Object; => ROS Parse routines don't need to do this
return STATUS_SUCCESS;
}
End = wcschr((*Path) + 1, '\\');
if (End != NULL)
{
DPRINT("Name contains illegal characters\n");
return STATUS_UNSUCCESSFUL;
}
/* Check for leading slash */
if (RemainingName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
{
/* Skip it */
RemainingName->Buffer++;
RemainingName->Length -= sizeof(WCHAR);
RemainingName->MaximumLength -= sizeof(WCHAR);
}
FoundObject = IntWinStaObjectFind(Object, (*Path) + 1, Attributes);
if (FoundObject == NULL)
{
DPRINT("Name was not found\n");
return STATUS_UNSUCCESSFUL;
}
/* Check if there is still a slash */
if (wcschr(RemainingName->Buffer, OBJ_NAME_PATH_SEPARATOR))
{
/* In this case, fail */
return STATUS_OBJECT_PATH_INVALID;
}
Status = ObReferenceObjectByPointer(
FoundObject,
STANDARD_RIGHTS_REQUIRED,
NULL,
UserMode);
/*
* Check if we are parsing a desktop.
* FIXME: ROS Sends the wrong Object Type. The parsed object's type
* should be sent, not the parsed parent's.
*/
if (ObjectType == ExWindowStationObjectType)
{
/* Then call the desktop parse routine */
return IntDesktopObjectParse(Object,
ObjectType,
AccessState,
AccessMode,
Attributes,
FullPath,
RemainingName,
Context,
SecurityQos,
NextObject);
}
*NextObject = FoundObject;
*Path = NULL;
return Status;
/* Should hopefully never get here */
return STATUS_OBJECT_TYPE_MISMATCH;
}
/* PRIVATE FUNCTIONS **********************************************************/
@ -824,14 +797,14 @@ NtUserGetObjectInformation(
case UOI_NAME:
if (WinStaObject != NULL)
{
pvData = WinStaObject->Name.Buffer;
nDataSize = WinStaObject->Name.Length+2;
pvData = ((PUNICODE_STRING)GET_DESKTOP_NAME(WinStaObject))->Buffer;
nDataSize = ((PUNICODE_STRING)GET_DESKTOP_NAME(WinStaObject))->Length + 2;
Status = STATUS_SUCCESS;
}
else if (DesktopObject != NULL)
{
pvData = DesktopObject->Name.Buffer;
nDataSize = DesktopObject->Name.Length+2;
pvData = ((PUNICODE_STRING)GET_DESKTOP_NAME(DesktopObject))->Buffer;
nDataSize = ((PUNICODE_STRING)GET_DESKTOP_NAME(DesktopObject))->Length + 2;
Status = STATUS_SUCCESS;
}
else
@ -1407,7 +1380,7 @@ BuildDesktopNameList(
DesktopEntry = DesktopEntry->Flink)
{
DesktopObject = CONTAINING_RECORD(DesktopEntry, DESKTOP_OBJECT, ListEntry);
ReturnLength += DesktopObject->Name.Length + sizeof(WCHAR);
ReturnLength += ((PUNICODE_STRING)GET_DESKTOP_NAME(DesktopObject))->Length + sizeof(WCHAR);
EntryCount++;
}
DPRINT("Required size: %d Entry count: %d\n", ReturnLength, EntryCount);
@ -1450,14 +1423,14 @@ BuildDesktopNameList(
DesktopEntry = DesktopEntry->Flink)
{
DesktopObject = CONTAINING_RECORD(DesktopEntry, DESKTOP_OBJECT, ListEntry);
Status = MmCopyToCaller(lpBuffer, DesktopObject->Name.Buffer, DesktopObject->Name.Length);
Status = MmCopyToCaller(lpBuffer, ((PUNICODE_STRING)GET_DESKTOP_NAME(DesktopObject))->Buffer, ((PUNICODE_STRING)GET_DESKTOP_NAME(DesktopObject))->Length);
if (! NT_SUCCESS(Status))
{
KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
ObDereferenceObject(WindowStation);
return Status;
}
lpBuffer = (PVOID) ((PCHAR) lpBuffer + DesktopObject->Name.Length);
lpBuffer = (PVOID) ((PCHAR) lpBuffer + ((PUNICODE_STRING)GET_DESKTOP_NAME(DesktopObject))->Length);
Status = MmCopyToCaller(lpBuffer, &NullWchar, sizeof(WCHAR));
if (! NT_SUCCESS(Status))
{