|
|
/*++
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; } }
|