Author: ion
Date: Tue Jan 9 10:28:40 2007
New Revision: 25392
URL:
http://svn.reactos.org/svn/reactos?rev=25392&view=rev
Log:
- 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.
Modified:
trunk/reactos/ntoskrnl/include/internal/ob_x.h
trunk/reactos/ntoskrnl/ob/obhandle.c
trunk/reactos/ntoskrnl/ob/obname.c
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 (original)
+++ trunk/reactos/ntoskrnl/include/internal/ob_x.h Tue Jan 9 10:28:40 2007
@@ -6,6 +6,8 @@
* PROGRAMMERS: Alex Ionescu (alex.ionescu(a)reactos.org)
*/
+#include "ex.h"
+
#if DBG
VOID
FORCEINLINE
@@ -55,6 +57,193 @@
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)
{
/* Sanity check */
@@ -176,3 +365,5 @@
ObpFreeCapturedAttributes(ObjectCreateInfo, LookasideCreateInfoList);
}
+
+
Modified: trunk/reactos/ntoskrnl/ob/obhandle.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obhandle.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obhandle.c (original)
+++ trunk/reactos/ntoskrnl/ob/obhandle.c Tue Jan 9 10:28:40 2007
@@ -2352,6 +2352,16 @@
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 @@
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 @@
if (!NT_SUCCESS(Status))
{
/* Fail */
+ if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
ObDereferenceObject(Object);
return Status;
}
@@ -2489,7 +2502,10 @@
/* 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 @@
/* 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 @@
}
/* Return failure code */
+ KEBUGCHECK(0);
return Status;
}
}
@@ -2608,8 +2627,8 @@
RealStatus = Status;
}
-
-
+ /* Remove a query reference */
+ if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
/* Remove the extra keep-alive reference */
if (Handle) ObDereferenceObject(Object);
Modified: trunk/reactos/ntoskrnl/ob/obname.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obname.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obname.c (original)
+++ trunk/reactos/ntoskrnl/ob/obname.c Tue Jan 9 10:28:40 2007
@@ -173,6 +173,17 @@
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,61 +193,88 @@
(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)
- {
- /* Call it */
- ObjectType->TypeInfo.SecurityProcedure(Object,
- DeleteSecurityDescriptor,
- 0,
- NULL,
- NULL,
- &ObjectHeader->
- SecurityDescriptor,
- ObjectType->
- TypeInfo.PoolType,
- NULL);
+ /* Make sure we can still delete the object */
+ if (!(ObjectHeader->HandleCount) &&
+ !(ObjectHeader->Flags & OB_FLAG_PERMANENT))
+ {
+ /* 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);
}
}