- Pretty much the last Ob implementation/optimization patch (Except for a minor fix by Thomas to fix handle sweeping), re-implemented the ObFindObject routine by using some code that I had written almost 2 years ago with help from Thomas and Filip, plus some fixes discovered today while testing.

- Fixed symbolic link and desktop/winsta parse procedures to become NT-compatible now that ObFindObject is as well. Also fixed file/device parse routine for these changes.
- ObFindObject now supports STATUS_REPARSE_OBJECT, and has an optimized path for parsing when a root directory is given, as well as is entirely unicode_string-based.
- Cleaned up ob.h and added ob_x.h for the inlined functions.
- Implemented new Ob tracing system.

svn path=/trunk/; revision=22319
This commit is contained in:
Alex Ionescu 2006-06-12 05:58:08 +00:00
parent 119738339b
commit 8d3f5096fd
9 changed files with 778 additions and 498 deletions

View file

@ -1,53 +1,89 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: include/internal/objmgr.h
* PURPOSE: Object manager definitions
* PROGRAMMER: David Welch (welch@mcmail.com)
*/
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/include/ob.h
* PURPOSE: Internal header for the Object Manager
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
#include "ob_x.h"
#ifndef __INCLUDE_INTERNAL_OBJMGR_H
#define __INCLUDE_INTERNAL_OBJMGR_H
//
// Define this if you want debugging support
//
#define _OB_DEBUG_ 0x00
//
// These define the Debug Masks Supported
//
#define OB_HANDLE_DEBUG 0x01
#define OB_NAMESPACE_DEBUG 0x02
#define OB_SECURITY_DEBUG 0x04
#define OB_REFERENCE_DEBUG 0x08
#define OB_CALLBACK_DEBUG 0x10
//
// Debug/Tracing support
//
#if _OB_DEBUG_
#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented
#define OBTRACE DbgPrintEx
#else
#define OBTRACE(x, ...) \
if (x & ObpTraceLevel) DbgPrint(__VA_ARGS__)
#endif
#else
#define OBTRACE(x, ...) DPRINT(__VA_ARGS__)
#endif
//
// Mask to detect GENERIC_XXX access masks being used
//
#define GENERIC_ACCESS \
(GENERIC_READ | \
GENERIC_WRITE | \
GENERIC_EXECUTE | \
GENERIC_ALL)
//
// Identifies a Kernel Handle
//
#define KERNEL_HANDLE_FLAG \
(1 << ((sizeof(HANDLE) * 8) - 1))
#define ObIsKernelHandle(Handle, ProcessorMode) \
(((ULONG_PTR)(Handle) & KERNEL_HANDLE_FLAG) && \
((ProcessorMode) == KernelMode))
//
// Converts to and from a Kernel Handle to a normal handle
//
#define ObKernelHandleToHandle(Handle) \
(HANDLE)((ULONG_PTR)(Handle) & ~KERNEL_HANDLE_FLAG)
#define ObMarkHandleAsKernelHandle(Handle) \
(HANDLE)((ULONG_PTR)(Handle) | KERNEL_HANDLE_FLAG)
//
// Returns the number of handles in a handle table
//
#define ObpGetHandleCountByHandleTable(HandleTable) \
((PHANDLE_TABLE)HandleTable)->HandleCount
//
// Context Structures for Ex*Handle Callbacks
//
typedef struct _OBP_SET_HANDLE_ATTRIBUTES_CONTEXT
{
KPROCESSOR_MODE PreviousMode;
OBJECT_HANDLE_ATTRIBUTE_INFORMATION Information;
} OBP_SET_HANDLE_ATTRIBUTES_CONTEXT, *POBP_SET_HANDLE_ATTRIBUTES_CONTEXT;
typedef struct _OBP_CLOSE_HANDLE_CONTEXT
{
PHANDLE_TABLE HandleTable;
KPROCESSOR_MODE AccessMode;
} OBP_CLOSE_HANDLE_CONTEXT, *POBP_CLOSE_HANDLE_CONTEXT;
#define GENERIC_ACCESS (GENERIC_READ | \
GENERIC_WRITE | \
GENERIC_EXECUTE | \
GENERIC_ALL)
#define KERNEL_HANDLE_FLAG (1 << ((sizeof(HANDLE) * 8) - 1))
#define ObIsKernelHandle(Handle, ProcessorMode) \
(((ULONG_PTR)(Handle) & KERNEL_HANDLE_FLAG) && \
((ProcessorMode) == KernelMode))
#define ObKernelHandleToHandle(Handle) \
(HANDLE)((ULONG_PTR)(Handle) & ~KERNEL_HANDLE_FLAG)
#define ObMarkHandleAsKernelHandle(Handle) \
(HANDLE)((ULONG_PTR)(Handle) | KERNEL_HANDLE_FLAG)
#define ObpGetHandleCountByHandleTable(HandleTable) \
((PHANDLE_TABLE)HandleTable)->HandleCount
extern KEVENT ObpDefaultObject;
extern POBJECT_TYPE ObpTypeObjectType;
extern POBJECT_TYPE ObSymbolicLinkType;
extern POBJECT_TYPE ObTypeObjectType;
extern POBJECT_DIRECTORY NameSpaceRoot;
extern POBJECT_DIRECTORY ObpTypeDirectoryObject;
extern PHANDLE_TABLE ObpKernelHandleTable;
extern WORK_QUEUE_ITEM ObpReaperWorkItem;
extern volatile PVOID ObpReaperList;
extern NPAGED_LOOKASIDE_LIST ObpNmLookasideList, ObpCiLookasideList;
//
// Directory Namespace Functions
//
BOOLEAN
NTAPI
ObpDeleteEntryDirectory(
@ -72,12 +108,33 @@ ObpLookupEntryDirectory(
IN POBP_LOOKUP_CONTEXT Context
);
//
// Symbolic Link Functions
//
VOID
NTAPI
ObInitSymbolicLinkImplementation(
VOID
);
NTSTATUS
NTAPI
ObpParseSymbolicLink(
IN PVOID ParsedObject,
IN PVOID ObjectType,
IN OUT PACCESS_STATE AccessState,
IN KPROCESSOR_MODE AccessMode,
IN ULONG Attributes,
IN OUT PUNICODE_STRING FullPath,
IN OUT PUNICODE_STRING RemainingName,
IN OUT PVOID Context OPTIONAL,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
OUT PVOID *NextObject
);
//
// Process/Handle Table Init/Rundown
//
NTSTATUS
NTAPI
ObpCreateHandleTable(
@ -91,6 +148,9 @@ ObKillProcess(
IN PEPROCESS Process
);
//
// Object Lookup Functions
//
NTSTATUS
NTAPI
ObFindObject(
@ -107,6 +167,9 @@ ObFindObject(
IN PVOID Insert
);
//
// Object Attribute Functions
//
BOOLEAN
NTAPI
ObpSetHandleAttributes(
@ -115,12 +178,6 @@ ObpSetHandleAttributes(
IN PVOID Context
);
VOID
NTAPI
ObpDeleteNameCheck(
IN PVOID Object
);
VOID
NTAPI
ObQueryDeviceMapInformation(
@ -128,13 +185,9 @@ ObQueryDeviceMapInformation(
OUT PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo
);
VOID
FASTCALL
ObpSetPermanentObject(
IN PVOID ObjectBody,
IN BOOLEAN Permanent
);
//
// Object Lifetime Functions
//
VOID
FASTCALL
ObpDeleteObject(
@ -147,11 +200,27 @@ ObpReapObject(
IN PVOID Unused
);
/* Security descriptor cache functions */
VOID
FASTCALL
ObpSetPermanentObject(
IN PVOID ObjectBody,
IN BOOLEAN Permanent
);
VOID
NTAPI
ObpDeleteNameCheck(
IN PVOID Object
);
//
// Security descriptor cache functions
//
NTSTATUS
NTAPI
ObpInitSdCache(VOID);
ObpInitSdCache(
VOID
);
NTSTATUS
NTAPI
@ -162,7 +231,9 @@ ObpAddSecurityDescriptor(
NTSTATUS
NTAPI
ObpRemoveSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor);
ObpRemoveSecurityDescriptor(
IN PSECURITY_DESCRIPTOR SecurityDescriptor
);
PSECURITY_DESCRIPTOR
NTAPI
@ -172,37 +243,45 @@ ObpReferenceCachedSecurityDescriptor(
VOID
NTAPI
ObpDereferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor);
ObpDereferenceCachedSecurityDescriptor(
IN PSECURITY_DESCRIPTOR SecurityDescriptor
);
//
// Executive Fast Referencing Functions
//
VOID
FASTCALL
ObInitializeFastReference(
IN PEX_FAST_REF FastRef,
PVOID Object
IN PVOID Object
);
PVOID
FASTCALL
ObFastReplaceObject(
IN PEX_FAST_REF FastRef,
PVOID Object
IN PVOID Object
);
PVOID
FASTCALL
ObFastReferenceObject(IN PEX_FAST_REF FastRef);
ObFastReferenceObject(
IN PEX_FAST_REF FastRef
);
VOID
FASTCALL
ObFastDereferenceObject(
IN PEX_FAST_REF FastRef,
PVOID Object
IN PVOID Object
);
/* Object Create and Object Name Capture Functions */
//
// Object Create and Object Name Capture Functions
//
NTSTATUS
STDCALL
NTAPI
ObpCaptureObjectName(
IN PUNICODE_STRING CapturedName,
IN PUNICODE_STRING ObjectName,
@ -211,7 +290,7 @@ ObpCaptureObjectName(
);
NTSTATUS
STDCALL
NTAPI
ObpCaptureObjectAttributes(
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN KPROCESSOR_MODE AccessMode,
@ -220,119 +299,17 @@ ObpCaptureObjectAttributes(
OUT PUNICODE_STRING ObjectName
);
VOID
static __inline
ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo)
{
/* Check if we have a security descriptor */
if (ObjectCreateInfo->SecurityDescriptor)
{
/* Release it */
SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor,
ObjectCreateInfo->ProbeMode,
TRUE);
ObjectCreateInfo->SecurityDescriptor = NULL;
}
}
PVOID
static __inline
ObpAllocateCapturedAttributes(IN PP_NPAGED_LOOKASIDE_NUMBER Type)
{
PKPRCB Prcb = KeGetCurrentPrcb();
PVOID Buffer;
PNPAGED_LOOKASIDE_LIST List;
/* Get the P list first */
List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[Type].P;
/* Attempt allocation */
List->L.TotalAllocates++;
Buffer = (PVOID)InterlockedPopEntrySList(&List->L.ListHead);
if (!Buffer)
{
/* Let the balancer know that the P list failed */
List->L.AllocateMisses++;
/* Try the L List */
List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[Type].L;
List->L.TotalAllocates++;
Buffer = (PVOID)InterlockedPopEntrySList(&List->L.ListHead);
if (!Buffer)
{
/* Let the balancer know the L list failed too */
List->L.AllocateMisses++;
/* Allocate it */
Buffer = List->L.Allocate(List->L.Type, List->L.Size, List->L.Tag);
}
}
/* Return buffer */
return Buffer;
}
VOID
static __inline
ObpFreeCapturedAttributes(IN PVOID Buffer,
IN PP_NPAGED_LOOKASIDE_NUMBER Type)
{
PKPRCB Prcb = KeGetCurrentPrcb();
PNPAGED_LOOKASIDE_LIST List;
/* Use the P List */
List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[Type].P;
List->L.TotalFrees++;
/* Check if the Free was within the Depth or not */
if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth)
{
/* Let the balancer know */
List->L.FreeMisses++;
/* Use the L List */
List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[Type].L;
List->L.TotalFrees++;
/* Check if the Free was within the Depth or not */
if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth)
{
/* All lists failed, use the pool */
List->L.FreeMisses++;
List->L.Free(Buffer);
}
}
else
{
/* The free was within the Depth */
InterlockedPushEntrySList(&List->L.ListHead,
(PSINGLE_LIST_ENTRY)Buffer);
}
}
VOID
static __inline
ObpReleaseCapturedName(IN PUNICODE_STRING Name)
{
/* We know this is a pool-allocation if the size doesn't match */
if (Name->MaximumLength != 248)
{
ExFreePool(Name->Buffer);
}
else
{
/* Otherwise, free from the lookaside */
ObpFreeCapturedAttributes(Name, LookasideNameBufferList);
}
}
VOID
static __inline
ObpFreeAndReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo)
{
/* First release the attributes, then free them from the lookaside list */
ObpReleaseCapturedAttributes(ObjectCreateInfo);
ObpFreeCapturedAttributes(ObjectCreateInfo, LookasideCreateInfoList);
}
#endif /* __INCLUDE_INTERNAL_OBJMGR_H */
//
// Global data inside the Object Manager
//
extern ULONG ObpTraceLevel;
extern KEVENT ObpDefaultObject;
extern POBJECT_TYPE ObpTypeObjectType;
extern POBJECT_TYPE ObSymbolicLinkType;
extern POBJECT_TYPE ObTypeObjectType;
extern POBJECT_DIRECTORY NameSpaceRoot;
extern POBJECT_DIRECTORY ObpTypeDirectoryObject;
extern PHANDLE_TABLE ObpKernelHandleTable;
extern WORK_QUEUE_ITEM ObpReaperWorkItem;
extern volatile PVOID ObpReaperList;
extern NPAGED_LOOKASIDE_LIST ObpNmLookasideList, ObpCiLookasideList;

View file

@ -0,0 +1,123 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/include/ob_x.h
* PURPOSE: Intenral Inlined Functions for the Object Manager
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
VOID
static __inline
ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo)
{
/* Check if we have a security descriptor */
if (ObjectCreateInfo->SecurityDescriptor)
{
/* Release it */
SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor,
ObjectCreateInfo->ProbeMode,
TRUE);
ObjectCreateInfo->SecurityDescriptor = NULL;
}
}
PVOID
static __inline
ObpAllocateCapturedAttributes(IN PP_NPAGED_LOOKASIDE_NUMBER Type)
{
PKPRCB Prcb = KeGetCurrentPrcb();
PVOID Buffer;
PNPAGED_LOOKASIDE_LIST List;
/* Get the P list first */
List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[Type].P;
/* Attempt allocation */
List->L.TotalAllocates++;
Buffer = (PVOID)InterlockedPopEntrySList(&List->L.ListHead);
if (!Buffer)
{
/* Let the balancer know that the P list failed */
List->L.AllocateMisses++;
/* Try the L List */
List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[Type].L;
List->L.TotalAllocates++;
Buffer = (PVOID)InterlockedPopEntrySList(&List->L.ListHead);
if (!Buffer)
{
/* Let the balancer know the L list failed too */
List->L.AllocateMisses++;
/* Allocate it */
Buffer = List->L.Allocate(List->L.Type, List->L.Size, List->L.Tag);
}
}
/* Return buffer */
return Buffer;
}
VOID
static __inline
ObpFreeCapturedAttributes(IN PVOID Buffer,
IN PP_NPAGED_LOOKASIDE_NUMBER Type)
{
PKPRCB Prcb = KeGetCurrentPrcb();
PNPAGED_LOOKASIDE_LIST List;
/* Use the P List */
List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[Type].P;
List->L.TotalFrees++;
/* Check if the Free was within the Depth or not */
if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth)
{
/* Let the balancer know */
List->L.FreeMisses++;
/* Use the L List */
List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[Type].L;
List->L.TotalFrees++;
/* Check if the Free was within the Depth or not */
if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth)
{
/* All lists failed, use the pool */
List->L.FreeMisses++;
List->L.Free(Buffer);
}
}
else
{
/* The free was within the Depth */
InterlockedPushEntrySList(&List->L.ListHead,
(PSINGLE_LIST_ENTRY)Buffer);
}
}
VOID
static __inline
ObpReleaseCapturedName(IN PUNICODE_STRING Name)
{
/* We know this is a pool-allocation if the size doesn't match */
if (Name->MaximumLength != 248)
{
ExFreePool(Name->Buffer);
}
else
{
/* Otherwise, free from the lookaside */
ObpFreeCapturedAttributes(Name, LookasideNameBufferList);
}
}
VOID
static __inline
ObpFreeAndReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo)
{
/* First release the attributes, then free them from the lookaside list */
ObpReleaseCapturedAttributes(ObjectCreateInfo);
ObpFreeCapturedAttributes(ObjectCreateInfo, LookasideCreateInfoList);
}

