- Add internal macros for acquiring the object directory pushlock during lookup (not yet used).

- Add internal macros for incrementing/decrementing query references, and use them where appropriate. Do not yet support the path for an object which is currently being defer deleted.
- Add internal macros for cleaning up a directory lookup (not yet used and needs renaming/cleanup), initializing a directory lookup (not yet used).
- Don't call security callback in ObpDeleteNameCheck. Make sure permanent flag is still cleared after acquiring type lock. Add special call for symboilc links. Add commented out calls to lock the object directory.

svn path=/trunk/; revision=25392
This commit is contained in:
Alex Ionescu 2007-01-09 07:28:40 +00:00
parent 0202185efa
commit 6829abde13
3 changed files with 283 additions and 35 deletions

View file

@ -6,6 +6,8 @@
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
#include "ex.h"
#if DBG
VOID
FORCEINLINE
@ -53,6 +55,193 @@ ObpCalloutEnd(IN KIRQL CalloutIrql,
}
#endif
VOID
FORCEINLINE
_ObpAcquireDirectoryLockShared(IN POBJECT_DIRECTORY Directory,
IN POBP_LOOKUP_CONTEXT Context)
{
/* It's not, set lock flag */
Context->LockStateSignature = 0xBBBB1234;
/* Lock it */
KeEnterCriticalRegion();
ExAcquirePushLockShared(&Directory->Lock);
/* Update lock flag */
Context->LockStateSignature = 0xDDDD1234;
}
VOID
FORCEINLINE
_ObpAcquireDirectoryLockExclusive(IN POBJECT_DIRECTORY Directory,
IN POBP_LOOKUP_CONTEXT Context)
{
/* Update lock flag */
Context->LockStateSignature = 0xAAAA1234;
/* Lock it */
KeEnterCriticalRegion();
ExAcquirePushLockExclusive(&Directory->Lock);
}
VOID
FORCEINLINE
_ObpReleaseDirectoryLock(IN POBJECT_DIRECTORY Directory,
IN POBP_LOOKUP_CONTEXT Context)
{
/* Release the lock */
ExReleasePushLock(&Directory->Lock);
Context->LockStateSignature = 0xEEEE1234;
KeLeaveCriticalRegion();
}
ULONG
FORCEINLINE
ObpIncrementQueryReference(IN POBJECT_HEADER ObjectHeader,
IN POBJECT_HEADER_NAME_INFO ObjectNameInfo)
{
ULONG NewValue, References;
/* Get the number of references */
NewValue = ObjectNameInfo->QueryReferences;
while ((NewValue != 0) && (References = NewValue))
{
/* Increment the number of references */
if (InterlockedCompareExchange(&ObjectNameInfo->QueryReferences,
NewValue + 1,
NewValue) == References)
{
/* Check if the object is to be deferred deleted */
if (ObjectHeader->Flags & OB_FLAG_DEFER_DELETE)
{
/* FIXME: Unhandled*/
DbgPrint("OB: Unhandled path\n");
KEBUGCHECK(0);
}
/* Done looping */
NewValue = ObjectNameInfo->QueryReferences;
break;
}
}
/* Return the number of references */
return NewValue;
}
VOID
FORCEINLINE
_ObpDecrementQueryReference(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo)
{
POBJECT_DIRECTORY Directory;
/* Remove a query reference and check if it was the last one */
if (!InterlockedExchangeAdd(&HeaderNameInfo->QueryReferences, -1))
{
/* Check if we have a name */
if (HeaderNameInfo->Name.Buffer)
{
/* We can get rid of the object name now */
ExFreePool(HeaderNameInfo->Name.Buffer);
RtlInitEmptyUnicodeString(&HeaderNameInfo->Name, NULL, 0);
}
/* Check if the object has a directory associated to it */
Directory = HeaderNameInfo->Directory;
if (Directory)
{
/* Delete the directory */
HeaderNameInfo->Directory = NULL;
ObDereferenceObjectDeferDelete(Directory);
}
}
}
VOID
FORCEINLINE
_ObpCleanupDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context,
IN BOOLEAN DereferenceObject)
{
POBJECT_HEADER ObjectHeader;
POBJECT_HEADER_NAME_INFO HeaderNameInfo;
/* Check if we came back with the directory locked */
if (Context->DirectoryLocked)
{
/* Release the lock */
_ObpReleaseDirectoryLock(Context->Directory, Context);
}
/* Clear the context */
Context->Directory = NULL;
Context->DirectoryLocked = FALSE;
/* Check if we had found an object */
if (Context->Object)
{
/* Get the object name information */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Context->Object);
HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
/* Check if we do have name information */
if (HeaderNameInfo) _ObpDecrementQueryReference(HeaderNameInfo);
/* Check if we need to dereference it */
if (DereferenceObject) ObDereferenceObject(Context->Object);
}
}
VOID
FORCEINLINE
_ObpInitializeDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context)
{
/* Initialize a null context */
Context->Object = NULL;
Context->Directory = NULL;
Context->DirectoryLocked = FALSE;
Context->LockStateSignature = 0xFFFF1234;
}
#if _OB_DEBUG_
#define ObpAcquireDirectoryLockShared(a, b) \
{ \
DbgPrint("OB QUERY: Acquiring lock at %s %d\n", __FUNCTION__, __LINE__);\
_ObpAcquireDirectoryLockShared(a, b); \
}
#define ObpAcquireDirectoryLockExclusive(a, b) \
{ \
DbgPrint("OB QUERY: Acquiring lock at %s %d\n", __FUNCTION__, __LINE__);\
_ObpAcquireDirectoryLockExclusive(a, b); \
}
#define ObpReleaseDirectoryLock(a, b) \
{ \
DbgPrint("OB QUERY: Releasing lock at %s %d\n", __FUNCTION__, __LINE__);\
_ObpReleaseDirectoryLock(a, b); \
}
#define ObpInitializeDirectoryLookup(a) \
{ \
DbgPrint("OB QUERY: Initialization at %s %d\n", __FUNCTION__, __LINE__);\
_ObpInitializeDirectoryLookup(a); \
}
#define ObpCleanupDirectoryLookup(a, b) \
{ \
DbgPrint("OB QUERY: Cleanup at %s %d\n", __FUNCTION__, __LINE__); \
_ObpCleanupDirectoryLookup(a, b); \
}
#define ObpDecrementQueryReference(a) \
{ \
DbgPrint("OB QUERY: Decrement at %s %d\n", __FUNCTION__, __LINE__); \
_ObpDecrementQueryReference(a); \
}
#else
#define ObpDecrementQueryReference _ObpDecrementQueryReference
#define ObpAcquireDirectoryLockExclusive _ObpAcquireDirectoryLockExclusive
#define ObpAcquireDirectoryLockShared _ObpAcquireDirectoryLockShared
#define ObpReleaseDirectoryLock _ObpReleaseDirectoryLock
#define ObpInitializeDirectoryLookup _ObpInitializeDirectoryLookup
#define ObpCleanupDirectoryLookup _ObpCleanupDirectoryLookup
#endif
VOID
FORCEINLINE
ObpEnterObjectTypeMutex(IN POBJECT_TYPE ObjectType)
@ -176,3 +365,5 @@ ObpFreeAndReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateIn
ObpFreeCapturedAttributes(ObjectCreateInfo, LookasideCreateInfoList);
}

