Author: fireball
Date: Tue Apr 1 16:09:28 2008
New Revision: 32814
URL:
http://svn.reactos.org/svn/reactos?rev=32814&view=rev
Log:
- Rewrite the SD Cache functions to use the Windows 2003 structures (thanks to Alex for
providing them).
- Use pushlocks instead of the fast mutex that was previously used.
- Improve the performance of some paths by reducing lock acquisition time, and using
atomic operations instead when possible.
- Implement the exported Ob APIs which were added in Windows XP to access the Sd cache
(ObReference/DereferenceSecurityDescriptor and ObLogSecurityDescriptor). These are used by
file systems (such as NPFS) on Windows XP and higher.
Added:
trunk/reactos/ntoskrnl/ob/obsdcach.c
- copied, changed from r32796, trunk/reactos/ntoskrnl/ob/sdcache.c
Removed:
trunk/reactos/ntoskrnl/ob/sdcache.c
Modified:
trunk/reactos/ntoskrnl/include/internal/ob.h
trunk/reactos/ntoskrnl/include/internal/ob_x.h
trunk/reactos/ntoskrnl/ob/obsecure.c
Modified: trunk/reactos/ntoskrnl/include/internal/ob.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ob.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/ob.h [iso-8859-1] Tue Apr 1 16:09:28 2008
@@ -83,6 +83,18 @@
((POBJECT_HEADER)((ULONG_PTR)x->Object & ~OBJ_HANDLE_ATTRIBUTES))
//
+// Recovers the security descriptor from a cached security descriptor header
+//
+#define ObpGetHeaderForSd(x) \
+ CONTAINING_RECORD((x), SECURITY_DESCRIPTOR_HEADER, SecurityDescriptor)
+
+//
+// Recovers the security descriptor from a cached security descriptor list entry
+//
+#define ObpGetHeaderForEntry(x) \
+ CONTAINING_RECORD((x), SECURITY_DESCRIPTOR_HEADER, Link)
+
+//
// Context Structures for Ex*Handle Callbacks
//
typedef struct _OBP_SET_HANDLE_ATTRIBUTES_CONTEXT
@@ -90,17 +102,39 @@
KPROCESSOR_MODE PreviousMode;
OBJECT_HANDLE_ATTRIBUTE_INFORMATION Information;
} OBP_SET_HANDLE_ATTRIBUTES_CONTEXT, *POBP_SET_HANDLE_ATTRIBUTES_CONTEXT;
+
typedef struct _OBP_CLOSE_HANDLE_CONTEXT
{
PHANDLE_TABLE HandleTable;
KPROCESSOR_MODE AccessMode;
} OBP_CLOSE_HANDLE_CONTEXT, *POBP_CLOSE_HANDLE_CONTEXT;
+
typedef struct _OBP_FIND_HANDLE_DATA
{
POBJECT_HEADER ObjectHeader;
POBJECT_TYPE ObjectType;
POBJECT_HANDLE_INFORMATION HandleInformation;
} OBP_FIND_HANDLE_DATA, *POBP_FIND_HANDLE_DATA;
+
+//
+// Cached Security Descriptor Header
+//
+typedef struct _SECURITY_DESCRIPTOR_HEADER
+{
+ LIST_ENTRY Link;
+ ULONG RefCount;
+ ULONG FullHash;
+ QUAD SecurityDescriptor;
+} SECURITY_DESCRIPTOR_HEADER, *PSECURITY_DESCRIPTOR_HEADER;
+
+//
+// Cached Security Descriptor List
+//
+typedef struct _OB_SD_CACHE_LIST
+{
+ EX_PUSH_LOCK PushLock;
+ LIST_ENTRY Head;
+} OB_SD_CACHE_LIST, *POB_SD_CACHE_LIST;
//
// Structure for quick-compare of a DOS Device path
@@ -388,23 +422,10 @@
VOID
);
-NTSTATUS
-NTAPI
-ObpAddSecurityDescriptor(
- IN PSECURITY_DESCRIPTOR SourceSD,
- OUT PSECURITY_DESCRIPTOR *DestinationSD
-);
-
PSECURITY_DESCRIPTOR
NTAPI
-ObpReferenceCachedSecurityDescriptor(
- IN PSECURITY_DESCRIPTOR SecurityDescriptor
-);
-
-VOID
-NTAPI
-ObpDereferenceCachedSecurityDescriptor(
- IN PSECURITY_DESCRIPTOR SecurityDescriptor
+ObpReferenceSecurityDescriptor(
+ IN POBJECT_HEADER ObjectHeader
);
//
Modified: trunk/reactos/ntoskrnl/include/internal/ob_x.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ob_x.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/ob_x.h [iso-8859-1] Tue Apr 1 16:09:28 2008
@@ -29,13 +29,13 @@
{
ULONG Slot;
POBJECT_TYPE ObjectType = ObjectHeader->Type;
-
+
/* Sanity check */
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
-
+
/* Pick a slot */
Slot = ObpSelectObjectLockSlot(ObjectHeader);
-
+
/* Enter a critical region and acquire the resource */
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&ObjectType->ObjectLocks[Slot], TRUE);
@@ -47,13 +47,13 @@
{
ULONG Slot;
POBJECT_TYPE ObjectType = ObjectHeader->Type;
-
+
/* Sanity check */
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
-
+
/* Pick a slot */
Slot = ObpSelectObjectLockSlot(ObjectHeader);
-
+
/* Enter a critical region and acquire the resource */
KeEnterCriticalRegion();
ExAcquireResourceSharedLite(&ObjectType->ObjectLocks[Slot], TRUE);
@@ -65,14 +65,14 @@
{
ULONG Slot;
POBJECT_TYPE ObjectType = ObjectHeader->Type;
-
+
/* Pick a slot */
Slot = ObpSelectObjectLockSlot(ObjectHeader);
-
- /* Enter a critical region and acquire the resource */
+
+ /* Release the resource and leave a critical region */
ExReleaseResourceLite(&ObjectType->ObjectLocks[Slot]);
KeLeaveCriticalRegion();
-
+
/* Sanity check */
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
}
Copied: trunk/reactos/ntoskrnl/ob/obsdcach.c (from r32796,
trunk/reactos/ntoskrnl/ob/sdcache.c)
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obsdcach.c?p2=…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/sdcache.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ob/obsdcach.c [iso-8859-1] Tue Apr 1 16:09:28 2008
@@ -7,344 +7,330 @@
* PROGRAMMERS: David Welch (welch(a)cwcom.net)
*/
-/* INCLUDES *****************************************************************/
+/* INCLUDES *******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
-#include <internal/debug.h>
-
-
-/* TYPES ********************************************************************/
-
-typedef struct _SD_CACHE_ENTRY
-{
- LIST_ENTRY ListEntry;
- ULONG HashValue;
- ULONG Index;
- ULONG RefCount;
-} SD_CACHE_ENTRY, *PSD_CACHE_ENTRY;
-
-
-/* GLOBALS ******************************************************************/
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
#define SD_CACHE_ENTRIES 0x100
-
-LIST_ENTRY ObpSdCache[SD_CACHE_ENTRIES];
-FAST_MUTEX ObpSdCacheMutex;
-
-/* FUNCTIONS ****************************************************************/
+OB_SD_CACHE_LIST ObsSecurityDescriptorCache[SD_CACHE_ENTRIES];
+
+ULONGLONG Cycles;
+ULONG TimeDelta;
+
+#define ObpSdCacheBeginPerfCount() \
+ Cycles = __rdtsc();
+
+#define ObpSdCacheEndPerfCount() \
+ TimeDelta += __rdtsc() - Cycles;
+
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+VOID
+FORCEINLINE
+ObpSdAcquireLock(IN POB_SD_CACHE_LIST CacheEntry)
+{
+ /* Acquire the lock */
+ KeEnterCriticalRegion();
+ ExAcquirePushLockExclusive(&CacheEntry->PushLock);
+}
+
+VOID
+FORCEINLINE
+ObpSdReleaseLock(IN POB_SD_CACHE_LIST CacheEntry)
+{
+ /* Release the lock */
+ ExReleasePushLockExclusive(&CacheEntry->PushLock);
+ KeLeaveCriticalRegion();
+}
+
+VOID
+FORCEINLINE
+ObpSdAcquireLockShared(IN POB_SD_CACHE_LIST CacheEntry)
+{
+ /* Acquire the lock */
+ KeEnterCriticalRegion();
+ ExAcquirePushLockShared(&CacheEntry->PushLock);
+}
+
+VOID
+FORCEINLINE
+ObpSdReleaseLockShared(IN POB_SD_CACHE_LIST CacheEntry)
+{
+ /* Release the lock */
+ ExReleasePushLock(&CacheEntry->PushLock);
+ KeLeaveCriticalRegion();
+}
NTSTATUS
NTAPI
ObpInitSdCache(VOID)
{
- ULONG i;
-
- for (i = 0; i < (sizeof(ObpSdCache) / sizeof(ObpSdCache[0])); i++)
- {
- InitializeListHead(&ObpSdCache[i]);
- }
-
- ExInitializeFastMutex(&ObpSdCacheMutex);
-
- return STATUS_SUCCESS;
-}
-
-
-static __inline VOID
-ObpSdCacheLock(VOID)
-{
- /* can't acquire a fast mutex in the early boot process... */
- if(KeGetCurrentThread() != NULL)
- {
- ExAcquireFastMutex(&ObpSdCacheMutex);
- }
-}
-
-
-static __inline VOID
-ObpSdCacheUnlock(VOID)
-{
- /* can't acquire a fast mutex in the early boot process... */
- if(KeGetCurrentThread() != NULL)
- {
- ExReleaseFastMutex(&ObpSdCacheMutex);
- }
-}
-
-
-static ULONG
-ObpHash(PVOID Buffer,
- ULONG Length)
-{
- PUCHAR Ptr;
- ULONG Value;
- ULONG i;
-
- Ptr = (PUCHAR)Buffer;
- Value = 0;
- for (i = 0; i < Length; i++)
- {
- Value += *Ptr;
- Ptr++;
- }
-
- return Value;
-}
-
-
-static ULONG
-ObpHashSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
-{
- ULONG Value;
- BOOLEAN Defaulted;
- BOOLEAN DaclPresent;
- BOOLEAN SaclPresent;
- PSID Owner = NULL;
- PSID Group = NULL;
- PACL Dacl = NULL;
- PACL Sacl = NULL;
-
- RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
- &Owner,
- &Defaulted);
-
- RtlGetGroupSecurityDescriptor(SecurityDescriptor,
- &Group,
- &Defaulted);
-
- RtlGetDaclSecurityDescriptor(SecurityDescriptor,
- &DaclPresent,
- &Dacl,
- &Defaulted);
-
- RtlGetSaclSecurityDescriptor(SecurityDescriptor,
- &SaclPresent,
- &Sacl,
- &Defaulted);
-
- Value = 0;
- if (Owner != NULL)
- {
- Value += ObpHash(Owner, RtlLengthSid(Owner));
- }
-
- if (Group != NULL)
- {
- Value += ObpHash(Group, RtlLengthSid(Group));
- }
-
- if (DaclPresent == TRUE && Dacl != NULL)
- {
- Value += ObpHash(Dacl, Dacl->AclSize);
- }
-
- if (SaclPresent == TRUE && Sacl != NULL)
- {
- Value += ObpHash(Sacl, Sacl->AclSize);
- }
-
- return Value;
-}
-
-
-static PSD_CACHE_ENTRY
+ ULONG i;
+
+ /* Loop each cache entry */
+ for (i = 0; i < SD_CACHE_ENTRIES; i++)
+ {
+ /* Initialize the lock and the list */
+ InitializeListHead(&ObsSecurityDescriptorCache[i].Head);
+ ExInitializePushLock((PULONG_PTR)&ObsSecurityDescriptorCache[i].PushLock);
+ }
+
+ /* Return success */
+ return STATUS_SUCCESS;
+}
+
+ULONG
+NTAPI
+ObpHash(IN PVOID Buffer,
+ IN ULONG Length)
+{
+ PULONG p, pp;
+ PUCHAR pb, ppb;
+ ULONG Hash = 0;
+
+ /* Setup aligned and byte buffers */
+ p = Buffer;
+ ppb = (PUCHAR)((ULONG_PTR)Buffer + Length);
+ pp = (PULONG)ALIGN_DOWN(p + Length, ULONG);
+
+ /* Loop aligned data */
+ while (p < pp)
+ {
+ /* XOR-rotate */
+ Hash ^= *p++;
+ Hash = _rotl(Hash, 3);
+ }
+
+ /* Loop non-aligned data */
+ pb = (PUCHAR)p;
+ while (pb < ppb)
+ {
+ /* XOR-rotate */
+ Hash ^= *pb++;
+ Hash = _rotl(Hash, 3);
+ }
+
+ /* Return the hash */
+ return Hash;
+}
+
+ULONG
+NTAPI
+ObpHashSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
+ IN ULONG Length)
+{
+ /* Just hash the entire SD */
+ return ObpHash(SecurityDescriptor, Length);
+}
+
+PSECURITY_DESCRIPTOR_HEADER
+NTAPI
ObpCreateCacheEntry(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
- IN ULONG HashValue,
- IN ULONG Index,
- OUT PSECURITY_DESCRIPTOR *NewSD)
-{
- PSECURITY_DESCRIPTOR Sd;
- PSD_CACHE_ENTRY CacheEntry;
- ULONG Length;
-
- DPRINT("ObpCreateCacheEntry() called\n");
-
- Length = RtlLengthSecurityDescriptor(SecurityDescriptor);
-
- CacheEntry = ExAllocatePool(NonPagedPool,
- sizeof(SD_CACHE_ENTRY) + Length);
- if (CacheEntry == NULL)
- {
- DPRINT1("ExAllocatePool() failed\n");
- return NULL;
- }
-
- CacheEntry->HashValue = HashValue;
- CacheEntry->Index = Index;
- CacheEntry->RefCount = 1;
-
- Sd = (PSECURITY_DESCRIPTOR)(CacheEntry + 1);
- RtlCopyMemory(Sd,
- SecurityDescriptor,
- Length);
-
- *NewSD = Sd;
-
- DPRINT("ObpCreateCacheEntry() done\n");
-
- return CacheEntry;
-}
-
-
-static BOOLEAN
+ IN ULONG Length,
+ IN ULONG FullHash,
+ IN ULONG RefCount)
+{
+ ULONG CacheSize;
+ PSECURITY_DESCRIPTOR_HEADER SdHeader;
+ ASSERT(Length == RtlLengthSecurityDescriptor(SecurityDescriptor));
+
+ /* Calculate the memory we'll need to allocate and allocate it */
+ CacheSize = Length + (sizeof(SECURITY_DESCRIPTOR_HEADER) - sizeof(QUAD));
+ SdHeader = ExAllocatePoolWithTag(PagedPool, CacheSize, TAG('O', 'b',
'S', 'c'));
+ if (!SdHeader) return NULL;
+
+ /* Setup the header */
+ SdHeader->RefCount = RefCount;
+ SdHeader->FullHash = FullHash;
+
+ /* Copy the descriptor */
+ RtlCopyMemory(&SdHeader->SecurityDescriptor, SecurityDescriptor, Length);
+
+ /* Return it */
+ return SdHeader;
+}
+
+BOOLEAN
+NTAPI
ObpCompareSecurityDescriptors(IN PSECURITY_DESCRIPTOR Sd1,
- IN PSECURITY_DESCRIPTOR Sd2)
-{
- ULONG Length1;
- ULONG Length2;
-
- Length1 = RtlLengthSecurityDescriptor(Sd1);
- Length2 = RtlLengthSecurityDescriptor(Sd2);
- if (Length1 != Length2)
- return FALSE;
-
- if (RtlCompareMemory(Sd1, Sd2, Length1) != Length1)
- return FALSE;
-
- return TRUE;
-}
-
-
-NTSTATUS
-NTAPI
-ObpAddSecurityDescriptor(IN PSECURITY_DESCRIPTOR SourceSD,
- OUT PSECURITY_DESCRIPTOR *DestinationSD)
-{
- PSECURITY_DESCRIPTOR Sd;
- PLIST_ENTRY CurrentEntry;
- PSD_CACHE_ENTRY CacheEntry;
- ULONG HashValue;
- ULONG Index;
- NTSTATUS Status;
-
- DPRINT("ObpAddSecurityDescriptor() called\n");
-
- HashValue = ObpHashSecurityDescriptor(SourceSD);
- Index = HashValue & 0xFF;
-
- ObpSdCacheLock();
-
- if (!IsListEmpty(&ObpSdCache[Index]))
- {
- CurrentEntry = ObpSdCache[Index].Flink;
- while (CurrentEntry != &ObpSdCache[Index])
- {
- CacheEntry = CONTAINING_RECORD(CurrentEntry,
- SD_CACHE_ENTRY,
- ListEntry);
- Sd = (PSECURITY_DESCRIPTOR)(CacheEntry + 1);
-
- if (CacheEntry->HashValue == HashValue &&
- ObpCompareSecurityDescriptors(SourceSD, Sd))
- {
- CacheEntry->RefCount++;
- DPRINT("RefCount %lu\n", CacheEntry->RefCount);
- *DestinationSD = Sd;
-
- ObpSdCacheUnlock();
-
- DPRINT("ObpAddSecurityDescriptor() done\n");
-
- return STATUS_SUCCESS;
- }
-
- CurrentEntry = CurrentEntry->Flink;
- }
- }
-
- CacheEntry = ObpCreateCacheEntry(SourceSD,
- HashValue,
- Index,
- DestinationSD);
- if (CacheEntry == NULL)
- {
- DPRINT1("ObpCreateCacheEntry() failed\n");
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
- else
- {
- DPRINT("RefCount 1\n");
- InsertTailList(&ObpSdCache[Index], &CacheEntry->ListEntry);
- Status = STATUS_SUCCESS;
- }
-
- ObpSdCacheUnlock();
-
- DPRINT("ObpAddSecurityDescriptor() done\n");
-
- return Status;
-}
-
-
-NTSTATUS
-NTAPI
-ObpRemoveSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
-{
- PSD_CACHE_ENTRY CacheEntry;
-
- DPRINT("ObpRemoveSecurityDescriptor() called\n");
-
- ObpSdCacheLock();
-
- CacheEntry = (PSD_CACHE_ENTRY)((ULONG_PTR)SecurityDescriptor -
sizeof(SD_CACHE_ENTRY));
-
- CacheEntry->RefCount--;
- DPRINT("RefCount %lu\n", CacheEntry->RefCount);
- if (CacheEntry->RefCount == 0)
- {
- DPRINT("Remove cache entry\n");
- RemoveEntryList(&CacheEntry->ListEntry);
- ExFreePool(CacheEntry);
- }
-
- ObpSdCacheUnlock();
-
- DPRINT("ObpRemoveSecurityDescriptor() done\n");
-
- return STATUS_SUCCESS;
+ IN ULONG Length1,
+ IN PSECURITY_DESCRIPTOR Sd2)
+{
+ ULONG Length2;
+ ASSERT(Length1 == RtlLengthSecurityDescriptor(Sd1));
+
+ /* Get the length of the second SD */
+ Length2 = RtlLengthSecurityDescriptor(Sd2);
+
+ /* Compare lengths */
+ if (Length1 != Length2) return FALSE;
+
+ /* Compare contents */
+ return RtlEqualMemory(Sd1, Sd2, Length1);
+}
+
+PVOID
+NTAPI
+ObpDestroySecurityDescriptorHeader(IN PSECURITY_DESCRIPTOR_HEADER SdHeader)
+{
+ ASSERT(SdHeader->RefCount == 0);
+
+ /* Just unlink the SD and return it back to the caller */
+ RemoveEntryList(&SdHeader->Link);
+ return SdHeader;
}
PSECURITY_DESCRIPTOR
NTAPI
-ObpReferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
-{
- PSD_CACHE_ENTRY CacheEntry;
-
- /* Lock the cache */
- ObpSdCacheLock();
-
- /* Make sure we got a descriptor */
- if (SecurityDescriptor)
- {
- /* Get the entry */
- CacheEntry = (PSD_CACHE_ENTRY)((ULONG_PTR)SecurityDescriptor -
- sizeof(SD_CACHE_ENTRY));
-
- /* Reference it */
- CacheEntry->RefCount++;
- DPRINT("RefCount %lu\n", CacheEntry->RefCount);
- }
-
- /* Unlock the cache and return the descriptor */
- ObpSdCacheUnlock();
+ObpReferenceSecurityDescriptor(IN POBJECT_HEADER ObjectHeader)
+{
+ PSECURITY_DESCRIPTOR SecurityDescriptor;
+ PSECURITY_DESCRIPTOR_HEADER SdHeader;
+ ObpSdCacheBeginPerfCount();
+
+ /* Get the SD */
+ SecurityDescriptor = ObjectHeader->SecurityDescriptor;
+ if (!SecurityDescriptor)
+ {
+ /* No SD, nothing to do */
+ ObpSdCacheEndPerfCount();
+ return NULL;
+ }
+
+ /* Lock the object */
+ ObpAcquireObjectLockShared(ObjectHeader);
+
+ /* Get the object header */
+ SdHeader = ObpGetHeaderForSd(SecurityDescriptor);
+
+ /* Do the reference */
+ InterlockedIncrement((PLONG)&SdHeader->RefCount);
+
+ /* Release the lock and return */
+ ObpReleaseObjectLock(ObjectHeader);
+ ObpSdCacheEndPerfCount();
return SecurityDescriptor;
}
-VOID
-NTAPI
-ObpDereferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
-{
- DPRINT("ObpDereferenceCachedSecurityDescriptor() called\n");
-
- ObpRemoveSecurityDescriptor(SecurityDescriptor);
-
- DPRINT("ObpDereferenceCachedSecurityDescriptor() done\n");
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+/*++
+ * @name ObReferenceSecurityDescriptor
+ * @implemented NT5.2
+ *
+ * The ObReferenceSecurityDescriptor routine <FILLMEIN>
+ *
+ * @param SecurityDescriptor
+ * <FILLMEIN>
+ *
+ * @param Count
+ * <FILLMEIN>
+ *
+ * @return STATUS_SUCCESS or appropriate error value.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+NTAPI
+ObReferenceSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
+ IN ULONG Count)
+{
+ PSECURITY_DESCRIPTOR_HEADER SdHeader;
+ ObpSdCacheBeginPerfCount();
+
+ /* Get the header */
+ SdHeader = ObpGetHeaderForSd(SecurityDescriptor);
+
+ /* Do the references */
+ InterlockedExchangeAdd((PLONG)&SdHeader->RefCount, Count);
+ ObpSdCacheEndPerfCount();
+}
+
+/*++
+ * @name ObDereferenceSecurityDescriptor
+ * @implemented NT5.2
+ *
+ * The ObDereferenceSecurityDescriptor routine <FILLMEIN>
+ *
+ * @param SecurityDescriptor
+ * <FILLMEIN>
+ *
+ * @param Count
+ * <FILLMEIN>
+ *
+ * @return STATUS_SUCCESS or appropriate error value.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+NTAPI
+ObDereferenceSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
+ IN ULONG Count)
+{
+ PSECURITY_DESCRIPTOR_HEADER SdHeader;
+ LONG OldValue, NewValue;
+ ULONG Index;
+ POB_SD_CACHE_LIST CacheEntry;
+ ObpSdCacheBeginPerfCount();
+
+ /* Get the header */
+ SdHeader = ObpGetHeaderForSd(SecurityDescriptor);
+
+ /* Get the current reference count */
+ OldValue = SdHeader->RefCount;
+
+ /* Check if the caller is destroying this SD -- we need the lock for that */
+ while (OldValue != Count)
+ {
+ /* He isn't, we can just try to derefeference atomically */
+ NewValue = InterlockedCompareExchange((PLONG)&SdHeader->RefCount,
+ OldValue - Count,
+ OldValue);
+ if (NewValue == OldValue) ObpSdCacheEndPerfCount(); return;
+
+ /* Try again */
+ OldValue = NewValue;
+ }
+
+ /* At this point, we need the lock, so choose an entry */
+ Index = SdHeader->FullHash % SD_CACHE_ENTRIES;
+ CacheEntry = &ObsSecurityDescriptorCache[Index];
+
+ /* Acquire the lock for it */
+ ObpSdAcquireLock(CacheEntry);
+ ASSERT(SdHeader->RefCount != 0);
+
+ /* Now do the dereference */
+ if (InterlockedExchangeAdd((PLONG)&SdHeader->RefCount, -(LONG)Count) ==
Count)
+ {
+ /* We're down to zero -- destroy the header */
+ SdHeader = ObpDestroySecurityDescriptorHeader(SdHeader);
+
+ /* Release the lock */
+ ObpSdReleaseLock(CacheEntry);
+
+ /* Free the header */
+ ExFreePool(SdHeader);
+ }
+ else
+ {
+ /* Just release the lock */
+ ObpSdReleaseLock(CacheEntry);
+ }
+
+ ObpSdCacheEndPerfCount();
}
/*++
* @name ObLogSecurityDescriptor
-* @unimplemented NT5.2
+* @implemented NT5.2
*
* The ObLogSecurityDescriptor routine <FILLMEIN>
*
@@ -368,42 +354,107 @@
OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor,
IN ULONG RefBias)
{
- /* HACK: Return the same descriptor back */
- PISECURITY_DESCRIPTOR SdCopy;
- ULONG Length;
- DPRINT("ObLogSecurityDescriptor is not implemented!\n",
- InputSecurityDescriptor);
-
+ PSECURITY_DESCRIPTOR_HEADER SdHeader = NULL, NewHeader = NULL;
+ ULONG Length, Hash, Index;
+ POB_SD_CACHE_LIST CacheEntry;
+ BOOLEAN Result;
+ PLIST_ENTRY NextEntry;
+ ObpSdCacheBeginPerfCount();
+
+ /* Get the length */
Length = RtlLengthSecurityDescriptor(InputSecurityDescriptor);
- SdCopy = ExAllocatePool(PagedPool, Length);
- RtlCopyMemory(SdCopy, InputSecurityDescriptor, Length);
- *OutputSecurityDescriptor = SdCopy;
+
+ /* Get the hash */
+ Hash = ObpHashSecurityDescriptor(InputSecurityDescriptor, Length);
+
+ /* Now select the appropriate cache entry */
+ Index = Hash % SD_CACHE_ENTRIES;
+ CacheEntry = &ObsSecurityDescriptorCache[Index];
+
+ /* Lock it shared */
+ ObpSdAcquireLockShared(CacheEntry);
+
+ /* Start our search */
+ while (TRUE)
+ {
+ /* Reset result found */
+ Result = FALSE;
+
+ /* Loop the hash list */
+ NextEntry = CacheEntry->Head.Flink;
+ while (NextEntry != &CacheEntry->Head)
+ {
+ /* Get the header */
+ SdHeader = ObpGetHeaderForEntry(NextEntry);
+
+ /* Our hashes are ordered, so quickly check if we should stop now */
+ if (SdHeader->FullHash > Hash) break;
+
+ /* We survived the quick hash check, now check for equalness */
+ if (SdHeader->FullHash == Hash)
+ {
+ /* Hashes match, now compare descriptors */
+ Result = ObpCompareSecurityDescriptors(InputSecurityDescriptor,
+ Length,
+
&SdHeader->SecurityDescriptor);
+ if (Result) break;
+ }
+
+ /* Go to the next entry */
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* Check if we found anything */
+ if (Result)
+ {
+ /* Increment its reference count */
+ InterlockedExchangeAdd((PLONG)&SdHeader->RefCount, RefBias);
+
+ /* Release the lock */
+ ObpSdReleaseLockShared(CacheEntry);
+
+ /* Return the descriptor */
+ *OutputSecurityDescriptor = &SdHeader->SecurityDescriptor;
+
+ /* Free anything that we may have had to create */
+ if (NewHeader) ExFreePool(NewHeader);
+ ObpSdCacheEndPerfCount();
+ return STATUS_SUCCESS;
+ }
+
+ /* Check if we got here, and didn't create a descriptor yet */
+ if (!NewHeader)
+ {
+ /* Release the lock */
+ ObpSdReleaseLockShared(CacheEntry);
+
+ /* This should be our first time in the loop, create it */
+ NewHeader = ObpCreateCacheEntry(InputSecurityDescriptor,
+ Length,
+ Hash,
+ RefBias);
+ if (!NewHeader) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Now acquire the exclusive lock and we should hit the right path */
+ ObpSdAcquireLock(CacheEntry);
+ }
+ else
+ {
+ /* We have inserted the SD, we're fine now */
+ break;
+ }
+ }
+
+ /* Okay, now let's do the insert, we should have the exclusive lock */
+ InsertTailList(NextEntry, &NewHeader->Link);
+
+ /* Release the lock */
+ ObpSdReleaseLock(CacheEntry);
+
+ /* Return the SD*/
+ *OutputSecurityDescriptor = &NewHeader->SecurityDescriptor;
+ ObpSdCacheEndPerfCount();
return STATUS_SUCCESS;
}
-/*++
-* @name ObDereferenceSecurityDescriptor
-* @unimplemented NT5.2
-*
-* The ObDereferenceSecurityDescriptor routine <FILLMEIN>
-*
-* @param SecurityDescriptor
-* <FILLMEIN>
-*
-* @param Count
-* <FILLMEIN>
-*
-* @return STATUS_SUCCESS or appropriate error value.
-*
-* @remarks None.
-*
-*--*/
-VOID
-NTAPI
-ObDereferenceSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
- IN ULONG Count)
-{
- DPRINT1("ObDereferenceSecurityDescriptor is not implemented!\n");
-}
-
/* EOF */
Modified: trunk/reactos/ntoskrnl/ob/obsecure.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obsecure.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obsecure.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ob/obsecure.c [iso-8859-1] Tue Apr 1 16:09:28 2008
@@ -25,7 +25,7 @@
NTSTATUS Status;
PSECURITY_DESCRIPTOR NewSd;
PAGED_CODE();
-
+
/* Get the object header */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
if (!SecurityDescriptor)
@@ -34,19 +34,19 @@
ObjectHeader->SecurityDescriptor = NULL;
return STATUS_SUCCESS;
}
-
+
/* Add it to our internal cache */
- Status = ObpAddSecurityDescriptor(SecurityDescriptor, &NewSd);
+ Status = ObLogSecurityDescriptor(SecurityDescriptor, &NewSd, 1);
if (NT_SUCCESS(Status))
{
/* Free the old copy */
ExFreePool(SecurityDescriptor);
-
+
/* Set the new pointer */
ASSERT(NewSd);
ObjectHeader->SecurityDescriptor = NewSd;
}
-
+
/* Return status */
return Status;
}
@@ -56,11 +56,11 @@
ObDeassignSecurity(IN OUT PSECURITY_DESCRIPTOR *SecurityDescriptor)
{
/* Dereference it */
- ObpDereferenceCachedSecurityDescriptor(*SecurityDescriptor);
-
+ ObDereferenceSecurityDescriptor(*SecurityDescriptor, 1);
+
/* Don't free again later */
*SecurityDescriptor = NULL;
-
+
/* All done */
return STATUS_SUCCESS;
}
@@ -77,13 +77,13 @@
NTSTATUS Status;
PSECURITY_DESCRIPTOR ObjectSd;
PAGED_CODE();
-
+
/* Get the object header */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
-
+
/* Get the SD */
- ObjectSd =
ObpReferenceCachedSecurityDescriptor(ObjectHeader->SecurityDescriptor);
-
+ ObjectSd = ObpReferenceSecurityDescriptor(ObjectHeader);
+
/* Query the information */
Status = SeQuerySecurityDescriptorInfo(SecurityInformation,
SecurityDescriptor,
@@ -91,8 +91,8 @@
&ObjectSd);
/* Check if we have an object SD and dereference it, if so */
- if (ObjectSd) ObpDereferenceCachedSecurityDescriptor(ObjectSd);
-
+ if (ObjectSd) ObDereferenceSecurityDescriptor(ObjectSd, 1);
+
/* Return status */
return Status;
}
@@ -110,15 +110,15 @@
POBJECT_HEADER ObjectHeader;
PSECURITY_DESCRIPTOR OldDescriptor, NewDescriptor, CachedDescriptor;
PAGED_CODE();
-
+
/* Get the object header */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
while (TRUE)
{
/* Reference the old descriptor */
- OldDescriptor =
ObpReferenceCachedSecurityDescriptor(ObjectHeader->SecurityDescriptor);
+ OldDescriptor = ObpReferenceSecurityDescriptor(ObjectHeader);
NewDescriptor = OldDescriptor;
-
+
/* Set the SD information */
Status = SeSetSecurityDescriptorInfo(Object,
SecurityInformation,
@@ -129,39 +129,39 @@
if (NT_SUCCESS(Status))
{
/* Now add this to the cache */
- Status = ObpAddSecurityDescriptor(NewDescriptor, &CachedDescriptor);
-
+ Status = ObLogSecurityDescriptor(NewDescriptor, &CachedDescriptor, 1);
+
/* Let go of our uncached copy */
ExFreePool(NewDescriptor);
-
+
/* Check for success */
if (NT_SUCCESS(Status))
{
/* Dereference the old one */
ASSERT(OldDescriptor == ObjectHeader->SecurityDescriptor);
-
+
/* Now set this as the new descriptor */
ObjectHeader->SecurityDescriptor = CachedDescriptor;
-
+
/* And dereference the old one */
- ObpDereferenceCachedSecurityDescriptor(OldDescriptor);
+ ObDereferenceSecurityDescriptor(OldDescriptor, 1);
break;
}
else
{
/* We failed, dereference the old one */
- ObpDereferenceCachedSecurityDescriptor(OldDescriptor);
+ ObDereferenceSecurityDescriptor(OldDescriptor, 1);
break;
}
}
else
{
/* We failed, dereference the old one */
- if (OldDescriptor) ObpDereferenceCachedSecurityDescriptor(OldDescriptor);
+ if (OldDescriptor) ObDereferenceSecurityDescriptor(OldDescriptor, 1);
break;
}
}
-
+
/* Return status */
return Status;
}
@@ -585,8 +585,7 @@
if (Type->TypeInfo.SecurityProcedure == SeDefaultObjectMethod)
{
/* Reference the descriptor */
- *SecurityDescriptor =
- ObpReferenceCachedSecurityDescriptor(Header->SecurityDescriptor);
+ *SecurityDescriptor = ObpReferenceSecurityDescriptor(Header);
return STATUS_SUCCESS;
}
@@ -678,7 +677,7 @@
else
{
/* Otherwise this means we used an internal descriptor */
- ObpDereferenceCachedSecurityDescriptor(SecurityDescriptor);
+ ObDereferenceSecurityDescriptor(SecurityDescriptor, 1);
}
}
Removed: trunk/reactos/ntoskrnl/ob/sdcache.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/sdcache.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/sdcache.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ob/sdcache.c (removed)
@@ -1,409 +1,0 @@
-/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/ob/sdcache.c
- * PURPOSE: No purpose listed.
- *
- * PROGRAMMERS: David Welch (welch(a)cwcom.net)
- */
-
-/* INCLUDES *****************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <internal/debug.h>
-
-
-/* TYPES ********************************************************************/
-
-typedef struct _SD_CACHE_ENTRY
-{
- LIST_ENTRY ListEntry;
- ULONG HashValue;
- ULONG Index;
- ULONG RefCount;
-} SD_CACHE_ENTRY, *PSD_CACHE_ENTRY;
-
-
-/* GLOBALS ******************************************************************/
-
-#define SD_CACHE_ENTRIES 0x100
-
-LIST_ENTRY ObpSdCache[SD_CACHE_ENTRIES];
-FAST_MUTEX ObpSdCacheMutex;
-
-/* FUNCTIONS ****************************************************************/
-
-NTSTATUS
-NTAPI
-ObpInitSdCache(VOID)
-{
- ULONG i;
-
- for (i = 0; i < (sizeof(ObpSdCache) / sizeof(ObpSdCache[0])); i++)
- {
- InitializeListHead(&ObpSdCache[i]);
- }
-
- ExInitializeFastMutex(&ObpSdCacheMutex);
-
- return STATUS_SUCCESS;
-}
-
-
-static __inline VOID
-ObpSdCacheLock(VOID)
-{
- /* can't acquire a fast mutex in the early boot process... */
- if(KeGetCurrentThread() != NULL)
- {
- ExAcquireFastMutex(&ObpSdCacheMutex);
- }
-}
-
-
-static __inline VOID
-ObpSdCacheUnlock(VOID)
-{
- /* can't acquire a fast mutex in the early boot process... */
- if(KeGetCurrentThread() != NULL)
- {
- ExReleaseFastMutex(&ObpSdCacheMutex);
- }
-}
-
-
-static ULONG
-ObpHash(PVOID Buffer,
- ULONG Length)
-{
- PUCHAR Ptr;
- ULONG Value;
- ULONG i;
-
- Ptr = (PUCHAR)Buffer;
- Value = 0;
- for (i = 0; i < Length; i++)
- {
- Value += *Ptr;
- Ptr++;
- }
-
- return Value;
-}
-
-
-static ULONG
-ObpHashSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
-{
- ULONG Value;
- BOOLEAN Defaulted;
- BOOLEAN DaclPresent;
- BOOLEAN SaclPresent;
- PSID Owner = NULL;
- PSID Group = NULL;
- PACL Dacl = NULL;
- PACL Sacl = NULL;
-
- RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
- &Owner,
- &Defaulted);
-
- RtlGetGroupSecurityDescriptor(SecurityDescriptor,
- &Group,
- &Defaulted);
-
- RtlGetDaclSecurityDescriptor(SecurityDescriptor,
- &DaclPresent,
- &Dacl,
- &Defaulted);
-
- RtlGetSaclSecurityDescriptor(SecurityDescriptor,
- &SaclPresent,
- &Sacl,
- &Defaulted);
-
- Value = 0;
- if (Owner != NULL)
- {
- Value += ObpHash(Owner, RtlLengthSid(Owner));
- }
-
- if (Group != NULL)
- {
- Value += ObpHash(Group, RtlLengthSid(Group));
- }
-
- if (DaclPresent == TRUE && Dacl != NULL)
- {
- Value += ObpHash(Dacl, Dacl->AclSize);
- }
-
- if (SaclPresent == TRUE && Sacl != NULL)
- {
- Value += ObpHash(Sacl, Sacl->AclSize);
- }
-
- return Value;
-}
-
-
-static PSD_CACHE_ENTRY
-ObpCreateCacheEntry(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
- IN ULONG HashValue,
- IN ULONG Index,
- OUT PSECURITY_DESCRIPTOR *NewSD)
-{
- PSECURITY_DESCRIPTOR Sd;
- PSD_CACHE_ENTRY CacheEntry;
- ULONG Length;
-
- DPRINT("ObpCreateCacheEntry() called\n");
-
- Length = RtlLengthSecurityDescriptor(SecurityDescriptor);
-
- CacheEntry = ExAllocatePool(NonPagedPool,
- sizeof(SD_CACHE_ENTRY) + Length);
- if (CacheEntry == NULL)
- {
- DPRINT1("ExAllocatePool() failed\n");
- return NULL;
- }
-
- CacheEntry->HashValue = HashValue;
- CacheEntry->Index = Index;
- CacheEntry->RefCount = 1;
-
- Sd = (PSECURITY_DESCRIPTOR)(CacheEntry + 1);
- RtlCopyMemory(Sd,
- SecurityDescriptor,
- Length);
-
- *NewSD = Sd;
-
- DPRINT("ObpCreateCacheEntry() done\n");
-
- return CacheEntry;
-}
-
-
-static BOOLEAN
-ObpCompareSecurityDescriptors(IN PSECURITY_DESCRIPTOR Sd1,
- IN PSECURITY_DESCRIPTOR Sd2)
-{
- ULONG Length1;
- ULONG Length2;
-
- Length1 = RtlLengthSecurityDescriptor(Sd1);
- Length2 = RtlLengthSecurityDescriptor(Sd2);
- if (Length1 != Length2)
- return FALSE;
-
- if (RtlCompareMemory(Sd1, Sd2, Length1) != Length1)
- return FALSE;
-
- return TRUE;
-}
-
-
-NTSTATUS
-NTAPI
-ObpAddSecurityDescriptor(IN PSECURITY_DESCRIPTOR SourceSD,
- OUT PSECURITY_DESCRIPTOR *DestinationSD)
-{
- PSECURITY_DESCRIPTOR Sd;
- PLIST_ENTRY CurrentEntry;
- PSD_CACHE_ENTRY CacheEntry;
- ULONG HashValue;
- ULONG Index;
- NTSTATUS Status;
-
- DPRINT("ObpAddSecurityDescriptor() called\n");
-
- HashValue = ObpHashSecurityDescriptor(SourceSD);
- Index = HashValue & 0xFF;
-
- ObpSdCacheLock();
-
- if (!IsListEmpty(&ObpSdCache[Index]))
- {
- CurrentEntry = ObpSdCache[Index].Flink;
- while (CurrentEntry != &ObpSdCache[Index])
- {
- CacheEntry = CONTAINING_RECORD(CurrentEntry,
- SD_CACHE_ENTRY,
- ListEntry);
- Sd = (PSECURITY_DESCRIPTOR)(CacheEntry + 1);
-
- if (CacheEntry->HashValue == HashValue &&
- ObpCompareSecurityDescriptors(SourceSD, Sd))
- {
- CacheEntry->RefCount++;
- DPRINT("RefCount %lu\n", CacheEntry->RefCount);
- *DestinationSD = Sd;
-
- ObpSdCacheUnlock();
-
- DPRINT("ObpAddSecurityDescriptor() done\n");
-
- return STATUS_SUCCESS;
- }
-
- CurrentEntry = CurrentEntry->Flink;
- }
- }
-
- CacheEntry = ObpCreateCacheEntry(SourceSD,
- HashValue,
- Index,
- DestinationSD);
- if (CacheEntry == NULL)
- {
- DPRINT1("ObpCreateCacheEntry() failed\n");
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
- else
- {
- DPRINT("RefCount 1\n");
- InsertTailList(&ObpSdCache[Index], &CacheEntry->ListEntry);
- Status = STATUS_SUCCESS;
- }
-
- ObpSdCacheUnlock();
-
- DPRINT("ObpAddSecurityDescriptor() done\n");
-
- return Status;
-}
-
-
-NTSTATUS
-NTAPI
-ObpRemoveSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
-{
- PSD_CACHE_ENTRY CacheEntry;
-
- DPRINT("ObpRemoveSecurityDescriptor() called\n");
-
- ObpSdCacheLock();
-
- CacheEntry = (PSD_CACHE_ENTRY)((ULONG_PTR)SecurityDescriptor -
sizeof(SD_CACHE_ENTRY));
-
- CacheEntry->RefCount--;
- DPRINT("RefCount %lu\n", CacheEntry->RefCount);
- if (CacheEntry->RefCount == 0)
- {
- DPRINT("Remove cache entry\n");
- RemoveEntryList(&CacheEntry->ListEntry);
- ExFreePool(CacheEntry);
- }
-
- ObpSdCacheUnlock();
-
- DPRINT("ObpRemoveSecurityDescriptor() done\n");
-
- return STATUS_SUCCESS;
-}
-
-PSECURITY_DESCRIPTOR
-NTAPI
-ObpReferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
-{
- PSD_CACHE_ENTRY CacheEntry;
-
- /* Lock the cache */
- ObpSdCacheLock();
-
- /* Make sure we got a descriptor */
- if (SecurityDescriptor)
- {
- /* Get the entry */
- CacheEntry = (PSD_CACHE_ENTRY)((ULONG_PTR)SecurityDescriptor -
- sizeof(SD_CACHE_ENTRY));
-
- /* Reference it */
- CacheEntry->RefCount++;
- DPRINT("RefCount %lu\n", CacheEntry->RefCount);
- }
-
- /* Unlock the cache and return the descriptor */
- ObpSdCacheUnlock();
- return SecurityDescriptor;
-}
-
-VOID
-NTAPI
-ObpDereferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
-{
- DPRINT("ObpDereferenceCachedSecurityDescriptor() called\n");
-
- ObpRemoveSecurityDescriptor(SecurityDescriptor);
-
- DPRINT("ObpDereferenceCachedSecurityDescriptor() done\n");
-}
-
-/*++
-* @name ObLogSecurityDescriptor
-* @unimplemented NT5.2
-*
-* The ObLogSecurityDescriptor routine <FILLMEIN>
-*
-* @param InputSecurityDescriptor
-* <FILLMEIN>
-*
-* @param OutputSecurityDescriptor
-* <FILLMEIN>
-*
-* @param RefBias
-* <FILLMEIN>
-*
-* @return STATUS_SUCCESS or appropriate error value.
-*
-* @remarks None.
-*
-*--*/
-NTSTATUS
-NTAPI
-ObLogSecurityDescriptor(IN PSECURITY_DESCRIPTOR InputSecurityDescriptor,
- OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor,
- IN ULONG RefBias)
-{
- /* HACK: Return the same descriptor back */
- PISECURITY_DESCRIPTOR SdCopy;
- ULONG Length;
- DPRINT("ObLogSecurityDescriptor is not implemented!\n",
- InputSecurityDescriptor);
-
- Length = RtlLengthSecurityDescriptor(InputSecurityDescriptor);
- SdCopy = ExAllocatePool(PagedPool, Length);
- RtlCopyMemory(SdCopy, InputSecurityDescriptor, Length);
- *OutputSecurityDescriptor = SdCopy;
- return STATUS_SUCCESS;
-}
-
-/*++
-* @name ObDereferenceSecurityDescriptor
-* @unimplemented NT5.2
-*
-* The ObDereferenceSecurityDescriptor routine <FILLMEIN>
-*
-* @param SecurityDescriptor
-* <FILLMEIN>
-*
-* @param Count
-* <FILLMEIN>
-*
-* @return STATUS_SUCCESS or appropriate error value.
-*
-* @remarks None.
-*
-*--*/
-VOID
-NTAPI
-ObDereferenceSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
- IN ULONG Count)
-{
- DPRINT1("ObDereferenceSecurityDescriptor is not implemented!\n");
-}
-
-/* EOF */