mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +00:00
- 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:
parent
119738339b
commit
8d3f5096fd
9 changed files with 778 additions and 498 deletions
|
@ -1,53 +1,89 @@
|
||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* PROJECT: ReactOS Kernel
|
||||||
* PROJECT: ReactOS kernel
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: include/internal/objmgr.h
|
* FILE: ntoskrnl/include/ob.h
|
||||||
* PURPOSE: Object manager definitions
|
* PURPOSE: Internal header for the Object Manager
|
||||||
* PROGRAMMER: David Welch (welch@mcmail.com)
|
* 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
|
typedef struct _OBP_SET_HANDLE_ATTRIBUTES_CONTEXT
|
||||||
{
|
{
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode;
|
||||||
OBJECT_HANDLE_ATTRIBUTE_INFORMATION Information;
|
OBJECT_HANDLE_ATTRIBUTE_INFORMATION Information;
|
||||||
} OBP_SET_HANDLE_ATTRIBUTES_CONTEXT, *POBP_SET_HANDLE_ATTRIBUTES_CONTEXT;
|
} OBP_SET_HANDLE_ATTRIBUTES_CONTEXT, *POBP_SET_HANDLE_ATTRIBUTES_CONTEXT;
|
||||||
|
|
||||||
typedef struct _OBP_CLOSE_HANDLE_CONTEXT
|
typedef struct _OBP_CLOSE_HANDLE_CONTEXT
|
||||||
{
|
{
|
||||||
PHANDLE_TABLE HandleTable;
|
PHANDLE_TABLE HandleTable;
|
||||||
KPROCESSOR_MODE AccessMode;
|
KPROCESSOR_MODE AccessMode;
|
||||||
} OBP_CLOSE_HANDLE_CONTEXT, *POBP_CLOSE_HANDLE_CONTEXT;
|
} OBP_CLOSE_HANDLE_CONTEXT, *POBP_CLOSE_HANDLE_CONTEXT;
|
||||||
|
|
||||||
#define GENERIC_ACCESS (GENERIC_READ | \
|
//
|
||||||
GENERIC_WRITE | \
|
// Directory Namespace Functions
|
||||||
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;
|
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
ObpDeleteEntryDirectory(
|
ObpDeleteEntryDirectory(
|
||||||
|
@ -72,12 +108,33 @@ ObpLookupEntryDirectory(
|
||||||
IN POBP_LOOKUP_CONTEXT Context
|
IN POBP_LOOKUP_CONTEXT Context
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Symbolic Link Functions
|
||||||
|
//
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
ObInitSymbolicLinkImplementation(
|
ObInitSymbolicLinkImplementation(
|
||||||
VOID
|
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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
ObpCreateHandleTable(
|
ObpCreateHandleTable(
|
||||||
|
@ -91,6 +148,9 @@ ObKillProcess(
|
||||||
IN PEPROCESS Process
|
IN PEPROCESS Process
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Object Lookup Functions
|
||||||
|
//
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
ObFindObject(
|
ObFindObject(
|
||||||
|
@ -107,6 +167,9 @@ ObFindObject(
|
||||||
IN PVOID Insert
|
IN PVOID Insert
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Object Attribute Functions
|
||||||
|
//
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
ObpSetHandleAttributes(
|
ObpSetHandleAttributes(
|
||||||
|
@ -115,12 +178,6 @@ ObpSetHandleAttributes(
|
||||||
IN PVOID Context
|
IN PVOID Context
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
ObpDeleteNameCheck(
|
|
||||||
IN PVOID Object
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
ObQueryDeviceMapInformation(
|
ObQueryDeviceMapInformation(
|
||||||
|
@ -128,13 +185,9 @@ ObQueryDeviceMapInformation(
|
||||||
OUT PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo
|
OUT PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID
|
//
|
||||||
FASTCALL
|
// Object Lifetime Functions
|
||||||
ObpSetPermanentObject(
|
//
|
||||||
IN PVOID ObjectBody,
|
|
||||||
IN BOOLEAN Permanent
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
FASTCALL
|
FASTCALL
|
||||||
ObpDeleteObject(
|
ObpDeleteObject(
|
||||||
|
@ -147,11 +200,27 @@ ObpReapObject(
|
||||||
IN PVOID Unused
|
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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
ObpInitSdCache(VOID);
|
ObpInitSdCache(
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -162,7 +231,9 @@ ObpAddSecurityDescriptor(
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
ObpRemoveSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor);
|
ObpRemoveSecurityDescriptor(
|
||||||
|
IN PSECURITY_DESCRIPTOR SecurityDescriptor
|
||||||
|
);
|
||||||
|
|
||||||
PSECURITY_DESCRIPTOR
|
PSECURITY_DESCRIPTOR
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -172,37 +243,45 @@ ObpReferenceCachedSecurityDescriptor(
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
ObpDereferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor);
|
ObpDereferenceCachedSecurityDescriptor(
|
||||||
|
IN PSECURITY_DESCRIPTOR SecurityDescriptor
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Executive Fast Referencing Functions
|
||||||
|
//
|
||||||
VOID
|
VOID
|
||||||
FASTCALL
|
FASTCALL
|
||||||
ObInitializeFastReference(
|
ObInitializeFastReference(
|
||||||
IN PEX_FAST_REF FastRef,
|
IN PEX_FAST_REF FastRef,
|
||||||
PVOID Object
|
IN PVOID Object
|
||||||
);
|
);
|
||||||
|
|
||||||
PVOID
|
PVOID
|
||||||
FASTCALL
|
FASTCALL
|
||||||
ObFastReplaceObject(
|
ObFastReplaceObject(
|
||||||
IN PEX_FAST_REF FastRef,
|
IN PEX_FAST_REF FastRef,
|
||||||
PVOID Object
|
IN PVOID Object
|
||||||
);
|
);
|
||||||
|
|
||||||
PVOID
|
PVOID
|
||||||
FASTCALL
|
FASTCALL
|
||||||
ObFastReferenceObject(IN PEX_FAST_REF FastRef);
|
ObFastReferenceObject(
|
||||||
|
IN PEX_FAST_REF FastRef
|
||||||
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
FASTCALL
|
FASTCALL
|
||||||
ObFastDereferenceObject(
|
ObFastDereferenceObject(
|
||||||
IN PEX_FAST_REF FastRef,
|
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
|
NTSTATUS
|
||||||
STDCALL
|
NTAPI
|
||||||
ObpCaptureObjectName(
|
ObpCaptureObjectName(
|
||||||
IN PUNICODE_STRING CapturedName,
|
IN PUNICODE_STRING CapturedName,
|
||||||
IN PUNICODE_STRING ObjectName,
|
IN PUNICODE_STRING ObjectName,
|
||||||
|
@ -211,7 +290,7 @@ ObpCaptureObjectName(
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
NTAPI
|
||||||
ObpCaptureObjectAttributes(
|
ObpCaptureObjectAttributes(
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
IN KPROCESSOR_MODE AccessMode,
|
IN KPROCESSOR_MODE AccessMode,
|
||||||
|
@ -220,119 +299,17 @@ ObpCaptureObjectAttributes(
|
||||||
OUT PUNICODE_STRING ObjectName
|
OUT PUNICODE_STRING ObjectName
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID
|
//
|
||||||
static __inline
|
// Global data inside the Object Manager
|
||||||
ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo)
|
//
|
||||||
{
|
extern ULONG ObpTraceLevel;
|
||||||
/* Check if we have a security descriptor */
|
extern KEVENT ObpDefaultObject;
|
||||||
if (ObjectCreateInfo->SecurityDescriptor)
|
extern POBJECT_TYPE ObpTypeObjectType;
|
||||||
{
|
extern POBJECT_TYPE ObSymbolicLinkType;
|
||||||
/* Release it */
|
extern POBJECT_TYPE ObTypeObjectType;
|
||||||
SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor,
|
extern POBJECT_DIRECTORY NameSpaceRoot;
|
||||||
ObjectCreateInfo->ProbeMode,
|
extern POBJECT_DIRECTORY ObpTypeDirectoryObject;
|
||||||
TRUE);
|
extern PHANDLE_TABLE ObpKernelHandleTable;
|
||||||
ObjectCreateInfo->SecurityDescriptor = NULL;
|
extern WORK_QUEUE_ITEM ObpReaperWorkItem;
|
||||||
}
|
extern volatile PVOID ObpReaperList;
|
||||||
}
|
extern NPAGED_LOOKASIDE_LIST ObpNmLookasideList, ObpCiLookasideList;
|
||||||
|
|
||||||
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 */
|
|
||||||
|
|
123
reactos/ntoskrnl/include/internal/ob_x.h
Normal file
123
reactos/ntoskrnl/include/internal/ob_x.h
Normal 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);
|
||||||
|
}
|
||||||
|
|
|
@ -44,19 +44,15 @@ IopParseDevice(IN PVOID ParseObject,
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
DPRINT("IopParseDevice:\n"
|
DPRINT("IopParseDevice:\n"
|
||||||
"DeviceObject : %p, Type : %p, TypeName : %wZ\n"
|
"DeviceObject : %p\n"
|
||||||
"FileObject : %p, Type : %p, TypeName : %wZ\n"
|
"RelatedFileObject : %p\n"
|
||||||
"CompleteName : %wZ, RemainingName : %wZ\n",
|
"CompleteName : %wZ, RemainingName : %wZ\n",
|
||||||
ParseObject,
|
ParseObject,
|
||||||
ObjectType,
|
Context,
|
||||||
&ObjectType->Name,
|
CompleteName,
|
||||||
Context,
|
RemainingName);
|
||||||
Context ? OBJECT_TO_OBJECT_HEADER(Context)->Type : NULL,
|
|
||||||
Context ? &OBJECT_TO_OBJECT_HEADER(Context)->Type->Name: NULL,
|
|
||||||
CompleteName,
|
|
||||||
RemainingName);
|
|
||||||
|
|
||||||
if (!RemainingName || !RemainingName->Buffer)
|
if (!*RemainingName->Buffer)
|
||||||
{
|
{
|
||||||
DeviceObject = ParseObject;
|
DeviceObject = ParseObject;
|
||||||
|
|
||||||
|
@ -71,6 +67,7 @@ IopParseDevice(IN PVOID ParseObject,
|
||||||
(PVOID*)&FileObject);
|
(PVOID*)&FileObject);
|
||||||
/* Set File Object Data */
|
/* Set File Object Data */
|
||||||
FileObject->DeviceObject = IoGetAttachedDevice(DeviceObject);
|
FileObject->DeviceObject = IoGetAttachedDevice(DeviceObject);
|
||||||
|
DPRINT("DO. DRV Name: %p %wZ\n", DeviceObject, &DeviceObject->DriverObject->DriverName);
|
||||||
|
|
||||||
/* HACK */
|
/* HACK */
|
||||||
FileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
|
FileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
|
||||||
|
@ -88,7 +85,7 @@ IopParseDevice(IN PVOID ParseObject,
|
||||||
0,
|
0,
|
||||||
(PVOID*)&FileObject);
|
(PVOID*)&FileObject);
|
||||||
|
|
||||||
if (ObjectType == IoDeviceObjectType)
|
if (!Context)
|
||||||
{
|
{
|
||||||
/* Parent is a device object */
|
/* Parent is a device object */
|
||||||
DeviceObject = IoGetAttachedDevice((PDEVICE_OBJECT)ParseObject);
|
DeviceObject = IoGetAttachedDevice((PDEVICE_OBJECT)ParseObject);
|
||||||
|
@ -110,7 +107,6 @@ IopParseDevice(IN PVOID ParseObject,
|
||||||
RtlCreateUnicodeString(&FileObject->FileName, RemainingName->Buffer);
|
RtlCreateUnicodeString(&FileObject->FileName, RemainingName->Buffer);
|
||||||
FileObject->DeviceObject = DeviceObject;
|
FileObject->DeviceObject = DeviceObject;
|
||||||
*Object = FileObject;
|
*Object = FileObject;
|
||||||
RemainingName->Buffer = NULL; // ros hack
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,12 +19,6 @@
|
||||||
|
|
||||||
PHANDLE_TABLE ObpKernelHandleTable = NULL;
|
PHANDLE_TABLE ObpKernelHandleTable = NULL;
|
||||||
|
|
||||||
#ifdef _OBDEBUG_
|
|
||||||
#define OBTRACE DPRINT1
|
|
||||||
#else
|
|
||||||
#define OBTRACE DPRINT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS *********************************************************/
|
/* PRIVATE FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -103,7 +97,8 @@ ObpDecrementHandleCount(IN PVOID ObjectBody,
|
||||||
/* Get the object type and header */
|
/* Get the object type and header */
|
||||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
|
||||||
ObjectType = ObjectHeader->Type;
|
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__,
|
__FUNCTION__,
|
||||||
ObjectBody,
|
ObjectBody,
|
||||||
ObjectHeader->HandleCount,
|
ObjectHeader->HandleCount,
|
||||||
|
@ -132,7 +127,8 @@ ObpDecrementHandleCount(IN PVOID ObjectBody,
|
||||||
|
|
||||||
/* Decrease the total number of handles for this type */
|
/* Decrease the total number of handles for this type */
|
||||||
ObjectType->TotalNumberOfHandles--;
|
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__,
|
__FUNCTION__,
|
||||||
ObjectBody,
|
ObjectBody,
|
||||||
ObjectHeader->HandleCount,
|
ObjectHeader->HandleCount,
|
||||||
|
@ -183,7 +179,8 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable,
|
||||||
ObjectType = ObjectHeader->Type;
|
ObjectType = ObjectHeader->Type;
|
||||||
Body = &ObjectHeader->Body;
|
Body = &ObjectHeader->Body;
|
||||||
GrantedAccess = HandleEntry->GrantedAccess;
|
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__,
|
__FUNCTION__,
|
||||||
Handle,
|
Handle,
|
||||||
Body,
|
Body,
|
||||||
|
@ -243,7 +240,8 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable,
|
||||||
//ObDereferenceObject(Body); // FIXME: Needs sync changes in other code
|
//ObDereferenceObject(Body); // FIXME: Needs sync changes in other code
|
||||||
|
|
||||||
/* Return to caller */
|
/* 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__,
|
__FUNCTION__,
|
||||||
Handle,
|
Handle,
|
||||||
Body,
|
Body,
|
||||||
|
@ -297,7 +295,8 @@ ObpIncrementHandleCount(IN PVOID Object,
|
||||||
/* Get the object header and type */
|
/* Get the object header and type */
|
||||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
||||||
ObjectType = ObjectHeader->Type;
|
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__,
|
__FUNCTION__,
|
||||||
Object,
|
Object,
|
||||||
OpenReason,
|
OpenReason,
|
||||||
|
@ -376,7 +375,8 @@ ObpIncrementHandleCount(IN PVOID Object,
|
||||||
|
|
||||||
/* Increase total number of handles */
|
/* Increase total number of handles */
|
||||||
ObjectType->TotalNumberOfHandles++;
|
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__,
|
__FUNCTION__,
|
||||||
Object,
|
Object,
|
||||||
OpenReason,
|
OpenReason,
|
||||||
|
@ -429,7 +429,8 @@ ObpIncrementUnnamedHandleCount(IN PVOID Object,
|
||||||
/* Get the object header and type */
|
/* Get the object header and type */
|
||||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
||||||
ObjectType = ObjectHeader->Type;
|
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__,
|
__FUNCTION__,
|
||||||
Object,
|
Object,
|
||||||
ObjectHeader->HandleCount,
|
ObjectHeader->HandleCount,
|
||||||
|
@ -486,7 +487,8 @@ ObpIncrementUnnamedHandleCount(IN PVOID Object,
|
||||||
|
|
||||||
/* Increase total number of handles */
|
/* Increase total number of handles */
|
||||||
ObjectType->TotalNumberOfHandles++;
|
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__,
|
__FUNCTION__,
|
||||||
Object,
|
Object,
|
||||||
ObjectHeader->HandleCount,
|
ObjectHeader->HandleCount,
|
||||||
|
@ -546,7 +548,8 @@ ObpCreateUnnamedHandle(IN PVOID Object,
|
||||||
|
|
||||||
/* Get the object header and type */
|
/* Get the object header and type */
|
||||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
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__,
|
__FUNCTION__,
|
||||||
Object,
|
Object,
|
||||||
ObjectHeader->HandleCount,
|
ObjectHeader->HandleCount,
|
||||||
|
@ -606,7 +609,8 @@ ObpCreateUnnamedHandle(IN PVOID Object,
|
||||||
* ObpIncrementHandleCount to make sure that Object Security is valid
|
* ObpIncrementHandleCount to make sure that Object Security is valid
|
||||||
* (specified in Gl00my documentation on Ob)
|
* (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__,
|
__FUNCTION__,
|
||||||
NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess);
|
NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess);
|
||||||
Handle = ExCreateHandle(HandleTable, &NewEntry);
|
Handle = ExCreateHandle(HandleTable, &NewEntry);
|
||||||
|
@ -634,7 +638,8 @@ ObpCreateUnnamedHandle(IN PVOID Object,
|
||||||
/* Return handle and object */
|
/* Return handle and object */
|
||||||
*ReturnedHandle = Handle;
|
*ReturnedHandle = Handle;
|
||||||
if (ReturnedObject) *ReturnedObject = Object;
|
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__,
|
__FUNCTION__,
|
||||||
Handle,
|
Handle,
|
||||||
ObjectHeader->HandleCount,
|
ObjectHeader->HandleCount,
|
||||||
|
@ -716,7 +721,8 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason,
|
||||||
/* Get the object header and type */
|
/* Get the object header and type */
|
||||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
||||||
ObjectType = ObjectHeader->Type;
|
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__,
|
__FUNCTION__,
|
||||||
Object,
|
Object,
|
||||||
OpenReason,
|
OpenReason,
|
||||||
|
@ -787,7 +793,8 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason,
|
||||||
* ObpIncrementHandleCount to make sure that Object Security is valid
|
* ObpIncrementHandleCount to make sure that Object Security is valid
|
||||||
* (specified in Gl00my documentation on Ob)
|
* (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__,
|
__FUNCTION__,
|
||||||
NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess);
|
NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess);
|
||||||
Handle = ExCreateHandle(HandleTable, &NewEntry);
|
Handle = ExCreateHandle(HandleTable, &NewEntry);
|
||||||
|
@ -815,7 +822,8 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason,
|
||||||
/* Return handle and object */
|
/* Return handle and object */
|
||||||
*ReturnedHandle = Handle;
|
*ReturnedHandle = Handle;
|
||||||
if (ReturnedObject) *ReturnedObject = Object;
|
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__,
|
__FUNCTION__,
|
||||||
Handle,
|
Handle,
|
||||||
ObjectHeader->HandleCount,
|
ObjectHeader->HandleCount,
|
||||||
|
@ -857,7 +865,8 @@ ObpCloseHandle(IN HANDLE Handle,
|
||||||
PHANDLE_TABLE_ENTRY HandleTableEntry;
|
PHANDLE_TABLE_ENTRY HandleTableEntry;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PAGED_CODE();
|
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 */
|
/* Check if we're dealing with a kernel handle */
|
||||||
if (ObIsKernelHandle(Handle, AccessMode))
|
if (ObIsKernelHandle(Handle, AccessMode))
|
||||||
|
@ -924,7 +933,8 @@ ObpCloseHandle(IN HANDLE Handle,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return status */
|
/* 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);
|
__FUNCTION__, Handle, Status);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -1213,7 +1223,8 @@ ObDuplicateObject(IN PEPROCESS SourceProcess,
|
||||||
PHANDLE_TABLE HandleTable = NULL;
|
PHANDLE_TABLE HandleTable = NULL;
|
||||||
OBJECT_HANDLE_INFORMATION HandleInformation;
|
OBJECT_HANDLE_INFORMATION HandleInformation;
|
||||||
PAGED_CODE();
|
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__,
|
__FUNCTION__,
|
||||||
SourceHandle,
|
SourceHandle,
|
||||||
SourceProcess,
|
SourceProcess,
|
||||||
|
@ -1376,7 +1387,8 @@ ObDuplicateObject(IN PEPROCESS SourceProcess,
|
||||||
if (TargetHandle) *TargetHandle = NewHandle;
|
if (TargetHandle) *TargetHandle = NewHandle;
|
||||||
|
|
||||||
/* Return status */
|
/* 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__,
|
__FUNCTION__,
|
||||||
NewHandle,
|
NewHandle,
|
||||||
SourceProcess,
|
SourceProcess,
|
||||||
|
@ -1534,7 +1546,8 @@ Cleanup:
|
||||||
Quickie:
|
Quickie:
|
||||||
ObpReleaseCapturedAttributes(&ObjectCreateInfo);
|
ObpReleaseCapturedAttributes(&ObjectCreateInfo);
|
||||||
if (ObjectName.Buffer) ObpReleaseCapturedName(&ObjectName);
|
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__,
|
__FUNCTION__,
|
||||||
OBJECT_TO_OBJECT_HEADER(Object)->PointerCount,
|
OBJECT_TO_OBJECT_HEADER(Object)->PointerCount,
|
||||||
Status);
|
Status);
|
||||||
|
@ -1633,7 +1646,8 @@ ObOpenObjectByPointer(IN PVOID Object,
|
||||||
ObDereferenceObject(Object);
|
ObDereferenceObject(Object);
|
||||||
|
|
||||||
/* Return */
|
/* 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__,
|
__FUNCTION__,
|
||||||
OBJECT_TO_OBJECT_HEADER(Object)->PointerCount,
|
OBJECT_TO_OBJECT_HEADER(Object)->PointerCount,
|
||||||
Status);
|
Status);
|
||||||
|
@ -1993,11 +2007,12 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle,
|
||||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
OBTRACE("OBTRACE - %s - Duplicating handle: %lx for %lx into %lx.\n",
|
OBTRACE(OB_HANDLE_DEBUG,
|
||||||
__FUNCTION__,
|
"%s - Duplicating handle: %lx for %lx into %lx.\n",
|
||||||
SourceHandle,
|
__FUNCTION__,
|
||||||
SourceProcessHandle,
|
SourceHandle,
|
||||||
TargetProcessHandle);
|
SourceProcessHandle,
|
||||||
|
TargetProcessHandle);
|
||||||
|
|
||||||
if((TargetHandle) && (PreviousMode != KernelMode))
|
if((TargetHandle) && (PreviousMode != KernelMode))
|
||||||
{
|
{
|
||||||
|
@ -2083,7 +2098,8 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dereference the processes */
|
/* 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__,
|
__FUNCTION__,
|
||||||
hTarget,
|
hTarget,
|
||||||
TargetProcessHandle,
|
TargetProcessHandle,
|
||||||
|
|
|
@ -38,6 +38,7 @@ GENERIC_MAPPING ObpDirectoryMapping =
|
||||||
};
|
};
|
||||||
|
|
||||||
PDEVICE_MAP ObSystemDeviceMap = NULL;
|
PDEVICE_MAP ObSystemDeviceMap = NULL;
|
||||||
|
ULONG ObpTraceLevel = OB_NAMESPACE_DEBUG;
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS *********************************************************/
|
/* PRIVATE FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
|
|
|
@ -106,280 +106,433 @@ NTAPI
|
||||||
ObFindObject(IN HANDLE RootHandle,
|
ObFindObject(IN HANDLE RootHandle,
|
||||||
IN PUNICODE_STRING ObjectName,
|
IN PUNICODE_STRING ObjectName,
|
||||||
IN ULONG Attributes,
|
IN ULONG Attributes,
|
||||||
IN KPROCESSOR_MODE PreviousMode,
|
IN KPROCESSOR_MODE AccessMode,
|
||||||
IN PVOID *ReturnedObject,
|
IN PVOID *ReturnedObject,
|
||||||
IN POBJECT_TYPE ObjectType,
|
IN POBJECT_TYPE ObjectType,
|
||||||
IN POBP_LOOKUP_CONTEXT Context,
|
IN POBP_LOOKUP_CONTEXT Context,
|
||||||
IN PACCESS_STATE AccessState,
|
IN PACCESS_STATE AccessState,
|
||||||
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
|
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
|
||||||
IN PVOID ParseContext,
|
IN PVOID ParseContext,
|
||||||
IN PVOID Insert)
|
OUT PVOID ExpectedObject)
|
||||||
{
|
{
|
||||||
PVOID NextObject;
|
PVOID RootDirectory;
|
||||||
PVOID CurrentObject;
|
PVOID CurrentDirectory = NULL;
|
||||||
PVOID RootObject;
|
PVOID CurrentObject = NULL;
|
||||||
POBJECT_HEADER CurrentHeader;
|
POBJECT_HEADER CurrentHeader;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PWSTR current;
|
PVOID NewName;
|
||||||
UNICODE_STRING PathString;
|
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
|
||||||
UNICODE_STRING CurrentUs;
|
UNICODE_STRING RemainingPath, PartName;
|
||||||
UNICODE_STRING Path;
|
BOOLEAN InsideRoot = FALSE;
|
||||||
PUNICODE_STRING RemainingPath = &Path;
|
OB_PARSE_METHOD ParseRoutine;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
DPRINT("ObFindObject(ObjectCreateInfo %x, ReturnedObject %x, "
|
/* Assume failure */
|
||||||
"RemainingPath %x)\n",ObjectCreateInfo,ReturnedObject,RemainingPath);
|
OBTRACE(OB_NAMESPACE_DEBUG,
|
||||||
|
"%s - Finding Object: %wZ. Expecting: %p\n",
|
||||||
|
__FUNCTION__,
|
||||||
|
ObjectName,
|
||||||
|
ExpectedObject);
|
||||||
|
*ReturnedObject = NULL;
|
||||||
|
|
||||||
RtlInitUnicodeString (RemainingPath, NULL);
|
/* Check if we got a Root Directory */
|
||||||
|
if (RootHandle)
|
||||||
if (RootHandle == NULL)
|
|
||||||
{
|
|
||||||
ObReferenceObjectByPointer(NameSpaceRoot,
|
|
||||||
DIRECTORY_TRAVERSE,
|
|
||||||
NULL,
|
|
||||||
PreviousMode);
|
|
||||||
CurrentObject = NameSpaceRoot;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
/* We did. Reference it */
|
||||||
Status = ObReferenceObjectByHandle(RootHandle,
|
Status = ObReferenceObjectByHandle(RootHandle,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
PreviousMode,
|
AccessMode,
|
||||||
&CurrentObject,
|
&RootDirectory,
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
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;
|
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
|
else
|
||||||
{
|
{
|
||||||
/* ROS Hack */
|
/* We did not get a Root Directory, so use the root */
|
||||||
DPRINT("REmaining path: %wZ\n", RemainingPath);
|
RootDirectory = NameSpaceRoot;
|
||||||
if (RemainingPath->Buffer != NULL)
|
|
||||||
|
/* 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)
|
/* This name is invalid, so fail */
|
||||||
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
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
|
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;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,24 +100,45 @@ ObpParseSymbolicLink(IN PVOID ParsedObject,
|
||||||
POBJECT_SYMBOLIC_LINK SymlinkObject = (POBJECT_SYMBOLIC_LINK)ParsedObject;
|
POBJECT_SYMBOLIC_LINK SymlinkObject = (POBJECT_SYMBOLIC_LINK)ParsedObject;
|
||||||
PUNICODE_STRING TargetPath;
|
PUNICODE_STRING TargetPath;
|
||||||
PWSTR NewTargetPath;
|
PWSTR NewTargetPath;
|
||||||
ULONG LengthUsed, MaximumLength, RemainLength;
|
ULONG LengthUsed, MaximumLength;
|
||||||
PWSTR *RemainingPath = &RemainingName->Buffer;
|
NTSTATUS Status;
|
||||||
|
|
||||||
/*
|
/* Assume failure */
|
||||||
* Stop parsing if the entire path has been parsed and
|
*NextObject = NULL;
|
||||||
* the desired object is a symbolic link object.
|
|
||||||
*/
|
/* Check if we're out of name to parse */
|
||||||
if (((*RemainingPath == NULL) || (**RemainingPath == 0)) &&
|
if (!RemainingName->Length)
|
||||||
(Attributes & OBJ_OPENLINK))
|
|
||||||
{
|
{
|
||||||
*NextObject = NULL;
|
/* Check if we got an object type */
|
||||||
return(STATUS_SUCCESS);
|
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 */
|
/* Set the target path and length */
|
||||||
TargetPath = &SymlinkObject->LinkTarget;
|
TargetPath = &SymlinkObject->LinkTarget;
|
||||||
RemainLength = *RemainingPath ? wcslen(*RemainingPath) * sizeof(WCHAR) : 0;
|
LengthUsed = TargetPath->Length + RemainingName->Length;
|
||||||
LengthUsed = TargetPath->Length + RemainLength;
|
|
||||||
|
|
||||||
/* Optimization: check if the new name is shorter */
|
/* Optimization: check if the new name is shorter */
|
||||||
if (FullPath->MaximumLength <= LengthUsed)
|
if (FullPath->MaximumLength <= LengthUsed)
|
||||||
|
@ -136,12 +157,12 @@ ObpParseSymbolicLink(IN PVOID ParsedObject,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure we have a length */
|
/* Make sure we have a length */
|
||||||
if (RemainLength)
|
if (RemainingName->Length)
|
||||||
{
|
{
|
||||||
/* Copy the new path */
|
/* Copy the new path */
|
||||||
RtlMoveMemory((PVOID)((ULONG_PTR)NewTargetPath + TargetPath->Length),
|
RtlMoveMemory((PVOID)((ULONG_PTR)NewTargetPath + TargetPath->Length),
|
||||||
*RemainingPath,
|
RemainingName->Buffer,
|
||||||
RemainLength);
|
RemainingName->Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the target path and null-terminate it */
|
/* Copy the target path and null-terminate it */
|
||||||
|
@ -156,10 +177,7 @@ ObpParseSymbolicLink(IN PVOID ParsedObject,
|
||||||
FullPath->MaximumLength = MaximumLength;
|
FullPath->MaximumLength = MaximumLength;
|
||||||
FullPath->Buffer = NewTargetPath;
|
FullPath->Buffer = NewTargetPath;
|
||||||
|
|
||||||
/* Reinitialize RemainingPath for reparsing */
|
/* Tell the parse routine to start reparsing */
|
||||||
*RemainingPath = FullPath->Buffer;
|
|
||||||
|
|
||||||
*NextObject = NULL;
|
|
||||||
return STATUS_REPARSE;
|
return STATUS_REPARSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,6 @@ IntDesktopObjectParse(IN PVOID ParseObject,
|
||||||
/* Reference the desktop and return it */
|
/* Reference the desktop and return it */
|
||||||
ObReferenceObject(Desktop);
|
ObReferenceObject(Desktop);
|
||||||
*Object = Desktop;
|
*Object = Desktop;
|
||||||
RemainingName->Buffer = NULL; // => ROS Parse routines need to do this
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,7 +167,6 @@ IntDesktopObjectParse(IN PVOID ParseObject,
|
||||||
|
|
||||||
/* Set the desktop object and return success */
|
/* Set the desktop object and return success */
|
||||||
*Object = Desktop;
|
*Object = Desktop;
|
||||||
RemainingName->Buffer = NULL; // => ROS Parse routines need to do this
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,8 +126,8 @@ IntWinStaObjectParse(PWIN32_PARSEMETHOD_PARAMETERS Parameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reference the window station and return */
|
/* Reference the window station and return */
|
||||||
//ObReferenceObject(Object);
|
ObReferenceObject(Parameters->ParseObject);
|
||||||
//*NextObject = Object; => ROS Parse routines don't need to do this
|
*Parameters->Object = Parameters->ParseObject;
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,10 +149,8 @@ IntWinStaObjectParse(PWIN32_PARSEMETHOD_PARAMETERS Parameters)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if we are parsing a desktop.
|
* 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 */
|
/* Then call the desktop parse routine */
|
||||||
return IntDesktopObjectParse(Parameters->ParseObject,
|
return IntDesktopObjectParse(Parameters->ParseObject,
|
||||||
|
|
Loading…
Reference in a new issue