View file

@ -44,19 +44,15 @@ IopParseDevice(IN PVOID ParseObject,
NTSTATUS Status;
PFILE_OBJECT FileObject;
DPRINT("IopParseDevice:\n"
"DeviceObject : %p, Type : %p, TypeName : %wZ\n"
"FileObject : %p, Type : %p, TypeName : %wZ\n"
"CompleteName : %wZ, RemainingName : %wZ\n",
ParseObject,
ObjectType,
&ObjectType->Name,
Context,
Context ? OBJECT_TO_OBJECT_HEADER(Context)->Type : NULL,
Context ? &OBJECT_TO_OBJECT_HEADER(Context)->Type->Name: NULL,
CompleteName,
RemainingName);
"DeviceObject : %p\n"
"RelatedFileObject : %p\n"
"CompleteName : %wZ, RemainingName : %wZ\n",
ParseObject,
Context,
CompleteName,
RemainingName);
if (!RemainingName || !RemainingName->Buffer)
if (!*RemainingName->Buffer)
{
DeviceObject = ParseObject;
@ -71,6 +67,7 @@ IopParseDevice(IN PVOID ParseObject,
(PVOID*)&FileObject);
/* Set File Object Data */
FileObject->DeviceObject = IoGetAttachedDevice(DeviceObject);
DPRINT("DO. DRV Name: %p %wZ\n", DeviceObject, &DeviceObject->DriverObject->DriverName);
/* HACK */
FileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
@ -88,7 +85,7 @@ IopParseDevice(IN PVOID ParseObject,
0,
(PVOID*)&FileObject);
if (ObjectType == IoDeviceObjectType)
if (!Context)
{
/* Parent is a device object */
DeviceObject = IoGetAttachedDevice((PDEVICE_OBJECT)ParseObject);
@ -110,7 +107,6 @@ IopParseDevice(IN PVOID ParseObject,
RtlCreateUnicodeString(&FileObject->FileName, RemainingName->Buffer);
FileObject->DeviceObject = DeviceObject;
*Object = FileObject;
RemainingName->Buffer = NULL; // ros hack
return STATUS_SUCCESS;
}

View file

@ -19,12 +19,6 @@
PHANDLE_TABLE ObpKernelHandleTable = NULL;
#ifdef _OBDEBUG_
#define OBTRACE DPRINT1
#else
#define OBTRACE DPRINT
#endif
/* PRIVATE FUNCTIONS *********************************************************/
NTSTATUS
@ -103,7 +97,8 @@ ObpDecrementHandleCount(IN PVOID ObjectBody,
/* Get the object type and header */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
ObjectType = ObjectHeader->Type;
OBTRACE("OBTRACE - %s - Decrementing count for: %p. HC LC %lx %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Decrementing count for: %p. HC LC %lx %lx\n",
__FUNCTION__,
ObjectBody,
ObjectHeader->HandleCount,
@ -132,7 +127,8 @@ ObpDecrementHandleCount(IN PVOID ObjectBody,
/* Decrease the total number of handles for this type */
ObjectType->TotalNumberOfHandles--;
OBTRACE("OBTRACE - %s - Decremented count for: %p. HC LC %lx %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Decremented count for: %p. HC LC %lx %lx\n",
__FUNCTION__,
ObjectBody,
ObjectHeader->HandleCount,
@ -183,7 +179,8 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable,
ObjectType = ObjectHeader->Type;
Body = &ObjectHeader->Body;
GrantedAccess = HandleEntry->GrantedAccess;
OBTRACE("OBTRACE - %s - Closing handle: %lx for %p. HC LC %lx %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Closing handle: %lx for %p. HC LC %lx %lx\n",
__FUNCTION__,
Handle,
Body,
@ -243,7 +240,8 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable,
//ObDereferenceObject(Body); // FIXME: Needs sync changes in other code
/* Return to caller */
OBTRACE("OBTRACE - %s - Closed handle: %lx for %p. HC LC %lx %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Closed handle: %lx for %p. HC LC %lx %lx\n",
__FUNCTION__,
Handle,
Body,
@ -297,7 +295,8 @@ ObpIncrementHandleCount(IN PVOID Object,
/* Get the object header and type */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
ObjectType = ObjectHeader->Type;
OBTRACE("OBTRACE - %s - Incrementing count for: %p. Reason: %lx. HC LC %lx %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Incrementing count for: %p. Reason: %lx. HC LC %lx %lx\n",
__FUNCTION__,
Object,
OpenReason,
@ -376,7 +375,8 @@ ObpIncrementHandleCount(IN PVOID Object,
/* Increase total number of handles */
ObjectType->TotalNumberOfHandles++;
OBTRACE("OBTRACE - %s - Incremented count for: %p. Reason: %lx HC LC %lx %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Incremented count for: %p. Reason: %lx HC LC %lx %lx\n",
__FUNCTION__,
Object,
OpenReason,
@ -429,7 +429,8 @@ ObpIncrementUnnamedHandleCount(IN PVOID Object,
/* Get the object header and type */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
ObjectType = ObjectHeader->Type;
OBTRACE("OBTRACE - %s - Incrementing count for: %p. UNNAMED. HC LC %lx %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Incrementing count for: %p. UNNAMED. HC LC %lx %lx\n",
__FUNCTION__,
Object,
ObjectHeader->HandleCount,
@ -486,7 +487,8 @@ ObpIncrementUnnamedHandleCount(IN PVOID Object,
/* Increase total number of handles */
ObjectType->TotalNumberOfHandles++;
OBTRACE("OBTRACE - %s - Incremented count for: %p. UNNAMED HC LC %lx %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Incremented count for: %p. UNNAMED HC LC %lx %lx\n",
__FUNCTION__,
Object,
ObjectHeader->HandleCount,
@ -546,7 +548,8 @@ ObpCreateUnnamedHandle(IN PVOID Object,
/* Get the object header and type */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
OBTRACE("OBTRACE - %s - Creating handle for: %p. UNNAMED. HC LC %lx %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Creating handle for: %p. UNNAMED. HC LC %lx %lx\n",
__FUNCTION__,
Object,
ObjectHeader->HandleCount,
@ -606,7 +609,8 @@ ObpCreateUnnamedHandle(IN PVOID Object,
* ObpIncrementHandleCount to make sure that Object Security is valid
* (specified in Gl00my documentation on Ob)
*/
OBTRACE("OBTRACE - %s - Handle Properties: [%p-%lx-%lx]\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Handle Properties: [%p-%lx-%lx]\n",
__FUNCTION__,
NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess);
Handle = ExCreateHandle(HandleTable, &NewEntry);
@ -634,7 +638,8 @@ ObpCreateUnnamedHandle(IN PVOID Object,
/* Return handle and object */
*ReturnedHandle = Handle;
if (ReturnedObject) *ReturnedObject = Object;
OBTRACE("OBTRACE - %s - Returning Handle: %lx HC LC %lx %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s %s - Returning Handle: %lx HC LC %lx %lx\n",
__FUNCTION__,
Handle,
ObjectHeader->HandleCount,
@ -716,7 +721,8 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason,
/* Get the object header and type */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
ObjectType = ObjectHeader->Type;
OBTRACE("OBTRACE - %s - Creating handle for: %p. Reason: %lx. HC LC %lx %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Creating handle for: %p. Reason: %lx. HC LC %lx %lx\n",
__FUNCTION__,
Object,
OpenReason,
@ -787,7 +793,8 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason,
* ObpIncrementHandleCount to make sure that Object Security is valid
* (specified in Gl00my documentation on Ob)
*/
OBTRACE("OBTRACE - %s - Handle Properties: [%p-%lx-%lx]\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Handle Properties: [%p-%lx-%lx]\n",
__FUNCTION__,
NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess);
Handle = ExCreateHandle(HandleTable, &NewEntry);
@ -815,7 +822,8 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason,
/* Return handle and object */
*ReturnedHandle = Handle;
if (ReturnedObject) *ReturnedObject = Object;
OBTRACE("OBTRACE - %s - Returning Handle: %lx HC LC %lx %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Returning Handle: %lx HC LC %lx %lx\n",
__FUNCTION__,
Handle,
ObjectHeader->HandleCount,
@ -857,7 +865,8 @@ ObpCloseHandle(IN HANDLE Handle,
PHANDLE_TABLE_ENTRY HandleTableEntry;
NTSTATUS Status;
PAGED_CODE();
OBTRACE("OBTRACE - %s - Closing handle: %lx\n", __FUNCTION__, Handle);
OBTRACE(OB_HANDLE_DEBUG,
"%s - Closing handle: %lx\n", __FUNCTION__, Handle);
/* Check if we're dealing with a kernel handle */
if (ObIsKernelHandle(Handle, AccessMode))
@ -924,7 +933,8 @@ ObpCloseHandle(IN HANDLE Handle,
}
/* Return status */
OBTRACE("OBTRACE - %s - Closed handle: %lx S: %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Closed handle: %lx S: %lx\n",
__FUNCTION__, Handle, Status);
return Status;
}
@ -1213,7 +1223,8 @@ ObDuplicateObject(IN PEPROCESS SourceProcess,
PHANDLE_TABLE HandleTable = NULL;
OBJECT_HANDLE_INFORMATION HandleInformation;
PAGED_CODE();
OBTRACE("OBTRACE - %s - Duplicating handle: %lx for %p into %p\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Duplicating handle: %lx for %p into %p\n",
__FUNCTION__,
SourceHandle,
SourceProcess,
@ -1376,7 +1387,8 @@ ObDuplicateObject(IN PEPROCESS SourceProcess,
if (TargetHandle) *TargetHandle = NewHandle;
/* Return status */
OBTRACE("OBTRACE - %s - Duplicated handle: %lx for %p into %p. Source: %p HC PC %lx %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Duplicated handle: %lx for %p into %p. Source: %p HC PC %lx %lx\n",
__FUNCTION__,
NewHandle,
SourceProcess,
@ -1534,7 +1546,8 @@ Cleanup:
Quickie:
ObpReleaseCapturedAttributes(&ObjectCreateInfo);
if (ObjectName.Buffer) ObpReleaseCapturedName(&ObjectName);
OBTRACE("OBTRACE: %s returning Object with PC S: %lx %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s returning Object with PC S: %lx %lx\n",
__FUNCTION__,
OBJECT_TO_OBJECT_HEADER(Object)->PointerCount,
Status);
@ -1633,7 +1646,8 @@ ObOpenObjectByPointer(IN PVOID Object,
ObDereferenceObject(Object);
/* Return */
OBTRACE("OBTRACE: %s returning Object with PC S: %lx %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - returning Object with PC S: %lx %lx\n",
__FUNCTION__,
OBJECT_TO_OBJECT_HEADER(Object)->PointerCount,
Status);
@ -1993,11 +2007,12 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle,
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
OBTRACE("OBTRACE - %s - Duplicating handle: %lx for %lx into %lx.\n",
__FUNCTION__,
SourceHandle,
SourceProcessHandle,
TargetProcessHandle);
OBTRACE(OB_HANDLE_DEBUG,
"%s - Duplicating handle: %lx for %lx into %lx.\n",
__FUNCTION__,
SourceHandle,
SourceProcessHandle,
TargetProcessHandle);
if((TargetHandle) && (PreviousMode != KernelMode))
{
@ -2083,7 +2098,8 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle,
}
/* Dereference the processes */
OBTRACE("OBTRACE - %s - Duplicated handle: %lx into %lx S %lx\n",
OBTRACE(OB_HANDLE_DEBUG,
"%s - Duplicated handle: %lx into %lx S %lx\n",
__FUNCTION__,
hTarget,
TargetProcessHandle,

View file

@ -38,6 +38,7 @@ GENERIC_MAPPING ObpDirectoryMapping =
};
PDEVICE_MAP ObSystemDeviceMap = NULL;
ULONG ObpTraceLevel = OB_NAMESPACE_DEBUG;
/* PRIVATE FUNCTIONS *********************************************************/

View file

@ -106,280 +106,433 @@ NTAPI
ObFindObject(IN HANDLE RootHandle,
IN PUNICODE_STRING ObjectName,
IN ULONG Attributes,
IN KPROCESSOR_MODE PreviousMode,
IN KPROCESSOR_MODE AccessMode,
IN PVOID *ReturnedObject,
IN POBJECT_TYPE ObjectType,
IN POBP_LOOKUP_CONTEXT Context,
IN PACCESS_STATE AccessState,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
IN PVOID ParseContext,
IN PVOID Insert)
OUT PVOID ExpectedObject)
{
PVOID NextObject;
PVOID CurrentObject;
PVOID RootObject;
PVOID RootDirectory;
PVOID CurrentDirectory = NULL;
PVOID CurrentObject = NULL;
POBJECT_HEADER CurrentHeader;
NTSTATUS Status = STATUS_SUCCESS;
PWSTR current;
UNICODE_STRING PathString;
UNICODE_STRING CurrentUs;
UNICODE_STRING Path;
PUNICODE_STRING RemainingPath = &Path;
PVOID NewName;
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
UNICODE_STRING RemainingPath, PartName;
BOOLEAN InsideRoot = FALSE;
OB_PARSE_METHOD ParseRoutine;
PAGED_CODE();
DPRINT("ObFindObject(ObjectCreateInfo %x, ReturnedObject %x, "
"RemainingPath %x)\n",ObjectCreateInfo,ReturnedObject,RemainingPath);
/* Assume failure */
OBTRACE(OB_NAMESPACE_DEBUG,
"%s - Finding Object: %wZ. Expecting: %p\n",
__FUNCTION__,
ObjectName,
ExpectedObject);
*ReturnedObject = NULL;
RtlInitUnicodeString (RemainingPath, NULL);
if (RootHandle == NULL)
{
ObReferenceObjectByPointer(NameSpaceRoot,
DIRECTORY_TRAVERSE,
NULL,
PreviousMode);
CurrentObject = NameSpaceRoot;
}
else
/* Check if we got a Root Directory */
if (RootHandle)
{
/* We did. Reference it */
Status = ObReferenceObjectByHandle(RootHandle,
0,
NULL,
PreviousMode,
&CurrentObject,
NULL);
if (!NT_SUCCESS(Status))
0,
NULL,
AccessMode,
&RootDirectory,
NULL);
if (!NT_SUCCESS(Status)) return Status;
/* Get the header */
CurrentHeader = OBJECT_TO_OBJECT_HEADER(RootDirectory);
/* The name cannot start with a separator, unless this is a file */
if ((ObjectName->Buffer) &&
(ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR) &&
(CurrentHeader->Type != IoFileObjectType))
{
/* The syntax is bad, so fail this request */
ObDereferenceObject(RootDirectory);
return STATUS_OBJECT_PATH_SYNTAX_BAD;
}
/* Don't parse a Directory */
if (CurrentHeader->Type != ObDirectoryType)
{
/* Make sure the Object Type has a parse routine */
ParseRoutine = CurrentHeader->Type->TypeInfo.ParseProcedure;
if (!ParseRoutine)
{
/* We can't parse a name if we don't have a parse routine */
ObDereferenceObject(RootDirectory);
return STATUS_INVALID_HANDLE;
}
/* Now parse */
while (TRUE)
{
/* Start with the full name */
RemainingPath = *ObjectName;
/* Call the Parse Procedure */
Status = ParseRoutine(RootDirectory,
ObjectType,
AccessState,
AccessMode,
Attributes,
ObjectName,
&RemainingPath,
ParseContext,
SecurityQos,
&CurrentObject);
/* Check for success or failure, so not reparse */
if ((Status != STATUS_REPARSE) &&
(Status != STATUS_REPARSE_OBJECT))
{
/* Check for failure */
if (!NT_SUCCESS(Status))
{
/* Parse routine might not have cleared this, do it */
CurrentObject = NULL;
}
else if (!CurrentObject)
{
/* Modify status to reflect failure inside Ob */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
/* We're done, return the status and object */
*ReturnedObject = CurrentObject;
ObDereferenceObject(RootDirectory);
return Status;
}
else if ((!ObjectName->Length) ||
(!ObjectName->Buffer) ||
(ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
{
/* Reparsed to the root directory, so start over */
ObDereferenceObject(RootDirectory);
RootDirectory = NameSpaceRoot;
/* Don't use this anymore, since we're starting at root */
RootHandle = NULL;
break;
}
}
}
else if (!(ObjectName->Length) || !(ObjectName->Buffer))
{
/* Just return the Root Directory if we didn't get a name*/
Status = ObReferenceObjectByPointer(RootDirectory,
0,
ObjectType,
AccessMode);
if (NT_SUCCESS(Status)) *ReturnedObject = RootDirectory;
ObDereferenceObject(RootDirectory);
return Status;
}
}
if (ObjectName->Length == 0 ||
ObjectName->Buffer[0] == UNICODE_NULL)
{
*ReturnedObject = CurrentObject;
return STATUS_SUCCESS;
}
if (RootHandle == NULL &&
ObjectName->Buffer[0] != L'\\')
{
ObDereferenceObject (CurrentObject);
DPRINT1("failed\n");
return STATUS_UNSUCCESSFUL;
}
/* Create a zero-terminated copy of the object name */
PathString.Length = ObjectName->Length;
PathString.MaximumLength = ObjectName->Length + sizeof(WCHAR);
PathString.Buffer = ExAllocatePool (NonPagedPool,
PathString.MaximumLength);
if (PathString.Buffer == NULL)
{
ObDereferenceObject (CurrentObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory (PathString.Buffer,
ObjectName->Buffer,
ObjectName->Length);
PathString.Buffer[PathString.Length / sizeof(WCHAR)] = UNICODE_NULL;
current = PathString.Buffer;
RootObject = CurrentObject;
if (ObjectType == ObSymbolicLinkType)
Attributes |= OBJ_OPENLINK;
while (TRUE)
{
CurrentHeader = OBJECT_TO_OBJECT_HEADER(CurrentObject);
/* Loop as long as we're dealing with a directory */
while (CurrentHeader->Type == ObDirectoryType)
{
PWSTR Start, End;
PVOID FoundObject;
UNICODE_STRING StartUs;
NextObject = NULL;
if (!current) goto Next;
Start = current;
if (*Start == L'\\') Start++;
End = wcschr(Start, L'\\');
if (End != NULL) *End = 0;
RtlInitUnicodeString(&StartUs, Start);
Context->DirectoryLocked = TRUE;
Context->Directory = CurrentObject;
FoundObject = ObpLookupEntryDirectory(CurrentObject, &StartUs, Attributes, FALSE, Context);
if (FoundObject == NULL)
{
if (End != NULL)
{
*End = L'\\';
}
goto Next;
}
ObReferenceObjectByPointer(FoundObject,
STANDARD_RIGHTS_REQUIRED,
NULL,
UserMode);
if (End != NULL)
{
*End = L'\\';
current = End;
}
else
{
current = NULL;
}
NextObject = FoundObject;
Next:
if (NextObject == NULL)
{
break;
}
ObDereferenceObject(CurrentObject);
CurrentObject = NextObject;
CurrentHeader = OBJECT_TO_OBJECT_HEADER(CurrentObject);
}
if (CurrentHeader->Type->TypeInfo.ParseProcedure == NULL)
{
DPRINT("Current object can't parse\n");
break;
}
RtlInitUnicodeString(&CurrentUs, current);
Status = CurrentHeader->Type->TypeInfo.ParseProcedure(CurrentObject,
CurrentHeader->Type,
AccessState,
PreviousMode,
Attributes,
&PathString,
&CurrentUs,
ParseContext,
SecurityQos,
&NextObject);
current = CurrentUs.Buffer;
if (Status == STATUS_REPARSE)
{
/* reparse the object path */
NextObject = NameSpaceRoot;
current = PathString.Buffer;
ObReferenceObjectByPointer(NextObject,
DIRECTORY_TRAVERSE,
NULL,
PreviousMode);
}
if (NextObject == NULL)
{
break;
}
ObDereferenceObject(CurrentObject);
CurrentObject = NextObject;
if (!current) break;
}
if (current)
{
RtlpCreateUnicodeString (RemainingPath, current, NonPagedPool);
}
RtlFreeUnicodeString (&PathString);
*ReturnedObject = CurrentObject;
/*
* Icky hack: put the code that was in ObInsertObject here so that
* we can get rid of the "RemainingPath" stuff, which shouldn't
* be exposed outside of here.
* Also makes the interface closer to NT parsing, and will make the
* eventual changes easier to deal with
*/
if (Insert)
{
PVOID FoundObject = NULL;
POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(Insert);
POBJECT_HEADER FoundHeader = NULL;
FoundObject = *ReturnedObject;
if (FoundObject)
{
FoundHeader = OBJECT_TO_OBJECT_HEADER(FoundObject);
}
if (FoundHeader && RemainingPath->Buffer == NULL)
{
DPRINT("Object exists\n");
ObDereferenceObject(FoundObject);
return STATUS_OBJECT_NAME_COLLISION;
}
/*
* MiniHack
* If we still have a remaining path on a directory object, but we are
* a file object, then fail, because this means the file doesn't exist
*/
if ((RemainingPath->Buffer) &&
(FoundHeader && FoundHeader->Type == ObDirectoryType) &&
(Header->Type == IoFileObjectType))
{
/* Hack */
RtlFreeUnicodeString(RemainingPath);
*ReturnedObject = NULL;
return STATUS_OBJECT_PATH_NOT_FOUND;
}
if (FoundHeader && FoundHeader->Type == ObDirectoryType &&
RemainingPath->Buffer)
{
/* The name was changed so let's update it */
PVOID NewName;
PWSTR BufferPos = RemainingPath->Buffer;
ULONG Delta = 0;
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(Header);
if (BufferPos[0] == L'\\')
{
BufferPos++;
Delta = sizeof(WCHAR);
}
NewName = ExAllocatePool(NonPagedPool, RemainingPath->MaximumLength - Delta);
RtlMoveMemory(NewName, BufferPos, RemainingPath->MaximumLength - Delta);
if (ObjectNameInfo->Name.Buffer) ExFreePool(ObjectNameInfo->Name.Buffer);
ObjectNameInfo->Name.Buffer = NewName;
ObjectNameInfo->Name.Length = RemainingPath->Length - Delta;
ObjectNameInfo->Name.MaximumLength = RemainingPath->MaximumLength - Delta;
ObpInsertEntryDirectory(FoundObject, Context, Header);
}
RtlFreeUnicodeString(RemainingPath);
*ReturnedObject = Insert;
}
else
{
/* ROS Hack */
DPRINT("REmaining path: %wZ\n", RemainingPath);
if (RemainingPath->Buffer != NULL)
/* We did not get a Root Directory, so use the root */
RootDirectory = NameSpaceRoot;
/* It must start with a path separator */
if (!(ObjectName->Length) ||
!(ObjectName->Buffer) ||
(ObjectName->Buffer[0] != OBJ_NAME_PATH_SEPARATOR))
{
if (wcschr(RemainingPath->Buffer + 1, L'\\') == NULL)
Status = STATUS_OBJECT_NAME_NOT_FOUND;
/* This name is invalid, so fail */
return STATUS_OBJECT_PATH_SYNTAX_BAD;
}
/* Check if the name is only the path separator */
if (ObjectName->Length == sizeof(OBJ_NAME_PATH_SEPARATOR))
{
/* So the caller only wants the root directory; do we have one? */
if (!RootDirectory)
{
/* This must be the first time we're creating it... right? */
if (ExpectedObject)
{
/* Yes, so return it to ObInsert so that it can create it */
Status = ObReferenceObjectByPointer(ExpectedObject,
0,
ObjectType,
AccessMode);
if (NT_SUCCESS(Status)) *ReturnedObject = ExpectedObject;
return Status;
}
else
{
/* This should never really happen */
ASSERT(FALSE);
return STATUS_INVALID_PARAMETER;
}
}
else
Status =STATUS_OBJECT_PATH_NOT_FOUND;
{
/* We do have the root directory, so just return it */
Status = ObReferenceObjectByPointer(RootDirectory,
0,
ObjectType,
AccessMode);
if (NT_SUCCESS(Status)) *ReturnedObject = RootDirectory;
return Status;
}
}
}
/* Save the name */
ReparseNewDir:
RemainingPath = *ObjectName;
/* Reparse */
while (TRUE)
{
/* Check if we should use the Root Directory */
if (!InsideRoot)
{
/* Yes, use the root directory and remember that */
CurrentDirectory = RootDirectory;
InsideRoot = TRUE;
}
/* Check if the name starts with a path separator */
if ((RemainingPath.Length) &&
(RemainingPath.Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
{
/* Skip the path separator */
RemainingPath.Buffer++;
RemainingPath.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
}
/* Find the next Part Name */
PartName = RemainingPath;
while (RemainingPath.Length)
{
/* Break if we found the \ ending */
if (RemainingPath.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) break;
/* Move on */
RemainingPath.Buffer++;
RemainingPath.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
}
/* Get its size and make sure it's valid */
if (!(PartName.Length -= RemainingPath.Length))
{
Status = STATUS_OBJECT_NAME_INVALID;
break;
}
/* Do the look up */
Context->DirectoryLocked = TRUE;
Context->Directory = CurrentDirectory;
CurrentObject = ObpLookupEntryDirectory(CurrentDirectory,
&PartName,
Attributes,
FALSE,
Context);
if (!CurrentObject)
{
/* We didn't find it... do we still have a path? */
if (RemainingPath.Length)
{
/* Then tell the caller the path wasn't found */
Status = STATUS_OBJECT_PATH_NOT_FOUND;
break;
}
else if (!ExpectedObject)
{
/* Otherwise, we have a path, but the name isn't valid */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
break;
}
/* Reference newly to be inserted object */
ObReferenceObject(ExpectedObject);
CurrentHeader = OBJECT_TO_OBJECT_HEADER(ExpectedObject);
/* Create Object Name */
NewName = ExAllocatePoolWithTag(NonPagedPool,
PartName.MaximumLength,
OB_NAME_TAG);
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(CurrentHeader);
/* Copy the Name */
RtlMoveMemory(NewName, PartName.Buffer, PartName.MaximumLength);
/* Free old name */
if (ObjectNameInfo->Name.Buffer) ExFreePool(ObjectNameInfo->Name.Buffer);
/* Write new one */
ObjectNameInfo->Name.Buffer = NewName;
ObjectNameInfo->Name.Length = PartName.Length;
ObjectNameInfo->Name.MaximumLength = PartName.MaximumLength;
/* Rereference the Directory and insert */
ObReferenceObject(CurrentDirectory);
ObpInsertEntryDirectory(CurrentDirectory, Context, CurrentHeader);
/* Return Status and the Expected Object */
Status = STATUS_SUCCESS;
CurrentObject = ExpectedObject;
/* Get out of here */
break;
}
Reparse:
/* We found it, so now get its header */
CurrentHeader = OBJECT_TO_OBJECT_HEADER(CurrentObject);
/*
* Check for a parse Procedure, but don't bother to parse for an insert
* unless it's a Symbolic Link, in which case we MUST parse
*/
ParseRoutine = CurrentHeader->Type->TypeInfo.ParseProcedure;
if (ParseRoutine &&
(!ExpectedObject || ParseRoutine == ObpParseSymbolicLink))
{
/* Use the Root Directory next time */
InsideRoot = FALSE;
/* Call the Parse Procedure */
Status = ParseRoutine(CurrentObject,
ObjectType,
AccessState,
AccessMode,
Attributes,
ObjectName,
&RemainingPath,
ParseContext,
SecurityQos,
&CurrentObject);
/* Check if we have to reparse */
if ((Status == STATUS_REPARSE) ||
(Status == STATUS_REPARSE_OBJECT))
{
/* Start over from root if we got sent back there */
if ((Status == STATUS_REPARSE_OBJECT) ||
(ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
{
/* Check if we got a root directory */
if (RootHandle)
{
/* Stop using it, because we have a new directory now */
ObDereferenceObject(RootDirectory);
RootHandle = NULL;
}
/* Start at Root */
RootDirectory = NameSpaceRoot;
/* Check for reparse status */
if (Status == STATUS_REPARSE_OBJECT)
{
/* Did we actually get an object to which to reparse? */
if (!CurrentObject)
{
/* We didn't, so set a failure status */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
else
{
/* We did, so we're free to parse the new object */
InsideRoot = TRUE;
goto Reparse;
}
}
/* Restart the search */
goto ReparseNewDir;
}
else if (RootDirectory == NameSpaceRoot)
{
/* We got STATUS_REPARSE but are at the Root Directory */
CurrentObject = NULL;
Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
}
else if (!NT_SUCCESS(Status))
{
/* Total failure */
CurrentObject = NULL;
}
else if (!CurrentObject)
{
/* We didn't reparse but we didn't find the Object Either */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
/* Break out of the loop */
break;
}
else
{
/* No parse routine...do we still have a remaining name? */
if (!RemainingPath.Length)
{
/* Are we creating an object? */
if (!ExpectedObject)
{
/* We don't... reference the Object */
Status = ObReferenceObjectByPointer(CurrentObject,
0,
ObjectType,
AccessMode);
if (!NT_SUCCESS(Status)) CurrentObject = NULL;
}
/* And get out of the reparse loop */
break;
}
else
{
/* We still have a name; check if this is a directory object */
if (CurrentHeader->Type == ObDirectoryType)
{
/* Restart from this directory */
CurrentDirectory = CurrentObject;
}
else
{
/* We still have a name, but no parse routine for it */
Status = STATUS_OBJECT_TYPE_MISMATCH;
CurrentObject = NULL;
break;
}
}
}
}
/* Write what we found, and if it's null, check if we got success */
if (!(*ReturnedObject = CurrentObject) && (NT_SUCCESS(Status)))
{
/* Nothing found... but we have success. Correct the status code */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
/* Check if we had a root directory */
if (RootHandle)
{
/* Dereference it */
ObDereferenceObject(RootDirectory);
}
/* Return status to caller */
OBTRACE(OB_NAMESPACE_DEBUG,
"%s - Found Object: %p. Expected: %p\n",
__FUNCTION__,
*ReturnedObject,
ExpectedObject);
return Status;
}

View file

@ -100,24 +100,45 @@ ObpParseSymbolicLink(IN PVOID ParsedObject,
POBJECT_SYMBOLIC_LINK SymlinkObject = (POBJECT_SYMBOLIC_LINK)ParsedObject;
PUNICODE_STRING TargetPath;
PWSTR NewTargetPath;
ULONG LengthUsed, MaximumLength, RemainLength;
PWSTR *RemainingPath = &RemainingName->Buffer;
ULONG LengthUsed, MaximumLength;
NTSTATUS Status;
/*
* Stop parsing if the entire path has been parsed and
* the desired object is a symbolic link object.
*/
if (((*RemainingPath == NULL) || (**RemainingPath == 0)) &&
(Attributes & OBJ_OPENLINK))
/* Assume failure */
*NextObject = NULL;
/* Check if we're out of name to parse */
if (!RemainingName->Length)
{
*NextObject = NULL;
return(STATUS_SUCCESS);
/* Check if we got an object type */
if (ObjectType)
{
/* Reference the object only */
Status = ObReferenceObjectByPointer(ParsedObject,
0,
ObjectType,
AccessMode);
if (NT_SUCCESS(Status))
{
/* Return it */
*NextObject = ParsedObject;
}
if ((NT_SUCCESS(Status)) || (Status != STATUS_OBJECT_TYPE_MISMATCH))
{
/* Fail */
return Status;
}
}
}
else if (RemainingName->Buffer[0] != OBJ_NAME_PATH_SEPARATOR)
{
/* Symbolic links must start with a backslash */
return STATUS_OBJECT_TYPE_MISMATCH;
}
/* Set the target path and length */
TargetPath = &SymlinkObject->LinkTarget;
RemainLength = *RemainingPath ? wcslen(*RemainingPath) * sizeof(WCHAR) : 0;
LengthUsed = TargetPath->Length + RemainLength;
LengthUsed = TargetPath->Length + RemainingName->Length;
/* Optimization: check if the new name is shorter */
if (FullPath->MaximumLength <= LengthUsed)
@ -136,12 +157,12 @@ ObpParseSymbolicLink(IN PVOID ParsedObject,
}
/* Make sure we have a length */
if (RemainLength)
if (RemainingName->Length)
{
/* Copy the new path */
RtlMoveMemory((PVOID)((ULONG_PTR)NewTargetPath + TargetPath->Length),
*RemainingPath,
RemainLength);
RemainingName->Buffer,
RemainingName->Length);
}
/* Copy the target path and null-terminate it */
@ -156,10 +177,7 @@ ObpParseSymbolicLink(IN PVOID ParsedObject,
FullPath->MaximumLength = MaximumLength;
FullPath->Buffer = NewTargetPath;
/* Reinitialize RemainingPath for reparsing */
*RemainingPath = FullPath->Buffer;
*NextObject = NULL;
/* Tell the parse routine to start reparsing */
return STATUS_REPARSE;
}

View file

@ -133,7 +133,6 @@ IntDesktopObjectParse(IN PVOID ParseObject,
/* Reference the desktop and return it */
ObReferenceObject(Desktop);
*Object = Desktop;
RemainingName->Buffer = NULL; // => ROS Parse routines need to do this
return Status;
}
}
@ -168,7 +167,6 @@ IntDesktopObjectParse(IN PVOID ParseObject,
/* Set the desktop object and return success */
*Object = Desktop;
RemainingName->Buffer = NULL; // => ROS Parse routines need to do this
return STATUS_SUCCESS;
}

View file

@ -126,8 +126,8 @@ IntWinStaObjectParse(PWIN32_PARSEMETHOD_PARAMETERS Parameters)
}
/* Reference the window station and return */
//ObReferenceObject(Object);
//*NextObject = Object; => ROS Parse routines don't need to do this
ObReferenceObject(Parameters->ParseObject);
*Parameters->Object = Parameters->ParseObject;
return STATUS_SUCCESS;
}
@ -149,10 +149,8 @@ IntWinStaObjectParse(PWIN32_PARSEMETHOD_PARAMETERS Parameters)
/*
* 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 (Parameters->ObjectType == ExWindowStationObjectType)
if (Parameters->ObjectType == ExDesktopObjectType)
{
/* Then call the desktop parse routine */
return IntDesktopObjectParse(Parameters->ParseObject,