* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
+#include "ex.h"
+
#if DBG
VOID
FORCEINLINE
}
#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)
ObpFreeCapturedAttributes(ObjectCreateInfo, LookasideCreateInfoList);
}
+
+
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;
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);
if (!NT_SUCCESS(Status))
{
/* Fail */
+ if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
ObDereferenceObject(Object);
return Status;
}
/* 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)
{
/* 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)
{
}
/* Return failure code */
+ KEBUGCHECK(0);
return Status;
}
}
RealStatus = Status;
}
-
-
+ /* Remove a query reference */
+ if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
/* Remove the extra keep-alive reference */
if (Handle) ObDereferenceObject(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.
(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;
+ /* Cleanup after lookup */
+ //ObpCleanupDirectoryLookup(&Context, TRUE);
+ Context.Object = NULL;
- /* Clear the current directory and de-reference it */
- Directory = ObjectNameInfo->Directory;
- ObjectNameInfo->Directory = 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