Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

obp.h File Reference

#include "ntos.h"
#include "seopaque.h"
#include <zwapi.h>

Go to the source code of this file.

Classes

struct  _SECURITY_DESCRIPTOR_HEADER

Defines

#define ObpBeginTypeSpecificCallOut(IRQL)
#define ObpEndTypeSpecificCallOut(IRQL, str, ot, o)
#define ObpValidateIrql(str)
#define ObpIncrPointerCount(np)   InterlockedIncrement( &np->PointerCount )
#define ObpDecrPointerCount(np)   InterlockedDecrement( &np->PointerCount )
#define ObpDecrPointerCountWithResult(np)   (InterlockedDecrement( &np->PointerCount ) == 0)
#define ObpIncrHandleCount(np)   InterlockedIncrement( &np->HandleCount )
#define ObpDecrHandleCount(np)   (InterlockedDecrement( &np->HandleCount ) == 0)
#define ObpEnterObjectTypeMutex(_ObjectType)
#define ObpLeaveObjectTypeMutex(_ObjectType)
#define ObpEnterRootDirectoryMutex()
#define ObpLeaveRootDirectoryMutex()
#define ObpGetObjectTable()   (PsGetCurrentProcess()->ObjectTable)
#define ObpCentralizedSecurity(_ObjectType)   ((_ObjectType)->TypeInfo.SecurityProcedure == SeDefaultObjectMethod)
#define OBP_MAX_DEFINED_OBJECT_TYPES   24
#define OBJ_PROTECT_CLOSE   0x1
#define OBJ_AUDIT_OBJECT_CLOSE   0x00000004L
#define OBJ_HANDLE_ATTRIBUTES   (OBJ_PROTECT_CLOSE | OBJ_INHERIT | OBJ_AUDIT_OBJECT_CLOSE)
#define SD_TO_SD_HEADER(_sd)   CONTAINING_RECORD( (_sd), SECURITY_DESCRIPTOR_HEADER, SecurityDescriptor )
#define LINK_TO_SD_HEADER(_link)   CONTAINING_RECORD( (_link), SECURITY_DESCRIPTOR_HEADER, Link )
#define NEXT_SDHEADER(_sdh)
#define PREV_SDHEADER(_sdh)
#define SECURITY_DESCRIPTOR_CACHE_ENTRIES   256
#define OBJECT_NAME_BUFFER_SIZE   248
#define KERNEL_HANDLE_MASK   ((ULONG_PTR)((LONG)0x80000000))
#define IsKernelHandle(H, M)
#define EncodeKernelHandle(H)   (HANDLE)(KERNEL_HANDLE_MASK | (ULONG_PTR)(H))
#define DecodeKernelHandle(H)   (HANDLE)(KERNEL_HANDLE_MASK ^ (ULONG_PTR)(H))
#define ObpIsOverflow(A, B)   ((A) > ((A) + (B)))
#define ObpFreeObjectCreateInformation(_ObjectCreateInfo)
#define ObpReleaseObjectCreateInformation(_ObjectCreateInfo)
#define ObpAllocateObjectCreateInfoBuffer()   (POBJECT_CREATE_INFORMATION)ExAllocateFromPPNPagedLookasideList(LookasideCreateInfoList)
#define ObpFreeObjectCreateInfoBuffer(ObjectCreateInfo)   ExFreeToPPNPagedLookasideList(LookasideCreateInfoList, ObjectCreateInfo)

Typedefs

typedef _SECURITY_DESCRIPTOR_HEADER SECURITY_DESCRIPTOR_HEADER
typedef _SECURITY_DESCRIPTOR_HEADERPSECURITY_DESCRIPTOR_HEADER

Functions

VOID ObpAcquireDescriptorCacheWriteLock (VOID)
VOID ObpAcquireDescriptorCacheReadLock (VOID)
VOID ObpReleaseDescriptorCacheLock (VOID)
NTSTATUS ObpCaptureObjectCreateInformation (IN POBJECT_TYPE ObjectType OPTIONAL, IN KPROCESSOR_MODE ProbeMode, 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)
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)
PVOID ObpLookupDirectoryEntry (IN POBJECT_DIRECTORY Directory, IN PUNICODE_STRING Name, IN ULONG Attributes)
BOOLEAN ObpInsertDirectoryEntry (IN POBJECT_DIRECTORY Directory, IN PVOID Object)
BOOLEAN ObpDeleteDirectoryEntry (IN POBJECT_DIRECTORY Directory)
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 PBOOLEAN DirectoryLocked, OUT PVOID *FoundObject)
VOID ObpUnlockObjectDirectoryPath (IN POBJECT_DIRECTORY LockedDirectory)
VOID ObpDeleteNameCheck (IN PVOID Object, IN BOOLEAN TypeMutexHeld)
VOID ObpProcessRemoveObjectQueue (PVOID Parameter)
VOID ObpRemoveObjectRoutine (PVOID Object)
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 BOOLEAN DirectoryLocked, 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)
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)
NTSTATUS ObpInitSecurityDescriptorCache (VOID)
ULONG ObpHashSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor)
ULONG ObpHashBuffer (PVOID Data, ULONG Length)
NTSTATUS ObpLogSecurityDescriptor (IN PSECURITY_DESCRIPTOR InputSecurityDescriptor, OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor)
PSECURITY_DESCRIPTOR_HEADER ObpCreateCacheEntry (PSECURITY_DESCRIPTOR InputSecurityDescriptor, ULONG FullHash)
PSECURITY_DESCRIPTOR ObpReferenceSecurityDescriptor (PVOID Object)
VOID ObpDereferenceSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor)
VOID ObpDestroySecurityDescriptorHeader (IN PSECURITY_DESCRIPTOR_HEADER Header)
BOOLEAN ObpCompareSecurityDescriptors (IN PSECURITY_DESCRIPTOR SD1, IN PSECURITY_DESCRIPTOR SD2)
NTSTATUS ObpValidateAccessMask (PACCESS_STATE AccessState)

Variables

KSPIN_LOCK ObpLock
KEVENT ObpDefaultObject
WORK_QUEUE_ITEM ObpRemoveObjectWorkItem
PSINGLE_LIST_ENTRY ObpRemoveObjectQueue
KSPIN_LOCK ObpDeviceMapLock
POBJECT_TYPE ObpObjectTypes [OBP_MAX_DEFINED_OBJECT_TYPES]
POBJECT_TYPE ObpTypeObjectType
POBJECT_TYPE ObpDirectoryObjectType
POBJECT_TYPE ObpSymbolicLinkObjectType
POBJECT_TYPE ObpDeviceMapObjectType
POBJECT_DIRECTORY ObpRootDirectoryObject
POBJECT_DIRECTORY ObpTypeDirectoryObject
ULARGE_INTEGER ObpDosDevicesShortNamePrefix
ULARGE_INTEGER ObpDosDevicesShortNameRoot
UNICODE_STRING ObpDosDevicesShortName
ERESOURCE ObpRootDirectoryMutex
ERESOURCE SecurityDescriptorCacheLock
NPAGED_LOOKASIDE_LIST ObpCreateInfoLookasideList
NPAGED_LOOKASIDE_LIST ObpNameBufferLookasideList
PHANDLE_TABLE ObpKernelHandleTable


Define Documentation

#define DecodeKernelHandle  )     (HANDLE)(KERNEL_HANDLE_MASK ^ (ULONG_PTR)(H))
 

Definition at line 418 of file obp.h.

Referenced by NtClose(), NtSetInformationObject(), NtWaitForMultipleObjects(), and ObReferenceObjectByHandle().

#define EncodeKernelHandle  )     (HANDLE)(KERNEL_HANDLE_MASK | (ULONG_PTR)(H))
 

Definition at line 416 of file obp.h.

Referenced by ObpCreateHandle(), and ObpCreateUnnamedHandle().

#define IsKernelHandle H,
 ) 
 

Value:

(((KERNEL_HANDLE_MASK & (ULONG_PTR)(H)) == KERNEL_HANDLE_MASK) && \ ((M) == KernelMode) && \ ((H) != NtCurrentThread()) && \ ((H) != NtCurrentProcess()))

Definition at line 410 of file obp.h.

#define KERNEL_HANDLE_MASK   ((ULONG_PTR)((LONG)0x80000000))
 

Definition at line 408 of file obp.h.

#define LINK_TO_SD_HEADER _link   )     CONTAINING_RECORD( (_link), SECURITY_DESCRIPTOR_HEADER, Link )
 

Definition at line 318 of file obp.h.

Referenced by ObpLogSecurityDescriptor().

#define NEXT_SDHEADER _sdh   ) 
 

Value:

( \ (_sdh)->Link.Flink == NULL ? NULL : \ CONTAINING_RECORD( (_sdh)->Link.Flink, SECURITY_DESCRIPTOR_HEADER, Link ) \ )

Definition at line 325 of file obp.h.

#define OBJ_AUDIT_OBJECT_CLOSE   0x00000004L
 

Definition at line 282 of file obp.h.

#define OBJ_HANDLE_ATTRIBUTES   (OBJ_PROTECT_CLOSE | OBJ_INHERIT | OBJ_AUDIT_OBJECT_CLOSE)
 

Definition at line 289 of file obp.h.

Referenced by NtClose(), NtDuplicateObject(), NtWaitForMultipleObjects(), ObDupHandleProcedure(), ObpCaptureHandleInformation(), ObpCreateHandle(), ObpCreateUnnamedHandle(), ObpEnumFindHandleProcedure(), ObpSetHandleAttributes(), and ObReferenceObjectByHandle().

#define OBJ_PROTECT_CLOSE   0x1
 

Definition at line 261 of file obp.h.

Referenced by NtClose(), NtQueryObject(), and ObpSetHandleAttributes().

#define OBJECT_NAME_BUFFER_SIZE   248
 

Definition at line 390 of file obp.h.

Referenced by ObInitSystem(), ObpAllocateObjectNameBuffer(), and ObpFreeObjectNameBuffer().

#define OBP_MAX_DEFINED_OBJECT_TYPES   24
 

Definition at line 228 of file obp.h.

Referenced by NtQueryObject(), and ObCreateObjectType().

 
#define ObpAllocateObjectCreateInfoBuffer  )     (POBJECT_CREATE_INFORMATION)ExAllocateFromPPNPagedLookasideList(LookasideCreateInfoList)
 

Definition at line 519 of file obp.h.

Referenced by ObCreateObject().

#define ObpBeginTypeSpecificCallOut IRQL   ) 
 

Definition at line 56 of file obp.h.

Referenced by NtClose(), ObAssignSecurity(), ObGetObjectSecurity(), ObpDecrementHandleCount(), ObpDeleteNameCheck(), ObpIncrementHandleCount(), ObpIncrementUnnamedHandleCount(), ObpLookupObjectName(), ObpRemoveObjectRoutine(), and ObQueryNameString().

#define ObpCentralizedSecurity _ObjectType   )     ((_ObjectType)->TypeInfo.SecurityProcedure == SeDefaultObjectMethod)
 

Definition at line 221 of file obp.h.

Referenced by ObGetObjectSecurity(), and ObpReferenceSecurityDescriptor().

#define ObpDecrHandleCount np   )     (InterlockedDecrement( &np->HandleCount ) == 0)
 

Definition at line 148 of file obp.h.

Referenced by ObpDecrementHandleCount(), ObpIncrementHandleCount(), and ObpIncrementUnnamedHandleCount().

#define ObpDecrPointerCount np   )     InterlockedDecrement( &np->PointerCount )
 

Definition at line 144 of file obp.h.

Referenced by ObpCreateHandle(), and ObpCreateUnnamedHandle().

#define ObpDecrPointerCountWithResult np   )     (InterlockedDecrement( &np->PointerCount ) == 0)
 

Definition at line 145 of file obp.h.

Referenced by ObfDereferenceObject().

#define ObpEndTypeSpecificCallOut IRQL,
str,
ot,
 ) 
 

Definition at line 57 of file obp.h.

Referenced by NtClose(), ObAssignSecurity(), ObGetObjectSecurity(), ObpDecrementHandleCount(), ObpDeleteNameCheck(), ObpIncrementHandleCount(), ObpIncrementUnnamedHandleCount(), ObpLookupObjectName(), ObpRemoveObjectRoutine(), and ObQueryNameString().

#define ObpEnterObjectTypeMutex _ObjectType   ) 
 

Value:

{ \ ObpValidateIrql("ObpEnterObjectTypeMutex"); \ KeEnterCriticalRegion(); \ ExAcquireResourceExclusiveLite(&(_ObjectType)->Mutex, TRUE); \ }

Definition at line 163 of file obp.h.

Referenced by NtQuerySymbolicLinkObject(), ObCheckCreateObjectAccess(), ObCheckObjectAccess(), ObCreateObjectType(), ObEnumerateObjectsByType(), ObGetObjectInformation(), ObpCheckObjectReference(), ObpCheckTraverseAccess(), ObpCreateTypeArray(), ObpDecrementHandleCount(), ObpDeleteNameCheck(), ObpIncrementHandleCount(), ObpIncrementUnnamedHandleCount(), and ObpRemoveObjectRoutine().

 
#define ObpEnterRootDirectoryMutex  ) 
 

Value:

{ \ ObpValidateIrql("ObpEnterRootDirectoryMutex"); \ KeEnterCriticalRegion(); \ ExAcquireResourceExclusiveLite(&ObpRootDirectoryMutex, TRUE); \ }

Definition at line 189 of file obp.h.

Referenced by NtQueryDirectoryObject(), NtQueryObject(), ObCreateObjectType(), ObInitSystem(), ObpDeleteNameCheck(), ObpDeleteSymbolicLinkName(), ObpLookupObjectName(), ObpParseSymbolicLink(), and ObQueryNameString().

#define ObpFreeObjectCreateInfoBuffer ObjectCreateInfo   )     ExFreeToPPNPagedLookasideList(LookasideCreateInfoList, ObjectCreateInfo)
 

Definition at line 547 of file obp.h.

Referenced by ObCreateObject(), and ObFreeObjectCreateInfoBuffer().

#define ObpFreeObjectCreateInformation _ObjectCreateInfo   ) 
 

Value:

{ \ ObpReleaseObjectCreateInformation((_ObjectCreateInfo)); \ ObpFreeObjectCreateInfoBuffer((_ObjectCreateInfo)); \ }

Definition at line 431 of file obp.h.

Referenced by ObDeleteCapturedInsertInfo(), ObInsertObject(), ObOpenObjectByName(), and ObpFreeObject().

 
#define ObpGetObjectTable  )     (PsGetCurrentProcess()->ObjectTable)
 

Definition at line 213 of file obp.h.

Referenced by NtClose(), NtDuplicateObject(), NtSetInformationObject(), NtWaitForMultipleObjects(), ObpCreateHandle(), ObpCreateUnnamedHandle(), ObQueryObjectAuditingByHandle(), ObReferenceObjectByHandle(), and obtest().

#define ObpIncrHandleCount np   )     InterlockedIncrement( &np->HandleCount )
 

Definition at line 147 of file obp.h.

Referenced by ObpIncrementHandleCount(), and ObpIncrementUnnamedHandleCount().

#define ObpIncrPointerCount np   )     InterlockedIncrement( &np->PointerCount )
 

Definition at line 143 of file obp.h.

Referenced by NtWaitForMultipleObjects(), ObDupHandleProcedure(), ObfReferenceObject(), ObpCreateHandle(), ObpCreateUnnamedHandle(), ObpLookupObjectName(), ObReferenceObjectByHandle(), and ObReferenceObjectByPointer().

#define ObpIsOverflow A,
 )     ((A) > ((A) + (B)))
 

Definition at line 424 of file obp.h.

Referenced by NtQueryDirectoryObject().

#define ObpLeaveObjectTypeMutex _ObjectType   ) 
 

Value:

{ \ ExReleaseResource(&(_ObjectType)->Mutex); \ KeLeaveCriticalRegion(); \ ObpValidateIrql("ObpLeaveObjectTypeMutex"); \ }

Definition at line 176 of file obp.h.

Referenced by NtQuerySymbolicLinkObject(), ObCheckCreateObjectAccess(), ObCheckObjectAccess(), ObCreateObjectType(), ObEnumerateObjectsByType(), ObGetObjectInformation(), ObpCheckObjectReference(), ObpCheckTraverseAccess(), ObpCreateTypeArray(), ObpDecrementHandleCount(), ObpDeleteNameCheck(), ObpIncrementHandleCount(), ObpIncrementUnnamedHandleCount(), and ObpRemoveObjectRoutine().

 
#define ObpLeaveRootDirectoryMutex  ) 
 

Value:

{ \ ExReleaseResource(&ObpRootDirectoryMutex); \ KeLeaveCriticalRegion(); \ ObpValidateIrql("ObpLeaveRootDirectoryMutex"); \ }

Definition at line 202 of file obp.h.

Referenced by NtQueryDirectoryObject(), NtQueryObject(), ObCreateObjectType(), ObInitSystem(), ObInsertObject(), ObOpenObjectByName(), ObpCreateHandle(), ObpDeleteNameCheck(), ObpDeleteSymbolicLinkName(), ObpLookupObjectName(), ObpParseSymbolicLink(), ObQueryNameString(), and ObReferenceObjectByName().

#define ObpReleaseObjectCreateInformation _ObjectCreateInfo   ) 
 

Value:

{ \ if ((_ObjectCreateInfo)->SecurityDescriptor != NULL) { \ SeReleaseSecurityDescriptor((_ObjectCreateInfo)->SecurityDescriptor, \ (_ObjectCreateInfo)->ProbeMode, \ TRUE); \ (_ObjectCreateInfo)->SecurityDescriptor = NULL; \ } \ }

Definition at line 436 of file obp.h.

Referenced by ObCreateObject(), ObOpenObjectByName(), and ObpCaptureObjectCreateInformation().

#define ObpValidateIrql str   ) 
 

Definition at line 71 of file obp.h.

Referenced by NtClose(), NtCreateDirectoryObject(), NtOpenDirectoryObject(), NtQueryDirectoryObject(), ObCreateObjectType(), ObInsertObject(), ObKillProcess(), ObOpenObjectByName(), ObOpenObjectByPointer(), ObpCreateHandle(), ObpCreateUnnamedHandle(), ObpDeleteNameCheck(), ObpIncrementHandleCount(), ObpIncrementUnnamedHandleCount(), ObpLookupObjectName(), ObpRemoveObjectRoutine(), ObQueryObjectAuditingByHandle(), ObReferenceObjectByHandle(), and ObReferenceObjectByName().

#define PREV_SDHEADER _sdh   ) 
 

Value:

( \ (sdh)->Link.Blink == NULL ? NULL : \ CONTAINING_RECORD( (sdh)->Link.Blink, SECURITY_DESCRIPTOR_HEADER, Link ) \ )

Definition at line 330 of file obp.h.

#define SD_TO_SD_HEADER _sd   )     CONTAINING_RECORD( (_sd), SECURITY_DESCRIPTOR_HEADER, SecurityDescriptor )
 

Definition at line 311 of file obp.h.

Referenced by ObDeassignSecurity(), ObpDereferenceSecurityDescriptor(), and ObpReferenceSecurityDescriptor().

#define SECURITY_DESCRIPTOR_CACHE_ENTRIES   256
 

Definition at line 339 of file obp.h.

Referenced by ObpInitSecurityDescriptorCache().


Typedef Documentation

typedef struct _SECURITY_DESCRIPTOR_HEADER * PSECURITY_DESCRIPTOR_HEADER
 

typedef struct _SECURITY_DESCRIPTOR_HEADER SECURITY_DESCRIPTOR_HEADER
 


Function Documentation

VOID ObpAcquireDescriptorCacheReadLock VOID   ) 
 

Definition at line 914 of file obsdata.c.

References ExAcquireResourceShared, KeEnterCriticalRegion, ObsSecurityDescriptorCacheLock, TRUE, and VOID().

Referenced by NtQueryObject(), and ObQuerySecurityDescriptorInfo().

00920 : 00921 00922 Takes a read lock on the security descriptor cache. 00923 00924 Arguments: 00925 00926 none 00927 00928 Return Value: 00929 00930 None. 00931 00932 --*/ 00933 00934 { 00935 KeEnterCriticalRegion(); 00936 (VOID)ExAcquireResourceShared( &ObsSecurityDescriptorCacheLock,TRUE ); 00937 00938 return; 00939 }

VOID ObpAcquireDescriptorCacheWriteLock VOID   ) 
 

Definition at line 886 of file obsdata.c.

References ExAcquireResourceExclusive, KeEnterCriticalRegion, ObsSecurityDescriptorCacheLock, TRUE, and VOID().

Referenced by ObDeassignSecurity(), ObpDereferenceSecurityDescriptor(), ObpLogSecurityDescriptor(), ObpReferenceSecurityDescriptor(), and ObSetSecurityDescriptorInfo().

00892 : 00893 00894 Takes a write lock on the security descriptor cache. 00895 00896 Arguments: 00897 00898 none 00899 00900 Return Value: 00901 00902 None. 00903 00904 --*/ 00905 00906 { 00907 KeEnterCriticalRegion(); 00908 (VOID)ExAcquireResourceExclusive( &ObsSecurityDescriptorCacheLock, TRUE ); 00909 00910 return; 00911 }

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
 

Definition at line 761 of file obcreate.c.

References _OBJECT_HEADER_CREATOR_INFO::CreatorBackTraceIndex, _OBJECT_HEADER_CREATOR_INFO::CreatorUniqueProcess, DbgPrint, _OBJECT_HEADER_NAME_INFO::Directory, ExAllocatePoolWithTag, _OBJECT_HEADER_QUOTA_INFO::ExclusiveProcess, _OBJECT_HEADER::Flags, _OBJECT_HEADER::HandleCount, _OBJECT_HANDLE_COUNT_ENTRY::HandleCount, _OBJECT_HEADER::HandleInfoOffset, KernelMode, _OBJECT_HEADER_NAME_INFO::Name, _OBJECT_HEADER::NameInfoOffset, NonPagedPool, _OBJECT_HEADER_QUOTA_INFO::NonPagedPoolCharge, NTSTATUS(), NULL, OB_FLAG_CREATOR_INFO, OB_FLAG_EXCLUSIVE_OBJECT, OB_FLAG_KERNEL_OBJECT, OB_FLAG_NEW_OBJECT, OB_FLAG_PERMANENT_OBJECT, OB_FLAG_SINGLE_HANDLE_ENTRY, _OBJECT_HEADER::ObjectCreateInfo, ObpObjectsCreated, ObpObjectsWithCreatorInfo, ObpObjectsWithHandleDB, ObpObjectsWithName, ObpObjectsWithPoolQuota, PAGED_CODE, PagedPool, _OBJECT_HEADER_QUOTA_INFO::PagedPoolCharge, _OBJECT_HEADER::PointerCount, POOL_TYPE, PROTECTED_POOL, PsGetCurrentProcess, _OBJECT_HEADER::QuotaInfoOffset, SE_DEFAULT_SECURITY_QUOTA, _OBJECT_HEADER::SecurityDescriptor, _OBJECT_HEADER_QUOTA_INFO::SecurityDescriptorCharge, _OBJECT_HEADER_HANDLE_INFO::SingleEntry, Status, _OBJECT_HEADER::Type, and _OBJECT_HEADER_CREATOR_INFO::TypeList.

Referenced by ObCreateObject(), and ObCreateObjectType().