View file

@ -2352,6 +2352,16 @@ ObInsertObject(IN PVOID Object,
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
ObjectType = ObjectHeader->Type;
/* Check if we have name information */
if (ObjectNameInfo)
{
/* Add a query reference */
if (!ObpIncrementQueryReference(ObjectHeader, ObjectNameInfo))
{
/* There are no query references, so the name info is invalid */
ObjectNameInfo = NULL;
}
}
/* Check if this is an named object */
ObjectName = NULL;
@ -2394,6 +2404,8 @@ ObInsertObject(IN PVOID Object,
ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo);
ObjectHeader->ObjectCreateInfo = NULL;
/* Remove a query reference if we added one */
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
/* Remove the extra keep-alive reference */
if (Handle) ObDereferenceObject(Object);
@ -2419,6 +2431,7 @@ ObInsertObject(IN PVOID Object,
if (!NT_SUCCESS(Status))
{
/* Fail */
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
ObDereferenceObject(Object);
return Status;
}
@ -2489,7 +2502,10 @@ ObInsertObject(IN PVOID Object,
/* Check if anything until now failed */
if (!NT_SUCCESS(Status))
{
/* We failed, dereference the object and delete the access state */
/* Remove query reference that we added */
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
/* Dereference the object and delete the access state */
ObDereferenceObject(Object);
if (AccessState == &LocalAccessState)
{
@ -2554,8 +2570,10 @@ ObInsertObject(IN PVOID Object,
/* Check if anything until now failed */
if (!NT_SUCCESS(Status))
{
/* We failed, dereference the object and delete the access state */
KEBUGCHECK(0);
/* Remove query reference that we added */
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
/* Dereference the object and delete the access state */
ObDereferenceObject(Object);
if (AccessState == &LocalAccessState)
{
@ -2564,6 +2582,7 @@ ObInsertObject(IN PVOID Object,
}
/* Return failure code */
KEBUGCHECK(0);
return Status;
}
}
@ -2608,8 +2627,8 @@ ObInsertObject(IN PVOID Object,
RealStatus = Status;
}
/* Remove a query reference */
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
/* Remove the extra keep-alive reference */
if (Handle) ObDereferenceObject(Object);

View file

@ -173,6 +173,17 @@ ObpDeleteNameCheck(IN PVOID Object)
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
ObjectType = ObjectHeader->Type;
/* Check if we have a name information structure */
if (ObjectNameInfo)
{
/* Add a query reference */
if (!ObpIncrementQueryReference(ObjectHeader, ObjectNameInfo))
{
/* No references, so the name info is invalid */
ObjectNameInfo = NULL;
}
}
/*
* Check if the handle count is 0, if the object is named,
* and if the object isn't a permanent object.
@ -182,62 +193,89 @@ ObpDeleteNameCheck(IN PVOID Object)
(ObjectNameInfo->Name.Length) &&
!(ObjectHeader->Flags & OB_FLAG_PERMANENT))
{
/* Setup a lookup context */
Context.Object = NULL;
/* Make sure it's still inserted */
/* Lock the directory */
//ObpAcquireDirectoryLockExclusive(ObjectNameInfo->Directory, &Context);
/* Set the lookup parameters */
Context.Directory = ObjectNameInfo->Directory;
Context.DirectoryLocked = TRUE;
Context.LockStateSignature = 0xCCCC1234;
/* Do the lookup */
Object = ObpLookupEntryDirectory(ObjectNameInfo->Directory,
&ObjectNameInfo->Name,
0,
FALSE,
&Context);
if ((Object) && !(ObjectHeader->HandleCount))
if (Object)
{
/* Lock the object type */
ObpEnterObjectTypeMutex(ObjectType);
/* First delete it from the directory */
ObpDeleteEntryDirectory(&Context);
/* Now check if we have a security callback */
if (ObjectType->TypeInfo.SecurityRequired)
/* Make sure we can still delete the object */
if (!(ObjectHeader->HandleCount) &&
!(ObjectHeader->Flags & OB_FLAG_PERMANENT))
{
/* Call it */
ObjectType->TypeInfo.SecurityProcedure(Object,
DeleteSecurityDescriptor,
0,
NULL,
NULL,
&ObjectHeader->
SecurityDescriptor,
ObjectType->
TypeInfo.PoolType,
NULL);
/* First delete it from the directory */
ObpDeleteEntryDirectory(&Context);
/* Check if this is a symbolic link */
if (ObjectType == ObSymbolicLinkType)
{
/* Remove internal name */
ObpDeleteSymbolicLinkName(Object);
}
/* Add a query reference */
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
if (!ObpIncrementQueryReference(ObjectHeader, ObjectNameInfo))
{
/* No references, so the name info is invalid */
ObjectNameInfo = NULL;
}
/* Check if the magic protection flag is set */
if ((ObjectNameInfo) &&
(ObjectNameInfo->QueryReferences & 0x40000000))
{
/* Add deletion flag */
InterlockedExchangeAdd(&ObjectNameInfo->QueryReferences,
0xC0000000);
}
/* Get the directory */
Directory = ObjectNameInfo->Directory;
}
/* Release the lock */
ObpLeaveObjectTypeMutex(ObjectType);
/* Free the name */
ExFreePool(ObjectNameInfo->Name.Buffer);
RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, NULL, 0);
Context.Object = NULL;
/* Clear the current directory and de-reference it */
Directory = ObjectNameInfo->Directory;
ObjectNameInfo->Directory = NULL;
}
/* Cleanup after lookup */
//ObpCleanupDirectoryLookup(&Context, TRUE);
Context.Object = NULL;
/* Remove another query reference since we added one on top */
ObpDecrementQueryReference(ObjectNameInfo);
/* Check if we were inserted in a directory */
if (Directory)
{
/* We were, so dereference the directory and the object as well */
ObDereferenceObject(Directory);
/* We were, so first remove the extra reference we had added */
ObpDecrementQueryReference(ObjectNameInfo);
/* Now dereference the object as well */
ObDereferenceObject(Object);
}
}
else
{
/* Remove the reference we added */
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
}
}
NTSTATUS