mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1270 lines
29 KiB
1270 lines
29 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
obp.h
|
|
|
|
Abstract:
|
|
|
|
Private include file for the OB subcomponent of the NTOS project
|
|
|
|
Author:
|
|
|
|
Steve Wood (stevewo) 31-Mar-1989
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "ntos.h"
|
|
#include "seopaque.h"
|
|
#include <zwapi.h>
|
|
|
|
#define OBP_PAGEDPOOL_NAMESPACE
|
|
|
|
//
|
|
// The Object Header structures are private, but are defined in ob.h
|
|
// so that various macros can directly access header fields.
|
|
//
|
|
|
|
struct _OBJECT_HEADER;
|
|
struct _OBJECT_BODY_HEADER;
|
|
|
|
//
|
|
// Setup default pool tags
|
|
//
|
|
|
|
#ifdef POOL_TAGGING
|
|
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,' bO')
|
|
#define ExAllocatePoolWithQuota(a,b) ExAllocatePoolWithQuotaTag(a,b,' bO')
|
|
#endif
|
|
|
|
//
|
|
// Define some macros that will verify that our callbacks don't give us a bad irql
|
|
//
|
|
|
|
#if DBG
|
|
#define ObpBeginTypeSpecificCallOut( IRQL ) (IRQL)=KeGetCurrentIrql()
|
|
#define ObpEndTypeSpecificCallOut( IRQL, str, ot, o ) { \
|
|
if ((IRQL)!=KeGetCurrentIrql()) { \
|
|
DbgPrint( "OB: ObjectType: %wZ Procedure: %s Object: %08x\n", &ot->Name, str, o ); \
|
|
DbgPrint( " Returned at %x IRQL, but was called at %x IRQL\n", KeGetCurrentIrql(), IRQL ); \
|
|
DbgBreakPoint(); \
|
|
} \
|
|
}
|
|
#else
|
|
#define ObpBeginTypeSpecificCallOut( IRQL )
|
|
#define ObpEndTypeSpecificCallOut( IRQL, str, ot, o )
|
|
#endif // DBG
|
|
|
|
//
|
|
// Define some more macros to validate the current irql
|
|
//
|
|
|
|
#if DBG
|
|
#define ObpValidateIrql( str ) \
|
|
if (KeGetCurrentIrql() > APC_LEVEL) { \
|
|
DbgPrint( "OB: %s called at IRQL %d\n", (str), KeGetCurrentIrql() ); \
|
|
DbgBreakPoint(); \
|
|
}
|
|
#else
|
|
#define ObpValidateIrql( str )
|
|
#endif // DBG
|
|
|
|
|
|
//
|
|
// This global lock protects the granted access lists when we are collecting stack traces
|
|
//
|
|
|
|
EX_PUSH_LOCK ObpLock;
|
|
|
|
KEVENT ObpDefaultObject;
|
|
WORK_QUEUE_ITEM ObpRemoveObjectWorkItem;
|
|
PVOID ObpRemoveObjectList;
|
|
|
|
//
|
|
// This global lock is used to protect the device map tear down and build up
|
|
// We can no longer use an individual lock in the device map itself because
|
|
// that wasn't sufficient to protect the device map itself.
|
|
//
|
|
|
|
#ifdef OBP_PAGEDPOOL_NAMESPACE
|
|
|
|
#define OB_NAMESPACE_POOL_TYPE PagedPool
|
|
|
|
FAST_MUTEX ObpDeviceMapLock;
|
|
|
|
#define OBP_DECLARE_OLDIRQL
|
|
|
|
#define ObpLockDeviceMap() \
|
|
ExAcquireFastMutex( &ObpDeviceMapLock )
|
|
|
|
#define ObpUnlockDeviceMap() \
|
|
ExReleaseFastMutex( &ObpDeviceMapLock )
|
|
|
|
#else // !OBP_PAGEDPOOL_NAMESPACE
|
|
|
|
#define OB_NAMESPACE_POOL_TYPE NonPagedPool
|
|
|
|
KSPIN_LOCK ObpDeviceMapLock;
|
|
|
|
#define ObpLockDeviceMap() \
|
|
ExAcquireSpinLock( &ObpDeviceMapLock, &OldIrql )
|
|
|
|
#define ObpUnlockDeviceMap() \
|
|
ExReleaseSpinLock( &ObpDeviceMapLock, OldIrql )
|
|
|
|
#endif // OBP_PAGEDPOOL_NAMESPACE
|
|
|
|
#define ObpIncrPointerCountEx(np,Count) (InterlockedExchangeAdd (&np->PointerCount, Count) + Count)
|
|
#define ObpDecrPointerCountEx(np,Count) (InterlockedExchangeAdd (&np->PointerCount, -(LONG)(Count)) - Count)
|
|
|
|
#ifndef POOL_TAGGING
|
|
|
|
#define ObpIncrPointerCount(np) InterlockedIncrement( &np->PointerCount )
|
|
#define ObpDecrPointerCount(np) InterlockedDecrement( &np->PointerCount )
|
|
#define ObpDecrPointerCountWithResult(np) (InterlockedDecrement( &np->PointerCount ) == 0)
|
|
|
|
#define ObpPushStackInfo(np, inc)
|
|
|
|
#else //POOL_TAGGING
|
|
|
|
VOID
|
|
ObpInitStackTrace();
|
|
|
|
VOID
|
|
ObpRegisterObject (
|
|
POBJECT_HEADER ObjectHeader
|
|
);
|
|
|
|
VOID
|
|
ObpDeregisterObject (
|
|
POBJECT_HEADER ObjectHeader
|
|
);
|
|
|
|
VOID
|
|
ObpPushStackInfo (
|
|
POBJECT_HEADER ObjectHeader,
|
|
BOOLEAN IsRef
|
|
);
|
|
|
|
extern BOOLEAN ObpTraceEnabled;
|
|
|
|
#define ObpIncrPointerCount(np) ((ObpTraceEnabled ? ObpPushStackInfo(np,TRUE) : 0),InterlockedIncrement( &np->PointerCount ))
|
|
#define ObpDecrPointerCount(np) ((ObpTraceEnabled ? ObpPushStackInfo(np,FALSE) : 0),InterlockedDecrement( &np->PointerCount ))
|
|
#define ObpDecrPointerCountWithResult(np) ((ObpTraceEnabled ? ObpPushStackInfo(np,FALSE) : 0),(InterlockedDecrement( &np->PointerCount ) == 0))
|
|
|
|
#endif //POOL_TAGGING
|
|
|
|
#define ObpIncrHandleCount(np) InterlockedIncrement( &np->HandleCount )
|
|
#define ObpDecrHandleCount(np) (InterlockedDecrement( &np->HandleCount ) == 0)
|
|
|
|
|
|
|
|
//
|
|
// Define macros to acquire and release an object type fast mutex.
|
|
//
|
|
//
|
|
// VOID
|
|
// ObpEnterObjectTypeMutex (
|
|
// IN POBJECT_TYPE ObjectType
|
|
// )
|
|
//
|
|
|
|
#define ObpEnterObjectTypeMutex(_ObjectType) { \
|
|
ObpValidateIrql("ObpEnterObjectTypeMutex"); \
|
|
KeEnterCriticalRegion(); \
|
|
ExAcquireResourceExclusiveLite(&(_ObjectType)->Mutex, TRUE); \
|
|
}
|
|
|
|
//
|
|
// VOID
|
|
// ObpLeaveObjectTypeMutex (
|
|
// IN POBJECT_TYPE ObjectType
|
|
// )
|
|
//
|
|
|
|
#define ObpLeaveObjectTypeMutex(_ObjectType) { \
|
|
ExReleaseResourceLite(&(_ObjectType)->Mutex); \
|
|
KeLeaveCriticalRegion(); \
|
|
ObpValidateIrql("ObpLeaveObjectTypeMutex"); \
|
|
}
|
|
|
|
#define LOCK_HASH_MASK (OBJECT_LOCK_COUNT - 1)
|
|
|
|
#define ObpHashObjectHeader(_ObjectHeader) \
|
|
((((ULONG_PTR)(_ObjectHeader)) >> 8) & LOCK_HASH_MASK)
|
|
|
|
#define ObpLockObject(_ObjectHeader) { \
|
|
ULONG_PTR LockIndex = ObpHashObjectHeader(_ObjectHeader); \
|
|
ObpValidateIrql("ObpEnterObjectTypeMutex"); \
|
|
KeEnterCriticalRegion(); \
|
|
ExAcquireResourceExclusiveLite(&((_ObjectHeader)->Type->ObjectLocks[LockIndex]), TRUE); \
|
|
}
|
|
|
|
#define ObpLockObjectShared(_ObjectHeader) { \
|
|
ULONG_PTR LockIndex = ObpHashObjectHeader(_ObjectHeader); \
|
|
ObpValidateIrql("ObpEnterObjectTypeMutex"); \
|
|
KeEnterCriticalRegion(); \
|
|
ExAcquireResourceSharedLite(&((_ObjectHeader)->Type->ObjectLocks[LockIndex]), TRUE); \
|
|
}
|
|
|
|
#define ObpUnlockObject(_ObjectHeader) { \
|
|
ULONG_PTR LockIndex = ObpHashObjectHeader(_ObjectHeader); \
|
|
ExReleaseResourceLite(&((_ObjectHeader)->Type->ObjectLocks[LockIndex])); \
|
|
KeLeaveCriticalRegion(); \
|
|
ObpValidateIrql("ObpLeaveObjectTypeMutex"); \
|
|
}
|
|
|
|
|
|
//
|
|
// A Macro to return the object table for the current process
|
|
//
|
|
|
|
#define ObpGetObjectTable() (PsGetCurrentProcess()->ObjectTable)
|
|
|
|
//
|
|
// Macro to test whether or not the object manager is responsible for
|
|
// an object's security descriptor, or if the object has its own
|
|
// security management routines.
|
|
//
|
|
|
|
#define ObpCentralizedSecurity(_ObjectType) \
|
|
((_ObjectType)->TypeInfo.SecurityProcedure == SeDefaultObjectMethod)
|
|
|
|
//
|
|
// Declare a global table of object types.
|
|
//
|
|
|
|
#define OBP_MAX_DEFINED_OBJECT_TYPES 48
|
|
POBJECT_TYPE ObpObjectTypes[ OBP_MAX_DEFINED_OBJECT_TYPES ];
|
|
|
|
|
|
//
|
|
// This is some special purpose code to keep a table of access masks correlated with
|
|
// back traces. If used these routines replace the GrantedAccess mask in the
|
|
// preceding object table entry with a granted access index and a call back index.
|
|
//
|
|
|
|
#if i386
|
|
ACCESS_MASK
|
|
ObpTranslateGrantedAccessIndex (
|
|
USHORT GrantedAccessIndex
|
|
);
|
|
|
|
USHORT
|
|
ObpComputeGrantedAccessIndex (
|
|
ACCESS_MASK GrantedAccess
|
|
);
|
|
|
|
USHORT ObpCurCachedGrantedAccessIndex;
|
|
USHORT ObpMaxCachedGrantedAccessIndex;
|
|
PACCESS_MASK ObpCachedGrantedAccesses;
|
|
#endif // i386
|
|
|
|
//
|
|
// The three low order bits of the object table entry are used for handle
|
|
// attributes.
|
|
//
|
|
// Define the bit mask for the protect from close handle attribute.
|
|
//
|
|
|
|
#define OBJ_PROTECT_CLOSE 0x1
|
|
|
|
//
|
|
// We moved the PROTECT_CLOSE in the granted access mask
|
|
//
|
|
|
|
extern ULONG ObpAccessProtectCloseBit;
|
|
|
|
//
|
|
// The bit mask for inherit MUST be 0x2.
|
|
//
|
|
|
|
#if (OBJ_INHERIT != 0x2)
|
|
|
|
#error Object inheritance bit definition conflicts
|
|
|
|
#endif
|
|
|
|
//
|
|
// Define the bit mask for the generate audit on close attribute.
|
|
//
|
|
// When a handle to an object with security is created, audit routines will
|
|
// be called to perform any auditing that may be required. The audit routines
|
|
// will return a boolean indicating whether or not audits should be generated
|
|
// on close.
|
|
//
|
|
|
|
#define OBJ_AUDIT_OBJECT_CLOSE 0x00000004L
|
|
|
|
|
|
//
|
|
// The following three bits are available for handle attributes in the
|
|
// Object field of an ObjectTableEntry.
|
|
//
|
|
|
|
#define OBJ_HANDLE_ATTRIBUTES (OBJ_PROTECT_CLOSE | OBJ_INHERIT | OBJ_AUDIT_OBJECT_CLOSE)
|
|
|
|
#define ObpDecodeGrantedAccess(Access) \
|
|
((Access) & ~ObpAccessProtectCloseBit)
|
|
|
|
#define ObpGetHandleAttributes(HandleTableEntry) \
|
|
((((HandleTableEntry)->GrantedAccess) & ObpAccessProtectCloseBit) ? \
|
|
((((HandleTableEntry)->ObAttributes) & OBJ_HANDLE_ATTRIBUTES) | OBJ_PROTECT_CLOSE) : \
|
|
(((HandleTableEntry)->ObAttributes) & (OBJ_INHERIT | OBJ_AUDIT_OBJECT_CLOSE)) )
|
|
|
|
#define ObpEncodeProtectClose(ObjectTableEntry) \
|
|
if ( (ObjectTableEntry).ObAttributes & OBJ_PROTECT_CLOSE ) { \
|
|
\
|
|
(ObjectTableEntry).ObAttributes &= ~OBJ_PROTECT_CLOSE; \
|
|
(ObjectTableEntry).GrantedAccess |= ObpAccessProtectCloseBit; \
|
|
}
|
|
|
|
|
|
//
|
|
// Security Descriptor Cache
|
|
//
|
|
// Cache entry header.
|
|
//
|
|
|
|
typedef struct _SECURITY_DESCRIPTOR_HEADER {
|
|
|
|
LIST_ENTRY Link;
|
|
ULONG RefCount;
|
|
ULONG FullHash;
|
|
#if defined (_WIN64)
|
|
PVOID Spare; // Align to 16 byte boundary.
|
|
#endif
|
|
QUAD SecurityDescriptor;
|
|
|
|
} SECURITY_DESCRIPTOR_HEADER, *PSECURITY_DESCRIPTOR_HEADER;
|
|
|
|
//
|
|
// Macro to convert a security descriptor into its security descriptor header
|
|
//
|
|
|
|
#define SD_TO_SD_HEADER(_sd) \
|
|
CONTAINING_RECORD( (_sd), SECURITY_DESCRIPTOR_HEADER, SecurityDescriptor )
|
|
|
|
//
|
|
// Macro to convert a header link into its security descriptor header
|
|
//
|
|
|
|
#define LINK_TO_SD_HEADER(_link) \
|
|
CONTAINING_RECORD( (_link), SECURITY_DESCRIPTOR_HEADER, Link )
|
|
|
|
|
|
//
|
|
// Number of minor hash entries
|
|
//
|
|
|
|
#define SECURITY_DESCRIPTOR_CACHE_ENTRIES 257
|
|
|
|
|
|
|
|
//
|
|
// Lock state signatures
|
|
//
|
|
|
|
#define OBP_LOCK_WAITEXCLUSIVE_SIGNATURE 0xAAAA1234
|
|
#define OBP_LOCK_WAITSHARED_SIGNATURE 0xBBBB1234
|
|
#define OBP_LOCK_OWNEDEXCLUSIVE_SIGNATURE 0xCCCC1234
|
|
#define OBP_LOCK_OWNEDSHARED_SIGNATURE 0xDDDD1234
|
|
#define OBP_LOCK_RELEASED_SIGNATURE 0xEEEE1234
|
|
#define OBP_LOCK_UNUSED_SIGNATURE 0xFFFF1234
|
|
|
|
//
|
|
// Lookup directories
|
|
//
|
|
|
|
typedef struct _OBP_LOOKUP_CONTEXT {
|
|
|
|
POBJECT_DIRECTORY Directory;
|
|
PVOID Object;
|
|
USHORT HashIndex;
|
|
BOOLEAN DirectoryLocked;
|
|
volatile ULONG LockStateSignature;
|
|
|
|
} OBP_LOOKUP_CONTEXT, *POBP_LOOKUP_CONTEXT;
|
|
|
|
//
|
|
// Context for the sweep routine. Passed through handle enumeration.
|
|
//
|
|
typedef struct _OBP_SWEEP_CONTEXT {
|
|
PHANDLE_TABLE HandleTable;
|
|
KPROCESSOR_MODE PreviousMode;
|
|
} OBP_SWEEP_CONTEXT, *POBP_SWEEP_CONTEXT;
|
|
|
|
|
|
//
|
|
// Global data
|
|
//
|
|
|
|
POBJECT_TYPE ObpTypeObjectType;
|
|
POBJECT_TYPE ObpDirectoryObjectType;
|
|
POBJECT_TYPE ObpSymbolicLinkObjectType;
|
|
POBJECT_TYPE ObpDeviceMapObjectType;
|
|
POBJECT_DIRECTORY ObpRootDirectoryObject;
|
|
POBJECT_DIRECTORY ObpTypeDirectoryObject;
|
|
|
|
typedef union {
|
|
WCHAR Name[sizeof(ULARGE_INTEGER)/sizeof(WCHAR)];
|
|
ULARGE_INTEGER Alignment;
|
|
} ALIGNEDNAME;
|
|
|
|
extern const ALIGNEDNAME ObpDosDevicesShortNamePrefix;
|
|
extern const ALIGNEDNAME ObpDosDevicesShortNameRoot;
|
|
extern const UNICODE_STRING ObpDosDevicesShortName;
|
|
|
|
ERESOURCE SecurityDescriptorCacheLock;
|
|
|
|
//
|
|
// Define date structures for the object creation information region.
|
|
//
|
|
|
|
extern GENERAL_LOOKASIDE ObpCreateInfoLookasideList;
|
|
|
|
//
|
|
// Define data structures for the object name buffer lookaside list.
|
|
//
|
|
|
|
#define OBJECT_NAME_BUFFER_SIZE 248
|
|
|
|
extern GENERAL_LOOKASIDE ObpNameBufferLookasideList;
|
|
|
|
//
|
|
// There is one global kernel handle table accessed via negative handle
|
|
// and only in kernel mode
|
|
//
|
|
|
|
PHANDLE_TABLE ObpKernelHandleTable;
|
|
|
|
//
|
|
// The following macros are used to test and manipulate special kernel
|
|
// handles. A kernel handle is just a regular handle with its sign
|
|
// bit set. But must exclude -1 and -2 values which are the current
|
|
// process and current thread constants.
|
|
//
|
|
|
|
#define KERNEL_HANDLE_MASK ((ULONG_PTR)((LONG)0x80000000))
|
|
|
|
#define IsKernelHandle(H,M) \
|
|
(((KERNEL_HANDLE_MASK & (ULONG_PTR)(H)) == KERNEL_HANDLE_MASK) && \
|
|
((M) == KernelMode) && \
|
|
((H) != NtCurrentThread()) && \
|
|
((H) != NtCurrentProcess()))
|
|
|
|
#define EncodeKernelHandle(H) (HANDLE)(KERNEL_HANDLE_MASK | (ULONG_PTR)(H))
|
|
|
|
#define DecodeKernelHandle(H) (HANDLE)(KERNEL_HANDLE_MASK ^ (ULONG_PTR)(H))
|
|
|
|
//
|
|
// Test macro for overflow
|
|
//
|
|
|
|
#define ObpIsOverflow(A,B) ((A) > ((A) + (B)))
|
|
|
|
|
|
//
|
|
// Internal Entry Points defined in obcreate.c and some associated macros
|
|
//
|
|
|
|
#define ObpFreeObjectCreateInformation(_ObjectCreateInfo) { \
|
|
ObpReleaseObjectCreateInformation((_ObjectCreateInfo)); \
|
|
ObpFreeObjectCreateInfoBuffer((_ObjectCreateInfo)); \
|
|
}
|
|
|
|
#define ObpReleaseObjectCreateInformation(_ObjectCreateInfo) { \
|
|
if ((_ObjectCreateInfo)->SecurityDescriptor != NULL) { \
|
|
SeReleaseSecurityDescriptor((_ObjectCreateInfo)->SecurityDescriptor, \
|
|
(_ObjectCreateInfo)->ProbeMode, \
|
|
TRUE); \
|
|
(_ObjectCreateInfo)->SecurityDescriptor = NULL; \
|
|
} \
|
|
}
|
|
|
|
NTSTATUS
|
|
ObpCaptureObjectCreateInformation (
|
|
IN POBJECT_TYPE ObjectType OPTIONAL,
|
|
IN KPROCESSOR_MODE ProbeMode,
|
|
IN KPROCESSOR_MODE CreatorMode,
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
|
OUT PUNICODE_STRING CapturedObjectName,
|
|
IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
|
|
IN LOGICAL UseLookaside
|
|
);
|
|
|
|
NTSTATUS
|
|
ObpCaptureObjectName (
|
|
IN KPROCESSOR_MODE ProbeMode,
|
|
IN PUNICODE_STRING ObjectName,
|
|
IN OUT PUNICODE_STRING CapturedObjectName,
|
|
IN LOGICAL UseLookaside
|
|
);
|
|
|
|
PWCHAR
|
|
ObpAllocateObjectNameBuffer (
|
|
IN ULONG Length,
|
|
IN LOGICAL UseLookaside,
|
|
IN OUT PUNICODE_STRING ObjectName
|
|
);
|
|
|
|
VOID
|
|
FASTCALL
|
|
ObpFreeObjectNameBuffer (
|
|
IN PUNICODE_STRING ObjectName
|
|
);
|
|
|
|
NTSTATUS
|
|
ObpAllocateObject (
|
|
IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
|
|
IN KPROCESSOR_MODE OwnershipMode,
|
|
IN POBJECT_TYPE ObjectType,
|
|
IN PUNICODE_STRING ObjectName,
|
|
IN ULONG ObjectBodySize,
|
|
OUT POBJECT_HEADER *ReturnedObjectHeader
|
|
);
|
|
|
|
|
|
VOID
|
|
FASTCALL
|
|
ObpFreeObject (
|
|
IN PVOID Object
|
|
);
|
|
|
|
|
|
/*++
|
|
|
|
POBJECT_CREATE_INFORMATION
|
|
ObpAllocateObjectCreateInfoBuffer (
|
|
VOID
|
|
)
|
|
|
|
Routine Description:
|
|
|
|
This function allocates a created information buffer.
|
|
|
|
N.B. This function is nonpageable.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
If the allocation is successful, then the address of the allocated
|
|
create information buffer is is returned as the function value.
|
|
Otherwise, a value of NULL is returned.
|
|
|
|
--*/
|
|
|
|
#define ObpAllocateObjectCreateInfoBuffer() \
|
|
(POBJECT_CREATE_INFORMATION)ExAllocateFromPPLookasideList(LookasideCreateInfoList)
|
|
|
|
|
|
/*++
|
|
|
|
VOID
|
|
FASTCALL
|
|
ObpFreeObjectCreateInfoBuffer (
|
|
IN POBJECT_CREATE_INFORMATION ObjectCreateInfo
|
|
)
|
|
|
|
Routine Description:
|
|
|
|
This function frees a create information buffer.
|
|
|
|
N.B. This function is nonpageable.
|
|
|
|
Arguments:
|
|
|
|
ObjectCreateInfo - Supplies a pointer to a create information buffer.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
#define ObpFreeObjectCreateInfoBuffer(ObjectCreateInfo) \
|
|
ExFreeToPPLookasideList(LookasideCreateInfoList, ObjectCreateInfo)
|
|
|
|
//
|
|
// Internal Entry Points defined in oblink.c
|
|
//
|
|
|
|
NTSTATUS
|
|
ObpParseSymbolicLink (
|
|
IN PVOID ParseObject,
|
|
IN PVOID ObjectType,
|
|
IN PACCESS_STATE AccessState,
|
|
IN KPROCESSOR_MODE AccessMode,
|
|
IN ULONG Attributes,
|
|
IN OUT PUNICODE_STRING CompleteName,
|
|
IN OUT PUNICODE_STRING RemainingName,
|
|
IN OUT PVOID Context OPTIONAL,
|
|
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
|
|
OUT PVOID *Object
|
|
);
|
|
|
|
VOID
|
|
ObpDeleteSymbolicLink (
|
|
IN PVOID Object
|
|
);
|
|
|
|
VOID
|
|
ObpCreateSymbolicLinkName (
|
|
POBJECT_SYMBOLIC_LINK SymbolicLink
|
|
);
|
|
|
|
VOID
|
|
ObpDeleteSymbolicLinkName (
|
|
POBJECT_SYMBOLIC_LINK SymbolicLink
|
|
);
|
|
|
|
|
|
//
|
|
// Internal Entry Points defined in obdir.c
|
|
//
|
|
|
|
PVOID
|
|
ObpLookupDirectoryEntry (
|
|
IN POBJECT_DIRECTORY Directory,
|
|
IN PUNICODE_STRING Name,
|
|
IN ULONG Attributes,
|
|
IN BOOLEAN SearchShadow,
|
|
OUT POBP_LOOKUP_CONTEXT LookupContext
|
|
);
|
|
|
|
|
|
BOOLEAN
|
|
ObpInsertDirectoryEntry (
|
|
IN POBJECT_DIRECTORY Directory,
|
|
IN POBP_LOOKUP_CONTEXT LookupContext,
|
|
IN POBJECT_HEADER ObjectHeader
|
|
);
|
|
|
|
|
|
BOOLEAN
|
|
ObpDeleteDirectoryEntry (
|
|
IN POBP_LOOKUP_CONTEXT LookupContext
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
ObpLookupObjectName (
|
|
IN HANDLE RootDirectoryHandle,
|
|
IN PUNICODE_STRING ObjectName,
|
|
IN ULONG Attributes,
|
|
IN POBJECT_TYPE ObjectType,
|
|
IN KPROCESSOR_MODE AccessMode,
|
|
IN PVOID ParseContext OPTIONAL,
|
|
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
|
|
IN PVOID InsertObject OPTIONAL,
|
|
IN OUT PACCESS_STATE AccessState,
|
|
OUT POBP_LOOKUP_CONTEXT LookupContext,
|
|
OUT PVOID *FoundObject
|
|
);
|
|
|
|
VOID
|
|
ObpUnlockObjectDirectoryPath (
|
|
IN POBJECT_DIRECTORY LockedDirectory
|
|
);
|
|
|
|
PDEVICE_MAP
|
|
ObpReferenceDeviceMap(
|
|
);
|
|
|
|
VOID
|
|
FASTCALL
|
|
ObfDereferenceDeviceMap(
|
|
IN PDEVICE_MAP DeviceMap
|
|
);
|
|
|
|
|
|
//
|
|
// Internal entry points defined in obref.c
|
|
//
|
|
|
|
|
|
VOID
|
|
ObpDeleteNameCheck (
|
|
IN PVOID Object
|
|
);
|
|
|
|
|
|
VOID
|
|
ObpProcessRemoveObjectQueue (
|
|
PVOID Parameter
|
|
);
|
|
|
|
VOID
|
|
ObpRemoveObjectRoutine (
|
|
IN PVOID Object,
|
|
IN BOOLEAN CalledOnWorkerThread
|
|
);
|
|
|
|
|
|
//
|
|
// Internal entry points defined in obhandle.c
|
|
//
|
|
|
|
|
|
POBJECT_HANDLE_COUNT_ENTRY
|
|
ObpInsertHandleCount (
|
|
POBJECT_HEADER ObjectHeader
|
|
);
|
|
|
|
NTSTATUS
|
|
ObpIncrementHandleCount (
|
|
OB_OPEN_REASON OpenReason,
|
|
PEPROCESS Process,
|
|
PVOID Object,
|
|
POBJECT_TYPE ObjectType,
|
|
PACCESS_STATE AccessState OPTIONAL,
|
|
KPROCESSOR_MODE AccessMode,
|
|
ULONG Attributes
|
|
);
|
|
|
|
|
|
VOID
|
|
ObpDecrementHandleCount (
|
|
PEPROCESS Process,
|
|
POBJECT_HEADER ObjectHeader,
|
|
POBJECT_TYPE ObjectType,
|
|
ACCESS_MASK GrantedAccess
|
|
);
|
|
|
|
NTSTATUS
|
|
ObpCreateHandle (
|
|
IN OB_OPEN_REASON OpenReason,
|
|
IN PVOID Object,
|
|
IN POBJECT_TYPE ExpectedObjectType OPTIONAL,
|
|
IN PACCESS_STATE AccessState,
|
|
IN ULONG ObjectPointerBias OPTIONAL,
|
|
IN ULONG Attributes,
|
|
IN POBP_LOOKUP_CONTEXT LookupContext,
|
|
IN KPROCESSOR_MODE AccessMode,
|
|
OUT PVOID *ReferencedNewObject OPTIONAL,
|
|
OUT PHANDLE Handle
|
|
);
|
|
|
|
NTSTATUS
|
|
ObpIncrementUnnamedHandleCount (
|
|
PACCESS_MASK DesiredAccess,
|
|
PEPROCESS Process,
|
|
PVOID Object,
|
|
POBJECT_TYPE ObjectType,
|
|
KPROCESSOR_MODE AccessMode,
|
|
ULONG Attributes
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
ObpCreateUnnamedHandle (
|
|
IN PVOID Object,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
IN ULONG ObjectPointerBias OPTIONAL,
|
|
IN ULONG Attributes,
|
|
IN KPROCESSOR_MODE AccessMode,
|
|
OUT PVOID *ReferencedNewObject OPTIONAL,
|
|
OUT PHANDLE Handle
|
|
);
|
|
|
|
NTSTATUS
|
|
ObpChargeQuotaForObject (
|
|
IN POBJECT_HEADER ObjectHeader,
|
|
IN POBJECT_TYPE ObjectType,
|
|
OUT PBOOLEAN NewObject
|
|
);
|
|
|
|
NTSTATUS
|
|
ObpValidateDesiredAccess (
|
|
IN ACCESS_MASK DesiredAccess
|
|
);
|
|
|
|
|
|
//
|
|
// Internal entry points defined in obse.c
|
|
//
|
|
|
|
BOOLEAN
|
|
ObpCheckPseudoHandleAccess (
|
|
IN PVOID Object,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
OUT PNTSTATUS AccessStatus,
|
|
IN BOOLEAN TypeMutexLocked
|
|
);
|
|
|
|
|
|
BOOLEAN
|
|
ObpCheckTraverseAccess (
|
|
IN PVOID DirectoryObject,
|
|
IN ACCESS_MASK TraverseAccess,
|
|
IN PACCESS_STATE AccessState OPTIONAL,
|
|
IN BOOLEAN TypeMutexLocked,
|
|
IN KPROCESSOR_MODE PreviousMode,
|
|
OUT PNTSTATUS AccessStatus
|
|
);
|
|
|
|
BOOLEAN
|
|
ObpCheckObjectReference (
|
|
IN PVOID Object,
|
|
IN OUT PACCESS_STATE AccessState,
|
|
IN BOOLEAN TypeMutexLocked,
|
|
IN KPROCESSOR_MODE AccessMode,
|
|
OUT PNTSTATUS AccessStatus
|
|
);
|
|
|
|
|
|
//
|
|
// Internal entry points defined in obsdata.c
|
|
//
|
|
|
|
NTSTATUS
|
|
ObpInitSecurityDescriptorCache (
|
|
VOID
|
|
);
|
|
|
|
ULONG
|
|
ObpHashSecurityDescriptor (
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor
|
|
);
|
|
|
|
ULONG
|
|
ObpHashBuffer (
|
|
PVOID Data,
|
|
ULONG Length
|
|
);
|
|
|
|
PSECURITY_DESCRIPTOR_HEADER
|
|
ObpCreateCacheEntry (
|
|
PSECURITY_DESCRIPTOR InputSecurityDescriptor,
|
|
ULONG FullHash,
|
|
ULONG RefBias
|
|
);
|
|
|
|
|
|
PSECURITY_DESCRIPTOR
|
|
ObpReferenceSecurityDescriptor (
|
|
POBJECT_HEADER ObjectHeader
|
|
);
|
|
|
|
|
|
PVOID
|
|
ObpDestroySecurityDescriptorHeader (
|
|
IN PSECURITY_DESCRIPTOR_HEADER Header
|
|
);
|
|
|
|
BOOLEAN
|
|
ObpCompareSecurityDescriptors (
|
|
IN PSECURITY_DESCRIPTOR SD1,
|
|
IN PSECURITY_DESCRIPTOR SD2
|
|
);
|
|
|
|
NTSTATUS
|
|
ObpValidateAccessMask (
|
|
PACCESS_STATE AccessState
|
|
);
|
|
|
|
ObpCloseHandleTableEntry (
|
|
IN PHANDLE_TABLE ObjectTable,
|
|
IN PHANDLE_TABLE_ENTRY ObjectTableEntry,
|
|
IN HANDLE Handle,
|
|
IN KPROCESSOR_MODE PreviousMode,
|
|
IN BOOLEAN Rundown,
|
|
IN BOOLEAN CanNotRaise
|
|
);
|
|
|
|
NTSTATUS
|
|
ObpCloseHandle (
|
|
IN HANDLE Handle,
|
|
IN KPROCESSOR_MODE PreviousMode,
|
|
IN BOOLEAN CanNotRaise
|
|
);
|
|
|
|
VOID
|
|
ObpDeleteObjectType (
|
|
IN PVOID Object
|
|
);
|
|
|
|
VOID
|
|
ObpAuditObjectAccess(
|
|
IN HANDLE Handle,
|
|
IN PHANDLE_TABLE_ENTRY_INFO ObjectTableEntryInfo,
|
|
IN PUNICODE_STRING ObjectTypeName,
|
|
IN ACCESS_MASK DesiredAccess
|
|
);
|
|
|
|
|
|
//
|
|
// Inline functions
|
|
//
|
|
|
|
FORCEINLINE
|
|
BOOLEAN
|
|
ObpSafeInterlockedIncrement(
|
|
IN OUT PLONG lpValue
|
|
)
|
|
|
|
/*
|
|
|
|
Routine Description:
|
|
|
|
This function increments the LONG value passed in.
|
|
Unlike the InterlockedIncrement function, this will not increment from 0 to 1.
|
|
It will return FALSE if it's trying to reference from 0.
|
|
|
|
Arguments:
|
|
|
|
lpValue - The pointer to the LONG value that should be safe incremented
|
|
|
|
Return Value:
|
|
|
|
Returns FALSE if the current value is 0 (so it cannot increment to 1). TRUE means the LONG
|
|
value was increnemted
|
|
|
|
*/
|
|
|
|
{
|
|
LONG PointerCount, NewPointerCount;
|
|
|
|
//
|
|
// If the object is being deleted then the reference count is zero. So the idea here is to reference
|
|
// the long value but avoid the 0 -> 1 transition that would cause a double delete.
|
|
//
|
|
|
|
PointerCount = *(volatile *) lpValue;
|
|
|
|
do {
|
|
if (PointerCount == 0) {
|
|
return FALSE;
|
|
}
|
|
NewPointerCount = InterlockedCompareExchange (lpValue,
|
|
PointerCount+1,
|
|
PointerCount);
|
|
|
|
//
|
|
// If the exchange compare completed ok then we did a reference so return true.
|
|
//
|
|
|
|
if (NewPointerCount == PointerCount) {
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// We failed because somebody else got in and changed the refence count on us. Use the new value to
|
|
// prime the exchange again.
|
|
//
|
|
|
|
PointerCount = NewPointerCount;
|
|
} while (TRUE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
POBJECT_HEADER_NAME_INFO
|
|
FORCEINLINE
|
|
ObpReferenceNameInfo(
|
|
IN POBJECT_HEADER ObjectHeader
|
|
)
|
|
|
|
/*
|
|
|
|
Routine Description:
|
|
This function references the name information structure. This is a substitute
|
|
for the previous global locking mechanism that used the RootDirectoryMutex to protect
|
|
the fields inside the NAME_INFO as well.
|
|
If the function returnes a non-NULL name info, the name buffer and Directory will not go away
|
|
until the ObpDereferenceNameInfo call.
|
|
|
|
Arguments:
|
|
|
|
ObjectHeader - The object header whose name should be safe-referenced
|
|
|
|
Return Value:
|
|
Returns NULL if the object doesn't have a name information structure, or if the name info is being deleted
|
|
Returns a pointer to the POBJECT_HEADER_NAME_INFO if it's safe to use the fields inside it.
|
|
|
|
*/
|
|
|
|
{
|
|
POBJECT_HEADER_NAME_INFO NameInfo;
|
|
NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );
|
|
|
|
if ((NameInfo != NULL)
|
|
&&
|
|
ObpSafeInterlockedIncrement( &NameInfo->QueryReferences )) {
|
|
|
|
return NameInfo;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
VOID
|
|
FORCEINLINE
|
|
ObpDereferenceNameInfo(
|
|
IN POBJECT_HEADER_NAME_INFO NameInfo
|
|
)
|
|
|
|
/*
|
|
|
|
Routine Description:
|
|
This function dereferences the name information structure. If the number of references
|
|
drops to 0, the name is freed and the directory dereferenced
|
|
|
|
Arguments:
|
|
|
|
NameInfo - The pointer to the name info structure, as returned by ObpReferenceNameInfo.
|
|
(NULL value is allowed)
|
|
|
|
Return Value:
|
|
None
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
if ( (NameInfo != NULL)
|
|
&&
|
|
(InterlockedDecrement(&NameInfo->QueryReferences) == 0)) {
|
|
|
|
PVOID DirObject;
|
|
|
|
//
|
|
// Free the name buffer and zero out the name data fields
|
|
//
|
|
|
|
if (NameInfo->Name.Buffer != NULL) {
|
|
|
|
ExFreePool( NameInfo->Name.Buffer );
|
|
|
|
NameInfo->Name.Buffer = NULL;
|
|
NameInfo->Name.Length = 0;
|
|
NameInfo->Name.MaximumLength = 0;
|
|
}
|
|
|
|
DirObject = NameInfo->Directory;
|
|
|
|
if (DirObject != NULL) {
|
|
|
|
NameInfo->Directory = NULL;
|
|
ObDereferenceObjectDeferDelete( DirObject );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
FORCEINLINE
|
|
ObpLockDirectoryExclusive(
|
|
IN POBJECT_DIRECTORY Directory,
|
|
IN POBP_LOOKUP_CONTEXT LockContext
|
|
)
|
|
|
|
/*
|
|
|
|
Routine Description:
|
|
This Function locks exclusively the Directory. It is used for write access to
|
|
the directory structure.
|
|
|
|
Arguments:
|
|
|
|
Directory - The directory being locked
|
|
|
|
Return Value:
|
|
None
|
|
|
|
*/
|
|
|
|
{
|
|
LockContext->LockStateSignature = OBP_LOCK_WAITEXCLUSIVE_SIGNATURE;
|
|
KeEnterCriticalRegion();
|
|
ExAcquirePushLockExclusive( &Directory->Lock );
|
|
LockContext->LockStateSignature = OBP_LOCK_OWNEDEXCLUSIVE_SIGNATURE;
|
|
}
|
|
|
|
|
|
VOID
|
|
FORCEINLINE
|
|
ObpLockDirectoryShared (
|
|
IN POBJECT_DIRECTORY Directory,
|
|
IN POBP_LOOKUP_CONTEXT LockContext
|
|
)
|
|
|
|
/*
|
|
|
|
Routine Description:
|
|
This Function locks shared the Directory. It is used to read fields inside
|
|
the directory structure.
|
|
|
|
Arguments:
|
|
|
|
Directory - The directory being locked
|
|
|
|
Return Value:
|
|
None
|
|
|
|
*/
|
|
|
|
{
|
|
LockContext->LockStateSignature = OBP_LOCK_WAITSHARED_SIGNATURE;
|
|
KeEnterCriticalRegion();
|
|
ExAcquirePushLockShared( &Directory->Lock );
|
|
LockContext->LockStateSignature = OBP_LOCK_OWNEDSHARED_SIGNATURE;
|
|
}
|
|
|
|
|
|
VOID
|
|
FORCEINLINE
|
|
ObpUnlockDirectory(
|
|
IN POBJECT_DIRECTORY Directory,
|
|
IN POBP_LOOKUP_CONTEXT LockContext
|
|
)
|
|
|
|
/*
|
|
|
|
Routine Description:
|
|
This Function unlocks a Directory (previously locked exclusive or shared).
|
|
|
|
Arguments:
|
|
|
|
Directory - The directory that needs to be unlocked
|
|
|
|
Return Value:
|
|
None
|
|
|
|
*/
|
|
|
|
{
|
|
ExReleasePushLock( &Directory->Lock );
|
|
LockContext->LockStateSignature = OBP_LOCK_RELEASED_SIGNATURE;
|
|
KeLeaveCriticalRegion();
|
|
}
|
|
|
|
|
|
VOID
|
|
FORCEINLINE
|
|
ObpInitializeLookupContext(
|
|
IN POBP_LOOKUP_CONTEXT LookupContext
|
|
)
|
|
|
|
/*
|
|
|
|
Routine Description:
|
|
This Function initialize a lookup context structure.
|
|
|
|
Arguments:
|
|
|
|
LookupContext - The LookupContext to be initialized
|
|
|
|
Return Value:
|
|
None
|
|
|
|
*/
|
|
|
|
{
|
|
LookupContext->DirectoryLocked = FALSE;
|
|
LookupContext->Object = NULL;
|
|
LookupContext->Directory = NULL;
|
|
LookupContext->LockStateSignature = OBP_LOCK_UNUSED_SIGNATURE;
|
|
}
|
|
|
|
|
|
VOID
|
|
FORCEINLINE
|
|
ObpLockLookupContext (
|
|
IN POBP_LOOKUP_CONTEXT LookupContext,
|
|
IN POBJECT_DIRECTORY Directory
|
|
)
|
|
|
|
/*
|
|
|
|
Routine Description:
|
|
This function locks a lookup context. The directory
|
|
is exclusively owned after this call and it's safe to access
|
|
the directory in write mode. This function is intended to be used in
|
|
insertion / deletion into/from the specified directory.
|
|
|
|
The directory is unlocked at the next ObpReleaseLookupContext.
|
|
|
|
Arguments:
|
|
|
|
LookupContext - The LookupContext to be initialized
|
|
|
|
Directory - The directory beling locked for exclusive access.
|
|
|
|
Return Value:
|
|
None
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
ObpLockDirectoryExclusive(Directory, LookupContext);
|
|
LookupContext->DirectoryLocked = TRUE;
|
|
LookupContext->Directory = Directory;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
FORCEINLINE
|
|
ObpReleaseLookupContext (
|
|
IN POBP_LOOKUP_CONTEXT LookupContext
|
|
)
|
|
|
|
/*
|
|
|
|
Routine Description:
|
|
This function undoes the references and locking changes during these calls:
|
|
ObpLockLookupContext and ObpLookupDirectoryEntry.
|
|
|
|
N.B. If ObpLookupDirectoryEntry is called several times in a loop, each call
|
|
will undo the references done at the previous call. ObpReleaseLookupContext
|
|
should be called only ones at the end.
|
|
|
|
Arguments:
|
|
|
|
LookupContext - The LookupContext to be released
|
|
|
|
Return Value:
|
|
None
|
|
|
|
*/
|
|
|
|
{
|
|
//
|
|
// If the context was locked we need to unlock the directory
|
|
//
|
|
|
|
if (LookupContext->DirectoryLocked) {
|
|
|
|
ObpUnlockDirectory( LookupContext->Directory, LookupContext );
|
|
LookupContext->Directory = NULL;
|
|
LookupContext->DirectoryLocked = FALSE;
|
|
}
|
|
|
|
//
|
|
// Remove the references added to the name info and object
|
|
//
|
|
|
|
if (LookupContext->Object) {
|
|
POBJECT_HEADER_NAME_INFO NameInfo;
|
|
|
|
NameInfo = OBJECT_HEADER_TO_NAME_INFO(OBJECT_TO_OBJECT_HEADER(LookupContext->Object));
|
|
|
|
ObpDereferenceNameInfo( NameInfo );
|
|
ObDereferenceObject(LookupContext->Object);
|
|
LookupContext->Object = NULL;
|
|
}
|
|
}
|
|
|
|
|