00772 : 00773 00774 This routine allocates a new object including the object header 00775 and body from pool and fill in the appropriate fields. 00776 00777 Arguments: 00778 00779 ObjectCreateInfo - Supplies the create information for the new object 00780 00781 OwnershipMode - Supplies the processor mode of who is going to own 00782 the object 00783 00784 ObjectType - Optionally supplies the object type of the object being 00785 created. If the object create info not null then this field must 00786 be supplied. 00787 00788 ObjectName - Supplies the name of the object being created 00789 00790 ObjectBodySize - Specifies the size, in bytes, of the body of the object 00791 being created 00792 00793 ReturnedObjectHeader - Receives a pointer to the object header for the 00794 newly created objet. 00795 00796 Return Value: 00797 00798 An appropriate status value. 00799 00800 --*/ 00801 00802 { 00803 ULONG HeaderSize; 00804 POBJECT_HEADER ObjectHeader; 00805 NTSTATUS Status; 00806 PVOID ZoneSegment; 00807 ULONG QuotaInfoSize; 00808 ULONG HandleInfoSize; 00809 ULONG NameInfoSize; 00810 ULONG CreatorInfoSize; 00811 POBJECT_HEADER_QUOTA_INFO QuotaInfo; 00812 POBJECT_HEADER_HANDLE_INFO HandleInfo; 00813 POBJECT_HEADER_NAME_INFO NameInfo; 00814 POBJECT_HEADER_CREATOR_INFO CreatorInfo; 00815 POOL_TYPE PoolType; 00816 00817 PAGED_CODE(); 00818 00819 ObpObjectsCreated += 1; 00820 00821 // 00822 // Compute the sizes of the optional object header components. 00823 // 00824 00825 if (ObjectCreateInfo == NULL) { 00826 00827 QuotaInfoSize = 0; 00828 HandleInfoSize = 0; 00829 NameInfoSize = sizeof( OBJECT_HEADER_NAME_INFO ); 00830 CreatorInfoSize = sizeof( OBJECT_HEADER_CREATOR_INFO ); 00831 00832 } else { 00833 00834 // 00835 // The caller specified some additional object create info 00836 // 00837 // First check to see if we need to set the quota 00838 // 00839 00840 if (ObjectCreateInfo->PagedPoolCharge != ObjectType->TypeInfo.DefaultPagedPoolCharge || 00841 ObjectCreateInfo->NonPagedPoolCharge != ObjectType->TypeInfo.DefaultNonPagedPoolCharge || 00842 ObjectCreateInfo->SecurityDescriptorCharge > SE_DEFAULT_SECURITY_QUOTA || 00843 (ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)) { 00844 00845 QuotaInfoSize = sizeof( OBJECT_HEADER_QUOTA_INFO ); 00846 ObpObjectsWithPoolQuota += 1; 00847 00848 } else { 00849 00850 QuotaInfoSize = 0; 00851 } 00852 00853 // 00854 // Check if we are to allocate space to maintain handle counts 00855 // 00856 00857 if (ObjectType->TypeInfo.MaintainHandleCount) { 00858 00859 HandleInfoSize = sizeof( OBJECT_HEADER_HANDLE_INFO ); 00860 ObpObjectsWithHandleDB += 1; 00861 00862 } else { 00863 00864 HandleInfoSize = 0; 00865 } 00866 00867 // 00868 // Check if we are to allocate space for the name 00869 // 00870 00871 if (ObjectName->Buffer != NULL) { 00872 00873 NameInfoSize = sizeof( OBJECT_HEADER_NAME_INFO ); 00874 ObpObjectsWithName += 1; 00875 00876 } else { 00877 00878 NameInfoSize = 0; 00879 } 00880 00881 // 00882 // Finally check if we are to maintain the creator info 00883 // 00884 00885 if (ObjectType->TypeInfo.MaintainTypeList) { 00886 00887 CreatorInfoSize = sizeof( OBJECT_HEADER_CREATOR_INFO ); 00888 ObpObjectsWithCreatorInfo += 1; 00889 00890 } else { 00891 00892 CreatorInfoSize = 0; 00893 } 00894 } 00895 00896 // 00897 // Now compute the total header size 00898 // 00899 00900 HeaderSize = QuotaInfoSize + 00901 HandleInfoSize + 00902 NameInfoSize + 00903 CreatorInfoSize + 00904 FIELD_OFFSET( OBJECT_HEADER, Body ); 00905 00906 // 00907 // Allocate and initialize the object. 00908 // 00909 // If the object type is not specified or specifies nonpaged pool, 00910 // then allocate the object from nonpaged pool. 00911 // Otherwise, allocate the object from paged pool. 00912 // 00913 00914 if ((ObjectType == NULL) || (ObjectType->TypeInfo.PoolType == NonPagedPool)) { 00915 00916 PoolType = NonPagedPool; 00917 00918 } else { 00919 00920 PoolType = PagedPool; 00921 } 00922 00923 ObjectHeader = ExAllocatePoolWithTag( PoolType, 00924 HeaderSize + ObjectBodySize, 00925 (ObjectType == NULL ? 'TjbO' : ObjectType->Key) | 00926 PROTECTED_POOL ); 00927 00928 if (ObjectHeader == NULL) { 00929 00930 return STATUS_INSUFFICIENT_RESOURCES; 00931 } 00932 00933 // 00934 // Now based on if we are to put in the quota, handle, name, or creator info we 00935 // will do the extra work. This order is very important because we rely on 00936 // it to free the object. 00937 // 00938 00939 if (QuotaInfoSize != 0) { 00940 00941 QuotaInfo = (POBJECT_HEADER_QUOTA_INFO)ObjectHeader; 00942 QuotaInfo->PagedPoolCharge = ObjectCreateInfo->PagedPoolCharge; 00943 QuotaInfo->NonPagedPoolCharge = ObjectCreateInfo->NonPagedPoolCharge; 00944 QuotaInfo->SecurityDescriptorCharge = ObjectCreateInfo->SecurityDescriptorCharge; 00945 QuotaInfo->ExclusiveProcess = NULL; 00946 ObjectHeader = (POBJECT_HEADER)(QuotaInfo + 1); 00947 } 00948 00949 if (HandleInfoSize != 0) { 00950 00951 HandleInfo = (POBJECT_HEADER_HANDLE_INFO)ObjectHeader; 00952 HandleInfo->SingleEntry.HandleCount = 0; 00953 ObjectHeader = (POBJECT_HEADER)(HandleInfo + 1); 00954 } 00955 00956 if (NameInfoSize != 0) { 00957 00958 NameInfo = (POBJECT_HEADER_NAME_INFO)ObjectHeader; 00959 NameInfo->Name = *ObjectName; 00960 NameInfo->Directory = NULL; 00961 ObjectHeader = (POBJECT_HEADER)(NameInfo + 1); 00962 } 00963 00964 if (CreatorInfoSize != 0) { 00965 00966 CreatorInfo = (POBJECT_HEADER_CREATOR_INFO)ObjectHeader; 00967 CreatorInfo->CreatorBackTraceIndex = 0; 00968 CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcess()->UniqueProcessId; 00969 InitializeListHead( &CreatorInfo->TypeList ); 00970 ObjectHeader = (POBJECT_HEADER)(CreatorInfo + 1); 00971 } 00972 00973 // 00974 // Compute the proper offsets based on what we have 00975 // 00976 00977 if (QuotaInfoSize != 0) { 00978 00979 ObjectHeader->QuotaInfoOffset = (UCHAR)(QuotaInfoSize + HandleInfoSize + NameInfoSize + CreatorInfoSize); 00980 00981 } else { 00982 00983 ObjectHeader->QuotaInfoOffset = 0; 00984 } 00985 00986 if (HandleInfoSize != 0) { 00987 00988 ObjectHeader->HandleInfoOffset = (UCHAR)(HandleInfoSize + NameInfoSize + CreatorInfoSize); 00989 00990 } else { 00991 00992 ObjectHeader->HandleInfoOffset = 0; 00993 } 00994 00995 if (NameInfoSize != 0) { 00996 00997 ObjectHeader->NameInfoOffset = (UCHAR)(NameInfoSize + CreatorInfoSize); 00998 00999 } else { 01000 01001 ObjectHeader->NameInfoOffset = 0; 01002 } 01003 01004 // 01005 // Say that this is a new object, and conditionally set the other flags 01006 // 01007 01008 ObjectHeader->Flags = OB_FLAG_NEW_OBJECT; 01009 01010 if (CreatorInfoSize != 0) { 01011 01012 ObjectHeader->Flags |= OB_FLAG_CREATOR_INFO; 01013 } 01014 01015 if (HandleInfoSize != 0) { 01016 01017 ObjectHeader->Flags |= OB_FLAG_SINGLE_HANDLE_ENTRY; 01018 } 01019 01020 // 01021 // Set the counters and its type 01022 // 01023 01024 ObjectHeader->PointerCount = 1; 01025 ObjectHeader->HandleCount = 0; 01026 ObjectHeader->Type = ObjectType; 01027 01028 // 01029 // Initialize the object header. 01030 // 01031 // N.B. The initialization of the object header is done field by 01032 // field rather than zeroing the memory and then initializing 01033 // the pertinent fields. 01034 // 01035 // N.B. It is assumed that the caller will initialize the object 01036 // attributes, object ownership, and parse context. 01037 // 01038 01039 if (OwnershipMode == KernelMode) { 01040 01041 ObjectHeader->Flags |= OB_FLAG_KERNEL_OBJECT; 01042 } 01043 01044 if (ObjectCreateInfo != NULL && 01045 ObjectCreateInfo->Attributes & OBJ_PERMANENT ) { 01046 01047 ObjectHeader->Flags |= OB_FLAG_PERMANENT_OBJECT; 01048 } 01049 01050 if ((ObjectCreateInfo != NULL) && 01051 (ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)) { 01052 01053 ObjectHeader->Flags |= OB_FLAG_EXCLUSIVE_OBJECT; 01054 } 01055 01056 ObjectHeader->ObjectCreateInfo = ObjectCreateInfo; 01057 ObjectHeader->SecurityDescriptor = NULL; 01058 01059 if (ObjectType != NULL) { 01060 01061 ObjectType->TotalNumberOfObjects += 1; 01062 01063 if (ObjectType->TotalNumberOfObjects > ObjectType->HighWaterNumberOfObjects) { 01064 01065 ObjectType->HighWaterNumberOfObjects = ObjectType->TotalNumberOfObjects; 01066 } 01067 } 01068 01069 #if DBG 01070 01071 // 01072 // On a checked build echo out allocs 01073 // 01074 01075 if (ObpShowAllocAndFree) { 01076 01077 DbgPrint( "OB: Alloc %lx (%lx) %04lu", ObjectHeader, ObjectHeader, ObjectBodySize ); 01078 01079 if (ObjectType) { 01080 01081 DbgPrint(" - %wZ\n", &ObjectType->Name ); 01082 01083 } else { 01084 01085 DbgPrint(" - Type\n" ); 01086 } 01087 } 01088 #endif 01089 01090 *ReturnedObjectHeader = ObjectHeader; 01091 01092 return STATUS_SUCCESS; 01093 }

PWCHAR ObpAllocateObjectNameBuffer IN ULONG  Length,
IN LOGICAL  UseLookaside,
IN OUT PUNICODE_STRING  ObjectName
 

Definition at line 583 of file obcreate.c.

References Buffer, ExAllocateFromPPNPagedLookasideList(), ExAllocatePoolWithTag, FALSE, LookasideNameBufferList, NonPagedPool, OBJECT_NAME_BUFFER_SIZE, and USHORT.

Referenced by ObpCaptureObjectName().

00591 : 00592 00593 This function allocates an object name buffer. 00594 00595 N.B. This function is nonpageable. 00596 00597 Arguments: 00598 00599 Length - Supplies the length of the required buffer in bytes. 00600 00601 UseLookaside - Supplies a logical variable that determines whether an 00602 attempt is made to allocate the name buffer from the lookaside list. 00603 00604 ObjectName - Supplies a pointer to a name buffer string descriptor. 00605 00606 Return Value: 00607 00608 If the allocation is successful, then name buffer string descriptor 00609 is initialized and the address of the name buffer is returned as the 00610 function value. Otherwise, a value of NULL is returned. 00611 00612 --*/ 00613 00614 { 00615 PVOID Buffer; 00616 ULONG Maximum; 00617 KIRQL OldIrql; 00618 PKPRCB Prcb; 00619 00620 // 00621 // If allocation from the lookaside lists is specified and the buffer 00622 // size is less than the size of lookaside list entries, then attempt 00623 // to allocate the name buffer from the lookaside lists. Otherwise, 00624 // attempt to allocate the name buffer from nonpaged pool. 00625 // 00626 00627 Maximum = Length + sizeof(WCHAR); 00628 00629 if ((UseLookaside == FALSE) || (Maximum > OBJECT_NAME_BUFFER_SIZE)) { 00630 00631 // 00632 // Attempt to allocate the buffer from nonpaged pool. 00633 // 00634 00635 Buffer = ExAllocatePoolWithTag(NonPagedPool, Maximum, 'mNbO'); 00636 00637 } else { 00638 00639 // 00640 // Attempt to allocate the name buffer from the lookaside list. If 00641 // the allocation attempt fails, then attempt to allocate the name 00642 // buffer from pool. 00643 // 00644 00645 Maximum = OBJECT_NAME_BUFFER_SIZE; 00646 Buffer = ExAllocateFromPPNPagedLookasideList(LookasideNameBufferList); 00647 } 00648 00649 // 00650 // Initialize the string descriptor and return the buffer address. 00651 // 00652 00653 ObjectName->Length = (USHORT)Length; 00654 ObjectName->MaximumLength = (USHORT)Maximum; 00655 ObjectName->Buffer = Buffer; 00656 00657 return (PWCHAR)Buffer; 00658 }

NTSTATUS ObpCaptureObjectCreateInformation IN POBJECT_TYPE ObjectType  OPTIONAL,
IN KPROCESSOR_MODE  ProbeMode,
IN POBJECT_ATTRIBUTES  ObjectAttributes,
OUT PUNICODE_STRING  CapturedObjectName,
IN POBJECT_CREATE_INFORMATION  ObjectCreateInfo,
IN LOGICAL  UseLookaside
 

Referenced by ObCreateObject(), and ObOpenObjectByName().

NTSTATUS ObpCaptureObjectName IN KPROCESSOR_MODE  ProbeMode,
IN PUNICODE_STRING  ObjectName,
IN OUT PUNICODE_STRING  CapturedObjectName,
IN LOGICAL  UseLookaside
 

Definition at line 438 of file obcreate.c.

References ExFreePool(), ExSystemExceptionFilter(), KernelMode, NTSTATUS(), NULL, ObpAllocateObjectNameBuffer(), PAGED_CODE, ProbeAndReadUnicodeString, ProbeForRead, and Status.

Referenced by ObpCaptureObjectCreateInformation(), and ObReferenceObjectByName().

00447 : 00448 00449 This function captures the object name but first verifies that 00450 it is at least properly sized. 00451 00452 Arguments: 00453 00454 ProbeMode - Supplies the processor mode to use when probing 00455 the object name 00456 00457 ObjectName - Supplies the caller's version of the object name 00458 00459 CapturedObjectName - Receives the captured verified version 00460 of the object name 00461 00462 UseLookaside - Indicates if the captured name buffer should be 00463 allocated from the lookaside list or from straight pool 00464 00465 Return Value: 00466 00467 An appropriate status value 00468 00469 --*/ 00470 00471 { 00472 PWCH FreeBuffer; 00473 UNICODE_STRING InputObjectName; 00474 ULONG Length; 00475 NTSTATUS Status; 00476 00477 PAGED_CODE(); 00478 00479 // 00480 // Initialize the object name descriptor and capture the specified name 00481 // string. 00482 // 00483 00484 CapturedObjectName->Buffer = NULL; 00485 CapturedObjectName->Length = 0; 00486 CapturedObjectName->MaximumLength = 0; 00487 00488 Status = STATUS_SUCCESS; 00489 00490 try { 00491 00492 // 00493 // Probe and capture the name string descriptor and probe the 00494 // name string, if necessary. 00495 // 00496 00497 FreeBuffer = NULL; 00498 00499 if (ProbeMode != KernelMode) { 00500 00501 InputObjectName = ProbeAndReadUnicodeString(ObjectName); 00502 00503 ProbeForRead( InputObjectName.Buffer, 00504 InputObjectName.Length, 00505 sizeof(WCHAR) ); 00506 00507 } else { 00508 00509 InputObjectName = *ObjectName; 00510 } 00511 00512 // 00513 // If the length of the string is not zero, then capture the string. 00514 // 00515 00516 if (InputObjectName.Length != 0) { 00517 00518 // 00519 // If the length of the string is not an even multiple of the 00520 // size of a UNICODE character or cannot be zero terminated, 00521 // then return an error. 00522 // 00523 00524 Length = InputObjectName.Length; 00525 00526 if (((Length & (sizeof(WCHAR) - 1)) != 0) || 00527 (Length == (MAXUSHORT - sizeof(WCHAR) + 1))) { 00528 00529 Status = STATUS_OBJECT_NAME_INVALID; 00530 00531 } else { 00532 00533 // 00534 // Allocate a buffer for the specified name string. 00535 // 00536 // N.B. The name buffer allocation routine adds one 00537 // UNICODE character to the length and initializes 00538 // the string descriptor. 00539 // 00540 00541 FreeBuffer = ObpAllocateObjectNameBuffer( Length, 00542 UseLookaside, 00543 CapturedObjectName ); 00544 00545 if (FreeBuffer == NULL) { 00546 00547 Status = STATUS_INSUFFICIENT_RESOURCES; 00548 00549 } else { 00550 00551 // 00552 // Copy the specified name string to the destination 00553 // buffer. 00554 // 00555 00556 RtlMoveMemory(FreeBuffer, InputObjectName.Buffer, Length); 00557 00558 // 00559 // Zero terminate the name string and initialize the 00560 // string descriptor. 00561 // 00562 00563 FreeBuffer[Length / sizeof(WCHAR)] = UNICODE_NULL; 00564 } 00565 } 00566 } 00567 00568 } except(ExSystemExceptionFilter()) { 00569 00570 Status = GetExceptionCode(); 00571 00572 if (FreeBuffer != NULL) { 00573 00574 ExFreePool(FreeBuffer); 00575 } 00576 } 00577 00578 return Status; 00579 }

NTSTATUS ObpChargeQuotaForObject IN POBJECT_HEADER  ObjectHeader,
IN POBJECT_TYPE  ObjectType,
OUT PBOOLEAN  NewObject
 

Definition at line 1861 of file obhandle.c.

References FALSE, _OBJECT_HEADER_QUOTA_INFO::NonPagedPoolCharge, NULL, OB_FLAG_DEFAULT_SECURITY_QUOTA, OB_FLAG_NEW_OBJECT, OBJECT_HEADER_TO_QUOTA_INFO, _OBJECT_HEADER_QUOTA_INFO::PagedPoolCharge, PsChargeSharedPoolQuota(), PsGetCurrentProcess, SE_DEFAULT_SECURITY_QUOTA, _OBJECT_HEADER_QUOTA_INFO::SecurityDescriptorCharge, and TRUE.

Referenced by ObpIncrementHandleCount(), and ObpIncrementUnnamedHandleCount().

01869 : 01870 01871 This routine charges quota against the current process for the new 01872 object 01873 01874 Arguments: 01875 01876 ObjectHeader - Supplies a pointer to the new object being charged for 01877 01878 ObjectType - Supplies the type of the new object 01879 01880 NewObject - Returns true if the object is really new and false otherwise 01881 01882 Return Value: 01883 01884 An appropriate status value 01885 01886 --*/ 01887 01888 { 01889 POBJECT_HEADER_QUOTA_INFO QuotaInfo; 01890 ULONG NonPagedPoolCharge; 01891 ULONG PagedPoolCharge; 01892 01893 // 01894 // Get a pointer to the quota block for this object 01895 // 01896 01897 QuotaInfo = OBJECT_HEADER_TO_QUOTA_INFO( ObjectHeader ); 01898 01899 *NewObject = FALSE; 01900 01901 // 01902 // If the object is new then we have work to do otherwise 01903 // we'll return with NewObject set to false 01904 // 01905 01906 if (ObjectHeader->Flags & OB_FLAG_NEW_OBJECT) { 01907 01908 // 01909 // Say the object now isn't new 01910 // 01911 01912 ObjectHeader->Flags &= ~OB_FLAG_NEW_OBJECT; 01913 01914 // 01915 // If there does exist a quota info structure for this 01916 // object then calculate what our charge should be from 01917 // the information stored in that structure 01918 // 01919 01920 if (QuotaInfo != NULL) { 01921 01922 PagedPoolCharge = QuotaInfo->PagedPoolCharge + 01923 QuotaInfo->SecurityDescriptorCharge; 01924 NonPagedPoolCharge = QuotaInfo->NonPagedPoolCharge; 01925 01926 } else { 01927 01928 // 01929 // There isn't any quota information so we're on our own 01930 // Paged pool charge is the default for the object plus 01931 // the security descriptor if present. Nonpaged pool charge 01932 // is the default for the object. 01933 // 01934 01935 PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge; 01936 01937 if (ObjectHeader->SecurityDescriptor != NULL) { 01938 01939 ObjectHeader->Flags |= OB_FLAG_DEFAULT_SECURITY_QUOTA; 01940 PagedPoolCharge += SE_DEFAULT_SECURITY_QUOTA; 01941 } 01942 01943 NonPagedPoolCharge = ObjectType->TypeInfo.DefaultNonPagedPoolCharge; 01944 } 01945 01946 // 01947 // Now charge for the quota and make sure it succeeds 01948 // 01949 01950 ObjectHeader->QuotaBlockCharged = (PVOID)PsChargeSharedPoolQuota( PsGetCurrentProcess(), 01951 PagedPoolCharge, 01952 NonPagedPoolCharge ); 01953 01954 if (ObjectHeader->QuotaBlockCharged == NULL) { 01955 01956 return STATUS_QUOTA_EXCEEDED; 01957 } 01958 01959 *NewObject = TRUE; 01960 } 01961 01962 return STATUS_SUCCESS; 01963 }

BOOLEAN ObpCheckObjectReference IN PVOID  Object,
IN OUT PACCESS_STATE  AccessState,
IN BOOLEAN  TypeMutexLocked,
IN KPROCESSOR_MODE  AccessMode,
OUT PNTSTATUS  AccessStatus
 

Definition at line 602 of file obse.c.

References FALSE, _OBJECT_TYPE_INITIALIZER::GenericMapping, NT_SUCCESS, NTSTATUS(), NULL, ObGetObjectSecurity(), OBJECT_TO_OBJECT_HEADER, ObpEnterObjectTypeMutex, ObpLeaveObjectTypeMutex, ObReleaseObjectSecurity(), PAGED_CODE, SeAccessCheck(), SeLockSubjectContext(), SeObjectReferenceAuditAlarm(), SeUnlockSubjectContext(), Status, TRUE, _OBJECT_HEADER::Type, and _OBJECT_TYPE::TypeInfo.

Referenced by ObReferenceObjectByName().

00612 : 00613 00614 The routine performs access validation on the passed object. The 00615 remaining desired access mask is extracted from the AccessState 00616 parameter and passes to the appropriate security routine to 00617 perform the access check. 00618 00619 If the access attempt is successful, SeAccessCheck returns a mask 00620 containing the granted accesses. The bits in this mask are turned 00621 on in the PreviouslyGrantedAccess field of the AccessState, and 00622 are turned off in the RemainingDesiredAccess field. 00623 00624 This routine differs from ObpCheckObjectAccess in that it calls 00625 a different audit routine. 00626 00627 Arguments: 00628 00629 Object - The object being examined. 00630 00631 AccessState - The ACCESS_STATE structure containing accumulated 00632 information about the current attempt to gain access to the object. 00633 00634 TypeMutexLocked - Indicates whether the type mutex for this object's 00635 type is locked. The type mutex is used to protect the object's 00636 security descriptor from being modified while it is being accessed. 00637 00638 AccessMode - The previous processor mode. 00639 00640 AccessStatus - Pointer to a variable to return the status code of the 00641 access attempt. In the case of failure this status code must be 00642 propagated back to the user. 00643 00644 00645 Return Value: 00646 00647 BOOLEAN - TRUE if access is allowed and FALSE otherwise 00648 00649 --*/ 00650 00651 { 00652 BOOLEAN AccessAllowed; 00653 ACCESS_MASK GrantedAccess = 0; 00654 BOOLEAN MemoryAllocated; 00655 PSECURITY_DESCRIPTOR SecurityDescriptor; 00656 NTSTATUS Status; 00657 POBJECT_HEADER ObjectHeader; 00658 POBJECT_TYPE ObjectType; 00659 PPRIVILEGE_SET Privileges = NULL; 00660 00661 PAGED_CODE(); 00662 00663 // 00664 // Map the object body to an object header and the 00665 // corresponding object type 00666 // 00667 00668 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 00669 ObjectType = ObjectHeader->Type; 00670 00671 // 00672 // If the caller does not have the object type locked 00673 // then lock it down 00674 // 00675 00676 if (!TypeMutexLocked) { 00677 00678 ObpEnterObjectTypeMutex( ObjectType ); 00679 } 00680 00681 // 00682 // Obtain the object's security descriptor 00683 // 00684 00685 Status = ObGetObjectSecurity( Object, 00686 &SecurityDescriptor, 00687 &MemoryAllocated ); 00688 00689 // 00690 // If we failed in getting the security descriptor then 00691 // put the object type lock back where it was and return 00692 // the error back to our caller 00693 // 00694 00695 if (!NT_SUCCESS( Status )) { 00696 00697 if (!TypeMutexLocked) { 00698 00699 ObpLeaveObjectTypeMutex( ObjectType ); 00700 } 00701 00702 *AccessStatus = Status; 00703 00704 return( FALSE ); 00705 } 00706 00707 // 00708 // Lock the caller's tokens until after auditing has been 00709 // performed. 00710 // 00711 00712 SeLockSubjectContext( &AccessState->SubjectSecurityContext ); 00713 00714 // 00715 // Do the access check, and if we have some privileges then 00716 // put those in the access state too. 00717 // 00718 00719 AccessAllowed = SeAccessCheck( SecurityDescriptor, 00720 &AccessState->SubjectSecurityContext, 00721 TRUE, // Tokens are locked 00722 AccessState->RemainingDesiredAccess, 00723 AccessState->PreviouslyGrantedAccess, 00724 &Privileges, 00725 &ObjectType->TypeInfo.GenericMapping, 00726 AccessMode, 00727 &GrantedAccess, 00728 AccessStatus ); 00729 00730 if (AccessAllowed) { 00731 00732 AccessState->PreviouslyGrantedAccess |= GrantedAccess; 00733 AccessState->RemainingDesiredAccess &= ~GrantedAccess; 00734 } 00735 00736 // 00737 // If we have a security descriptor then call the security routine 00738 // to audit this reference and then unlock the caller's token 00739 // 00740 00741 if ( SecurityDescriptor != NULL ) { 00742 00743 SeObjectReferenceAuditAlarm( &AccessState->OperationID, 00744 Object, 00745 SecurityDescriptor, 00746 &AccessState->SubjectSecurityContext, 00747 AccessState->RemainingDesiredAccess | AccessState->PreviouslyGrantedAccess, 00748 ((PAUX_ACCESS_DATA)(AccessState->AuxData))->PrivilegesUsed, 00749 AccessAllowed, 00750 AccessMode ); 00751 } 00752 00753 SeUnlockSubjectContext( &AccessState->SubjectSecurityContext ); 00754 00755 // 00756 // If the caller didn't have the object type locked then remove 00757 // our lock 00758 // 00759 00760 if (!TypeMutexLocked) { 00761 00762 ObpLeaveObjectTypeMutex( ObjectType ); 00763 } 00764 00765 // 00766 // Finally free the security descriptor 00767 // and return to our caller 00768 // 00769 00770 ObReleaseObjectSecurity( SecurityDescriptor, 00771 MemoryAllocated ); 00772 00773 return( AccessAllowed ); 00774 }

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
 

Definition at line 778 of file obse.c.

References FALSE, _OBJECT_TYPE_INITIALIZER::GenericMapping, NT_SUCCESS, NTSTATUS(), NULL, ObGetObjectSecurity(), OBJECT_TO_OBJECT_HEADER, ObpEnterObjectTypeMutex, ObpLeaveObjectTypeMutex, ObReleaseObjectSecurity(), PAGED_CODE, SeAccessCheck(), SeAppendPrivileges(), SeFastTraverseCheck(), SeFreePrivileges(), SeLockSubjectContext(), SeUnlockSubjectContext(), Status, TOKEN_IS_RESTRICTED, TRUE, _OBJECT_HEADER::Type, and _OBJECT_TYPE::TypeInfo.

Referenced by ObpLookupObjectName().

00789 : 00790 00791 This routine checks for traverse access to the given directory object. 00792 00793 Note that the contents of the AccessState structure are not 00794 modified, since it is assumed that this access check is incidental 00795 to another access operation. 00796 00797 Arguments: 00798 00799 DirectoryObject - The object body of the object being examined. 00800 00801 TraverseAccess - The desired access to the object, most likely DIRECTORY 00802 TRAVERSE access. 00803 00804 AccessState - Checks for traverse access will typically be incidental 00805 to some other access attempt. Information on the current state of 00806 that access attempt is required so that the constituent access 00807 attempts may be associated with each other in the audit log. 00808 This is an OPTIONAL parameter, in which case the call will 00809 success ONLY if the Directory Object grants World traverse 00810 access rights. 00811 00812 TypeMutexLocked - Indicates whether the type mutex for this object's 00813 type is locked. The type mutex is used to protect the object's 00814 security descriptor from being modified while it is being accessed. 00815 00816 PreviousMode - The previous processor mode. 00817 00818 AccessStatus - Pointer to a variable to return the status code of the 00819 access attempt. In the case of failure this status code must be 00820 propagated back to the user. 00821 00822 Return Value: 00823 00824 BOOLEAN - TRUE if access is allowed and FALSE otherwise. AccessStatus 00825 contains the status code to be passed back to the caller. It is not 00826 correct to simply pass back STATUS_ACCESS_DENIED, since this will have 00827 to change with the advent of mandatory access control. 00828 00829 --*/ 00830 00831 { 00832 BOOLEAN AccessAllowed; 00833 ACCESS_MASK GrantedAccess = 0; 00834 PSECURITY_DESCRIPTOR SecurityDescriptor; 00835 BOOLEAN MemoryAllocated; 00836 NTSTATUS Status; 00837 POBJECT_HEADER ObjectHeader; 00838 POBJECT_TYPE ObjectType; 00839 BOOLEAN SubjectContextLocked = FALSE; 00840 PPRIVILEGE_SET Privileges = NULL; 00841 00842 PAGED_CODE(); 00843 00844 // 00845 // Map the object body to an object header and corresponding 00846 // object type 00847 // 00848 00849 ObjectHeader = OBJECT_TO_OBJECT_HEADER( DirectoryObject ); 00850 ObjectType = ObjectHeader->Type; 00851 00852 // 00853 // If the caller hasn't locked down the object type then 00854 // lock it down now 00855 // 00856 00857 if (!TypeMutexLocked) { 00858 00859 ObpEnterObjectTypeMutex( ObjectType ); 00860 } 00861 00862 // 00863 // Obtain the object's security descriptor and make it was 00864 // successful 00865 // 00866 00867 Status = ObGetObjectSecurity( DirectoryObject, 00868 &SecurityDescriptor, 00869 &MemoryAllocated ); 00870 00871 if (!NT_SUCCESS( Status )) { 00872 00873 if (!TypeMutexLocked) { 00874 00875 ObpLeaveObjectTypeMutex( ObjectType ); 00876 } 00877 00878 *AccessStatus = Status; 00879 00880 return( FALSE ); 00881 } 00882 00883 // 00884 // Check to see if WORLD has TRAVERSE access, by seeing if the 00885 // token is restricted or the fast traverse check fails meaning 00886 // that the world does not have traverse access 00887 // 00888 00889 if (((AccessState->Flags & TOKEN_IS_RESTRICTED) != 0) 00890 00891 || 00892 00893 (!SeFastTraverseCheck( SecurityDescriptor, 00894 DIRECTORY_TRAVERSE, 00895 PreviousMode ))) { 00896 00897 // 00898 // SeFastTraverseCheck could be modified to tell us that 00899 // no one has any access to this directory. However, 00900 // we're going to have to fail this entire call if 00901 // that is the case, so we really don't need to worry 00902 // all that much about making it blindingly fast. 00903 // 00904 00905 if (ARGUMENT_PRESENT( AccessState )) { 00906 00907 // 00908 // The world does not have traverse access and we have 00909 // the client's access state so lock down the client's 00910 // token and then do the access check, appending privileges 00911 // if present. The access check will give the answer 00912 // we return back to our caller 00913 // 00914 00915 SeLockSubjectContext( &AccessState->SubjectSecurityContext ); 00916 00917 SubjectContextLocked = TRUE; 00918 00919 AccessAllowed = SeAccessCheck( SecurityDescriptor, 00920 &AccessState->SubjectSecurityContext, 00921 TRUE, // Tokens are locked 00922 TraverseAccess, 00923 0, 00924 &Privileges, 00925 &ObjectType->TypeInfo.GenericMapping, 00926 PreviousMode, 00927 &GrantedAccess, 00928 AccessStatus ); 00929 00930 if (Privileges != NULL) { 00931 00932 Status = SeAppendPrivileges( AccessState, 00933 Privileges ); 00934 00935 SeFreePrivileges( Privileges ); 00936 } 00937 } 00938 00939 } else { 00940 00941 // 00942 // At this point the world has traverse access 00943 // 00944 00945 AccessAllowed = TRUE; 00946 } 00947 00948 // 00949 // If the client's token is locked then now we can unlock it 00950 // 00951 // **** this should be able to move up into the preceding clause 00952 // where it is locked 00953 // 00954 00955 if ( SubjectContextLocked ) { 00956 00957 SeUnlockSubjectContext( &AccessState->SubjectSecurityContext ); 00958 } 00959 00960 // 00961 // If the caller did not lock the object type then we 00962 // now need to unlock it 00963 // 00964 00965 if (!TypeMutexLocked) { 00966 00967 ObpLeaveObjectTypeMutex( ObjectType ); 00968 } 00969 00970 // 00971 // Finally free the security descriptor 00972 // and then return to our caller 00973 // 00974 00975 ObReleaseObjectSecurity( SecurityDescriptor, 00976 MemoryAllocated ); 00977 00978 return( AccessAllowed ); 00979 }

BOOLEAN ObpCompareSecurityDescriptors IN PSECURITY_DESCRIPTOR  SD1,
IN PSECURITY_DESCRIPTOR  SD2
 

Definition at line 839 of file obsdata.c.

References Compare(), FALSE, and RtlLengthSecurityDescriptor().

Referenced by ObpLogSecurityDescriptor().

00846 : 00847 00848 Performs a byte by byte comparison of two self relative security 00849 descriptors to determine if they are identical. 00850 00851 Arguments: 00852 00853 SD1, SD2 - Security descriptors to be compared. 00854 00855 Return Value: 00856 00857 TRUE - They are the same. 00858 00859 FALSE - They are different. 00860 00861 --*/ 00862 00863 { 00864 ULONG Length1; 00865 ULONG Length2; 00866 ULONG Compare; 00867 00868 // 00869 // Calculating the length is pretty fast, see if we 00870 // can get away with doing only that. 00871 // 00872 00873 Length1 = RtlLengthSecurityDescriptor ( SD1 ); 00874 Length2 = RtlLengthSecurityDescriptor ( SD2 ); 00875 00876 if (Length1 != Length2) { 00877 00878 return( FALSE ); 00879 } 00880 00881 return (BOOLEAN)RtlEqualMemory ( SD1, SD2, Length1 ); 00882 }

PSECURITY_DESCRIPTOR_HEADER ObpCreateCacheEntry PSECURITY_DESCRIPTOR  InputSecurityDescriptor,
ULONG  FullHash
 

Definition at line 491 of file obsdata.c.

References ExAllocatePoolWithTag, _SECURITY_DESCRIPTOR_HEADER::FullHash, _SECURITY_DESCRIPTOR_HEADER::Link, NULL, PagedPool, _SECURITY_DESCRIPTOR_HEADER::RefCount, RtlLengthSecurityDescriptor(), and _SECURITY_DESCRIPTOR_HEADER::SecurityDescriptor.

Referenced by ObpLogSecurityDescriptor().

00498 : 00499 00500 Allocates and initializes a new cache entry. 00501 00502 Arguments: 00503 00504 InputSecurityDescriptor - The security descriptor to be cached. 00505 00506 FullHash - Full 32 bit hash of the security descriptor. 00507 00508 Return Value: 00509 00510 A pointer to the newly allocated cache entry, or NULL 00511 00512 --*/ 00513 00514 { 00515 00516 ULONG SecurityDescriptorLength; 00517 ULONG CacheEntrySize; 00518 PSECURITY_DESCRIPTOR_HEADER NewDescriptor; 00519 00520 // 00521 // Compute the size that we'll need to allocate. We need space for 00522 // the security descriptor cache minus the funny quad at the end and the 00523 // security descriptor itself. 00524 // 00525 00526 SecurityDescriptorLength = RtlLengthSecurityDescriptor ( InputSecurityDescriptor ); 00527 CacheEntrySize = SecurityDescriptorLength + (sizeof(SECURITY_DESCRIPTOR_HEADER) - sizeof( QUAD )); 00528 00529 // 00530 // Now allocate space for the cached entry 00531 // 00532 00533 NewDescriptor = ExAllocatePoolWithTag( PagedPool, CacheEntrySize, 'dSeS'); 00534 00535 if ( NewDescriptor == NULL ) { 00536 00537 return( NULL ); 00538 } 00539 00540 // 00541 // Fill the header, copy over the descriptor data, and return to our 00542 // caller 00543 // 00544 00545 NewDescriptor->RefCount = 1; 00546 NewDescriptor->FullHash = FullHash; 00547 NewDescriptor->Link.Flink = NULL; 00548 NewDescriptor->Link.Blink = NULL; 00549 00550 RtlCopyMemory( &NewDescriptor->SecurityDescriptor, 00551 InputSecurityDescriptor, 00552 SecurityDescriptorLength ); 00553 00554 return( NewDescriptor ); 00555 }

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 BOOLEAN  DirectoryLocked,
IN KPROCESSOR_MODE  AccessMode,
OUT PVOID *ReferencedNewObject  OPTIONAL,
OUT PHANDLE  Handle
 

Definition at line 2160 of file obhandle.c.

References _HANDLE_TABLE_ENTRY::CreatorBackTraceIndex, EncodeKernelHandle, ExCreateHandle(), FALSE, _HANDLE_TABLE_ENTRY::GrantedAccess, _HANDLE_TABLE_ENTRY::GrantedAccessIndex, Handle, KernelMode, KeStackAttachProcess(), KeUnstackDetachProcess(), NT_SUCCESS, NtGlobalFlag, NTSTATUS(), NULL, _HANDLE_TABLE_ENTRY::ObAttributes, ObCreateHandle, OBJ_AUDIT_OBJECT_CLOSE, OBJ_HANDLE_ATTRIBUTES, _HANDLE_TABLE_ENTRY::Object, OBJECT_TO_OBJECT_HEADER, ObpDecrementHandleCount(), ObpDecrPointerCount, ObpGetObjectTable, ObpIncrementHandleCount(), ObpIncrPointerCount, ObpKernelHandleTable, ObpLeaveRootDirectoryMutex, ObpValidateIrql, PAGED_CODE, PAUX_ACCESS_DATA, _EPROCESS::Pcb, _AUX_ACCESS_DATA::PrivilegesUsed, PsGetCurrentProcess, PsInitialSystemProcess, SeAuditHandleCreation(), SePrivilegeObjectAuditAlarm(), Status, TRUE, _OBJECT_HEADER::Type, _OBJECT_TYPE::TypeInfo, and _OBJECT_TYPE_INITIALIZER::ValidAccessMask.

Referenced by ObInsertObject(), ObOpenObjectByName(), and ObOpenObjectByPointer().

02175 : 02176 02177 This function creates a new handle to an existing object 02178 02179 Arguments: 02180 02181 OpenReason - The reason why we are doing this work 02182 02183 Object - A pointer to the body of the new object 02184 02185 ExpectedObjectType - Optionally Supplies the object type that 02186 the caller is expecting 02187 02188 AccessState - Supplies the access state for the handle requested 02189 by the caller 02190 02191 ObjectPointerBias - Optionally supplies a count of addition 02192 increments we do to the pointer count for the object 02193 02194 Attributes - Desired attributes for the handle 02195 02196 DirectoryLocked - Indicates if the root directory mutex is already held 02197 02198 AccessMode - Supplies the mode of the requestor. 02199 02200 ReferencedNewObject - Optionally receives a pointer to the body 02201 of the new object 02202 02203 Handle - Receives the new handle value 02204 02205 Return Value: 02206 02207 An appropriate status value 02208 02209 --*/ 02210 02211 { 02212 NTSTATUS Status; 02213 POBJECT_HEADER ObjectHeader; 02214 POBJECT_TYPE ObjectType; 02215 PVOID ObjectTable; 02216 HANDLE_TABLE_ENTRY ObjectTableEntry; 02217 HANDLE NewHandle; 02218 ACCESS_MASK DesiredAccess; 02219 ACCESS_MASK GrantedAccess; 02220 ULONG BiasCount; 02221 BOOLEAN AttachedToProcess = FALSE; 02222 BOOLEAN KernelHandle = FALSE; 02223 KAPC_STATE ApcState; 02224 02225 PAGED_CODE(); 02226 02227 ObpValidateIrql( "ObpCreateHandle" ); 02228 02229 // 02230 // Merge both the remaining desired access and the currently 02231 // granted access states into one mask 02232 // 02233 // **** why is this being done here and then later in the this 02234 // same routine. 02235 // 02236 02237 DesiredAccess = AccessState->RemainingDesiredAccess | 02238 AccessState->PreviouslyGrantedAccess; 02239 02240 // 02241 // Get a pointer to the object header and object type 02242 // 02243 02244 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 02245 ObjectType = ObjectHeader->Type; 02246 02247 // 02248 // If the object type isn't what was expected then 02249 // return an error to our caller, but first see if 02250 // we should release the directory mutex 02251 // 02252 02253 if ((ARGUMENT_PRESENT( ExpectedObjectType )) && 02254 (ObjectType != ExpectedObjectType )) { 02255 02256 if (DirectoryLocked) { 02257 02258 ObpLeaveRootDirectoryMutex(); 02259 } 02260 02261 return( STATUS_OBJECT_TYPE_MISMATCH ); 02262 } 02263 02264 // 02265 // Set the first ulong of the object table entry to point 02266 // back to the object header 02267 // 02268 02269 ObjectTableEntry.Object = ObjectHeader; 02270 02271 // 02272 // Now get a pointer to the object table for either the current process 02273 // of the kernel handle table 02274 // 02275 02276 if ((Attributes & OBJ_KERNEL_HANDLE) && (AccessMode == KernelMode)) { 02277 02278 ObjectTable = ObpKernelHandleTable; 02279 KernelHandle = TRUE; 02280 02281 // 02282 // Go to the system process if we have to 02283 // 02284 02285 if (PsGetCurrentProcess() != PsInitialSystemProcess) { 02286 KeStackAttachProcess (&PsInitialSystemProcess->Pcb, &ApcState); 02287 AttachedToProcess = TRUE; 02288 } 02289 02290 02291 } else { 02292 02293 ObjectTable = ObpGetObjectTable(); 02294 } 02295 02296 // 02297 // ObpIncrementHandleCount will perform access checking on the 02298 // object being opened as appropriate. 02299 // 02300 02301 Status = ObpIncrementHandleCount( OpenReason, 02302 PsGetCurrentProcess(), 02303 Object, 02304 ObjectType, 02305 AccessState, 02306 AccessMode, 02307 Attributes ); 02308 02309 if (AccessState->GenerateOnClose) { 02310 02311 Attributes |= OBJ_AUDIT_OBJECT_CLOSE; 02312 } 02313 02314 // 02315 // Or in some low order bits into the first ulong of the object 02316 // table entry 02317 // 02318 02319 ObjectTableEntry.ObAttributes |= (Attributes & OBJ_HANDLE_ATTRIBUTES); 02320 02321 // 02322 // Merge both the remaining desired access and the currently 02323 // granted access states into one mask and then compute 02324 // the granted access 02325 // 02326 02327 DesiredAccess = AccessState->RemainingDesiredAccess | 02328 AccessState->PreviouslyGrantedAccess; 02329 02330 GrantedAccess = DesiredAccess & 02331 (ObjectType->TypeInfo.ValidAccessMask | ACCESS_SYSTEM_SECURITY ); 02332 02333 // 02334 // Unlock the directory if it is locked and make sure 02335 // we've been successful so far 02336 // 02337 02338 if (DirectoryLocked) { 02339 02340 ObpLeaveRootDirectoryMutex(); 02341 } 02342 02343 if (!NT_SUCCESS( Status )) { 02344 02345 // 02346 // If we are attached to the system process then return 02347 // back to our caller 02348 // 02349 02350 if (AttachedToProcess) { 02351 KeUnstackDetachProcess(&ApcState); 02352 AttachedToProcess = FALSE; 02353 } 02354 02355 return( Status ); 02356 } 02357 02358 // 02359 // Bias the pointer count if that is what the caller wanted 02360 // 02361 02362 if (ARGUMENT_PRESENT( (PVOID)(ULONG_PTR)ObjectPointerBias )) { 02363 02364 BiasCount = ObjectPointerBias; 02365 02366 while (BiasCount--) { 02367 02368 ObpIncrPointerCount( ObjectHeader ); 02369 } 02370 } 02371 02372 // 02373 // Set the granted access mask in the object table entry (second ulong) 02374 // 02375 02376 #if i386 && !FPO 02377 02378 if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) { 02379 02380 ObjectTableEntry.GrantedAccessIndex = ObpComputeGrantedAccessIndex( GrantedAccess ); 02381 ObjectTableEntry.CreatorBackTraceIndex = RtlLogStackBackTrace(); 02382 02383 } else { 02384 02385 ObjectTableEntry.GrantedAccess = GrantedAccess; 02386 } 02387 02388 #else 02389 02390 ObjectTableEntry.GrantedAccess = GrantedAccess; 02391 02392 #endif // i386 && !FPO 02393 02394 // 02395 // Add this new object table entry to the object table for the process 02396 // 02397 02398 NewHandle = ExCreateHandle( ObjectTable, &ObjectTableEntry ); 02399 02400 // 02401 // If we didn't get a handle then cleanup after ourselves and return 02402 // the error to our caller 02403 // 02404 02405 if (NewHandle == NULL) { 02406 02407 if (ARGUMENT_PRESENT( (PVOID)(ULONG_PTR)ObjectPointerBias )) { 02408 02409 BiasCount = ObjectPointerBias; 02410 02411 while (BiasCount--) { 02412 02413 ObpDecrPointerCount( ObjectHeader ); 02414 } 02415 } 02416 02417 ObpDecrementHandleCount( PsGetCurrentProcess(), 02418 ObjectHeader, 02419 ObjectType, 02420 GrantedAccess ); 02421 02422 // 02423 // If we are attached to the system process then return 02424 // back to our caller 02425 // 02426 02427 if (AttachedToProcess) { 02428 KeUnstackDetachProcess(&ApcState); 02429 AttachedToProcess = FALSE; 02430 } 02431 02432 return( STATUS_INSUFFICIENT_RESOURCES ); 02433 } 02434 02435 // 02436 // We have a new Ex style handle now make it an ob style handle and also 02437 // adjust for the kernel handle by setting the sign bit in the handle 02438 // value 02439 // 02440 02441 if (KernelHandle) { 02442 02443 NewHandle = EncodeKernelHandle( NewHandle ); 02444 } 02445 02446 *Handle = NewHandle; 02447 02448 // 02449 // If requested, generate audit messages to indicate that a new handle 02450 // has been allocated. 02451 // 02452 // This is the final security operation in the creation/opening of the 02453 // object. 02454 // 02455 02456 if ( AccessState->GenerateAudit ) { 02457 02458 SeAuditHandleCreation( AccessState, 02459 *Handle ); 02460 } 02461 02462 if (OpenReason == ObCreateHandle) { 02463 02464 PAUX_ACCESS_DATA AuxData = AccessState->AuxData; 02465 02466 if ( ( AuxData->PrivilegesUsed != NULL) && (AuxData->PrivilegesUsed->PrivilegeCount > 0) ) { 02467 02468 SePrivilegeObjectAuditAlarm( *Handle, 02469 &AccessState->SubjectSecurityContext, 02470 GrantedAccess, 02471 AuxData->PrivilegesUsed, 02472 TRUE, 02473 KeGetPreviousMode() ); 02474 } 02475 } 02476 02477 // 02478 // If the caller had a pointer bias and wanted the new reference object 02479 // then return that value 02480 // 02481 02482 if ((ARGUMENT_PRESENT( (PVOID)(ULONG_PTR)ObjectPointerBias )) && 02483 (ARGUMENT_PRESENT( ReferencedNewObject ))) { 02484 02485 *ReferencedNewObject = Object; 02486 } 02487 02488 // 02489 // If we are attached to the system process then return 02490 // back to our caller 02491 // 02492 02493 if (AttachedToProcess) { 02494 KeUnstackDetachProcess(&ApcState); 02495 AttachedToProcess = FALSE; 02496 } 02497 02498 // 02499 // And return to our caller 02500 // 02501 02502 return( STATUS_SUCCESS ); 02503 }

VOID ObpCreateSymbolicLinkName POBJECT_SYMBOLIC_LINK  SymbolicLink  ) 
 

Definition at line 1015 of file oblink.c.

References CREATE_SYMBOLIC_LINK, _OBJECT_DIRECTORY::DeviceMap, _OBJECT_HEADER_NAME_INFO::Directory, _OBJECT_SYMBOLIC_LINK::DosDeviceDriveIndex, L, _OBJECT_HEADER_NAME_INFO::Name, NULL, OBJECT_HEADER_TO_NAME_INFO, OBJECT_TO_OBJECT_HEADER, ObpProcessDosDeviceSymbolicLink(), and RtlUpcaseUnicodeChar().

Referenced by ObInsertObject().

01021 : 01022 01023 This routine does extra processing for symbolic links being created in 01024 object directories controlled by device map objects. 01025 01026 This processing consists of: 01027 01028 1. Determine if the name of the symbolic link is a drive letter. 01029 If so, then we will need to update the drive type in the 01030 associated device map object. 01031 01032 2. Process the link target, trying to resolve it into a pointer to 01033 an object other than a object directory object. All object 01034 directories traversed must grant world traverse access other 01035 wise we bail out. If we successfully find a non object 01036 directory object, then reference the object pointer and store it 01037 in the symbolic link object, along with a remaining string if 01038 any. ObpLookupObjectName will used this cache object pointer to 01039 short circuit the name lookup directly to the cached object's 01040 parse routine. For any object directory objects traversed along 01041 the way, increment their symbolic link SymbolicLinkUsageCount 01042 field. This field is used whenever an object directory is 01043 deleted or its security is changed such that it no longer grants 01044 world traverse access. In either case, if the field is non-zero 01045 we walk all the symbolic links and resnap them. 01046 01047 Arguments: 01048 01049 SymbolicLink - pointer to symbolic link object being created. 01050 01051 Return Value: 01052 01053 None. 01054 01055 --*/ 01056 01057 { 01058 POBJECT_HEADER ObjectHeader; 01059 POBJECT_HEADER_NAME_INFO NameInfo; 01060 WCHAR DosDeviceDriveLetter; 01061 ULONG DosDeviceDriveIndex; 01062 01063 // 01064 // Now see if this symbolic link is being created in an object directory 01065 // controlled by a device map object. Since we are only called from 01066 // NtCreateSymbolicLinkObject, after the handle to this symbolic link 01067 // has been created but before it is returned to the caller the handle can't 01068 // be closed while we are executing, unless via a random close, 01069 // So no need to hold the type specific mutex while we look at the name. 01070 // 01071 01072 ObjectHeader = OBJECT_TO_OBJECT_HEADER( SymbolicLink ); 01073 NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader ); 01074 01075 if ((NameInfo == NULL) || 01076 (NameInfo->Directory == NULL) || 01077 (NameInfo->Directory->DeviceMap == NULL)) { 01078 01079 return; 01080 } 01081 01082 // 01083 // Here if we are creating a symbolic link in an object directory controlled 01084 // by a device map object. See if this is a drive letter definition. If so 01085 // calculate the drive letter index and remember in the symbolic link object. 01086 // 01087 01088 DosDeviceDriveIndex = 0; 01089 01090 if ((NameInfo->Name.Length == (2 * sizeof( WCHAR ))) && 01091 (NameInfo->Name.Buffer[ 1 ] == L':')) { 01092 01093 DosDeviceDriveLetter = RtlUpcaseUnicodeChar( NameInfo->Name.Buffer[ 0 ] ); 01094 01095 if ((DosDeviceDriveLetter >= L'A') && (DosDeviceDriveLetter <= L'Z')) { 01096 01097 DosDeviceDriveIndex = DosDeviceDriveLetter - L'A'; 01098 DosDeviceDriveIndex += 1; 01099 01100 SymbolicLink->DosDeviceDriveIndex = DosDeviceDriveIndex; 01101 } 01102 } 01103 01104 // 01105 // Now traverse the target path seeing if we can snap the link now. 01106 // 01107 01108 ObpProcessDosDeviceSymbolicLink( SymbolicLink, CREATE_SYMBOLIC_LINK ); 01109 01110 return; 01111 }

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
 

Definition at line 2507 of file obhandle.c.

References _HANDLE_TABLE_ENTRY::CreatorBackTraceIndex, EncodeKernelHandle, ExCreateHandle(), FALSE, _HANDLE_TABLE_ENTRY::GrantedAccess, _HANDLE_TABLE_ENTRY::GrantedAccessIndex, Handle, KernelMode, KeStackAttachProcess(), KeUnstackDetachProcess(), NT_SUCCESS, NtGlobalFlag, NTSTATUS(), NULL, _HANDLE_TABLE_ENTRY::ObAttributes, OBJ_HANDLE_ATTRIBUTES, _HANDLE_TABLE_ENTRY::Object, OBJECT_TO_OBJECT_HEADER, ObpDecrementHandleCount(), ObpDecrPointerCount, ObpGetObjectTable, ObpIncrementUnnamedHandleCount(), ObpIncrPointerCount, ObpKernelHandleTable, ObpValidateIrql, PAGED_CODE, _EPROCESS::Pcb, PsGetCurrentProcess, PsInitialSystemProcess, Status, TRUE, _OBJECT_HEADER::Type, _OBJECT_TYPE::TypeInfo, and _OBJECT_TYPE_INITIALIZER::ValidAccessMask.

Referenced by ObInsertObject().

02519 : 02520 02521 This function creates a new unnamed handle for an existing object 02522 02523 Arguments: 02524 02525 Object - A pointer to the body of the new object 02526 02527 DesiredAccess - Supplies the access mask being requsted 02528 02529 ObjectPointerBias - Optionally supplies a count of addition 02530 increments we do to the pointer count for the object 02531 02532 Attributes - Desired attributes for the handle 02533 02534 AccessMode - Supplies the mode of the requestor. 02535 02536 ReferencedNewObject - Optionally receives a pointer to the body 02537 of the new object 02538 02539 Handle - Receives the new handle value 02540 02541 Return Value: 02542 02543 An appropriate status value 02544 02545 --*/ 02546 02547 { 02548 NTSTATUS Status; 02549 POBJECT_HEADER ObjectHeader; 02550 POBJECT_TYPE ObjectType; 02551 PVOID ObjectTable; 02552 HANDLE_TABLE_ENTRY ObjectTableEntry; 02553 HANDLE NewHandle; 02554 ULONG BiasCount; 02555 ACCESS_MASK GrantedAccess; 02556 BOOLEAN AttachedToProcess = FALSE; 02557 BOOLEAN KernelHandle = FALSE; 02558 KAPC_STATE ApcState; 02559 02560 PAGED_CODE(); 02561 02562 ObpValidateIrql( "ObpCreateUnnamedHandle" ); 02563 02564 // 02565 // Get the object header and type for the new object 02566 // 02567 02568 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 02569 ObjectType = ObjectHeader->Type; 02570 02571 // 02572 // Set the first ulong of the object table entry to point 02573 // to the object header and then or in the low order attribute 02574 // bits 02575 // 02576 02577 ObjectTableEntry.Object = ObjectHeader; 02578 02579 ObjectTableEntry.ObAttributes |= (Attributes & OBJ_HANDLE_ATTRIBUTES); 02580 02581 // 02582 // Now get a pointer to the object table for either the current process 02583 // of the kernel handle table 02584 // 02585 02586 if ((Attributes & OBJ_KERNEL_HANDLE) && (AccessMode == KernelMode)) { 02587 02588 ObjectTable = ObpKernelHandleTable; 02589 KernelHandle = TRUE; 02590 02591 // 02592 // Go to the system process if we have to 02593 // 02594 02595 if (PsGetCurrentProcess() != PsInitialSystemProcess) { 02596 KeStackAttachProcess (&PsInitialSystemProcess->Pcb, &ApcState); 02597 AttachedToProcess = TRUE; 02598 } 02599 02600 } else { 02601 02602 ObjectTable = ObpGetObjectTable(); 02603 } 02604 02605 // 02606 // Increment the handle count, this routine also does the access 02607 // check if necessary 02608 // 02609 02610 Status = ObpIncrementUnnamedHandleCount( &DesiredAccess, 02611 PsGetCurrentProcess(), 02612 Object, 02613 ObjectType, 02614 AccessMode, 02615 Attributes ); 02616 02617 02618 GrantedAccess = DesiredAccess & 02619 (ObjectType->TypeInfo.ValidAccessMask | ACCESS_SYSTEM_SECURITY ); 02620 02621 if (!NT_SUCCESS( Status )) { 02622 02623 // 02624 // If we are attached to the system process then return 02625 // back to our caller 02626 // 02627 02628 if (AttachedToProcess) { 02629 KeUnstackDetachProcess(&ApcState); 02630 AttachedToProcess = FALSE; 02631 } 02632 02633 return( Status ); 02634 } 02635 02636 // 02637 // Bias the pointer count if that is what the caller wanted 02638 // 02639 02640 if (ARGUMENT_PRESENT( (PVOID)(ULONG_PTR)ObjectPointerBias )) { 02641 02642 BiasCount = ObjectPointerBias; 02643 02644 while (BiasCount--) { 02645 02646 ObpIncrPointerCount( ObjectHeader ); 02647 } 02648 } 02649 02650 // 02651 // Set the granted access mask in the object table entry (second ulong) 02652 // 02653 02654 #if i386 && !FPO 02655 02656 if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) { 02657 02658 ObjectTableEntry.GrantedAccessIndex = ObpComputeGrantedAccessIndex( GrantedAccess ); 02659 ObjectTableEntry.CreatorBackTraceIndex = RtlLogStackBackTrace(); 02660 02661 } else { 02662 02663 ObjectTableEntry.GrantedAccess = GrantedAccess; 02664 } 02665 02666 #else 02667 02668 ObjectTableEntry.GrantedAccess = GrantedAccess; 02669 02670 #endif // i386 && !FPO 02671 02672 // 02673 // Add this new object table entry to the object table for the process 02674 // 02675 02676 NewHandle = ExCreateHandle( ObjectTable, &ObjectTableEntry ); 02677 02678 // 02679 // If we didn't get a handle then cleanup after ourselves and return 02680 // the error to our caller 02681 // 02682 02683 if (NewHandle == NULL) { 02684 02685 if (ARGUMENT_PRESENT( (PVOID)(ULONG_PTR)ObjectPointerBias )) { 02686 02687 BiasCount = ObjectPointerBias; 02688 02689 while (BiasCount--) { 02690 02691 ObpDecrPointerCount( ObjectHeader ); 02692 } 02693 } 02694 02695 ObpDecrementHandleCount( PsGetCurrentProcess(), 02696 ObjectHeader, 02697 ObjectType, 02698 GrantedAccess ); 02699 02700 // 02701 // If we are attached to the system process then return 02702 // back to our caller 02703 // 02704 02705 if (AttachedToProcess) { 02706 KeUnstackDetachProcess(&ApcState); 02707 AttachedToProcess = FALSE; 02708 } 02709 02710 return( STATUS_INSUFFICIENT_RESOURCES ); 02711 } 02712 02713 // 02714 // We have a new Ex style handle now make it an ob style handle and also 02715 // adjust for the kernel handle by setting the sign bit in the handle 02716 // value 02717 // 02718 02719 if (KernelHandle) { 02720 02721 NewHandle = EncodeKernelHandle( NewHandle ); 02722 } 02723 02724 *Handle = NewHandle; 02725 02726 // 02727 // If the caller had a pointer bias and wanted the new reference object 02728 // then return that value 02729 // 02730 02731 if ((ARGUMENT_PRESENT( (PVOID)(ULONG_PTR)ObjectPointerBias )) && 02732 (ARGUMENT_PRESENT( ReferencedNewObject ))) { 02733 02734 *ReferencedNewObject = Object; 02735 } 02736 02737 // 02738 // If we are attached to the system process then return 02739 // back to our caller 02740 // 02741 02742 if (AttachedToProcess) { 02743 KeUnstackDetachProcess(&ApcState); 02744 AttachedToProcess = FALSE; 02745 } 02746 02747 return( STATUS_SUCCESS ); 02748 }

VOID ObpDecrementHandleCount PEPROCESS  Process,
POBJECT_HEADER  ObjectHeader,
POBJECT_TYPE  ObjectType,
ACCESS_MASK  GrantedAccess
 

Definition at line 1967 of file obhandle.c.

References ASSERT, _OBJECT_HEADER::Body, _OBJECT_TYPE_INITIALIZER::CloseProcedure, _OBJECT_HANDLE_COUNT_DATABASE::CountEntries, FALSE, _OBJECT_HEADER::Flags, _OBJECT_HANDLE_COUNT_ENTRY::HandleCount, _OBJECT_HEADER::HandleCount, _OBJECT_HEADER_HANDLE_INFO::HandleCountDataBase, _OBJECT_HANDLE_COUNT_DATABASE::HandleCountEntries, _OBJECT_TYPE_INITIALIZER::MaintainHandleCount, NULL, OB_FLAG_EXCLUSIVE_OBJECT, OB_FLAG_SINGLE_HANDLE_ENTRY, OBJECT_HEADER_TO_CREATOR_INFO, OBJECT_HEADER_TO_HANDLE_INFO, OBJECT_HEADER_TO_QUOTA_INFO, ObpBeginTypeSpecificCallOut, ObpDecrHandleCount, ObpDeleteNameCheck(), ObpEndTypeSpecificCallOut, ObpEnterObjectTypeMutex, ObpLeaveObjectTypeMutex, PAGED_CODE, _OBJECT_HANDLE_COUNT_ENTRY::Process, _OBJECT_HEADER_HANDLE_INFO::SingleEntry, _OBJECT_TYPE::TotalNumberOfHandles, TRUE, _OBJECT_TYPE::TypeInfo, and _OBJECT_HEADER_CREATOR_INFO::TypeList.

Referenced by NtClose(), NtDuplicateObject(), ObpCreateHandle(), and ObpCreateUnnamedHandle().

01976 : 01977 01978 This procedure decrements the handle count for the specified object 01979 01980 Arguments: 01981 01982 Process - Supplies the process where the handle existed 01983 01984 ObjectHeader - Supplies a pointer to the object header for the object 01985 01986 ObjectType - Supplies a type of the object 01987 01988 GrantedAccess - Supplies the current access mask to the object 01989 01990 Return Value: 01991 01992 None. 01993 01994 --*/ 01995 01996 { 01997 POBJECT_HEADER_HANDLE_INFO HandleInfo; 01998 POBJECT_HANDLE_COUNT_DATABASE HandleCountDataBase; 01999 POBJECT_HANDLE_COUNT_ENTRY HandleCountEntry; 02000 POBJECT_HEADER_CREATOR_INFO CreatorInfo; 02001 PVOID Object; 02002 ULONG CountEntries; 02003 ULONG ProcessHandleCount; 02004 ULONG SystemHandleCount; 02005 BOOLEAN HandleCountIsZero; 02006 02007 PAGED_CODE(); 02008 02009 ObpEnterObjectTypeMutex( ObjectType ); 02010 02011 Object = (PVOID)&ObjectHeader->Body; 02012 02013 SystemHandleCount = ObjectHeader->HandleCount; 02014 ProcessHandleCount = 0; 02015 02016 // 02017 // Decrement the handle count and it was one and it 02018 // was an exclusive object then zero out the exclusive 02019 // process 02020 // 02021 02022 HandleCountIsZero = ObpDecrHandleCount( ObjectHeader ); 02023 02024 if ( HandleCountIsZero && 02025 (ObjectHeader->Flags & OB_FLAG_EXCLUSIVE_OBJECT)) { 02026 02027 OBJECT_HEADER_TO_QUOTA_INFO( ObjectHeader )->ExclusiveProcess = NULL; 02028 } 02029 02030 if ( HandleCountIsZero ) { 02031 02032 CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO( ObjectHeader ); 02033 02034 // 02035 // If there is a creator info record and we are on the list 02036 // for the object type then remove this object from the list 02037 // 02038 02039 if (CreatorInfo != NULL && !IsListEmpty( &CreatorInfo->TypeList )) { 02040 02041 RemoveEntryList( &CreatorInfo->TypeList ); 02042 02043 InitializeListHead( &CreatorInfo->TypeList ); 02044 } 02045 } 02046 02047 // 02048 // If the object maintains a handle count database then 02049 // search through the handle database and decrement 02050 // the necessary information 02051 // 02052 02053 if (ObjectType->TypeInfo.MaintainHandleCount) { 02054 02055 HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO( ObjectHeader ); 02056 02057 // 02058 // Check if there is a single handle entry, then it better 02059 // be ours 02060 // 02061 02062 if (ObjectHeader->Flags & OB_FLAG_SINGLE_HANDLE_ENTRY) { 02063 02064 ASSERT(HandleInfo->SingleEntry.Process == Process); 02065 ASSERT(HandleInfo->SingleEntry.HandleCount > 0); 02066 02067 ProcessHandleCount = HandleInfo->SingleEntry.HandleCount--; 02068 HandleCountEntry = &HandleInfo->SingleEntry; 02069 02070 } else { 02071 02072 // 02073 // Otherwise search the database for a process match 02074 // 02075 02076 HandleCountDataBase = HandleInfo->HandleCountDataBase; 02077 02078 if (HandleCountDataBase != NULL) { 02079 02080 CountEntries = HandleCountDataBase->CountEntries; 02081 HandleCountEntry = &HandleCountDataBase->HandleCountEntries[ 0 ]; 02082 02083 while (CountEntries) { 02084 02085 if ((HandleCountEntry->HandleCount != 0) && 02086 (HandleCountEntry->Process == Process)) { 02087 02088 ProcessHandleCount = HandleCountEntry->HandleCount--; 02089 02090 break; 02091 } 02092 02093 HandleCountEntry++; 02094 CountEntries--; 02095 } 02096 } 02097 } 02098 02099 // 02100 // Now if the process is giving up all handles to the object 02101 // then zero out the handle count entry. For a single handle 02102 // entry this is just the single entry in the header handle info 02103 // structure 02104 // 02105 02106 if (ProcessHandleCount == 1) { 02107 02108 HandleCountEntry->Process = NULL; 02109 HandleCountEntry->HandleCount = 0; 02110 } 02111 } 02112 02113 // 02114 // If the Object Type has a Close Procedure, then release the type 02115 // mutex before calling it, and then call ObpDeleteNameCheck without 02116 // the mutex held. 02117 // 02118 02119 if (ObjectType->TypeInfo.CloseProcedure) { 02120 02121 KIRQL SaveIrql; 02122 02123 ObpLeaveObjectTypeMutex( ObjectType ); 02124 02125 ObpBeginTypeSpecificCallOut( SaveIrql ); 02126 02127 (*ObjectType->TypeInfo.CloseProcedure)( Process, 02128 Object, 02129 GrantedAccess, 02130 ProcessHandleCount, 02131 SystemHandleCount ); 02132 02133 ObpEndTypeSpecificCallOut( SaveIrql, "Close", ObjectType, Object ); 02134 02135 ObpDeleteNameCheck( Object, FALSE ); 02136 02137 } else { 02138 02139 // 02140 // If there is no Close Procedure, then just call ObpDeleteNameCheck 02141 // with the mutex held. 02142 // 02143 // The following call will release the type mutex 02144 // 02145 02146 ObpDeleteNameCheck( Object, TRUE ); 02147 } 02148 02149 ObpEnterObjectTypeMutex( ObjectType ); 02150 02151 ObjectType->TotalNumberOfHandles -= 1; 02152 02153 ObpLeaveObjectTypeMutex( ObjectType ); 02154 02155 return; 02156 }

BOOLEAN ObpDeleteDirectoryEntry IN POBJECT_DIRECTORY  Directory  ) 
 

Definition at line 1009 of file obdir.c.

References _OBJECT_DIRECTORY_ENTRY::ChainLink, Directory(), ExFreePool(), FALSE, NULL, and TRUE.

Referenced by ObInsertObject(), and ObpDeleteNameCheck().

01015 : 01016 01017 This routine deletes the most recently found directory entry from 01018 the specified directory object. It will only succeed after a 01019 successful ObpLookupDirectoryEntry call. 01020 01021 Arguments: 01022 01023 Directory - Supplies the directory being modified 01024 01025 Return Value: 01026 01027 TRUE if the deletion succeeded and FALSE otherwise 01028 01029 --*/ 01030 01031 { 01032 POBJECT_DIRECTORY_ENTRY *HeadDirectoryEntry; 01033 POBJECT_DIRECTORY_ENTRY DirectoryEntry; 01034 01035 // 01036 // Make sure we have a directory and that it has a found entry 01037 // 01038 01039 if (!Directory || !Directory->LookupFound) { 01040 01041 return( FALSE ); 01042 } 01043 01044 // 01045 // Also make sure that the lookup bucket is valid 01046 // 01047 01048 HeadDirectoryEntry = Directory->LookupBucket; 01049 01050 if (!HeadDirectoryEntry) { 01051 01052 return( FALSE ); 01053 } 01054 01055 DirectoryEntry = *HeadDirectoryEntry; 01056 01057 if (!DirectoryEntry) { 01058 01059 return( FALSE ); 01060 } 01061 01062 // 01063 // Unlink the entry from the head of the bucket chain and free the 01064 // memory for the entry. 01065 // 01066 01067 *HeadDirectoryEntry = DirectoryEntry->ChainLink; 01068 DirectoryEntry->ChainLink = NULL; 01069 01070 ExFreePool( DirectoryEntry ); 01071 01072 // 01073 // Return success 01074 // 01075 01076 return( TRUE ); 01077 }

VOID ObpDeleteNameCheck IN PVOID  Object,
IN BOOLEAN  TypeMutexHeld
 

Definition at line 1497 of file obref.c.

References DeleteSecurityDescriptor, _OBJECT_HEADER_NAME_INFO::Directory, ExFreePool(), _OBJECT_HEADER::Flags, _OBJECT_HEADER::HandleCount, _OBJECT_HEADER_NAME_INFO::Name, NULL, OB_FLAG_PERMANENT_OBJECT, ObDereferenceObject, OBJECT_HEADER_TO_NAME_INFO, OBJECT_TO_OBJECT_HEADER, ObpBeginTypeSpecificCallOut, ObpDeleteDirectoryEntry(), ObpDeleteSymbolicLinkName(), ObpEndTypeSpecificCallOut, ObpEnterObjectTypeMutex, ObpEnterRootDirectoryMutex, ObpLeaveObjectTypeMutex, ObpLeaveRootDirectoryMutex, ObpLookupDirectoryEntry(), ObpSymbolicLinkObjectType, ObpValidateIrql, PAGED_CODE, _OBJECT_TYPE_INITIALIZER::PoolType, _OBJECT_HEADER::SecurityDescriptor, _OBJECT_TYPE_INITIALIZER::SecurityProcedure, _OBJECT_TYPE_INITIALIZER::SecurityRequired, _OBJECT_HEADER::Type, and _OBJECT_TYPE::TypeInfo.

Referenced by ObInsertObject(), ObMakeTemporaryObject(), and ObpDecrementHandleCount().

01504 : 01505 01506 This routine removes the name of an object from its parent directory 01507 01508 Arguments: 01509 01510 Object - Supplies a pointer to the object body whose name is being checked 01511 01512 TypeMutexHeld - Indicates if the lock on object type is being held by the 01513 caller 01514 01515 Return Value: 01516 01517 None. 01518 01519 --*/ 01520 01521 { 01522 POBJECT_HEADER ObjectHeader; 01523 POBJECT_TYPE ObjectType; 01524 POBJECT_HEADER_NAME_INFO NameInfo; 01525 PVOID DirObject; 01526 01527 PAGED_CODE(); 01528 01529 ObpValidateIrql( "ObpDeleteNameCheck" ); 01530 01531 // 01532 // Translate the object body to an object header also get 01533 // the object type and name info if present 01534 // 01535 01536 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 01537 NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader ); 01538 ObjectType = ObjectHeader->Type; 01539 01540 // 01541 // If the lock is not held then get the lock now 01542 // 01543 01544 if (!TypeMutexHeld) { 01545 01546 ObpEnterObjectTypeMutex( ObjectType ); 01547 } 01548 01549 // 01550 // Make sure that the object has a zero handle count, has a non 01551 // empty name buffer, and is not a permanent object 01552 // 01553 01554 if ((ObjectHeader->HandleCount == 0) && 01555 (NameInfo != NULL) && 01556 (NameInfo->Name.Length != 0) && 01557 (!(ObjectHeader->Flags & OB_FLAG_PERMANENT_OBJECT))) { 01558 01559 // 01560 // Give up the lock on the object type and instead 01561 // get the lock on the object directories 01562 // 01563 01564 ObpLeaveObjectTypeMutex( ObjectType ); 01565 ObpEnterRootDirectoryMutex(); 01566 DirObject = NULL; 01567 01568 // 01569 // Check that the object we is still in the directory otherwise 01570 // then is nothing for us to remove 01571 // 01572 01573 if (Object == ObpLookupDirectoryEntry( NameInfo->Directory, 01574 &NameInfo->Name, 01575 0 )) { 01576 01577 // 01578 // Now reacquire the lock on the object type and 01579 // check check the handle count again. If it is still 01580 // zero then we can do the actual delete name operation 01581 // 01582 01583 ObpEnterObjectTypeMutex( ObjectType ); 01584 01585 if (ObjectHeader->HandleCount == 0) { 01586 01587 KIRQL SaveIrql; 01588 01589 // 01590 // Delete the directory entry 01591 // 01592 01593 ObpDeleteDirectoryEntry( NameInfo->Directory ); 01594 01595 // 01596 // If security is not required invoke the 01597 // security callback to delete the security descriptor 01598 // 01599 01600 if ( !ObjectType->TypeInfo.SecurityRequired ) { 01601 01602 ObpBeginTypeSpecificCallOut( SaveIrql ); 01603 01604 (ObjectType->TypeInfo.SecurityProcedure)( Object, 01605 DeleteSecurityDescriptor, 01606 NULL, 01607 NULL, 01608 NULL, 01609 &ObjectHeader->SecurityDescriptor, 01610 ObjectType->TypeInfo.PoolType, 01611 NULL ); 01612 01613 ObpEndTypeSpecificCallOut( SaveIrql, "Security", ObjectType, Object ); 01614 } 01615 01616 // 01617 // If this is a symbolic link object then we also need to 01618 // delete the symbolic link 01619 // 01620 01621 if (ObjectType == ObpSymbolicLinkObjectType) { 01622 01623 ObpDeleteSymbolicLinkName( (POBJECT_SYMBOLIC_LINK)Object ); 01624 } 01625 01626 // 01627 // Free the name buffer and zero out the name data fields 01628 // 01629 01630 ExFreePool( NameInfo->Name.Buffer ); 01631 01632 NameInfo->Name.Buffer = NULL; 01633 NameInfo->Name.Length = 0; 01634 NameInfo->Name.MaximumLength = 0; 01635 01636 DirObject = NameInfo->Directory; 01637 NameInfo->Directory = NULL; 01638 } 01639 01640 ObpLeaveObjectTypeMutex( ObjectType ); 01641 } 01642 01643 ObpLeaveRootDirectoryMutex(); 01644 01645 // 01646 // If there is a directory object for the name then decrement 01647 // its reference count for it and for the object 01648 // 01649 01650 if (DirObject != NULL) { 01651 01652 ObDereferenceObject( DirObject ); 01653 ObDereferenceObject( Object ); 01654 } 01655 01656 } else { 01657 01658 // 01659 // Otherwise don't do any work but simply release the object type 01660 // lock and return to our caller 01661 // 01662 01663 ObpLeaveObjectTypeMutex( ObjectType ); 01664 } 01665 01666 return; 01667 }

VOID ObpDeleteSymbolicLink IN PVOID  Object  ) 
 

Definition at line 904 of file oblink.c.

References ExFreePool(), _OBJECT_SYMBOLIC_LINK::LinkTarget, NULL, and PAGED_CODE.

Referenced by ObInitSystem().

00910 : 00911 00912 This routine is called when a reference to a symbolic link goes to zero. 00913 Its job is to clean up the memory used to the symbolic link string 00914 00915 Arguments: 00916 00917 Object - Supplies a pointer to the symbolic link object being deleted 00918 00919 Return Value: 00920 00921 None. 00922 00923 --*/ 00924 00925 { 00926 POBJECT_SYMBOLIC_LINK SymbolicLink = (POBJECT_SYMBOLIC_LINK)Object; 00927 00928 PAGED_CODE(); 00929 00930 // 00931 // The only cleaning up we need to do is to free the link target 00932 // buffer 00933 // 00934 00935 if (SymbolicLink->LinkTarget.Buffer != NULL) { 00936 00937 ExFreePool( SymbolicLink->LinkTarget.Buffer ); 00938 } 00939 00940 SymbolicLink->LinkTarget.Buffer = NULL; 00941 00942 // 00943 // And return to our caller 00944 // 00945 00946 return; 00947 }

VOID ObpDeleteSymbolicLinkName POBJECT_SYMBOLIC_LINK  SymbolicLink  ) 
 

Definition at line 951 of file oblink.c.

References DELETE_SYMBOLIC_LINK, _OBJECT_SYMBOLIC_LINK::LinkTargetObject, NULL, ObDereferenceObject, ObpEnterRootDirectoryMutex, ObpLeaveRootDirectoryMutex, ObpProcessDosDeviceSymbolicLink(), and ObReferenceObject.

Referenced by ObpDeleteNameCheck().

00957 : 00958 00959 This routine delete the symbolic from the system 00960 00961 Arguments: 00962 00963 SymbolicLink - Supplies a pointer to the object body for the symbolic 00964 link object to delete 00965 00966 Return Value: 00967 00968 None. 00969 00970 --*/ 00971 00972 { 00973 PVOID CapturedLinkTargetObject; 00974 00975 CapturedLinkTargetObject = NULL; 00976 00977 // 00978 // Lock the root directory mutex while we look at the target path to 00979 // prevent names from disappearing out from under us. Also protects 00980 // against collisions with NtCreateSymbolicLink 00981 // 00982 00983 ObpEnterRootDirectoryMutex(); 00984 00985 // 00986 // Capture the link target object and referenced one more time 00987 // to avoid destroying while the RootDirectoryMutex is hold 00988 // 00989 00990 CapturedLinkTargetObject = SymbolicLink->LinkTargetObject; 00991 00992 if (CapturedLinkTargetObject != NULL) { 00993 00994 ObReferenceObject(CapturedLinkTargetObject); 00995 } 00996 00997 ObpProcessDosDeviceSymbolicLink( SymbolicLink, DELETE_SYMBOLIC_LINK ); 00998 00999 ObpLeaveRootDirectoryMutex(); 01000 01001 // 01002 // Remove the extra-reference for the link target object 01003 // 01004 01005 if (CapturedLinkTargetObject != NULL) { 01006 01007 ObDereferenceObject(CapturedLinkTargetObject); 01008 } 01009 01010 return; 01011 }

VOID ObpDereferenceSecurityDescriptor PSECURITY_DESCRIPTOR  SecurityDescriptor  ) 
 

Definition at line 700 of file obsdata.c.

References ASSERT, _SECURITY_DESCRIPTOR_HEADER::FullHash, ObpAcquireDescriptorCacheWriteLock(), ObpDestroySecurityDescriptorHeader(), ObpReleaseDescriptorCacheLock(), ObPrint, _SECURITY_DESCRIPTOR_HEADER::RefCount, and SD_TO_SD_HEADER.

Referenced by ObDeassignSecurity(), ObReleaseObjectSecurity(), and ObSetSecurityDescriptorInfo().

00706 : 00707 00708 Decrements the refcount of a cached security descriptor 00709 00710 Arguments: 00711 00712 SecurityDescriptor - Points to a cached security descriptor 00713 00714 Return Value: 00715 00716 None. 00717 00718 --*/ 00719 00720 { 00721 PSECURITY_DESCRIPTOR_HEADER SecurityDescriptorHeader; 00722 00723 // 00724 // Lock the security descriptor cache and get a pointer 00725 // to the security descriptor header 00726 // 00727 00728 ObpAcquireDescriptorCacheWriteLock(); 00729 00730 SecurityDescriptorHeader = SD_TO_SD_HEADER( SecurityDescriptor ); 00731 00732 // 00733 // Do some debug work 00734 // 00735 00736 ObPrint( SHOW_REFERENCES, ("Dereferencing SecurityDescriptor %x, hash %lx, refcount = %d \n", SecurityDescriptor, SecurityDescriptorHeader->FullHash,SecurityDescriptorHeader->RefCount)); 00737 00738 ASSERT(SecurityDescriptorHeader->RefCount != 0); 00739 00740 // 00741 // Decrement the ref count and if it is now zero then 00742 // we can completely remove this entry from the cache 00743 // 00744 00745 if (--SecurityDescriptorHeader->RefCount == 0) { 00746 00747 ObpDestroySecurityDescriptorHeader( SecurityDescriptorHeader ); 00748 } 00749 00750 // 00751 // Unlock the security descriptor cache and return to our caller 00752 // 00753 00754 ObpReleaseDescriptorCacheLock(); 00755 }

VOID ObpDestroySecurityDescriptorHeader IN PSECURITY_DESCRIPTOR_HEADER  Header  ) 
 

Definition at line 759 of file obsdata.c.

References ASSERT, ExFreePool(), Header, NULL, ObPrint, and ObsSecurityDescriptorCache.

Referenced by ObpDereferenceSecurityDescriptor().

00765 : 00766 00767 Frees a cached security descriptor and unlinks it from the chain. 00768 00769 Arguments: 00770 00771 Header - Pointer to a security descriptor header (cached security 00772 descriptor) 00773 00774 Return Value: 00775 00776 None. 00777 00778 --*/ 00779 00780 { 00781 PLIST_ENTRY Forward; 00782 PLIST_ENTRY Rear; 00783 UCHAR SmallHash; 00784 00785 ASSERT ( Header->RefCount == 0 ); 00786 00787 #if OB_DIAGNOSTICS_ENABLED 00788 00789 ObsTotalCacheEntries--; 00790 00791 #endif 00792 00793 ObPrint( SHOW_STATISTICS, ("ObsTotalCacheEntries = %d \n",ObsTotalCacheEntries)); 00794 00795 // 00796 // Unlink the cached security descriptor from its linked list and 00797 // from the small hash table if it was at the head of the list 00798 // 00799 // **** this should all be rewritten to use the regular set of 00800 // link list macros 00801 // 00802 00803 SmallHash = (UCHAR)Header->FullHash; 00804 00805 Forward = Header->Link.Flink; 00806 Rear = Header->Link.Blink; 00807 00808 if ( Forward != NULL ) { 00809 00810 Forward->Blink = Rear; 00811 } 00812 00813 if ( Rear != NULL ) { 00814 00815 Rear->Flink = Forward; 00816 00817 } else { 00818 00819 // 00820 // if Rear is NULL, we're deleting the head of the list 00821 // 00822 00823 ObsSecurityDescriptorCache[SmallHash] = Forward; 00824 } 00825 00826 ObPrint( SHOW_HEADER_FREE, ("Freeing memory at %x \n",Header)); 00827 00828 // 00829 // Now return the cached descriptor to pool and return to our caller 00830 // 00831 00832 ExFreePool( Header ); 00833 00834 return; 00835 }

VOID FASTCALL ObpFreeObject IN PVOID  Object  ) 
 

Definition at line 1098 of file obcreate.c.

References DbgPrint, _OBJECT_TYPE_INITIALIZER::DefaultNonPagedPoolCharge, _OBJECT_TYPE_INITIALIZER::DefaultPagedPoolCharge, ExFreePool(), ExFreePoolWithTag, _OBJECT_HEADER_HANDLE_INFO::HandleCountDataBase, _OBJECT_HEADER_NAME_INFO::Name, _OBJECT_TYPE::Name, _OBJECT_HEADER_QUOTA_INFO::NonPagedPoolCharge, NULL, OB_FLAG_DEFAULT_SECURITY_QUOTA, OB_FLAG_NEW_OBJECT, OB_FLAG_SINGLE_HANDLE_ENTRY, OBJECT_HEADER_TO_CREATOR_INFO, OBJECT_HEADER_TO_HANDLE_INFO, OBJECT_HEADER_TO_NAME_INFO, OBJECT_HEADER_TO_QUOTA_INFO, OBJECT_TO_OBJECT_HEADER, ObpFreeObjectCreateInformation, PAGED_CODE, _OBJECT_HEADER_QUOTA_INFO::PagedPoolCharge, PROTECTED_POOL, PsReturnSharedPoolQuota(), SE_DEFAULT_SECURITY_QUOTA, _OBJECT_HEADER_QUOTA_INFO::SecurityDescriptorCharge, _OBJECT_TYPE::TotalNumberOfObjects, _OBJECT_HEADER::Type, and _OBJECT_TYPE::TypeInfo.

Referenced by ObCreateObject(), and ObpRemoveObjectRoutine().

01104 : 01105 01106 This routine undoes ObpAllocateObject. It returns the object back to free pool. 01107 01108 Arguments: 01109 01110 Object - Supplies a pointer to the body of the object being freed. 01111 01112 Return Value: 01113 01114 None. 01115 01116 --*/ 01117 01118 { 01119 POBJECT_HEADER ObjectHeader; 01120 POBJECT_TYPE ObjectType; 01121 POBJECT_HEADER_QUOTA_INFO QuotaInfo; 01122 POBJECT_HEADER_HANDLE_INFO HandleInfo; 01123 POBJECT_HEADER_NAME_INFO NameInfo; 01124 POBJECT_HEADER_CREATOR_INFO CreatorInfo; 01125 PVOID FreeBuffer; 01126 ULONG NonPagedPoolCharge; 01127 ULONG PagedPoolCharge; 01128 01129 PAGED_CODE(); 01130 01131 // 01132 // Get the address of the object header. 01133 // 01134 01135 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 01136 ObjectType = ObjectHeader->Type; 01137 01138 // 01139 // Now from the header determine the start of the allocation. We need 01140 // to backup based on what precedes the header. The order is very 01141 // important and must be the inverse of that used by ObpAllocateObject 01142 // 01143 01144 FreeBuffer = ObjectHeader; 01145 01146 CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO( ObjectHeader ); 01147 01148 if (CreatorInfo != NULL) { 01149 01150 FreeBuffer = CreatorInfo; 01151 } 01152 01153 NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader ); 01154 01155 if (NameInfo != NULL) { 01156 01157 FreeBuffer = NameInfo; 01158 } 01159 01160 HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO( ObjectHeader ); 01161 01162 if (HandleInfo != NULL) { 01163 01164 FreeBuffer = HandleInfo; 01165 } 01166 01167 QuotaInfo = OBJECT_HEADER_TO_QUOTA_INFO( ObjectHeader ); 01168 01169 if (QuotaInfo != NULL) { 01170 01171 FreeBuffer = QuotaInfo; 01172 } 01173 01174 #if DBG 01175 01176 // 01177 // On a checked build echo out frees 01178 // 01179 01180 if (ObpShowAllocAndFree) { 01181 01182 DbgPrint( "OB: Free %lx (%lx) - Type: %wZ\n", ObjectHeader, ObjectHeader, &ObjectType->Name ); 01183 } 01184 #endif 01185 01186 // 01187 // Decrement the number of objects of this type 01188 // 01189 01190 ObjectType->TotalNumberOfObjects -= 1; 01191 01192 // 01193 // Check where we were in the object initialization phase. This 01194 // flag really only tests if we have charged quota for this object. 01195 // This is because the object create info and the quota block charged 01196 // are unioned together. 01197 // 01198 01199 if (ObjectHeader->Flags & OB_FLAG_NEW_OBJECT) { 01200 01201 if (ObjectHeader->ObjectCreateInfo != NULL) { 01202 01203 ObpFreeObjectCreateInformation( ObjectHeader->ObjectCreateInfo ); 01204 01205 ObjectHeader->ObjectCreateInfo = NULL; 01206 } 01207 01208 } else { 01209 01210 if (ObjectHeader->QuotaBlockCharged != NULL) { 01211 01212 if (QuotaInfo != NULL) { 01213 01214 PagedPoolCharge = QuotaInfo->PagedPoolCharge + 01215 QuotaInfo->SecurityDescriptorCharge; 01216 01217 NonPagedPoolCharge = QuotaInfo->NonPagedPoolCharge; 01218 01219 } else { 01220 01221 PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge; 01222 01223 if (ObjectHeader->Flags & OB_FLAG_DEFAULT_SECURITY_QUOTA ) { 01224 01225 PagedPoolCharge += SE_DEFAULT_SECURITY_QUOTA; 01226 } 01227 01228 NonPagedPoolCharge = ObjectType->TypeInfo.DefaultNonPagedPoolCharge; 01229 } 01230 01231 PsReturnSharedPoolQuota( ObjectHeader->QuotaBlockCharged, 01232 PagedPoolCharge, 01233 NonPagedPoolCharge ); 01234 } 01235 } 01236 01237 if ((HandleInfo != NULL) && 01238 ((ObjectHeader->Flags & OB_FLAG_SINGLE_HANDLE_ENTRY) == 0)) { 01239 01240 // 01241 // If a handle database has been allocated, then free the memory. 01242 // 01243 01244 ExFreePool( HandleInfo->HandleCountDataBase ); 01245 01246 HandleInfo->HandleCountDataBase = NULL; 01247 } 01248 01249 // 01250 // If a name string buffer has been allocated, then free the memory. 01251 // 01252 01253 if (NameInfo != NULL && NameInfo->Name.Buffer != NULL) { 01254 01255 ExFreePool( NameInfo->Name.Buffer ); 01256 01257 NameInfo->Name.Buffer = NULL; 01258 } 01259 01260 // 01261 // Trash type field so we don't get far if we attempt to 01262 // use a stale object pointer to this object. 01263 // 01264 // Sundown Note: trash it by zero-extended it. 01265 // sign-extension will create a valid kernel address. 01266 01267 01268 ObjectHeader->Type = UIntToPtr(0xBAD0B0B0); 01269 ExFreePoolWithTag( FreeBuffer, 01270 (ObjectType == NULL ? 'TjbO' : ObjectType->Key) | 01271 PROTECTED_POOL ); 01272 01273 return; 01274 }

VOID FASTCALL ObpFreeObjectNameBuffer IN PUNICODE_STRING  ObjectName  ) 
 

Referenced by ObCreateObject(), ObOpenObjectByName(), and ObReferenceObjectByName().

ULONG ObpHashBuffer PVOID  Data,
ULONG  Length
 

Definition at line 253 of file obsdata.c.

References Buffer.

Referenced by ObpHashSecurityDescriptor().

00260 : 00261 00262 Hashes a buffer into a 32 bit value 00263 00264 Arguments: 00265 00266 Data - Buffer containing the data to be hashed. 00267 00268 Length - The length in bytes of the buffer 00269 00270 00271 Return Value: 00272 00273 ULONG - a 32 bit hash value. 00274 00275 --*/ 00276 00277 { 00278 PCHAR Buffer; 00279 ULONG Result = 0; 00280 LONG i; 00281 00282 Buffer = (PCHAR)Data; 00283 00284 for (i = 0; i <= (LONG)((Length-3)-sizeof(ULONG)); i++) { 00285 00286 ULONG Tmp; 00287 00288 Tmp = *((ULONG UNALIGNED *)(Buffer + i)); 00289 Result += Tmp; 00290 } 00291 00292 return( Result ); 00293 }

ULONG ObpHashSecurityDescriptor PSECURITY_DESCRIPTOR  SecurityDescriptor  ) 
 

Definition at line 182 of file obsdata.c.

References Dacl, FALSE, Group, NTSTATUS(), NULL, ObpHashBuffer(), Owner, RtlGetDaclSecurityDescriptor(), RtlGetGroupSecurityDescriptor(), RtlGetOwnerSecurityDescriptor(), RtlGetSaclSecurityDescriptor(), RtlLengthSid(), and Status.

Referenced by ObpLogSecurityDescriptor().

00188 : 00189 00190 Hashes a security descriptor to a 32 bit value 00191 00192 Arguments: 00193 00194 SecurityDescriptor - Provides the security descriptor to be hashed 00195 00196 Return Value: 00197 00198 ULONG - a 32 bit hash value. 00199 00200 --*/ 00201 00202 { 00203 PSID Owner = NULL; 00204 PSID Group = NULL; 00205 00206 PACL Dacl; 00207 PACL Sacl; 00208 00209 ULONG Hash = 0; 00210 BOOLEAN Junk; 00211 NTSTATUS Status; 00212 BOOLEAN DaclPresent = FALSE; 00213 BOOLEAN SaclPresent = FALSE; 00214 PISECURITY_DESCRIPTOR sd; 00215 00216 // 00217 // Cast the actually opaque security descriptor into something 00218 // that we can decipher 00219 // 00220 00221 sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 00222 00223 Status = RtlGetOwnerSecurityDescriptor( sd, &Owner, &Junk ); 00224 Status = RtlGetGroupSecurityDescriptor( sd, &Group, &Junk ); 00225 Status = RtlGetDaclSecurityDescriptor( sd, &DaclPresent, &Dacl, &Junk ); 00226 Status = RtlGetSaclSecurityDescriptor( sd, &SaclPresent, &Sacl, &Junk ); 00227 00228 if ( Owner != NULL ) { 00229 00230 Hash = ObpHashBuffer( Owner, RtlLengthSid( Owner )); 00231 } 00232 00233 if ( Group != NULL ) { 00234 00235 Hash += ObpHashBuffer( Group, RtlLengthSid( Group)); 00236 } 00237 00238 if ( DaclPresent && (Dacl != NULL)) { 00239 00240 Hash += ObpHashBuffer( Dacl, Dacl->AclSize); 00241 } 00242 00243 if ( SaclPresent && (Sacl != NULL)) { 00244 00245 Hash += ObpHashBuffer( Sacl, Sacl->AclSize); 00246 } 00247 00248 return( Hash ); 00249 }

NTSTATUS ObpIncrementHandleCount OB_OPEN_REASON  OpenReason,
PEPROCESS  Process,
PVOID  Object,
POBJECT_TYPE  ObjectType,
PACCESS_STATE AccessState  OPTIONAL,
KPROCESSOR_MODE  AccessMode,
ULONG  Attributes
 

Definition at line 1232 of file obhandle.c.

References _OBJECT_TYPE_INITIALIZER::CloseProcedure, EXCEPTION_EXECUTE_HANDLER, FALSE, _OBJECT_HEADER::Flags, GENERIC_ACCESS, _OBJECT_TYPE_INITIALIZER::GenericMapping, _OBJECT_HEADER::HandleCount, _OBJECT_TYPE::HighWaterNumberOfHandles, _OBJECT_TYPE_INITIALIZER::MaintainHandleCount, NT_SUCCESS, NTSTATUS(), NULL, OB_FLAG_EXCLUSIVE_OBJECT, ObCheckObjectAccess(), ObCreateHandle, ObDuplicateHandle, OBJECT_HEADER_TO_CREATOR_INFO, OBJECT_HEADER_TO_EXCLUSIVE_PROCESS, OBJECT_HEADER_TO_QUOTA_INFO, OBJECT_TO_OBJECT_HEADER, ObOpenHandle, ObpBeginTypeSpecificCallOut, ObpChargeQuotaForObject(), ObpDecrHandleCount, ObpEndTypeSpecificCallOut, ObpEnterObjectTypeMutex, ObpIncrementHandleDataBase(), ObpIncrHandleCount, ObpLeaveObjectTypeMutex, ObpValidateIrql, _OBJECT_TYPE_INITIALIZER::OpenProcedure, PAGED_CODE, PsGetCurrentProcess, RtlMapGenericMask(), SeAppendPrivileges(), SePrivilegeCheck(), SePrivilegedServiceAuditAlarm(), SeSecurityPrivilege, Status, _OBJECT_TYPE::TotalNumberOfHandles, TRUE, _OBJECT_TYPE::TypeInfo, _OBJECT_HEADER_CREATOR_INFO::TypeList, _OBJECT_TYPE::TypeList, and VOID().

Referenced by NtDuplicateObject(), ObDupHandleProcedure(), and ObpCreateHandle().

01244 : 01245 01246 Increments the count of number of handles to the given object. 01247 01248 If the object is being opened or created, access validation and 01249 auditing will be performed as appropriate. 01250 01251 Arguments: 01252 01253 OpenReason - Supplies the reason the handle count is being incremented. 01254 01255 Process - Pointer to the process in which the new handle will reside. 01256 01257 Object - Supplies a pointer to the body of the object. 01258 01259 ObjectType - Supplies the type of the object. 01260 01261 AccessState - Optional parameter supplying the current accumulated 01262 security information describing the attempt to access the object. 01263 01264 AccessMode - Supplies the mode of the requestor. 01265 01266 Attributes - Desired attributes for the handle 01267 01268 Return Value: 01269 01270 An appropriate status value 01271 01272 --*/ 01273 01274 { 01275 NTSTATUS Status; 01276 ULONG ProcessHandleCount; 01277 BOOLEAN ExclusiveHandle; 01278 POBJECT_HEADER_CREATOR_INFO CreatorInfo; 01279 POBJECT_HEADER_QUOTA_INFO QuotaInfo; 01280 POBJECT_HEADER ObjectHeader; 01281 BOOLEAN HasPrivilege = FALSE; 01282 PRIVILEGE_SET Privileges; 01283 BOOLEAN NewObject; 01284 BOOLEAN HoldObjectTypeMutex = FALSE; 01285 01286 PAGED_CODE(); 01287 01288 ObpValidateIrql( "ObpIncrementHandleCount" ); 01289 01290 // 01291 // Get a pointer to the object header 01292 // 01293 01294 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 01295 01296 // 01297 // Charge the user quota for the object 01298 // 01299 01300 Status = ObpChargeQuotaForObject( ObjectHeader, ObjectType, &NewObject ); 01301 01302 if (!NT_SUCCESS( Status )) { 01303 01304 return Status; 01305 } 01306 01307 ObpEnterObjectTypeMutex( ObjectType ); 01308 HoldObjectTypeMutex = TRUE; 01309 01310 try { 01311 01312 ExclusiveHandle = FALSE; 01313 01314 // 01315 // Check if the caller wants exlusive access and if so then 01316 // make sure the attributes and header flags match up correctly 01317 // 01318 01319 if (Attributes & OBJ_EXCLUSIVE) { 01320 01321 if ((Attributes & OBJ_INHERIT) || 01322 ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE_OBJECT) == 0)) { 01323 01324 Status = STATUS_INVALID_PARAMETER; 01325 leave; 01326 } 01327 01328 if (((OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) == NULL) && 01329 (ObjectHeader->HandleCount != 0)) 01330 01331 || 01332 01333 ((OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != NULL) && 01334 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != PsGetCurrentProcess()))) { 01335 01336 Status = STATUS_ACCESS_DENIED; 01337 leave; 01338 } 01339 01340 ExclusiveHandle = TRUE; 01341 01342 // 01343 // The user doesn't want exclusive access so now check to make sure 01344 // the attriutes and header flags match up correctly 01345 // 01346 01347 } else if ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE_OBJECT) && 01348 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != NULL)) { 01349 01350 Status = STATUS_ACCESS_DENIED; 01351 leave; 01352 } 01353 01354 // 01355 // If handle count going from zero to one for an existing object that 01356 // maintains a handle count database, but does not have an open procedure 01357 // just a close procedure, then fail the call as they are trying to 01358 // reopen an object by pointer and the close procedure will not know 01359 // that the object has been 'recreated' 01360 // 01361 01362 if ((ObjectHeader->HandleCount == 0) && 01363 (!NewObject) && 01364 (ObjectType->TypeInfo.MaintainHandleCount) && 01365 (ObjectType->TypeInfo.OpenProcedure == NULL) && 01366 (ObjectType->TypeInfo.CloseProcedure != NULL)) { 01367 01368 Status = STATUS_UNSUCCESSFUL; 01369 leave; 01370 } 01371 01372 if ((OpenReason == ObOpenHandle) || 01373 ((OpenReason == ObDuplicateHandle) && ARGUMENT_PRESENT(AccessState))) { 01374 01375 // 01376 // Perform Access Validation to see if we can open this 01377 // (already existing) object. 01378 // 01379 01380 if (!ObCheckObjectAccess( Object, 01381 AccessState, 01382 TRUE, 01383 AccessMode, 01384 &Status )) { 01385 01386 leave; 01387 } 01388 01389 } else if ((OpenReason == ObCreateHandle)) { 01390 01391 // 01392 // We are creating a new instance of this object type. 01393 // A total of three audit messages may be generated: 01394 // 01395 // 1 - Audit the attempt to create an instance of this 01396 // object type. 01397 // 01398 // 2 - Audit the successful creation. 01399 // 01400 // 3 - Audit the allocation of the handle. 01401 // 01402 01403 // 01404 // At this point, the RemainingDesiredAccess field in 01405 // the AccessState may still contain either Generic access 01406 // types, or MAXIMUM_ALLOWED. We will map the generics 01407 // and substitute GenericAll for MAXIMUM_ALLOWED. 01408 // 01409 01410 if ( AccessState->RemainingDesiredAccess & MAXIMUM_ALLOWED ) { 01411 01412 AccessState->RemainingDesiredAccess &= ~MAXIMUM_ALLOWED; 01413 AccessState->RemainingDesiredAccess |= GENERIC_ALL; 01414 } 01415 01416 if ((GENERIC_ACCESS & AccessState->RemainingDesiredAccess) != 0) { 01417 01418 RtlMapGenericMask( &AccessState->RemainingDesiredAccess, 01419 &ObjectType->TypeInfo.GenericMapping ); 01420 } 01421 01422 // 01423 // Since we are creating the object, we can give any access the caller 01424 // wants. The only exception is ACCESS_SYSTEM_SECURITY, which requires 01425 // a privilege. 01426 // 01427 01428 if ( AccessState->RemainingDesiredAccess & ACCESS_SYSTEM_SECURITY ) { 01429 01430 // 01431 // We could use SeSinglePrivilegeCheck here, but it 01432 // captures the subject context again, and we don't 01433 // want to do that in this path for performance reasons. 01434 // 01435 01436 Privileges.PrivilegeCount = 1; 01437 Privileges.Control = PRIVILEGE_SET_ALL_NECESSARY; 01438 Privileges.Privilege[0].Luid = SeSecurityPrivilege; 01439 Privileges.Privilege[0].Attributes = 0; 01440 01441 HasPrivilege = SePrivilegeCheck( &Privileges, 01442 &AccessState->SubjectSecurityContext, 01443 KeGetPreviousMode() ); 01444 01445 if (!HasPrivilege) { 01446 01447 SePrivilegedServiceAuditAlarm ( NULL, 01448 &AccessState->SubjectSecurityContext, 01449 &Privileges, 01450 FALSE ); 01451 01452 Status = STATUS_PRIVILEGE_NOT_HELD; 01453 leave; 01454 } 01455 01456 AccessState->RemainingDesiredAccess &= ~ACCESS_SYSTEM_SECURITY; 01457 AccessState->PreviouslyGrantedAccess |= ACCESS_SYSTEM_SECURITY; 01458 01459 (VOID) SeAppendPrivileges( AccessState, 01460 &Privileges ); 01461 } 01462 01463 // 01464 // Get the objects creator info block and insert it on the 01465 // global list of objects for that type 01466 // 01467 01468 CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO( ObjectHeader ); 01469 01470 if (CreatorInfo != NULL) { 01471 01472 InsertTailList( &ObjectType->TypeList, &CreatorInfo->TypeList ); 01473 } 01474 } 01475 01476 if (ExclusiveHandle) { 01477 01478 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = Process; 01479 } 01480 01481 ObpIncrHandleCount( ObjectHeader ); 01482 ProcessHandleCount = 0; 01483 01484 // 01485 // If the object type wants us to keep try of the handle counts 01486 // then call our routine to do the work 01487 // 01488 01489 if (ObjectType->TypeInfo.MaintainHandleCount) { 01490 01491 Status = ObpIncrementHandleDataBase( ObjectHeader, 01492 Process, 01493 &ProcessHandleCount ); 01494 01495 if (!NT_SUCCESS(Status)) { 01496 // BUG BUG, We probably need more backout than this, NeillC 01497 ObpDecrHandleCount( ObjectHeader ); 01498 01499 leave; 01500 } 01501 } 01502 01503 // 01504 // Set our preliminary status now to success because 01505 // the call to the open procedure might change this 01506 // 01507 01508 Status = STATUS_SUCCESS; 01509 01510 // 01511 // If the object type has an open procedure 01512 // then invoke that procedure 01513 // 01514 01515 if (ObjectType->TypeInfo.OpenProcedure != NULL) { 01516 01517 KIRQL SaveIrql; 01518 01519 // 01520 // Leave the object type mutex when call the OpenProcedure. If an exception 01521 // while OpenProcedure the HoldObjectTypeMutex disable leaving the mutex 01522 // on finally block 01523 // 01524 01525 ObpLeaveObjectTypeMutex( ObjectType ); 01526 HoldObjectTypeMutex = FALSE; 01527 01528 ObpBeginTypeSpecificCallOut( SaveIrql ); 01529 01530 try { 01531 01532 (*ObjectType->TypeInfo.OpenProcedure)( OpenReason, 01533 Process, 01534 Object, 01535 AccessState ? 01536 AccessState->PreviouslyGrantedAccess : 01537 0, 01538 ProcessHandleCount ); 01539 01540 } except( EXCEPTION_EXECUTE_HANDLER ) { 01541 01542 Status = GetExceptionCode(); 01543 } 01544 01545 ObpEndTypeSpecificCallOut( SaveIrql, "Open", ObjectType, Object ); 01546 01547 // 01548 // Hold back the object type mutex and set the HoldObjectTypeMutex variable 01549 // to allow releasing the mutex while leaving this procedure 01550 // 01551 01552 ObpEnterObjectTypeMutex( ObjectType ); 01553 HoldObjectTypeMutex = TRUE; 01554 01555 if (!NT_SUCCESS(Status)) { 01556 01557 (VOID)ObpDecrHandleCount( ObjectHeader ); 01558 leave; 01559 } 01560 } 01561 01562 // 01563 // Do some simple bookkeeping for the handle counts 01564 // and then return to our caller 01565 // 01566 01567 ObjectType->TotalNumberOfHandles += 1; 01568 01569 if (ObjectType->TotalNumberOfHandles > ObjectType->HighWaterNumberOfHandles) { 01570 01571 ObjectType->HighWaterNumberOfHandles = ObjectType->TotalNumberOfHandles; 01572 } 01573 01574 } finally { 01575 01576 if ( HoldObjectTypeMutex ) { 01577 01578 ObpLeaveObjectTypeMutex( ObjectType ); 01579 } 01580 } 01581 01582 return( Status ); 01583 }

NTSTATUS ObpIncrementUnnamedHandleCount PACCESS_MASK  DesiredAccess,
PEPROCESS  Process,
PVOID  Object,
POBJECT_TYPE  ObjectType,
KPROCESSOR_MODE  AccessMode,
ULONG  Attributes
 

Definition at line 1587 of file obhandle.c.

References _OBJECT_TYPE_INITIALIZER::CloseProcedure, EXCEPTION_EXECUTE_HANDLER, FALSE, _OBJECT_HEADER::Flags, GENERIC_ACCESS, _OBJECT_TYPE_INITIALIZER::GenericMapping, _OBJECT_HEADER::HandleCount, _OBJECT_TYPE::HighWaterNumberOfHandles, _OBJECT_TYPE_INITIALIZER::MaintainHandleCount, NT_SUCCESS, NTSTATUS(), NULL, OB_FLAG_EXCLUSIVE_OBJECT, ObCreateHandle, OBJECT_HEADER_TO_CREATOR_INFO, OBJECT_HEADER_TO_EXCLUSIVE_PROCESS, OBJECT_HEADER_TO_QUOTA_INFO, OBJECT_TO_OBJECT_HEADER, ObpBeginTypeSpecificCallOut, ObpChargeQuotaForObject(), ObpDecrHandleCount, ObpEndTypeSpecificCallOut, ObpEnterObjectTypeMutex, ObpIncrementHandleDataBase(), ObpIncrHandleCount, ObpLeaveObjectTypeMutex, ObpValidateIrql, _OBJECT_TYPE_INITIALIZER::OpenProcedure, PAGED_CODE, PsGetCurrentProcess, RtlMapGenericMask(), Status, _OBJECT_TYPE::TotalNumberOfHandles, TRUE, _OBJECT_TYPE::TypeInfo, _OBJECT_HEADER_CREATOR_INFO::TypeList, _OBJECT_TYPE::TypeList, and VOID().

Referenced by ObpCreateUnnamedHandle().

01598 : 01599 01600 Increments the count of number of handles to the given object. 01601 01602 Arguments: 01603 01604 Desired Access - Supplies the desired access to the object and receives 01605 the assign access mask 01606 01607 Process - Pointer to the process in which the new handle will reside. 01608 01609 Object - Supplies a pointer to the body of the object. 01610 01611 ObjectType - Supplies the type of the object. 01612 01613 AccessMode - Supplies the mode of the requestor. 01614 01615 Attributes - Desired attributes for the handle 01616 01617 Return Value: 01618 01619 An appropriate status value 01620 01621 --*/ 01622 01623 { 01624 NTSTATUS Status; 01625 BOOLEAN ExclusiveHandle; 01626 POBJECT_HEADER_CREATOR_INFO CreatorInfo; 01627 POBJECT_HEADER_QUOTA_INFO QuotaInfo; 01628 POBJECT_HEADER ObjectHeader; 01629 BOOLEAN NewObject; 01630 ULONG ProcessHandleCount; 01631 BOOLEAN HoldObjectTypeMutex = FALSE; 01632 01633 PAGED_CODE(); 01634 01635 ObpValidateIrql( "ObpIncrementUnnamedHandleCount" ); 01636 01637 // 01638 // Get a pointer to the object header 01639 // 01640 01641 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 01642 01643 // 01644 // Charge the user quota for the object 01645 // 01646 01647 Status = ObpChargeQuotaForObject( ObjectHeader, ObjectType, &NewObject ); 01648 01649 if (!NT_SUCCESS( Status )) { 01650 01651 return Status; 01652 } 01653 01654 ObpEnterObjectTypeMutex( ObjectType ); 01655 HoldObjectTypeMutex = TRUE; 01656 01657 try { 01658 01659 ExclusiveHandle = FALSE; 01660 01661 // 01662 // Check if the caller wants exlusive access and if so then 01663 // make sure the attributes and header flags match up correctly 01664 // 01665 01666 if (Attributes & OBJ_EXCLUSIVE) { 01667 01668 if ((Attributes & OBJ_INHERIT) || 01669 ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE_OBJECT) == 0)) { 01670 01671 Status = STATUS_INVALID_PARAMETER; 01672 leave; 01673 } 01674 01675 if (((OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) == NULL) && 01676 (ObjectHeader->HandleCount != 0)) 01677 01678 || 01679 01680 ((OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != NULL) && 01681 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != PsGetCurrentProcess()))) { 01682 01683 Status = STATUS_ACCESS_DENIED; 01684 leave; 01685 } 01686 01687 ExclusiveHandle = TRUE; 01688 01689 // 01690 // The user doesn't want exclusive access so now check to make sure 01691 // the attriutes and header flags match up correctly 01692 // 01693 01694 } else if ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE_OBJECT) && 01695 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != NULL)) { 01696 01697 Status = STATUS_ACCESS_DENIED; 01698 leave; 01699 } 01700 01701 // 01702 // If handle count going from zero to one for an existing object that 01703 // maintains a handle count database, but does not have an open procedure 01704 // just a close procedure, then fail the call as they are trying to 01705 // reopen an object by pointer and the close procedure will not know 01706 // that the object has been 'recreated' 01707 // 01708 01709 if ((ObjectHeader->HandleCount == 0) && 01710 (!NewObject) && 01711 (ObjectType->TypeInfo.MaintainHandleCount) && 01712 (ObjectType->TypeInfo.OpenProcedure == NULL) && 01713 (ObjectType->TypeInfo.CloseProcedure != NULL)) { 01714 01715 Status = STATUS_UNSUCCESSFUL; 01716 01717 leave; 01718 } 01719 01720 // 01721 // If the user asked for the maximum allowed then remove the bit and 01722 // or in generic all access 01723 // 01724 01725 if ( *DesiredAccess & MAXIMUM_ALLOWED ) { 01726 01727 *DesiredAccess &= ~MAXIMUM_ALLOWED; 01728 *DesiredAccess |= GENERIC_ALL; 01729 } 01730 01731 // If the user asked for any generic bit then translate it to 01732 // someone more appropriate for the object type 01733 // 01734 01735 if ((GENERIC_ACCESS & *DesiredAccess) != 0) { 01736 01737 RtlMapGenericMask( DesiredAccess, 01738 &ObjectType->TypeInfo.GenericMapping ); 01739 } 01740 01741 // 01742 // Get a pointer to the creator info block for the object and insert 01743 // it on the global list of object for that type 01744 // 01745 01746 CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO( ObjectHeader ); 01747 01748 if (CreatorInfo != NULL) { 01749 01750 InsertTailList( &ObjectType->TypeList, &CreatorInfo->TypeList ); 01751 } 01752 01753 if (ExclusiveHandle) { 01754 01755 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = Process; 01756 } 01757 01758 ObpIncrHandleCount( ObjectHeader ); 01759 ProcessHandleCount = 0; 01760 01761 // 01762 // If the object type wants us to keep try of the handle counts 01763 // then call our routine to do the work 01764 // 01765 01766 if (ObjectType->TypeInfo.MaintainHandleCount) { 01767 01768 Status = ObpIncrementHandleDataBase( ObjectHeader, 01769 Process, 01770 &ProcessHandleCount ); 01771 01772 if (!NT_SUCCESS(Status)) { 01773 // BUG BUG, We probably need more backout than this, NeillC 01774 ObpDecrHandleCount( ObjectHeader ); 01775 leave; 01776 } 01777 } 01778 01779 // 01780 // Set our preliminary status now to success because 01781 // the call to the open procedure might change this 01782 // 01783 01784 Status = STATUS_SUCCESS; 01785 01786 // 01787 // If the object type has an open procedure 01788 // then invoke that procedure 01789 // 01790 01791 if (ObjectType->TypeInfo.OpenProcedure != NULL) { 01792 01793 KIRQL SaveIrql; 01794 01795 // 01796 // Leave the object type mutex when call the OpenProcedure. If an exception 01797 // while OpenProcedure the HoldObjectTypeMutex disable leaving the mutex 01798 // on finally block 01799 // 01800 01801 ObpLeaveObjectTypeMutex( ObjectType ); 01802 HoldObjectTypeMutex = FALSE; 01803 01804 ObpBeginTypeSpecificCallOut( SaveIrql ); 01805 01806 try { 01807 01808 (*ObjectType->TypeInfo.OpenProcedure)( ObCreateHandle, 01809 Process, 01810 Object, 01811 *DesiredAccess, 01812 ProcessHandleCount ); 01813 01814 } except( EXCEPTION_EXECUTE_HANDLER ) { 01815 01816 Status = GetExceptionCode(); 01817 } 01818 01819 ObpEndTypeSpecificCallOut( SaveIrql, "Open", ObjectType, Object ); 01820 01821 // 01822 // Hold back the object type mutex and set the HoldObjectTypeMutex variable 01823 // to allow releasing the mutex while leaving this procedure 01824 // 01825 01826 ObpEnterObjectTypeMutex( ObjectType ); 01827 HoldObjectTypeMutex = TRUE; 01828 01829 if (!NT_SUCCESS(Status)) { 01830 01831 (VOID)ObpDecrHandleCount( ObjectHeader ); 01832 leave; 01833 } 01834 } 01835 01836 // 01837 // Do some simple bookkeeping for the handle counts 01838 // and then return to our caller 01839 // 01840 01841 ObjectType->TotalNumberOfHandles += 1; 01842 01843 if (ObjectType->TotalNumberOfHandles > ObjectType->HighWaterNumberOfHandles) { 01844 01845 ObjectType->HighWaterNumberOfHandles = ObjectType->TotalNumberOfHandles; 01846 } 01847 01848 } finally { 01849 01850 if ( HoldObjectTypeMutex ) { 01851 01852 ObpLeaveObjectTypeMutex( ObjectType ); 01853 } 01854 } 01855 01856 return( Status ); 01857 }

NTSTATUS ObpInitSecurityDescriptorCache VOID   ) 
 

Definition at line 118 of file obsdata.c.

References ExAllocatePoolWithTag, ExFreePool(), ExInitializeResource, IF_OB_GLOBAL, NT_SUCCESS, NTSTATUS(), NULL, ObsSecurityDescriptorCache, ObsSecurityDescriptorCacheLock, PagedPool, SECURITY_DESCRIPTOR_CACHE_ENTRIES, Size, and Status.

Referenced by ObInitSystem().

00124 : 00125 00126 Allocates and initializes the globalSecurity Descriptor Cache 00127 00128 Arguments: 00129 00130 None 00131 00132 Return Value: 00133 00134 STATUS_SUCCESS on success, NTSTATUS on failure. 00135 00136 --*/ 00137 00138 { 00139 ULONG Size; 00140 NTSTATUS Status; 00141 00142 IF_OB_GLOBAL( BREAK_ON_INIT ) { 00143 00144 DbgBreakPoint(); 00145 } 00146 00147 // 00148 // Allocate the cache of pointers and zero it out 00149 // 00150 00151 Size = SECURITY_DESCRIPTOR_CACHE_ENTRIES * sizeof(PLIST_ENTRY); 00152 ObsSecurityDescriptorCache = ExAllocatePoolWithTag( PagedPool, Size, 'cCdS' ); 00153 00154 if (ObsSecurityDescriptorCache == NULL ) { 00155 00156 return( STATUS_INSUFFICIENT_RESOURCES ); 00157 } 00158 00159 RtlZeroMemory( ObsSecurityDescriptorCache, Size ); 00160 00161 // 00162 // Initialize the resource used to protect the security cache 00163 // 00164 00165 Status = ExInitializeResource ( &ObsSecurityDescriptorCacheLock ); 00166 00167 if ( !NT_SUCCESS(Status) ) { 00168 00169 ExFreePool( ObsSecurityDescriptorCache ); 00170 return( Status ); 00171 } 00172 00173 // 00174 // And return to our caller 00175 // 00176 00177 return( STATUS_SUCCESS ); 00178 }

BOOLEAN ObpInsertDirectoryEntry IN POBJECT_DIRECTORY  Directory,
IN PVOID  Object
 

Definition at line 903 of file obdir.c.

References _OBJECT_DIRECTORY_ENTRY::ChainLink, _OBJECT_HEADER_NAME_INFO::Directory, Directory(), ExAllocatePoolWithTag, FALSE, NULL, _OBJECT_DIRECTORY_ENTRY::Object, OBJECT_HEADER_TO_NAME_INFO, OBJECT_TO_OBJECT_HEADER, PagedPool, and TRUE.

Referenced by ObCreateObjectType(), ObInitSystem(), and ObpLookupObjectName().

00910 : 00911 00912 This routine will insert a new directory entry into a directory 00913 object. The directory must have already have been searched using 00914 ObpLookupDirectoryEntry because that routine sets the LookupBucket 00915 00916 Arguments: 00917 00918 Directory - Supplies the directory object being modified. This 00919 function assumes that we earlier did a lookup on the name 00920 that was successful or we just did an insertion 00921 00922 Object - Supplies the object to insert into the directory 00923 00924 Return Value: 00925 00926 TRUE if the object is inserted successfully and FALSE otherwise 00927 00928 --*/ 00929 00930 { 00931 POBJECT_DIRECTORY_ENTRY *HeadDirectoryEntry; 00932 POBJECT_DIRECTORY_ENTRY NewDirectoryEntry; 00933 POBJECT_HEADER_NAME_INFO NameInfo; 00934 00935 // 00936 // Make sure we have a directory and that the last search was 00937 // successful, meaning there is a lookupbuket 00938 // 00939 00940 if (!Directory || Directory->LookupFound) { 00941 00942 return( FALSE ); 00943 } 00944 00945 // 00946 // Also verify that we have a good lookupbucket 00947 // 00948 00949 HeadDirectoryEntry = Directory->LookupBucket; 00950 00951 if (!HeadDirectoryEntry) { 00952 00953 return( FALSE ); 00954 } 00955 00956 // 00957 // Translate the object into a name info record, and make sure 00958 // that the object has a name 00959 // 00960 00961 NameInfo = OBJECT_HEADER_TO_NAME_INFO( OBJECT_TO_OBJECT_HEADER( Object ) ); 00962 00963 if (NameInfo == NULL) { 00964 00965 return FALSE; 00966 } 00967 00968 // 00969 // Allocate memory for a new entry, and fail if not enough memory. 00970 // 00971 00972 NewDirectoryEntry = (POBJECT_DIRECTORY_ENTRY)ExAllocatePoolWithTag( PagedPool, 00973 sizeof( OBJECT_DIRECTORY_ENTRY ), 00974 'iDbO' ); 00975 00976 if (NewDirectoryEntry == NULL) { 00977 00978 return( FALSE ); 00979 } 00980 00981 // 00982 // Link the new entry into the chain at the insertion point. 00983 // This puts the new object right at the head of the current 00984 // hash bucket chain 00985 // 00986 00987 NewDirectoryEntry->ChainLink = *HeadDirectoryEntry; 00988 *HeadDirectoryEntry = NewDirectoryEntry; 00989 NewDirectoryEntry->Object = Object; 00990 00991 // 00992 // Point the object header back to the directory we just inserted 00993 // it into. 00994 // 00995 00996 NameInfo->Directory = Directory; 00997 00998 // 00999 // Return success. 01000 // 01001 01002 Directory->LookupFound = TRUE; 01003 01004 return( TRUE ); 01005 }

POBJECT_HANDLE_COUNT_ENTRY ObpInsertHandleCount POBJECT_HEADER  ObjectHeader  ) 
 

Definition at line 908 of file obhandle.c.

References _OBJECT_HANDLE_COUNT_DATABASE::CountEntries, ExAllocatePoolWithTag, ExFreePool(), _OBJECT_HEADER::Flags, _OBJECT_HEADER_HANDLE_INFO::HandleCountDataBase, _OBJECT_HANDLE_COUNT_DATABASE::HandleCountEntries, NULL, OB_FLAG_SINGLE_HANDLE_ENTRY, OBJECT_HEADER_TO_HANDLE_INFO, PAGED_CODE, PagedPool, and _OBJECT_HEADER_HANDLE_INFO::SingleEntry.

Referenced by ObpIncrementHandleDataBase().

00914 : 00915 00916 This function will increase the size of the handle database 00917 stored in the handle information of an object header. If 00918 necessary it will allocate new and free old handle databases. 00919 00920 This routine should not be called if there is already free 00921 space in the handle table. 00922 00923 Arguments: 00924 00925 ObjectHeader - The object whose handle count is being incremented 00926 00927 Return Value: 00928 00929 The pointer to the next free handle count entry within the 00930 handle database. 00931 00932 --*/ 00933 00934 { 00935 POBJECT_HEADER_HANDLE_INFO HandleInfo; 00936 POBJECT_HANDLE_COUNT_DATABASE OldHandleCountDataBase; 00937 POBJECT_HANDLE_COUNT_DATABASE NewHandleCountDataBase; 00938 POBJECT_HANDLE_COUNT_ENTRY FreeHandleCountEntry; 00939 ULONG CountEntries; 00940 ULONG OldSize; 00941 ULONG NewSize; 00942 OBJECT_HANDLE_COUNT_DATABASE SingleEntryDataBase; 00943 00944 PAGED_CODE(); 00945 00946 // 00947 // Check if the object has any handle information 00948 // 00949 00950 HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader); 00951 00952 if (HandleInfo == NULL) { 00953 00954 return NULL; 00955 } 00956 00957 // 00958 // The object does have some handle information. If it has 00959 // a single handle entry then we'll construct a local dummy 00960 // handle count database and come up with a new data base for 00961 // storing two entries. 00962 // 00963 00964 if (ObjectHeader->Flags & OB_FLAG_SINGLE_HANDLE_ENTRY) { 00965 00966 SingleEntryDataBase.CountEntries = 1; 00967 SingleEntryDataBase.HandleCountEntries[0] = HandleInfo->SingleEntry; 00968 00969 OldHandleCountDataBase = &SingleEntryDataBase; 00970 00971 OldSize = sizeof( SingleEntryDataBase ); 00972 00973 CountEntries = 2; 00974 00975 NewSize = sizeof(OBJECT_HANDLE_COUNT_DATABASE) + 00976 ((CountEntries - 1) * sizeof( OBJECT_HANDLE_COUNT_ENTRY )); 00977 00978 } else { 00979 00980 // 00981 // The object already has multiple handles so we reference the 00982 // current handle database, and compute a new size bumped by four 00983 // 00984 00985 OldHandleCountDataBase = HandleInfo->HandleCountDataBase; 00986 00987 CountEntries = OldHandleCountDataBase->CountEntries; 00988 00989 OldSize = sizeof(OBJECT_HANDLE_COUNT_DATABASE) + 00990 ((CountEntries - 1) * sizeof( OBJECT_HANDLE_COUNT_ENTRY)); 00991 00992 CountEntries += 4; 00993 00994 NewSize = sizeof(OBJECT_HANDLE_COUNT_DATABASE) + 00995 ((CountEntries - 1) * sizeof( OBJECT_HANDLE_COUNT_ENTRY)); 00996 } 00997 00998 // 00999 // Now allocate pool for the new handle database. 01000 // 01001 01002 NewHandleCountDataBase = ExAllocatePoolWithTag(PagedPool, NewSize,'dHbO'); 01003 01004 if (NewHandleCountDataBase == NULL) { 01005 01006 return NULL; 01007 } 01008 01009 // 01010 // Copy over the old database. Note that this might just copy our 01011 // local dummy entry for the single entry case 01012 // 01013 01014 RtlMoveMemory(NewHandleCountDataBase, OldHandleCountDataBase, OldSize); 01015 01016 // 01017 // If the previous mode was a single entry then remove that 01018 // indication otherwise free up with previous handle database 01019 // 01020 01021 if (ObjectHeader->Flags & OB_FLAG_SINGLE_HANDLE_ENTRY) { 01022 01023 ObjectHeader->Flags &= ~OB_FLAG_SINGLE_HANDLE_ENTRY; 01024 01025 } else { 01026 01027 ExFreePool( OldHandleCountDataBase ); 01028 } 01029 01030 // 01031 // Find the end of the new database that is used and zero out 01032 // the memory 01033 // 01034 01035 FreeHandleCountEntry = 01036 (POBJECT_HANDLE_COUNT_ENTRY)((PCHAR)NewHandleCountDataBase + OldSize); 01037 01038 RtlZeroMemory(FreeHandleCountEntry, NewSize - OldSize); 01039 01040 // 01041 // Set the new database to the proper entry count and put it 01042 // all in the object 01043 // 01044 01045 NewHandleCountDataBase->CountEntries = CountEntries; 01046 01047 HandleInfo->HandleCountDataBase = NewHandleCountDataBase; 01048 01049 // 01050 // And return to our caller 01051 // 01052 01053 return FreeHandleCountEntry; 01054 }

NTSTATUS ObpLogSecurityDescriptor IN PSECURITY_DESCRIPTOR  InputSecurityDescriptor,
OUT PSECURITY_DESCRIPTOR *  OutputSecurityDescriptor
 

Definition at line 297 of file obsdata.c.

References ExFreePool(), FALSE, Header, _SECURITY_DESCRIPTOR_HEADER::Link, LINK_TO_SD_HEADER, NULL, ObpAcquireDescriptorCacheWriteLock(), ObpCompareSecurityDescriptors(), ObpCreateCacheEntry(), ObpHashSecurityDescriptor(), ObpReleaseDescriptorCacheLock(), ObPrint, ObsSecurityDescriptorCache, and _SECURITY_DESCRIPTOR_HEADER::SecurityDescriptor.

Referenced by ObAssignObjectSecurityDescriptor(), and ObSetSecurityDescriptorInfo().

00304 : 00305 00306 Takes a passed security descriptor and registers it into the 00307 security descriptor database. 00308 00309 Arguments: 00310 00311 InputSecurityDescriptor - The new security descriptor to be logged into 00312 the database. On a successful return this memory will have been 00313 freed back to pool. 00314 00315 OutputSecurityDescriptor - Output security descriptor to be used by the 00316 caller. 00317 00318 Return Value: 00319 00320 An appropriate status value 00321 00322 --*/ 00323 00324 { 00325 ULONG FullHash; 00326 UCHAR SmallHash; 00327 PSECURITY_DESCRIPTOR_HEADER NewDescriptor; 00328 PLIST_ENTRY Front; 00329 PLIST_ENTRY Back; 00330 PSECURITY_DESCRIPTOR_HEADER Header; 00331 BOOLEAN Match; 00332 00333 FullHash = ObpHashSecurityDescriptor( InputSecurityDescriptor ); 00334 SmallHash = (UCHAR)FullHash; 00335 00336 // 00337 // See if the entry matching SmallHash is in use. 00338 // Lock the table first, unlock if if we don't need it. 00339 // 00340 00341 ObpAcquireDescriptorCacheWriteLock(); 00342 00343 Front = ObsSecurityDescriptorCache[SmallHash]; 00344 Back = NULL; 00345 Match = FALSE; 00346 00347 // 00348 // Zoom down the hash bucket looking for a full hash match 00349 // 00350 00351 while ( Front != NULL ) { 00352 00353 Header = LINK_TO_SD_HEADER( Front ); 00354 00355 // 00356 // **** is this test really right? Is the full hash value really 00357 // ordered like this? 00358 // 00359 00360 if ( Header->FullHash > FullHash ) { 00361 00362 break; 00363 } 00364 00365 if ( Header->FullHash == FullHash ) { 00366 00367 Match = ObpCompareSecurityDescriptors( InputSecurityDescriptor, 00368 &Header->SecurityDescriptor ); 00369 00370 if ( Match ) { 00371 00372 break; 00373 } 00374 00375 ObPrint( SHOW_COLLISIONS,("Got a collision on %d, no match\n",SmallHash)); 00376 } 00377 00378 Back = Front; 00379 Front = Front->Flink; 00380 } 00381 00382 // 00383 // If we have a match then we'll get the caller to use the old 00384 // cached descriptor, but bumping its ref count, freeing what 00385 // the caller supplied and returning the old one to our caller 00386 // 00387 00388 if ( Match ) { 00389 00390 Header->RefCount++; 00391 00392 ObPrint( SHOW_REFERENCES, ("Reference Hash = 0x%lX, New RefCount = %d\n",Header->FullHash,Header->RefCount)); 00393 00394 *OutputSecurityDescriptor = &Header->SecurityDescriptor; 00395 00396 ExFreePool( InputSecurityDescriptor ); 00397 00398 ObpReleaseDescriptorCacheLock(); 00399 00400 return( STATUS_SUCCESS ); 00401 } 00402 00403 // 00404 // Can't use an existing one, create a new entry 00405 // and insert it into the list. 00406 // 00407 00408 NewDescriptor = ObpCreateCacheEntry( InputSecurityDescriptor, 00409 FullHash ); 00410 00411 if ( NewDescriptor == NULL ) { 00412 00413 ObpReleaseDescriptorCacheLock(); 00414 00415 return( STATUS_INSUFFICIENT_RESOURCES ); 00416 } 00417 00418 #if OB_DIAGNOSTICS_ENABLED 00419 00420 ObsTotalCacheEntries++; 00421 00422 #endif 00423 00424 ObPrint( SHOW_STATISTICS, ("ObsTotalCacheEntries = %d \n",ObsTotalCacheEntries)); 00425 ObPrint( SHOW_COLLISIONS, ("Adding new entry for index #%d \n",SmallHash)); 00426 00427 // 00428 // We don't need the old security descriptor any more. 00429 // 00430 00431 ExFreePool( InputSecurityDescriptor ); 00432 00433 // 00434 // The following logic inserts the new security descriptor into the 00435 // small hash list. We need to first decide if the we're adding 00436 // the entry to the beginning of the list (back is null) or if we're 00437 // further in the list. 00438 // 00439 // **** This logic is plain bizzare because (1) the small hash 00440 // should probably just be an array of list heads and not single 00441 // pointer value and (2) the doubly linked list of security descriptors 00442 // is not circular! This should be fixed to use the regular set 00443 // of link list macros 00444 // 00445 00446 if ( Back == NULL ) { 00447 00448 // 00449 // We're inserting at the beginning of the list for this 00450 // minor index 00451 // 00452 00453 NewDescriptor->Link.Flink = ObsSecurityDescriptorCache[SmallHash]; 00454 ObsSecurityDescriptorCache[SmallHash] = &NewDescriptor->Link; 00455 00456 if ( NewDescriptor->Link.Flink != NULL ) { 00457 00458 NewDescriptor->Link.Flink->Blink = &NewDescriptor->Link; 00459 } 00460 00461 } else { 00462 00463 // 00464 // Hook new descriptor entry into list. 00465 // 00466 00467 NewDescriptor->Link.Flink = Front; 00468 00469 NewDescriptor->Link.Blink = Back; 00470 00471 Back->Flink = &NewDescriptor->Link; 00472 00473 if (Front != NULL) { 00474 00475 Front->Blink = &NewDescriptor->Link; 00476 } 00477 } 00478 00479 // 00480 // Set the output security descriptor and return to our caller 00481 // 00482 00483 *OutputSecurityDescriptor = &NewDescriptor->SecurityDescriptor; 00484 ObpReleaseDescriptorCacheLock(); 00485 00486 return( STATUS_SUCCESS ); 00487 }

PVOID ObpLookupDirectoryEntry IN POBJECT_DIRECTORY  Directory,
IN PUNICODE_STRING  Name,
IN ULONG  Attributes
 

Definition at line 705 of file obdir.c.

References Buffer, _OBJECT_DIRECTORY_ENTRY::ChainLink, Directory(), FALSE, _OBJECT_HEADER_NAME_INFO::Name, Name, NULL, NUMBER_HASH_BUCKETS, _OBJECT_DIRECTORY_ENTRY::Object, OBJECT_HEADER_TO_NAME_INFO, OBJECT_TO_OBJECT_HEADER, PAGED_CODE, RtlEqualUnicodeString(), RtlUpcaseUnicodeChar(), and TRUE.

Referenced by ObCreateObjectType(), ObInitSystem(), ObpDeleteNameCheck(), ObpLookupObjectName(), and ObpProcessDosDeviceSymbolicLink().

00713 : 00714 00715 This routine will lookup a single directory entry in a given directory. 00716 00717 I believe this routine assumes that it is called with the root directory 00718 locked. 00719 00720 Also note that this routine does not reference the returned object 00721 00722 Arguments: 00723 00724 Directory - Supplies the directory being searched 00725 00726 Name - Supplies the name of entry we're looking for 00727 00728 Attributes - Indicates if the lookup should be case insensitive 00729 or not 00730 00731 Return Value: 00732 00733 Returns a pointer to the corresponding object body if found and NULL 00734 otherwise. 00735 00736 --*/ 00737 00738 { 00739 POBJECT_DIRECTORY_ENTRY *HeadDirectoryEntry; 00740 POBJECT_DIRECTORY_ENTRY DirectoryEntry; 00741 POBJECT_HEADER ObjectHeader; 00742 POBJECT_HEADER_NAME_INFO NameInfo; 00743 PWCH Buffer; 00744 WCHAR Wchar; 00745 ULONG HashIndex; 00746 ULONG WcharLength; 00747 BOOLEAN CaseInSensitive; 00748 00749 PAGED_CODE(); 00750 00751 // 00752 // The caller needs to specify both a directory and a name otherwise 00753 // we can't process the request 00754 // 00755 00756 if (!Directory || !Name) { 00757 00758 return( NULL ); // BUG BUG 00759 } 00760 00761 // 00762 // Set a local variable to tell us if the search is case sensitive 00763 // 00764 00765 if (Attributes & OBJ_CASE_INSENSITIVE) { 00766 00767 CaseInSensitive = TRUE; 00768 00769 } else { 00770 00771 CaseInSensitive = FALSE; 00772 } 00773 00774 // 00775 // Establish our local pointer to the input name buffer and get the 00776 // number of unicode characters in the input name. Also make sure 00777 // the caller gave us a non null name 00778 // 00779 00780 Buffer = Name->Buffer; 00781 WcharLength = Name->Length / sizeof( *Buffer ); 00782 00783 if (!WcharLength || !Buffer) { 00784 00785 return( NULL ); // BUG BUG 00786 } 00787 00788 // 00789 // Compute the address of the head of the bucket chain for this name. 00790 // 00791 00792 HashIndex = 0; 00793 while (WcharLength--) { 00794 00795 Wchar = *Buffer++; 00796 HashIndex += (HashIndex << 1) + (HashIndex >> 1); 00797 00798 if (Wchar < 'a') { 00799 00800 HashIndex += Wchar; 00801 00802 } else if (Wchar > 'z') { 00803 00804 HashIndex += RtlUpcaseUnicodeChar( Wchar ); 00805 00806 } else { 00807 00808 HashIndex += (Wchar - ('a'-'A')); 00809 } 00810 } 00811 00812 HashIndex %= NUMBER_HASH_BUCKETS; 00813 00814 HeadDirectoryEntry = (POBJECT_DIRECTORY_ENTRY *)&Directory->HashBuckets[ HashIndex ]; 00815 00816 Directory->LookupBucket = HeadDirectoryEntry; 00817 00818 // 00819 // Walk the chain of directory entries for this hash bucket, looking 00820 // for either a match, or the insertion point if no match in the chain. 00821 // 00822 00823 while ((DirectoryEntry = *HeadDirectoryEntry) != NULL) { 00824 00825 // 00826 // Get the object header and name from the object body 00827 // 00828 // This function assumes the name must exist, otherwise it 00829 // wouldn't be in a directory 00830 // 00831 00832 ObjectHeader = OBJECT_TO_OBJECT_HEADER( DirectoryEntry->Object ); 00833 NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader ); 00834 00835 // 00836 // Compare strings using appropriate function. 00837 // 00838 00839 if ((Name->Length == NameInfo->Name.Length) && 00840 RtlEqualUnicodeString( Name, 00841 &NameInfo->Name, 00842 CaseInSensitive )) { 00843 00844 // 00845 // If name matches, then exit loop with DirectoryEntry 00846 // pointing to matching entry. 00847 // 00848 00849 break; 00850 } 00851 00852 HeadDirectoryEntry = &DirectoryEntry->ChainLink; 00853 } 00854 00855 // 00856 // At this point, there are two possiblilities: 00857 // 00858 // - we found an entry that matched and DirectoryEntry points to that 00859 // entry. Update the bucket chain so that the entry found is at the 00860 // head of the bucket chain. This is so the ObpDeleteDirectoryEntry 00861 // and ObpInsertDirectoryEntry functions will work. Also repeated 00862 // lookups of the same name will succeed quickly. 00863 // 00864 // - we did not find an entry that matched and DirectoryEntry is NULL. 00865 // 00866 00867 if (DirectoryEntry) { 00868 00869 Directory->LookupFound = TRUE; 00870 00871 // 00872 // The following convoluted piece of code moves a directory entry 00873 // we've found to the front of the hash list. 00874 // 00875 00876 if (HeadDirectoryEntry != Directory->LookupBucket) { 00877 00878 *HeadDirectoryEntry = DirectoryEntry->ChainLink; 00879 DirectoryEntry->ChainLink = *(Directory->LookupBucket); 00880 *(Directory->LookupBucket) = DirectoryEntry; 00881 } 00882 00883 // 00884 // Now return the object to our caller 00885 // 00886 00887 return( DirectoryEntry->Object ); 00888 00889 } else { 00890 00891 // 00892 // Otherwise we didn't find anything so return null 00893 // 00894 00895 Directory->LookupFound = FALSE; 00896 00897 return( NULL ); 00898 } 00899 }

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 PBOOLEAN  DirectoryLocked,
OUT PVOID *  FoundObject
 

Definition at line 1081 of file obdir.c.

References ASSERT, _OBJECT_HEADER::Body, _OBJECT_DIRECTORY::DeviceMap, Directory(), _DEVICE_MAP::DosDevicesDirectory, ExAllocatePoolWithTag, ExFreePool(), FALSE, IoFileObjectType, _OBJECT_HEADER_NAME_INFO::Name, NewName, NT_SUCCESS, NTSTATUS(), NULL, OB_PARSE_METHOD, ObCheckCreateObjectAccess(), ObDereferenceObject, OBJECT_HEADER_TO_NAME_INFO, OBJECT_TO_OBJECT_HEADER, ObpBeginTypeSpecificCallOut, ObpCheckTraverseAccess(), ObpDeviceMapLock, ObpDirectoryObjectType, ObpDosDevicesShortName, ObpDosDevicesShortNamePrefix, ObpDosDevicesShortNameRoot, ObpEndTypeSpecificCallOut, ObpEnterRootDirectoryMutex, ObpIncrPointerCount, ObpInsertDirectoryEntry(), ObpLeaveRootDirectoryMutex, ObpLookupDirectoryEntry(), ObpParseSymbolicLink(), ObpRootDirectoryObject, ObpValidateIrql, ObReferenceObject, ObReferenceObjectByHandle(), ObReferenceObjectByPointer(), PagedPool, _OBJECT_TYPE_INITIALIZER::ParseProcedure, PsGetCurrentProcess, _DEVICE_MAP::ReferenceCount, SecurityQos, Status, TOKEN_HAS_TRAVERSE_PRIVILEGE, TRUE, _OBJECT_HEADER::Type, and _OBJECT_TYPE::TypeInfo.

Referenced by ObInsertObject(), ObOpenObjectByName(), and ObReferenceObjectByName().

01097 : 01098 01099 This function will search a given directoroy for a specified 01100 object name. It will also create a new object specified by 01101 InsertObject. 01102 01103 Arguments: 01104 01105 RootDirectoryHandle - Optionally supplies the directory being 01106 searched. If not supplied then this routine searches 01107 the root directory 01108 01109 ObjectName - Supplies the name of object to lookup 01110 01111 Attributes - Specifies the attributes for the lookup (e.g., case 01112 insensitive) 01113 01114 ObjectType - Specifies the type of the object to lookup 01115 01116 AccessMode - Specifies the callers processor mode 01117 01118 ParseContext - Optionally supplies a parse context that is blindly 01119 passed to the parse callback routines 01120 01121 SecurityQos - Optionally supplies a pointer to the passed Security 01122 Quality of Service parameter that is blindly passed to the parse 01123 callback routines 01124 01125 InsertObject - Optionally supplies the object we think will be found. 01126 This is used if the caller did not give a root directory handle 01127 and the object name is "\" and the root object directory hasn't 01128 been created yet. In other cases where we wind up creating 01129 a new directory entry this is the object inserted. 01130 01131 AccessState - Current access state, describing already granted access 01132 types, the privileges used to get them, and any access types yet to 01133 be granted. The access masks may not contain any generic access 01134 types. 01135 01136 DirectoryLocked - Receives an indication if this routine has returned 01137 with the input directory locked 01138 01139 FoundObject - Receives a pointer to the object body if found 01140 01141 Return Value: 01142 01143 An appropriate status value 01144 01145 --*/ 01146 01147 { 01148 POBJECT_DIRECTORY RootDirectory; 01149 POBJECT_DIRECTORY Directory; 01150 POBJECT_DIRECTORY ParentDirectory = NULL; 01151 POBJECT_HEADER ObjectHeader; 01152 POBJECT_HEADER_NAME_INFO NameInfo; 01153 PDEVICE_MAP DeviceMap = NULL; 01154 PVOID Object; 01155 UNICODE_STRING RemainingName; 01156 UNICODE_STRING ComponentName; 01157 PWCH NewName; 01158 NTSTATUS Status; 01159 BOOLEAN Reparse; 01160 ULONG MaxReparse = OBJ_MAX_REPARSE_ATTEMPTS; 01161 OB_PARSE_METHOD ParseProcedure; 01162 extern POBJECT_TYPE IoFileObjectType; 01163 01164 ObpValidateIrql( "ObpLookupObjectName" ); 01165 01166 // 01167 // Initialize our output variables to say we haven't lock or found 01168 // anything but we were successful at it 01169 // 01170 01171 *DirectoryLocked = FALSE; 01172 *FoundObject = NULL; 01173 Status = STATUS_SUCCESS; 01174 01175 Object = NULL; 01176 01177 // 01178 // Check if the caller has given us a directory to search. Otherwise 01179 // we'll search the root object directory 01180 // 01181 01182 if (ARGUMENT_PRESENT( RootDirectoryHandle )) { 01183 01184 // 01185 // Otherwise reference the directory object and make sure 01186 // that we successfully got the object 01187 // 01188 01189 Status = ObReferenceObjectByHandle( RootDirectoryHandle, 01190 0, 01191 NULL, 01192 AccessMode, 01193 (PVOID *)&RootDirectory, 01194 NULL ); 01195 01196 if (!NT_SUCCESS( Status )) { 01197 01198 return( Status ); 01199 } 01200 01201 // 01202 // Translate the directory object to its object header 01203 // 01204 01205 ObjectHeader = OBJECT_TO_OBJECT_HEADER( RootDirectory ); 01206 01207 // 01208 // Now if the name we're looking up starts with a "\" and it 01209 // does not have a parse procedure then the syntax is bad 01210 // 01211 01212 if ((ObjectName->Buffer != NULL) && 01213 (*(ObjectName->Buffer) == OBJ_NAME_PATH_SEPARATOR) && 01214 (ObjectHeader->Type != IoFileObjectType)) { 01215 01216 ObDereferenceObject( RootDirectory ); 01217 01218 return( STATUS_OBJECT_PATH_SYNTAX_BAD ); 01219 } 01220 01221 // 01222 // Now make sure that we do not have the directory of the 01223 // object types 01224 // 01225 01226 if (ObjectHeader->Type != ObpDirectoryObjectType) { 01227 01228 // 01229 // We have an object directory that is not the object type 01230 // directory. So now if it doesn't have a parse routine 01231 // then there is nothing we can 01232 // 01233 01234 if (ObjectHeader->Type->TypeInfo.ParseProcedure == NULL) { 01235 01236 ObDereferenceObject( RootDirectory ); 01237 01238 return( STATUS_INVALID_HANDLE ); 01239 01240 } else { 01241 01242 MaxReparse = OBJ_MAX_REPARSE_ATTEMPTS; 01243 01244 // 01245 // The following loop cycles cycles through the various 01246 // parse routine to we could encounter trying to resolve 01247 // this name through symbolic links. 01248 // 01249 01250 while (TRUE) { 01251 01252 KIRQL SaveIrql; 01253 01254 RemainingName = *ObjectName; 01255 01256 // 01257 // Invoke the callback routine to parse the remaining 01258 // object name 01259 // 01260 01261 ObpBeginTypeSpecificCallOut( SaveIrql ); 01262 01263 Status = (*ObjectHeader->Type->TypeInfo.ParseProcedure)( RootDirectory, 01264 ObjectType, 01265 AccessState, 01266 AccessMode, 01267 Attributes, 01268 ObjectName, 01269 &RemainingName, 01270 ParseContext, 01271 SecurityQos, 01272 &Object ); 01273 01274 ObpEndTypeSpecificCallOut( SaveIrql, "Parse", ObjectHeader->Type, Object ); 01275 01276 // 01277 // If the status was not to do a reparse and the lookup 01278 // was not successful then we found nothing so we 01279 // dereference the directory and return the status to 01280 // our caller. If the object we got back was null then 01281 // we'll tell our caller that we couldn't find the name. 01282 // Lastly if we did not get a reparse and we were 01283 // successful and the object is not null then everything 01284 // gets nicely returned to our caller 01285 // 01286 01287 if ( ( Status != STATUS_REPARSE ) && 01288 ( Status != STATUS_REPARSE_OBJECT )) { 01289 01290 if (!NT_SUCCESS( Status )) { 01291 01292 Object = NULL; 01293 01294 } else if (Object == NULL) { 01295 01296 Status = STATUS_OBJECT_NAME_NOT_FOUND; 01297 } 01298 01299 ObDereferenceObject( RootDirectory ); 01300 01301 *FoundObject = Object; 01302 01303 return( Status ); 01304 01305 // 01306 // We got a status reparse, which means the object 01307 // name has been modified to have use start all over 01308 // again. If the reparse target is now empty or it 01309 // is a path separator then we start the parse at the 01310 // root directory 01311 // 01312 01313 } else if ((ObjectName->Length == 0) || 01314 (ObjectName->Buffer == NULL) || 01315 (*(ObjectName->Buffer) == OBJ_NAME_PATH_SEPARATOR)) { 01316 01317 // 01318 // Restart the parse relative to the root directory. 01319 // 01320 01321 ObDereferenceObject( RootDirectory ); 01322 01323 RootDirectory = ObpRootDirectoryObject; 01324 RootDirectoryHandle = NULL; 01325 01326 break; 01327 01328 // 01329 // We got a reparse and we actually have a new name to 01330 // go to we if we haven't exhausted our reparse attempts 01331 // yet then just continue to the top of this loop. 01332 // 01333 01334 } else if (--MaxReparse) { 01335 01336 continue; 01337 01338 // 01339 // We got a reparse and we've exhausted our times through 01340 // the loop so we'll return what we found. 01341 // 01342 // **** this doesn't seem right. It probably should be 01343 // an error 01344 // 01345 01346 } else { 01347 01348 ObDereferenceObject( RootDirectory ); 01349 01350 *FoundObject = Object; 01351 01352 // 01353 // At this point we were failing in stress by 01354 // returning to the caller with a success status but 01355 // a null object pointer. 01356 // 01357 01358 if (Object == NULL) { 01359 01360 Status = STATUS_OBJECT_NAME_NOT_FOUND; 01361 } 01362 01363 return( Status ); 01364 } 01365 } 01366 } 01367 01368 // 01369 // At this point the caller has given us the directory of object 01370 // types. If the caller didn't specify a name then we'll return 01371 // a pointer to the root object directory. 01372 // 01373 01374 } else if ((ObjectName->Length == 0) || 01375 (ObjectName->Buffer == NULL)) { 01376 01377 Status = ObReferenceObjectByPointer( RootDirectory, 01378 0, 01379 ObjectType, 01380 AccessMode ); 01381 01382 if (NT_SUCCESS( Status )) { 01383 01384 Object = RootDirectory; 01385 } 01386 01387 ObDereferenceObject( RootDirectory ); 01388 01389 *FoundObject = Object; 01390 01391 return( Status ); 01392 } 01393 01394 // 01395 // Otherwise the caller did not specify a directory to search so 01396 // we'll default to the object root directory 01397 // 01398 01399 } else { 01400 01401 RootDirectory = ObpRootDirectoryObject; 01402 01403 // 01404 // If the name we're looking for is empty then it is illformed. 01405 // Also it has to start with a "\" or it is illformed. 01406 // 01407 01408 if ((ObjectName->Length == 0) || 01409 (ObjectName->Buffer == NULL) || 01410 (*(ObjectName->Buffer) != OBJ_NAME_PATH_SEPARATOR)) { 01411 01412 return( STATUS_OBJECT_PATH_SYNTAX_BAD ); 01413 } 01414 01415 // 01416 // Check if the name is has only one character (that is the "\") 01417 // Which means that the caller really just wants to lookup the 01418 // root directory. 01419 // 01420 01421 if (ObjectName->Length == sizeof( OBJ_NAME_PATH_SEPARATOR )) { 01422 01423 // 01424 // If there is not a root directory yet. Then we really 01425 // can't return it, however if the caller specified 01426 // an insert object that is the one we'll reference and 01427 // return to our caller 01428 // 01429 01430 if (!RootDirectory) { 01431 01432 if (InsertObject) { 01433 01434 Status = ObReferenceObjectByPointer( InsertObject, 01435 0, 01436 ObjectType, 01437 AccessMode ); 01438 01439 if (NT_SUCCESS( Status )) { 01440 01441 *FoundObject = InsertObject; 01442 } 01443 01444 return( Status ); 01445 01446 } else { 01447 01448 return( STATUS_INVALID_PARAMETER ); 01449 } 01450 01451 // 01452 // At this point the caller did not specify a root directory, 01453 // the name is "\" and the root object directory exists so 01454 // we'll simply return the real root directory object 01455 // 01456 01457 } else { 01458 01459 Status = ObReferenceObjectByPointer( RootDirectory, 01460 0, 01461 ObjectType, 01462 AccessMode ); 01463 01464 if (NT_SUCCESS( Status )) { 01465 01466 *FoundObject = RootDirectory; 01467 } 01468 01469 return( Status ); 01470 } 01471 01472 // 01473 // At this pointer the caller did not specify a root directory, 01474 // and the name is more than just a "\" 01475 // 01476 // Now if the lookup is case insensitive, and the name buffer is a 01477 // legitimate pointer (meaning that is it quadword aligned), and 01478 // there is a dos device map for the process. Then we'll handle 01479 // the situation here. First get the device map and make sure it 01480 // doesn't go away while we're using it. 01481 // 01482 01483 } else { 01484 01485 KIRQL OldIrql; 01486 01487 ExAcquireSpinLock( &ObpDeviceMapLock, &OldIrql ); 01488 01489 if ((DeviceMap = PsGetCurrentProcess()->DeviceMap) != NULL) { 01490 01491 DeviceMap->ReferenceCount++; 01492 ExReleaseSpinLock( &ObpDeviceMapLock, OldIrql ); 01493 01494 if (!((ULONG_PTR)(ObjectName->Buffer) & (sizeof(ULONGLONG)-1)) 01495 01496 && 01497 01498 (DeviceMap->DosDevicesDirectory != NULL )) { 01499 01500 // 01501 // Check if the object name is actually equal to the 01502 // global dos devices short name prefix "\??\" 01503 // 01504 01505 if ((ObjectName->Length >= ObpDosDevicesShortName.Length) 01506 01507 && 01508 01509 (*(PULONGLONG)(ObjectName->Buffer) == ObpDosDevicesShortNamePrefix.QuadPart)) { 01510 01511 // 01512 // The user gave us the dos short name prefix so we'll 01513 // look down the directory, and start the search at the 01514 // dos device directory 01515 // 01516 01517 *DirectoryLocked = TRUE; 01518 01519 ObpEnterRootDirectoryMutex(); 01520 01521 ParentDirectory = RootDirectory; 01522 01523 Directory = DeviceMap->DosDevicesDirectory; 01524 01525 RemainingName = *ObjectName; 01526 RemainingName.Buffer += (ObpDosDevicesShortName.Length / sizeof( WCHAR )); 01527 RemainingName.Length -= ObpDosDevicesShortName.Length; 01528 01529 goto quickStart; 01530 01531 // 01532 // The name is not equal to "\??\" but check if it is 01533 // equal to "\??" 01534 // 01535 01536 } else if ((ObjectName->Length == ObpDosDevicesShortName.Length - sizeof( WCHAR )) 01537 01538 && 01539 01540 (*(PULONG)(ObjectName->Buffer) == ObpDosDevicesShortNameRoot.LowPart) 01541 01542 && 01543 01544 (*((PWCHAR)(ObjectName->Buffer)+2) == (WCHAR)(ObpDosDevicesShortNameRoot.HighPart))) { 01545 01546 // 01547 // The user specified "\??" so we return to dos devices 01548 // directory to our caller 01549 // 01550 01551 Status = ObReferenceObjectByPointer( DeviceMap->DosDevicesDirectory, 01552 0, 01553 ObjectType, 01554 AccessMode ); 01555 01556 if (NT_SUCCESS( Status )) { 01557 01558 *FoundObject = DeviceMap->DosDevicesDirectory; 01559 } 01560 01561 // 01562 // Dereference the Device Map 01563 // 01564 01565 { 01566 KIRQL OldIrql; 01567 01568 ExAcquireSpinLock( &ObpDeviceMapLock, &OldIrql ); 01569 01570 DeviceMap->ReferenceCount--; 01571 01572 if (DeviceMap->ReferenceCount == 0) { 01573 01574 ExReleaseSpinLock( &ObpDeviceMapLock, OldIrql ); 01575 01576 DeviceMap->DosDevicesDirectory->DeviceMap = NULL; 01577 ObDereferenceObject( DeviceMap->DosDevicesDirectory ); 01578 01579 ExFreePool( DeviceMap ); 01580 01581 } else { 01582 01583 ExReleaseSpinLock( &ObpDeviceMapLock, OldIrql ); 01584 } 01585 } 01586 01587 return( Status ); 01588 } 01589 } 01590 01591 } else { 01592 01593 ExReleaseSpinLock( &ObpDeviceMapLock, OldIrql ); 01594 } 01595 } 01596 } 01597 01598 // 01599 // At this point either 01600 // 01601 // the user specified a directory that is not the object 01602 // type directory and got repase back to the root directory 01603 // 01604 // the user specified the object type directory and gave us 01605 // a name to actually look up 01606 // 01607 // the user did not specify a search directory (default 01608 // to root object directory) and if the name did start off 01609 // with the dos device prefix we've munged outselves back to 01610 // it to the dos device directory for the process 01611 // 01612 01613 Reparse = TRUE; 01614 MaxReparse = OBJ_MAX_REPARSE_ATTEMPTS; 01615 01616 while (Reparse) { 01617 01618 RemainingName = *ObjectName; 01619 01620 quickStart: 01621 01622 Reparse = FALSE; 01623 01624 while (TRUE) { 01625 01626 Object = NULL; 01627 01628 //if (RemainingName.Length == 0) { 01629 // Status = STATUS_OBJECT_NAME_INVALID; 01630 // break; 01631 // } 01632 01633 // 01634 // If the remaining name for the object starts with a 01635 // "\" then just gobble up the "\" 01636 // 01637 01638 if ( (RemainingName.Length != 0) && 01639 (*(RemainingName.Buffer) == OBJ_NAME_PATH_SEPARATOR) ) { 01640 01641 RemainingName.Buffer++; 01642 RemainingName.Length -= sizeof( OBJ_NAME_PATH_SEPARATOR ); 01643 } 01644 01645 // 01646 // The following piece of code will calculate the first 01647 // component of the remaining name. If there is not 01648 // a remaining component then the object name is illformed 01649 // 01650 01651 ComponentName = RemainingName; 01652 01653 while (RemainingName.Length != 0) { 01654 01655 if (*(RemainingName.Buffer) == OBJ_NAME_PATH_SEPARATOR) { 01656 01657 break; 01658 } 01659 01660 RemainingName.Buffer++; 01661 RemainingName.Length -= sizeof( OBJ_NAME_PATH_SEPARATOR ); 01662 } 01663 01664 ComponentName.Length -= RemainingName.Length; 01665 01666 if (ComponentName.Length == 0) { 01667 01668 Status = STATUS_OBJECT_NAME_INVALID; 01669 break; 01670 } 01671 01672 // 01673 // Now we have the first component name to lookup so we'll 01674 // look the directory is necessary 01675 // 01676 01677 if (!*DirectoryLocked) { 01678 01679 *DirectoryLocked = TRUE; 01680 ObpEnterRootDirectoryMutex(); 01681 Directory = RootDirectory; 01682 } 01683 01684 // 01685 // Now if the caller does not have traverse privilege and 01686 // there is a parent directory then we must check if the 01687 // user has traverse access to the directory. Our local 01688 // Reparse variable should be false at this point so we'll 01689 // drop out of both loops 01690 // 01691 01692 if ( !(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE) && (ParentDirectory != NULL) ) { 01693 01694 if (!ObpCheckTraverseAccess( ParentDirectory, 01695 DIRECTORY_TRAVERSE, 01696 AccessState, 01697 FALSE, 01698 AccessMode, 01699 &Status )) { 01700 01701 break; 01702 } 01703 } 01704 01705 // 01706 // If the object already exists in this directory, find it, 01707 // else return NULL. 01708 // 01709 01710 Object = ObpLookupDirectoryEntry( Directory, &ComponentName, Attributes ); 01711 01712 if (!Object) { 01713 01714 // 01715 // We didn't find the object. If there is some remaining 01716 // name left (meaning the component name is a directory in 01717 // path we trying to break) or the caller didn't specify an 01718 // insert object then we then we'll break out here with an 01719 // error status 01720 // 01721 01722 if (RemainingName.Length != 0) { 01723 01724 Status = STATUS_OBJECT_PATH_NOT_FOUND; 01725 break; 01726 } 01727 01728 if (!InsertObject) { 01729 01730 Status = STATUS_OBJECT_NAME_NOT_FOUND; 01731 break; 01732 } 01733 01734 // 01735 // Check that the caller has the access to the directory 01736 // to either create a subdirectory (in the object type 01737 // directory) or to create an object of the given component 01738 // name. If the call fails then we'll break out of here 01739 // with the status value set 01740 // 01741 01742 if (!ObCheckCreateObjectAccess( Directory, 01743 ObjectType == ObpDirectoryObjectType ? 01744 DIRECTORY_CREATE_SUBDIRECTORY : 01745 DIRECTORY_CREATE_OBJECT, 01746 AccessState, 01747 &ComponentName, 01748 FALSE, 01749 AccessMode, 01750 &Status )) { 01751 01752 break; 01753 } 01754 01755 // 01756 // The object does not exist in the directory and 01757 // we are allowed to create one. So allocate space 01758 // for the name and insert the name into the directory 01759 // 01760 01761 NewName = ExAllocatePoolWithTag( PagedPool, ComponentName.Length, 'mNbO' ); 01762 01763 if ((NewName == NULL) || 01764 !ObpInsertDirectoryEntry( Directory, InsertObject )) { 01765 01766 if (NewName != NULL) { 01767 01768 ExFreePool( NewName ); 01769 } 01770 01771 Status = STATUS_INSUFFICIENT_RESOURCES; 01772 break; 01773 } 01774 01775 // 01776 // We have an insert object so now get its name info, 01777 // because we are going to change its name and insert it 01778 // into the directory 01779 // 01780 01781 ObReferenceObject( InsertObject ); 01782 01783 ObjectHeader = OBJECT_TO_OBJECT_HEADER( InsertObject ); 01784 01785 NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader ); 01786 01787 ObReferenceObject( Directory ); 01788 01789 RtlMoveMemory( NewName, 01790 ComponentName.Buffer, 01791 ComponentName.Length ); 01792 01793 if (NameInfo->Name.Buffer) { 01794 01795 ExFreePool( NameInfo->Name.Buffer ); 01796 } 01797 01798 NameInfo->Name.Buffer = NewName; 01799 NameInfo->Name.Length = ComponentName.Length; 01800 NameInfo->Name.MaximumLength = ComponentName.Length; 01801 01802 Object = InsertObject; 01803 01804 Status = STATUS_SUCCESS; 01805 01806 break; 01807 } 01808 01809 // 01810 // At this point we've found the component name within 01811 // the directory. So we'll now grab the components object 01812 // header, and get its parse routine 01813 // 01814 01815 ReparseObject: 01816 01817 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 01818 ParseProcedure = ObjectHeader->Type->TypeInfo.ParseProcedure; 01819 01820 // 01821 // Now if there is a parse routine for the type and we are not 01822 // inserting a new object or the parse routine is for symbolic 01823 // links then we'll actually call the parse routine 01824 // 01825 01826 if (ParseProcedure && (!InsertObject || (ParseProcedure == ObpParseSymbolicLink))) { 01827 01828 KIRQL SaveIrql; 01829 01830 // 01831 // Reference the object and then free the directory lock 01832 // This will keep the object from going away with the 01833 // directory unlocked 01834 // 01835 01836 ObpIncrPointerCount( ObjectHeader ); 01837 01838 ASSERT(*DirectoryLocked); 01839 01840 ObpLeaveRootDirectoryMutex(); 01841 01842 *DirectoryLocked = FALSE; 01843 01844 ObpBeginTypeSpecificCallOut( SaveIrql ); 01845 01846 // 01847 // Call the objects parse routine 01848 // 01849 01850 Status = (*ParseProcedure)( Object, 01851 (PVOID)ObjectType, 01852 AccessState, 01853 AccessMode, 01854 Attributes, 01855 ObjectName, 01856 &RemainingName, 01857 ParseContext, 01858 SecurityQos, 01859 &Object ); 01860 01861 ObpEndTypeSpecificCallOut( SaveIrql, "Parse", ObjectHeader->Type, Object ); 01862 01863 // 01864 // We can now decrement the object reference count 01865 // 01866 01867 ObDereferenceObject( &ObjectHeader->Body ); 01868 01869 // 01870 // Check if we have some reparsing to do 01871 // 01872 01873 if ((Status == STATUS_REPARSE) || (Status == STATUS_REPARSE_OBJECT)) { 01874 01875 // 01876 // See if we've reparsed too many times already and if 01877 // so we'll fail the request 01878 // 01879 01880 if (--MaxReparse) { 01881 01882 // 01883 // Tell the outer loop to continue looping 01884 // 01885 01886 Reparse = TRUE; 01887 01888 // 01889 // Check if we have a reparse object or the name 01890 // starts with a "\" 01891 // 01892 01893 if ((Status == STATUS_REPARSE_OBJECT) || 01894 (*(ObjectName->Buffer) == OBJ_NAME_PATH_SEPARATOR)) { 01895 01896 // 01897 // If the user specified a start directory then 01898 // remove this information because we're taking 01899 // a reparse point to someplace else 01900 // 01901 01902 if (ARGUMENT_PRESENT( RootDirectoryHandle )) { 01903 01904 ObDereferenceObject( RootDirectory ); 01905 RootDirectoryHandle = NULL; 01906 } 01907 01908 // 01909 // And where we start is the root directory 01910 // object 01911 // 01912 01913 ParentDirectory = NULL; 01914 RootDirectory = ObpRootDirectoryObject; 01915 01916 // 01917 // Now if this is a reparse object (means we have 01918 // encountered a symbolic link that has already been 01919 // snapped so we have an object and remaining 01920 // name that need to be examined) and we didn't 01921 // find an object from the parse routine object 01922 // break out of both loops. 01923 // 01924 01925 if (Status == STATUS_REPARSE_OBJECT) { 01926 01927 Reparse = FALSE; 01928 01929 if (Object == NULL) { 01930 01931 Status = STATUS_OBJECT_NAME_NOT_FOUND; 01932 01933 } else { 01934 01935 // 01936 // At this point we have a reparse object 01937 // so we'll look the directory down and 01938 // parse the new object 01939 // 01940 01941 *DirectoryLocked = TRUE; 01942 ObpEnterRootDirectoryMutex(); 01943 01944 goto ReparseObject; 01945 } 01946 } 01947 01948 // 01949 // We did not have a reparse object and the name 01950 // does not start with a "\". Meaning we got back 01951 // STATUS_REPASE, so now check if the directory 01952 // is the root object directory and if so then 01953 // we didn't the name otherwise we'll drop out of 01954 // the inner loop and reparse true to get back to 01955 // outer loop 01956 // 01957 01958 } else if (RootDirectory == ObpRootDirectoryObject) { 01959 01960 Object = NULL; 01961 Status = STATUS_OBJECT_NAME_NOT_FOUND; 01962 01963 Reparse = FALSE; 01964 } 01965 01966 } else { 01967 01968 // 01969 // **** this should probably be a differnt error 01970 // status related to too many reparse points 01971 // 01972 01973 Object = NULL; 01974 Status = STATUS_OBJECT_NAME_NOT_FOUND; 01975 } 01976 01977 // 01978 // We are not reparsing and if we did not get success then 01979 // the object is null and we'll break out of our loops 01980 // 01981 01982 } else if (!NT_SUCCESS( Status )) { 01983 01984 Object = NULL; 01985 01986 // 01987 // We are not reparsing and we got back success but check 01988 // if the object is null because that means we really didn't 01989 // find the object, and then break out of our loops 01990 // 01991 // If the object is not null then we've been successful and 01992 // prosperous so break out with the object set. 01993 // 01994 01995 } else if (Object == NULL) { 01996 01997 Status = STATUS_OBJECT_NAME_NOT_FOUND; 01998 } 01999 02000 break; 02001 02002 } else { 02003 02004 // 02005 // At this point we do not have a parse routine or if there 02006 // is a parse routine it is not for symbolic links or there 02007 // may not be a specified insert object 02008 // 02009 // Check to see if we have exhausted the remaining name 02010 // 02011 02012 if (RemainingName.Length == 0) { 02013 02014 // 02015 // Check if the caller specified an object to insert. 02016 // If specified then we'll break out of our loops with 02017 // the object that we've found 02018 // 02019 02020 if (!InsertObject) { 02021 02022 // 02023 // The user did not specify an insert object 02024 // so we're opening an existing object. Make sure 02025 // we have traverse access to the container 02026 // directory. 02027 // 02028 02029 if ( !(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE) ) { 02030 02031 if (!ObpCheckTraverseAccess( Directory, 02032 DIRECTORY_TRAVERSE, 02033 AccessState, 02034 FALSE, 02035 AccessMode, 02036 &Status )) { 02037 02038 Object = NULL; 02039 break; 02040 } 02041 } 02042 02043 Status = ObReferenceObjectByPointer( Object, 02044 0, 02045 ObjectType, 02046 AccessMode ); 02047 02048 if (!NT_SUCCESS( Status )) { 02049 02050 Object = NULL; 02051 } 02052 } 02053 02054 break; 02055 02056 } else { 02057 02058 // 02059 // There is some name remaining names to process 02060 // if the directory we're looking at is the 02061 // directory of object types and set ourselves 02062 // up to parse it all over again. 02063 // 02064 02065 if (ObjectHeader->Type == ObpDirectoryObjectType) { 02066 02067 ParentDirectory = Directory; 02068 Directory = (POBJECT_DIRECTORY)Object; 02069 02070 } else { 02071 02072 // 02073 // Otherwise there has been a mismatch so we'll 02074 // set our error status and break out of the 02075 // loops 02076 // 02077 02078 Status = STATUS_OBJECT_TYPE_MISMATCH; 02079 Object = NULL; 02080 02081 break; 02082 } 02083 } 02084 } 02085 } 02086 } 02087 02088 // 02089 // If the device map has been referenced then dereference it 02090 // 02091 02092 if (DeviceMap != NULL) { 02093 02094 KIRQL OldIrql; 02095 02096 ExAcquireSpinLock( &ObpDeviceMapLock, &OldIrql ); 02097 02098 DeviceMap->ReferenceCount--; 02099 02100 if (DeviceMap->ReferenceCount == 0) { 02101 02102 ExReleaseSpinLock( &ObpDeviceMapLock, OldIrql ); 02103 02104 DeviceMap->DosDevicesDirectory->DeviceMap = NULL; 02105 ObDereferenceObject( DeviceMap->DosDevicesDirectory ); 02106 02107 ExFreePool( DeviceMap ); 02108 02109 } else { 02110 02111 ExReleaseSpinLock( &ObpDeviceMapLock, OldIrql ); 02112 } 02113 } 02114 02115 // 02116 // At this point we've parsed the object name as much as possible 02117 // going through symbolic links as necessary. So now set the 02118 // output object pointer, and if we really did not find an object 02119 // then we might need to modify the error status. If the 02120 // status was repase or some success status then translate it 02121 // to name not found. 02122 // 02123 02124 if (!(*FoundObject = Object)) { 02125 02126 if (Status == STATUS_REPARSE) { 02127 02128 Status = STATUS_OBJECT_NAME_NOT_FOUND; 02129 02130 } else if (NT_SUCCESS( Status )) { 02131 02132 Status = STATUS_OBJECT_NAME_NOT_FOUND; 02133 } 02134 } 02135 02136 // 02137 // If the caller gave us a root directory to search (and we didn't 02138 // zero out this value) then free up our reference 02139 // 02140 02141 if (ARGUMENT_PRESENT( RootDirectoryHandle )) { 02142 02143 ObDereferenceObject( RootDirectory ); 02144 RootDirectoryHandle = NULL; 02145 } 02146 02147 // 02148 // And return to our caller 02149 // 02150 02151 return( Status ); 02152 }

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
 

Definition at line 501 of file oblink.c.

References ExAllocatePoolWithTag, ExFreePool(), _OBJECT_SYMBOLIC_LINK::LinkTarget, _OBJECT_SYMBOLIC_LINK::LinkTargetObject, _OBJECT_SYMBOLIC_LINK::LinkTargetRemaining, NewName, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObpEnterRootDirectoryMutex, ObpLeaveRootDirectoryMutex, ObReferenceObjectByPointer(), PAGED_CODE, Status, and USHORT.

Referenced by ObInitSystem(), and ObpLookupObjectName().

00516 : 00517 00518 This is the call back routine for parsing symbolic link objects. It is invoked 00519 as part of ObpLookupObjectName 00520 00521 Arguments: 00522 00523 ParseObject - This will actually be a symbolic link object 00524 00525 ObjectType - Specifies the type of the object to lookup 00526 00527 AccessState - Current access state, describing already granted access 00528 types, the privileges used to get them, and any access types yet to 00529 be granted. The access masks may not contain any generic access 00530 types. 00531 00532 AccessMode - Specifies the callers processor mode 00533 00534 Attributes - Specifies the attributes for the lookup (e.g., case 00535 insensitive) 00536 00537 CompleteName - Supplies a pointer to the complete name that we are trying 00538 to open. On return this could be modified to fit the new reparse 00539 buffer 00540 00541 RemainingName - Supplies a pointer to the remaining name that we are 00542 trying to open. On return this will point to what remains after 00543 we processed the symbolic link. 00544 00545 Context - Unused 00546 00547 SecurityQos - Unused 00548 00549 Object - Receives a pointer to the symbolic link object that we 00550 resolve to 00551 00552 Return Value: 00553 00554 STATUS_REPARSE_OBJECT if the parse object is already a snapped 00555 symbolic link meaning we've modified the remaining name and 00556 and have returned the target object of the symbolic link 00557 00558 00559 STATUS_REPARSE if the parse object has not been snapped. In this 00560 case the Complete name has been modified with the link target 00561 name added in front of the remaining name. The parameters 00562 remaining name and object must now be ignored by the caller 00563 00564 An appropriate error value 00565 00566 --*/ 00567 00568 { 00569 ULONG NewLength; 00570 USHORT Length; 00571 USHORT MaximumLength; 00572 PWCHAR NewName, NewRemainingName; 00573 ULONG InsertAmount; 00574 NTSTATUS Status; 00575 POBJECT_SYMBOLIC_LINK SymbolicLink; 00576 PUNICODE_STRING LinkTargetName; 00577 00578 PAGED_CODE(); 00579 00580 // 00581 // This routine needs to be synchonized with the delete symbolic link 00582 // operation. Which uses the root directory mutex. 00583 // 00584 00585 ObpEnterRootDirectoryMutex(); 00586 00587 try { 00588 00589 *Object = NULL; 00590 00591 // 00592 // If there isn't any name remaining and the caller gave us 00593 // an object type then we'll reference the parse object. If 00594 // this is successful then that's the object we return. Otherwise 00595 // if the status is anything but a type mismatch then we'll 00596 // return that error status 00597 // 00598 00599 if (RemainingName->Length == 0) { 00600 00601 if ( ObjectType ) { 00602 00603 Status = ObReferenceObjectByPointer( ParseObject, 00604 0, 00605 ObjectType, 00606 AccessMode ); 00607 00608 if (NT_SUCCESS( Status )) { 00609 00610 *Object = ParseObject; 00611 00612 leave; 00613 00614 } else if (Status != STATUS_OBJECT_TYPE_MISMATCH) { 00615 00616 leave; 00617 } 00618 } 00619 00620 // 00621 // If the remaining name does not start with a "\" then 00622 // its is illformed and we'll call it a type mismatch 00623 // 00624 00625 } else if (*(RemainingName->Buffer) != OBJ_NAME_PATH_SEPARATOR) { 00626 00627 Status = STATUS_OBJECT_TYPE_MISMATCH; 00628 leave; 00629 } 00630 00631 // 00632 // A symbolic link has been encountered. See if this link has been snapped 00633 // to a particular object. 00634 // 00635 00636 SymbolicLink = (POBJECT_SYMBOLIC_LINK)ParseObject; 00637 00638 if (SymbolicLink->LinkTargetObject != NULL) { 00639 00640 // 00641 // This is a snapped link. Get the remaining portion of the 00642 // symbolic link target, if any. 00643 // 00644 00645 LinkTargetName = &SymbolicLink->LinkTargetRemaining; 00646 00647 if (LinkTargetName->Length == 0) { 00648 00649 // 00650 // Remaining link target string is zero, so return to caller 00651 // quickly with snapped object pointer and remaining object name 00652 // which we haven't touched yet. 00653 // 00654 00655 *Object = SymbolicLink->LinkTargetObject; 00656 00657 Status = STATUS_REPARSE_OBJECT; 00658 leave; 00659 } 00660 00661 // 00662 // We have a snapped symbolic link that has additional text. 00663 // Insert that in front of the current remaining name, preserving 00664 // and text between CompleteName and RemainingName 00665 // 00666 00667 InsertAmount = LinkTargetName->Length; 00668 00669 if ((LinkTargetName->Buffer[ (InsertAmount / sizeof( WCHAR )) - 1 ] == OBJ_NAME_PATH_SEPARATOR) 00670 00671 && 00672 00673 (*(RemainingName->Buffer) == OBJ_NAME_PATH_SEPARATOR)) { 00674 00675 // 00676 // Both the link target name ends in a "\" and the remaining 00677 // starts with a "\" but we only need one when we're done 00678 // 00679 00680 InsertAmount -= sizeof( WCHAR ); 00681 } 00682 00683 // 00684 // **** don't see why we need to bias the differnce between two 00685 // pointers with * sizeof(wchar) 00686 // 00687 00688 NewLength = (ULONG)(((RemainingName->Buffer - CompleteName->Buffer) * sizeof( WCHAR )) + 00689 InsertAmount + 00690 RemainingName->Length); 00691 00692 if (NewLength > 0xFFF0) { 00693 00694 Status = STATUS_NAME_TOO_LONG; 00695 leave; 00696 } 00697 00698 Length = (USHORT)NewLength; 00699 00700 // 00701 // Now check if the new computed length is too big for the input 00702 // buffer containing the complete name 00703 // 00704 00705 if (CompleteName->MaximumLength <= Length) { 00706 00707 // 00708 // The new concatentated name is larger than the buffer supplied for 00709 // the complete name. Allocate space for this new string 00710 // 00711 00712 MaximumLength = Length + sizeof( UNICODE_NULL ); 00713 NewName = ExAllocatePoolWithTag( NonPagedPool, MaximumLength, 'mNbO' ); 00714 00715 if (NewName == NULL) { 00716 00717 Status = STATUS_INSUFFICIENT_RESOURCES; 00718 leave; 00719 } 00720 00721 // 00722 // Calculate the pointer within this buffer for the remaining 00723 // name. This value has not been biased by the new link 00724 // target name 00725 // 00726 00727 NewRemainingName = NewName + (RemainingName->Buffer - CompleteName->Buffer); 00728 00729 // 00730 // Copy over all the names that we've processed so far 00731 // 00732 00733 RtlMoveMemory( NewName, 00734 CompleteName->Buffer, 00735 ((RemainingName->Buffer - CompleteName->Buffer) * sizeof( WCHAR ))); 00736 00737 // 00738 // If we have some remaining names then those over at the 00739 // the location offset to hold the link target name 00740 // 00741 00742 if (RemainingName->Length != 0) { 00743 00744 RtlMoveMemory( (PVOID)((PUCHAR)NewRemainingName + InsertAmount), 00745 RemainingName->Buffer, 00746 RemainingName->Length ); 00747 } 00748 00749 // 00750 // Now insert the link target name 00751 // 00752 00753 RtlMoveMemory( NewRemainingName, LinkTargetName->Buffer, InsertAmount ); 00754 00755 // 00756 // Free the old complete name buffer and reset the input 00757 // strings to use the new buffer 00758 // 00759 00760 ExFreePool( CompleteName->Buffer ); 00761 00762 CompleteName->Buffer = NewName; 00763 CompleteName->Length = Length; 00764 CompleteName->MaximumLength = MaximumLength; 00765 00766 RemainingName->Buffer = NewRemainingName; 00767 RemainingName->Length = Length - (USHORT)((PCHAR)NewRemainingName - (PCHAR)NewName); 00768 RemainingName->MaximumLength = RemainingName->Length + sizeof( UNICODE_NULL ); 00769 00770 } else { 00771 00772 // 00773 // Insert extra text associated with this symbolic link name before 00774 // existing remaining name, if any. 00775 // 00776 // First shove over the remaining name to make a hole for the 00777 // link target name 00778 // 00779 00780 if (RemainingName->Length != 0) { 00781 00782 RtlMoveMemory( (PVOID)((PUCHAR)RemainingName->Buffer + InsertAmount), 00783 RemainingName->Buffer, 00784 RemainingName->Length ); 00785 } 00786 00787 // 00788 // Now insert the link target name 00789 // 00790 00791 RtlMoveMemory( RemainingName->Buffer, LinkTargetName->Buffer, InsertAmount ); 00792 00793 // 00794 // Adjust input strings to account for this inserted text 00795 // 00796 00797 CompleteName->Length += LinkTargetName->Length; 00798 00799 RemainingName->Length += LinkTargetName->Length; 00800 RemainingName->MaximumLength += RemainingName->Length + sizeof( UNICODE_NULL ); 00801 00802 CompleteName->Buffer[ CompleteName->Length / sizeof( WCHAR ) ] = UNICODE_NULL; 00803 } 00804 00805 // 00806 // Return the object address associated with snapped symbolic link 00807 // and the reparse object status code. 00808 // 00809 00810 *Object = SymbolicLink->LinkTargetObject; 00811 00812 Status = STATUS_REPARSE_OBJECT; 00813 leave; 00814 } 00815 00816 // 00817 // The symbolic has not yet been snapped 00818 // 00819 // Compute the size of the new name and check if the name will 00820 // fit in the existing complete name buffer. 00821 // 00822 00823 LinkTargetName = &SymbolicLink->LinkTarget; 00824 NewLength = LinkTargetName->Length + RemainingName->Length; 00825 00826 if (NewLength > 0xFFF0) { 00827 00828 Status = STATUS_NAME_TOO_LONG; 00829 leave; 00830 } 00831 00832 Length = (USHORT)NewLength; 00833 00834 if (CompleteName->MaximumLength <= Length) { 00835 00836 // 00837 // The new concatentated name is larger than the buffer supplied for 00838 // the complete name. 00839 // 00840 00841 MaximumLength = Length + sizeof( UNICODE_NULL ); 00842 NewName = ExAllocatePoolWithTag( NonPagedPool, MaximumLength, 'mNbO' ); 00843 00844 if (NewName == NULL) { 00845 00846 Status = STATUS_INSUFFICIENT_RESOURCES; 00847 leave; 00848 } 00849 00850 } else { 00851 00852 MaximumLength = CompleteName->MaximumLength; 00853 NewName = CompleteName->Buffer; 00854 } 00855 00856 // 00857 // Concatenate the symbolic link name with the remaining name, 00858 // if any. What this does is overwrite the front of the complete 00859 // name up to the remaining name with the links target name 00860 // 00861 00862 if (RemainingName->Length != 0) { 00863 00864 RtlMoveMemory( (PVOID)((PUCHAR)NewName + LinkTargetName->Length), 00865 RemainingName->Buffer, 00866 RemainingName->Length ); 00867 } 00868 00869 RtlMoveMemory( NewName, LinkTargetName->Buffer, LinkTargetName->Length ); 00870 00871 NewName[ Length / sizeof( WCHAR ) ] = UNICODE_NULL; 00872 00873 // 00874 // If a new name buffer was allocated, then free the original complete 00875 // name buffer. 00876 // 00877 00878 if (NewName != CompleteName->Buffer) { 00879 00880 ExFreePool( CompleteName->Buffer ); 00881 } 00882 00883 // 00884 // Set the new complete name buffer parameters and return a reparse 00885 // status. 00886 // 00887 00888 CompleteName->Buffer = NewName; 00889 CompleteName->Length = Length; 00890 CompleteName->MaximumLength = MaximumLength; 00891 00892 Status = STATUS_REPARSE; 00893 00894 } finally { 00895 00896 ObpLeaveRootDirectoryMutex(); 00897 } 00898 00899 return Status; 00900 }

VOID ObpProcessRemoveObjectQueue PVOID  Parameter  ) 
 

Definition at line 1299 of file obref.c.

References _OBJECT_HEADER::Body, FALSE, NULL, ObpLock, ObpRemoveObjectQueue, ObpRemoveObjectRoutine(), and ObpRemoveQueueActive.

Referenced by ObfDereferenceObject().

01305 : 01306 01307 This is the work routine for the remove object work queue. Its 01308 job is to remove and process items from the remove object queue. 01309 01310 Arguments: 01311 01312 Parameter - Ignored 01313 01314 Return Value: 01315 01316 None. 01317 01318 --*/ 01319 01320 { 01321 PSINGLE_LIST_ENTRY Entry; 01322 POBJECT_HEADER ObjectHeader; 01323 KIRQL OldIrql; 01324 01325 // 01326 // Lock the work queue this will keep the preceding routine 01327 // from monkeying with the queue 01328 // 01329 01330 ExAcquireSpinLock( &ObpLock, &OldIrql ); 01331 01332 // 01333 // While there are items in our private remove object work queue 01334 // then we remove each item, get back up to the object header, 01335 // and delete the object. The latter part done outside of the 01336 // work queue lock 01337 // 01338 01339 Entry = PopEntryList( (PSINGLE_LIST_ENTRY)&ObpRemoveObjectQueue ); 01340 01341 while ( Entry != NULL ) { 01342 01343 ExReleaseSpinLock( &ObpLock, OldIrql ); 01344 01345 ObjectHeader = CONTAINING_RECORD( Entry, 01346 OBJECT_HEADER, 01347 SEntry ); 01348 01349 ObpRemoveObjectRoutine( &ObjectHeader->Body ); 01350 01351 ExAcquireSpinLock( &ObpLock, &OldIrql ); 01352 01353 Entry = PopEntryList((PSINGLE_LIST_ENTRY)&ObpRemoveObjectQueue ); 01354 } 01355 01356 // 01357 // Indicate that we are now going inactive and then unlock 01358 // the work queue 01359 // 01360 01361 ObpRemoveQueueActive = FALSE; 01362 01363 ExReleaseSpinLock( &ObpLock, OldIrql ); 01364 01365 return; 01366 }

PSECURITY_DESCRIPTOR ObpReferenceSecurityDescriptor PVOID  Object  ) 
 

Definition at line 559 of file obsdata.c.

References ASSERT, _SECURITY_DESCRIPTOR_HEADER::FullHash, IF_OB_GLOBAL, NULL, OBJECT_TO_OBJECT_HEADER, ObpAcquireDescriptorCacheWriteLock(), ObpCentralizedSecurity, ObpReleaseDescriptorCacheLock(), ObPrint, _SECURITY_DESCRIPTOR_HEADER::RefCount, RtlValidSecurityDescriptor(), SD_TO_SD_HEADER, and _OBJECT_HEADER::Type.

Referenced by ObGetObjectSecurity().

00565 : 00566 00567 References the security descriptor of the passed object. 00568 00569 Arguments: 00570 00571 Object - Object being access validated. 00572 00573 Return Value: 00574 00575 The security descriptor of the object. 00576 00577 --*/ 00578 00579 { 00580 PSECURITY_DESCRIPTOR_HEADER SecurityDescriptorHeader; 00581 POBJECT_HEADER ObjectHeader; 00582 POBJECT_TYPE ObjectType; 00583 PSECURITY_DESCRIPTOR SecurityDescriptor; 00584 00585 // 00586 // Make sure the sure that the object in question is being 00587 // maintained by the system and doesn't have it own security 00588 // management routines. 00589 // 00590 // **** the first two lines should probably be only done on 00591 // a checked build 00592 // 00593 00594 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 00595 ObjectType = ObjectHeader->Type; 00596 ASSERT( ObpCentralizedSecurity(ObjectType) ); 00597 00598 // 00599 // Lock the security descriptor cache and get the objects 00600 // security descriptor 00601 // 00602 00603 ObpAcquireDescriptorCacheWriteLock(); 00604 00605 SecurityDescriptor = OBJECT_TO_OBJECT_HEADER( Object )->SecurityDescriptor; 00606 00607 IF_OB_GLOBAL( STOP_INVALID_DESCRIPTOR ) { 00608 00609 if((SecurityDescriptor != NULL) && 00610 (!RtlValidSecurityDescriptor ( SecurityDescriptor ))) { 00611 00612 DbgBreakPoint(); 00613 } 00614 } 00615 00616 // 00617 // If the object has a security descriptor then we need to 00618 // get the security descriptor header and increment its 00619 // ref count before releasing the lock and returning to 00620 // our caller 00621 // 00622 00623 if ( SecurityDescriptor != NULL ) { 00624 00625 SecurityDescriptorHeader = SD_TO_SD_HEADER( SecurityDescriptor ); 00626 ObPrint( SHOW_REFERENCES, ("Referencing Hash %lX, Refcount = %d \n",SecurityDescriptorHeader->FullHash,SecurityDescriptorHeader->RefCount)); 00627 SecurityDescriptorHeader->RefCount++; 00628 } 00629 00630 ObpReleaseDescriptorCacheLock(); 00631 00632 return( SecurityDescriptor ); 00633 }

VOID ObpReleaseDescriptorCacheLock VOID   ) 
 

Definition at line 942 of file obsdata.c.

References ExReleaseResource, KeLeaveCriticalRegion, ObsSecurityDescriptorCacheLock, and VOID().

Referenced by NtQueryObject(), ObDeassignSecurity(), ObpDereferenceSecurityDescriptor(), ObpLogSecurityDescriptor(), ObpReferenceSecurityDescriptor(), ObQuerySecurityDescriptorInfo(), and ObSetSecurityDescriptorInfo().

00948 : 00949 00950 Releases a lock on the security descriptor cache. 00951 00952 Arguments: 00953 00954 none 00955 00956 Return Value: 00957 00958 None. 00959 00960 --*/ 00961 00962 { 00963 (VOID)ExReleaseResource( &ObsSecurityDescriptorCacheLock ); 00964 KeLeaveCriticalRegion (); 00965 00966 return; 00967 }

VOID ObpRemoveObjectRoutine PVOID  Object  ) 
 

Definition at line 1370 of file obref.c.

References _OBJECT_TYPE_INITIALIZER::DeleteProcedure, DeleteSecurityDescriptor, ExFreePool(), _OBJECT_HEADER_NAME_INFO::Name, NTSTATUS(), NULL, OBJECT_HEADER_TO_CREATOR_INFO, OBJECT_HEADER_TO_NAME_INFO, OBJECT_TO_OBJECT_HEADER, ObpBeginTypeSpecificCallOut, ObpEndTypeSpecificCallOut, ObpEnterObjectTypeMutex, ObpFreeObject(), ObpLeaveObjectTypeMutex, ObpValidateIrql, PAGED_CODE, _OBJECT_HEADER::SecurityDescriptor, _OBJECT_TYPE_INITIALIZER::SecurityProcedure, Status, _OBJECT_HEADER::Type, _OBJECT_TYPE::TypeInfo, and _OBJECT_HEADER_CREATOR_INFO::TypeList.

Referenced by ObfDereferenceObject(), and ObpProcessRemoveObjectQueue().

01376 : 01377 01378 This routine is used to delete an object whose reference count has 01379 gone to zero. 01380 01381 Arguments: 01382 01383 Object - Supplies a pointer to the body of the object being deleted 01384 01385 Return Value: 01386 01387 None. 01388 01389 --*/ 01390 01391 { 01392 NTSTATUS Status; 01393 POBJECT_HEADER ObjectHeader; 01394 POBJECT_TYPE ObjectType; 01395 POBJECT_HEADER_CREATOR_INFO CreatorInfo; 01396 POBJECT_HEADER_NAME_INFO NameInfo; 01397 01398 PAGED_CODE(); 01399 01400 ObpValidateIrql( "ObpRemoveObjectRoutine" ); 01401 01402 // 01403 // Retrieve an object header from the object body, and also get 01404 // the object type, creator and name info if available 01405 // 01406 01407 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 01408 ObjectType = ObjectHeader->Type; 01409 CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO( ObjectHeader ); 01410 NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader ); 01411 01412 // 01413 // Get exclusive access to the object type object 01414 // 01415 01416 ObpEnterObjectTypeMutex( ObjectType ); 01417 01418 // 01419 // If there is a creator info record and we are on the list 01420 // for the object type then remove this object from the list 01421 // 01422 01423 if (CreatorInfo != NULL && !IsListEmpty( &CreatorInfo->TypeList )) { 01424 01425 RemoveEntryList( &CreatorInfo->TypeList ); 01426 } 01427 01428 // 01429 // If there is a name info record and the name buffer is not null 01430 // then free the buffer and zero out the name record 01431 // 01432 01433 if (NameInfo != NULL && NameInfo->Name.Buffer != NULL) { 01434 01435 ExFreePool( NameInfo->Name.Buffer ); 01436 01437 NameInfo->Name.Buffer = NULL; 01438 NameInfo->Name.Length = 0; 01439 NameInfo->Name.MaximumLength = 0; 01440 } 01441 01442 // 01443 // We are done with the object type object so we can now release it 01444 // 01445 01446 ObpLeaveObjectTypeMutex( ObjectType ); 01447 01448 // 01449 // Security descriptor deletion must precede the 01450 // call to the object's DeleteProcedure. Check if we have 01451 // a security descriptor and if so then call the routine 01452 // to delete the security descritpor. 01453 // 01454 01455 if (ObjectHeader->SecurityDescriptor != NULL) { 01456 01457 KIRQL SaveIrql; 01458 01459 ObpBeginTypeSpecificCallOut( SaveIrql ); 01460 01461 Status = (ObjectType->TypeInfo.SecurityProcedure)( Object, 01462 DeleteSecurityDescriptor, 01463 NULL, NULL, NULL, 01464 &ObjectHeader->SecurityDescriptor, 01465 0, 01466 NULL ); 01467 01468 ObpEndTypeSpecificCallOut( SaveIrql, "Security", ObjectType, Object ); 01469 } 01470 01471 // 01472 // Now if there is a delete callback for the object type invoke 01473 // the routine 01474 // 01475 01476 if (ObjectType->TypeInfo.DeleteProcedure) { 01477 01478 KIRQL SaveIrql; 01479 01480 ObpBeginTypeSpecificCallOut( SaveIrql ); 01481 01482 (*(ObjectType->TypeInfo.DeleteProcedure))( Object ); 01483 01484 ObpEndTypeSpecificCallOut( SaveIrql, "Delete", ObjectType, Object ); 01485 } 01486 01487 // 01488 // Finally return the object back to pool including releasing any quota 01489 // charges 01490 // 01491 01492 ObpFreeObject( Object ); 01493 }

VOID ObpUnlockObjectDirectoryPath IN POBJECT_DIRECTORY  LockedDirectory  ) 
 

NTSTATUS ObpValidateAccessMask PACCESS_STATE  AccessState  ) 
 

Definition at line 1886 of file obse.c.

References NULL, PAGED_CODE, _ACCESS_STATE::PreviouslyGrantedAccess, _ACCESS_STATE::RemainingDesiredAccess, and _ACCESS_STATE::SecurityDescriptor.

Referenced by ObInsertObject(), and ObOpenObjectByName().

01892 : 01893 01894 Checks the desired access mask of a passed object against the 01895 passed security descriptor. 01896 01897 Arguments: 01898 01899 AccessState - A pointer to the AccessState for the pending operation. 01900 01901 Return Value: 01902 01903 Only returns STATUS_SUCCESS 01904 01905 --*/ 01906 01907 { 01908 SECURITY_DESCRIPTOR *SecurityDescriptor = AccessState->SecurityDescriptor; 01909 01910 PAGED_CODE(); 01911 01912 // 01913 // First make sure the access state has a security descriptor. If there 01914 // is one and it has a system acl and the previously granted access did 01915 // not include system security then add the fact that we want system 01916 // security to the remaining desired access state. 01917 // 01918 01919 if (SecurityDescriptor != NULL) { 01920 01921 if ( SecurityDescriptor->Control & SE_SACL_PRESENT ) { 01922 01923 if ( !(AccessState->PreviouslyGrantedAccess & ACCESS_SYSTEM_SECURITY)) { 01924 01925 AccessState->RemainingDesiredAccess |= ACCESS_SYSTEM_SECURITY; 01926 } 01927 } 01928 } 01929 01930 return( STATUS_SUCCESS ); 01931 }

NTSTATUS ObpValidateDesiredAccess IN ACCESS_MASK  DesiredAccess  ) 
 

Definition at line 2752 of file obhandle.c.

Referenced by NtDuplicateObject().

02758 : 02759 02760 This routine checks the input desired access mask to see that 02761 some invalid bits are not set. The invalid bits are the top 02762 two reserved bits and the top three standard rights bits. 02763 See \nt\public\sdk\inc\ntseapi.h for more details. 02764 02765 Arguments: 02766 02767 DesiredAccess - Supplies the mask being checked 02768 02769 Return Value: 02770 02771 STATUS_ACCESS_DENIED if one or more of the wrongs bits are set and 02772 STATUS_SUCCESS otherwise 02773 02774 --*/ 02775 02776 { 02777 if (DesiredAccess & 0x0CE00000) { 02778 02779 return( STATUS_ACCESS_DENIED ); 02780 02781 } else { 02782 02783 return( STATUS_SUCCESS ); 02784 } 02785 }


Variable Documentation

NPAGED_LOOKASIDE_LIST ObpCreateInfoLookasideList
 

Definition at line 384 of file obp.h.

Referenced by ObInitSystem().

KEVENT ObpDefaultObject
 

Definition at line 88 of file obp.h.

Referenced by ObCreateObjectType(), and ObInitSystem().

KSPIN_LOCK ObpDeviceMapLock
 

Definition at line 98 of file obp.h.

Referenced by ObDereferenceDeviceMap(), ObInheritDeviceMap(), ObInitSystem(), ObpLookupObjectName(), ObQueryDeviceMapInformation(), and ObSetDeviceMap().

POBJECT_TYPE ObpDeviceMapObjectType
 

Definition at line 369 of file obp.h.

POBJECT_TYPE ObpDirectoryObjectType
 

Definition at line 367 of file obp.h.

Referenced by NtCreateDirectoryObject(), NtOpenDirectoryObject(), NtQueryDirectoryObject(), ObAssignSecurity(), ObInitSystem(), ObpLookupObjectName(), ObpProcessDosDeviceSymbolicLink(), ObSetDeviceMap(), and ObSetSecurityDescriptorInfo().

UNICODE_STRING ObpDosDevicesShortName
 

Definition at line 375 of file obp.h.

ULARGE_INTEGER ObpDosDevicesShortNamePrefix
 

Definition at line 373 of file obp.h.

ULARGE_INTEGER ObpDosDevicesShortNameRoot
 

Definition at line 374 of file obp.h.

PHANDLE_TABLE ObpKernelHandleTable
 

Definition at line 399 of file obp.h.

Referenced by NtClose(), NtSetInformationObject(), NtWaitForMultipleObjects(), ObInitSystem(), ObpCreateHandle(), ObpCreateUnnamedHandle(), and ObReferenceObjectByHandle().

KSPIN_LOCK ObpLock
 

Definition at line 87 of file obp.h.

Referenced by ObfDereferenceObject(), ObInitSystem(), and ObpProcessRemoveObjectQueue().

NPAGED_LOOKASIDE_LIST ObpNameBufferLookasideList
 

Definition at line 392 of file obp.h.

Referenced by ObInitSystem().

POBJECT_TYPE ObpObjectTypes[OBP_MAX_DEFINED_OBJECT_TYPES]
 

Definition at line 229 of file obp.h.

Referenced by NtQueryObject(), and ObCreateObjectType().

PSINGLE_LIST_ENTRY ObpRemoveObjectQueue
 

Definition at line 90 of file obp.h.

Referenced by ObfDereferenceObject(), ObInitSystem(), and ObpProcessRemoveObjectQueue().

WORK_QUEUE_ITEM ObpRemoveObjectWorkItem
 

Definition at line 89 of file obp.h.

Referenced by ObfDereferenceObject().

ERESOURCE ObpRootDirectoryMutex
 

Definition at line 377 of file obp.h.

Referenced by ObInitSystem().

POBJECT_DIRECTORY ObpRootDirectoryObject
 

Definition at line 370 of file obp.h.

POBJECT_TYPE ObpSymbolicLinkObjectType
 

Definition at line 368 of file obp.h.

Referenced by NtCreateSymbolicLinkObject(), NtOpenSymbolicLinkObject(), NtQueryObject(), NtQuerySymbolicLinkObject(), ObInitSystem(), ObInsertObject(), ObpDeleteNameCheck(), ObpProcessDosDeviceSymbolicLink(), and ObReferenceObjectByPointer().

POBJECT_DIRECTORY ObpTypeDirectoryObject
 

Definition at line 371 of file obp.h.

Referenced by ObCreateObjectType(), and ObInitSystem().

POBJECT_TYPE ObpTypeObjectType
 

Definition at line 366 of file obp.h.

ERESOURCE SecurityDescriptorCacheLock
 

Definition at line 378 of file obp.h.


Generated on Sat May 15 19:44:59 2004 for test by doxygen 1.3.7