Author: ion
Date: Tue Jan 16 00:12:32 2007
New Revision: 25472
URL: http://svn.reactos.org/svn/reactos?rev=25472&view=rev
Log:
- Fix several bugs in the rundown protection implementation, mostly related to incorrect loop restarting in case of a race condition.
- The rundown event is a sync event, not a notification event.
- Only take slow path when waiting for release if the value changed *and* is still not active, not if only one of the two is true.
Modified:
trunk/reactos/ntoskrnl/ex/rundown.c
trunk/reactos/ntoskrnl/include/internal/ex.h
Modified: trunk/reactos/ntoskrnl/ex/rundown.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/rundown.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ex/rundown.c (original)
+++ trunk/reactos/ntoskrnl/ex/rundown.c Tue Jan 16 00:12:32 2007
@@ -36,21 +36,21 @@
{
ULONG_PTR Value = RunRef->Count, NewValue;
- /* Make sure a rundown is not active */
- if (Value & EX_RUNDOWN_ACTIVE) return FALSE;
-
/* Loop until successfully incremented the counter */
for (;;)
{
+ /* Make sure a rundown is not active */
+ if (Value & EX_RUNDOWN_ACTIVE) return FALSE;
+
/* Add a reference */
NewValue = Value + EX_RUNDOWN_COUNT_INC;
/* Change the value */
- Value = ExpChangeRundown(RunRef, NewValue, Value);
- if (Value == NewValue) return TRUE;
-
- /* Make sure a rundown is not active */
- if (Value & EX_RUNDOWN_ACTIVE) return FALSE;
+ NewValue = ExpChangeRundown(RunRef, NewValue, Value);
+ if (NewValue == Value) return TRUE;
+
+ /* Update it */
+ Value = NewValue;
}
}
@@ -78,25 +78,22 @@
IN ULONG Count)
{
ULONG_PTR Value = RunRef->Count, NewValue;
-
- /* Make sure a rundown is not active */
- if (Value & EX_RUNDOWN_ACTIVE) return FALSE;
-
- /* Convert the count to our internal representation */
- Count <<= EX_RUNDOWN_COUNT_SHIFT;
/* Loop until successfully incremented the counter */
for (;;)
{
- /* Add references */
- NewValue = Value + Count;
-
- /* Change the value */
- Value = ExpChangeRundown(RunRef, NewValue, Value);
- if (Value == NewValue) return TRUE;
-
/* Make sure a rundown is not active */
if (Value & EX_RUNDOWN_ACTIVE) return FALSE;
+
+ /* Add references */
+ NewValue = Value + EX_RUNDOWN_COUNT_INC * Count;
+
+ /* Change the value */
+ NewValue = ExpChangeRundown(RunRef, NewValue, Value);
+ if (NewValue == Value) return TRUE;
+
+ /* Update the value */
+ Value = NewValue;
}
}
@@ -201,11 +198,11 @@
ULONG_PTR Value = RunRef->Count, NewValue;
PEX_RUNDOWN_WAIT_BLOCK WaitBlock;
- /* Check if rundown is not active */
- if (!(Value & EX_RUNDOWN_ACTIVE))
+ /* Loop until successfully incremented the counter */
+ for (;;)
{
- /* Loop until successfully incremented the counter */
- for (;;)
+ /* Check if rundown is not active */
+ if (!(Value & EX_RUNDOWN_ACTIVE))
{
/* Sanity check */
ASSERT((Value >= EX_RUNDOWN_COUNT_INC) || (KeNumberProcessors > 1));
@@ -214,24 +211,29 @@
NewValue = Value - EX_RUNDOWN_COUNT_INC;
/* Change the value */
- Value = ExpChangeRundown(RunRef, NewValue, Value);
- if (Value == NewValue) return;
-
- /* Loop again if we're still not active */
- if (Value & EX_RUNDOWN_ACTIVE) break;
+ NewValue = ExpChangeRundown(RunRef, NewValue, Value);
+ if (NewValue == Value) break;
+
+ /* Update value */
+ Value = NewValue;
+ }
+ else
+ {
+ /* Get the wait block */
+ WaitBlock = (PEX_RUNDOWN_WAIT_BLOCK)(Value & ~EX_RUNDOWN_ACTIVE);
+ ASSERT((WaitBlock->Count > 0) || (KeNumberProcessors > 1));
+
+ /* Remove the one count */
+ if (!InterlockedDecrementSizeT(&WaitBlock->Count))
+ {
+ /* We're down to 0 now, so signal the event */
+ KeSetEvent(&WaitBlock->WakeEvent, IO_NO_INCREMENT, FALSE);
+ }
+
+ /* We're all done */
+ break;
}
}
-
- /* Get the wait block */
- WaitBlock = (PEX_RUNDOWN_WAIT_BLOCK)(Value & ~EX_RUNDOWN_ACTIVE);
- ASSERT((WaitBlock->Count > 0) || (KeNumberProcessors > 1));
-
- /* Remove the one count */
- if (!InterlockedDecrementSizeT(&WaitBlock->Count))
- {
- /* We're down to 0 now, so signal the event */
- KeSetEvent(&WaitBlock->WakeEvent, IO_NO_INCREMENT, FALSE);
- }
}
/*++
@@ -260,37 +262,43 @@
ULONG_PTR Value = RunRef->Count, NewValue;
PEX_RUNDOWN_WAIT_BLOCK WaitBlock;
- /* Check if rundown is not active */
- if (!(Value & EX_RUNDOWN_ACTIVE))
+ /* Loop until successfully incremented the counter */
+ for (;;)
{
- /* Loop until successfully incremented the counter */
- for (;;)
+ /* Check if rundown is not active */
+ if (!(Value & EX_RUNDOWN_ACTIVE))
{
/* Sanity check */
- ASSERT((Value >= EX_RUNDOWN_COUNT_INC * Count) || (KeNumberProcessors > 1));
+ ASSERT((Value >= EX_RUNDOWN_COUNT_INC * Count) ||
+ (KeNumberProcessors > 1));
/* Get the new value */
- NewValue = Value - (Count * EX_RUNDOWN_COUNT_INC);
+ NewValue = Value - EX_RUNDOWN_COUNT_INC * Count;
/* Change the value */
- Value = ExpChangeRundown(RunRef, NewValue, Value);
- if (Value == NewValue) return;
-
- /* Loop again if we're still not active */
- if (Value & EX_RUNDOWN_ACTIVE) break;
+ NewValue = ExpChangeRundown(RunRef, NewValue, Value);
+ if (NewValue == Value) break;
+
+ /* Update value */
+ Value = NewValue;
}
- }
-
- /* Get the wait block */
- WaitBlock = (PEX_RUNDOWN_WAIT_BLOCK)(Value & ~EX_RUNDOWN_ACTIVE);
- ASSERT((WaitBlock->Count >= Count) || (KeNumberProcessors > 1));
-
- /* Remove the count */
- if (InterlockedExchangeAddSizeT(&WaitBlock->Count, -(LONG)Count) ==
- (LONG)Count)
- {
- /* We're down to 0 now, so signal the event */
- KeSetEvent(&WaitBlock->WakeEvent, IO_NO_INCREMENT, FALSE);
+ else
+ {
+ /* Get the wait block */
+ WaitBlock = (PEX_RUNDOWN_WAIT_BLOCK)(Value & ~EX_RUNDOWN_ACTIVE);
+ ASSERT((WaitBlock->Count >= Count) || (KeNumberProcessors > 1));
+
+ /* Remove the counts */
+ if (InterlockedExchangeAddSizeT(&WaitBlock->Count,
+ -(LONG)Count) == (LONG)Count)
+ {
+ /* We're down to 0 now, so signal the event */
+ KeSetEvent(&WaitBlock->WakeEvent, IO_NO_INCREMENT, FALSE);
+ }
+
+ /* We're all done */
+ break;
+ }
}
}
@@ -330,17 +338,17 @@
EX_RUNDOWN_ACTIVE);
/* Start waitblock set loop */
- for(;;)
+ for (;;)
{
/* Save the count */
Count = Value >> EX_RUNDOWN_COUNT_SHIFT;
- /* If the count is over one or we don't have en event yet, create it */
- if (Count || !Event)
+ /* If the count is over one and we don't have en event yet, create it */
+ if ((Count) && !(Event))
{
/* Initialize the event */
KeInitializeEvent(&WaitBlock.WakeEvent,
- NotificationEvent,
+ SynchronizationEvent,
FALSE);
/* Set the pointer */
Modified: trunk/reactos/ntoskrnl/include/internal/ex.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ex.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ex.h Tue Jan 16 00:12:32 2007
@@ -364,7 +364,7 @@
FORCEINLINE
_ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef)
{
- ULONG_PTR Value, NewValue, OldValue;
+ ULONG_PTR Value, NewValue;
/* Get the current value and mask the active bit */
Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
@@ -373,8 +373,8 @@
NewValue = Value + EX_RUNDOWN_COUNT_INC;
/* Change the value */
- OldValue = ExpChangeRundown(RunRef, NewValue, Value);
- if (OldValue != Value)
+ NewValue = ExpChangeRundown(RunRef, NewValue, Value);
+ if (NewValue != Value)
{
/* Rundown was active, use long path */
return ExfAcquireRundownProtection(RunRef);
@@ -405,7 +405,7 @@
FORCEINLINE
_ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef)
{
- ULONG_PTR Value, NewValue, OldValue;
+ ULONG_PTR Value, NewValue;
/* Get the current value and mask the active bit */
Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
@@ -414,10 +414,10 @@
NewValue = Value - EX_RUNDOWN_COUNT_INC;
/* Change the value */
- OldValue = ExpChangeRundown(RunRef, NewValue, Value);
+ NewValue = ExpChangeRundown(RunRef, NewValue, Value);
/* Check if the rundown was active */
- if (OldValue != Value)
+ if (NewValue != Value)
{
/* Rundown was active, use long path */
ExfReleaseRundownProtection(RunRef);
@@ -476,7 +476,7 @@
/* Set the active bit */
Value = ExpChangeRundown(RunRef, EX_RUNDOWN_ACTIVE, 0);
- if ((Value) || (Value != EX_RUNDOWN_ACTIVE))
+ if ((Value) && (Value != EX_RUNDOWN_ACTIVE))
{
/* If the the rundown wasn't already active, then take the long path */
ExfWaitForRundownProtectionRelease(RunRef);
Author: ion
Date: Mon Jan 15 23:24:40 2007
New Revision: 25469
URL: http://svn.reactos.org/svn/reactos?rev=25469&view=rev
Log:
[12 bug fixes]:
- Isolate FuckedUpCm version of ObpLookupDirectoryObject into CmpLookupDirectoryObject to avoid name info leak.
- Rename ObpIncrementQueryReference to ObpAcquireNameInformation and ObpDecrementQueryReference to ObpReleaseNameInformation and make some changes to make calling a lot easier.
- Fixup reference increment loop in above function.
- Fix incorrect check for defer delete flag instead of query references flag.
- Only clear the directory/directory lock flag in ObpCleanupDirectoryLookup if the directory was actually locked.
- Fix lock logic in ObpLookupDirectoryEntry.
- Properly handle the case when lookup occurs after an existing object, avoid name information leak and reference leak.
- Hold shared lock inside NtQuerydirectoryObject.
- Properly initiailize the directory object in NtCreateDirectoryObject.
- Clear create info before creating the unnamed handle in ObInsertObject.
- Only dereference the target process if we actually have one in NtDuplicateObject.
- Don't double-reference the name information in ObpDeleteNameCheck, thus avoiding another leak.
- Fix object case sensitivity check in ObpLookupObjectName.
Modified:
trunk/reactos/ntoskrnl/cm/regobj.c
trunk/reactos/ntoskrnl/include/internal/ob_x.h
trunk/reactos/ntoskrnl/ob/obdir.c
trunk/reactos/ntoskrnl/ob/obhandle.c
trunk/reactos/ntoskrnl/ob/obname.c
Modified: trunk/reactos/ntoskrnl/cm/regobj.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/regobj.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/cm/regobj.c (original)
+++ trunk/reactos/ntoskrnl/cm/regobj.c Mon Jan 15 23:24:40 2007
@@ -27,6 +27,121 @@
PUNICODE_STRING TargetPath);
/* FUNCTONS *****************************************************************/
+
+PVOID
+NTAPI
+CmpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory,
+ IN PUNICODE_STRING Name,
+ IN ULONG Attributes,
+ IN UCHAR SearchShadow,
+ IN POBP_LOOKUP_CONTEXT Context)
+{
+ BOOLEAN CaseInsensitive = FALSE;
+ POBJECT_HEADER_NAME_INFO HeaderNameInfo;
+ ULONG HashValue;
+ ULONG HashIndex;
+ LONG TotalChars;
+ WCHAR CurrentChar;
+ POBJECT_DIRECTORY_ENTRY *AllocatedEntry;
+ POBJECT_DIRECTORY_ENTRY *LookupBucket;
+ POBJECT_DIRECTORY_ENTRY CurrentEntry;
+ PVOID FoundObject = NULL;
+ PWSTR Buffer;
+ PAGED_CODE();
+
+ /* Always disable this until we have DOS Device Maps */
+ SearchShadow = FALSE;
+
+ /* Fail if we don't have a directory or name */
+ if (!(Directory) || !(Name)) goto Quickie;
+
+ /* Get name information */
+ TotalChars = Name->Length / sizeof(WCHAR);
+ Buffer = Name->Buffer;
+
+ /* Fail if the name is empty */
+ if (!(Buffer) || !(TotalChars)) goto Quickie;
+
+ /* Set up case-sensitivity */
+ if (Attributes & OBJ_CASE_INSENSITIVE) CaseInsensitive = TRUE;
+
+ /* Create the Hash */
+ for (HashValue = 0; TotalChars; TotalChars--)
+ {
+ /* Go to the next Character */
+ CurrentChar = *Buffer++;
+
+ /* Prepare the Hash */
+ HashValue += (HashValue << 1) + (HashValue >> 1);
+
+ /* Create the rest based on the name */
+ if (CurrentChar < 'a') HashValue += CurrentChar;
+ else if (CurrentChar > 'z') HashValue += RtlUpcaseUnicodeChar(CurrentChar);
+ else HashValue += (CurrentChar - ('a'-'A'));
+ }
+
+ /* Merge it with our number of hash buckets */
+ HashIndex = HashValue % 37;
+
+ /* Save the result */
+ Context->HashValue = HashValue;
+ Context->HashIndex = (USHORT)HashIndex;
+
+ /* Get the root entry and set it as our lookup bucket */
+ AllocatedEntry = &Directory->HashBuckets[HashIndex];
+ LookupBucket = AllocatedEntry;
+
+ /* Start looping */
+ while ((CurrentEntry = *AllocatedEntry))
+ {
+ /* Do the hashes match? */
+ if (CurrentEntry->HashValue == HashValue)
+ {
+ /* Make sure that it has a name */
+ ASSERT(OBJECT_TO_OBJECT_HEADER(CurrentEntry->Object)->NameInfoOffset != 0);
+
+ /* Get the name information */
+ HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(OBJECT_TO_OBJECT_HEADER(CurrentEntry->Object));
+
+ /* Do the names match? */
+ if ((Name->Length == HeaderNameInfo->Name.Length) &&
+ (RtlEqualUnicodeString(Name, &HeaderNameInfo->Name, CaseInsensitive)))
+ {
+ break;
+ }
+ }
+
+ /* Move to the next entry */
+ AllocatedEntry = &CurrentEntry->ChainLink;
+ }
+
+ /* Check if we still have an entry */
+ if (CurrentEntry)
+ {
+ /* Set this entry as the first, to speed up incoming insertion */
+ if (AllocatedEntry != LookupBucket)
+ {
+ /* Set the Current Entry */
+ *AllocatedEntry = CurrentEntry->ChainLink;
+
+ /* Link to the old Hash Entry */
+ CurrentEntry->ChainLink = *LookupBucket;
+
+ /* Set the new Hash Entry */
+ *LookupBucket = CurrentEntry;
+ }
+
+ /* Save the found object */
+ FoundObject = CurrentEntry->Object;
+ if (!FoundObject) goto Quickie;
+ }
+
+Quickie:
+ /* Return the object we found */
+ Context->Object = FoundObject;
+ return FoundObject;
+}
+
NTSTATUS
NTAPI
CmFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
@@ -137,9 +252,10 @@
if (End != NULL) *End = 0;
RtlInitUnicodeString(&StartUs, Start);
+ ObpInitializeDirectoryLookup(&Context);
Context.DirectoryLocked = TRUE;
Context.Directory = CurrentObject;
- FoundObject = ObpLookupEntryDirectory(CurrentObject, &StartUs, Attributes, FALSE, &Context);
+ FoundObject = CmpLookupEntryDirectory(CurrentObject, &StartUs, Attributes, FALSE, &Context);
if (FoundObject == NULL)
{
if (End != NULL)
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 Mon Jan 15 23:24:40 2007
@@ -15,48 +15,58 @@
#define OBP_LOCK_STATE_RELEASED 0xEEEE1234
#define OBP_LOCK_STATE_INITIALIZED 0xFFFF1234
-ULONG
-FORCEINLINE
-ObpIncrementQueryReference(IN POBJECT_HEADER ObjectHeader,
- IN POBJECT_HEADER_NAME_INFO ObjectNameInfo)
-{
+POBJECT_HEADER_NAME_INFO
+FORCEINLINE
+ObpAcquireNameInformation(IN POBJECT_HEADER ObjectHeader)
+{
+ POBJECT_HEADER_NAME_INFO ObjectNameInfo;
ULONG NewValue, References;
+ /* Make sure we have name information at all */
+ ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
+ if (!ObjectNameInfo) return NULL;
+
/* Get the number of references */
- NewValue = ObjectNameInfo->QueryReferences;
- while ((NewValue != 0) && (References = NewValue))
- {
+ References = ObjectNameInfo->QueryReferences;
+ for (;;)
+ {
+ /* Check if the count is 0 and fail if so */
+ if (!References) return NULL;
+
/* Increment the number of references */
- if (InterlockedCompareExchange((PLONG)&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)
+ NewValue = InterlockedCompareExchange((PLONG)&ObjectNameInfo->
+ QueryReferences,
+ References + 1,
+ References);
+ if (NewValue == References) break;
+
+ /* We failed, try again */
+ References = NewValue;
+ }
+
+ /* Check for magic flag */
+ if (ObjectNameInfo->QueryReferences & 0x80000000)
+ {
+ /* FIXME: Unhandled*/
+ DbgPrint("OB: Unhandled path\n");
+ KEBUGCHECK(0);
+ }
+
+ /* Return the name information */
+ return ObjectNameInfo;
+}
+
+VOID
+FORCEINLINE
+ObpReleaseNameInformation(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo)
{
POBJECT_DIRECTORY Directory;
+ /* Bail out if there's no info at all */
+ if (!HeaderNameInfo) return;
+
/* Remove a query reference and check if it was the last one */
- if (!InterlockedExchangeAdd((PLONG)&HeaderNameInfo->QueryReferences, -1))
+ if (!InterlockedDecrement((PLONG)&HeaderNameInfo->QueryReferences))
{
/* Check if we have a name */
if (HeaderNameInfo->Name.Buffer)
@@ -149,8 +159,8 @@
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);
+ /* release the name information */
+ ObpReleaseNameInformation(HeaderNameInfo);
/* Dereference the object */
ObDereferenceObject(Context->Object);
@@ -167,11 +177,11 @@
{
/* Release the lock */
ObpReleaseDirectoryLock(Context->Directory, Context);
+ Context->Directory = NULL;
+ Context->DirectoryLocked = FALSE;
}
/* Clear the context */
- Context->Directory = NULL;
- Context->DirectoryLocked = FALSE;
ObpReleaseLookupContextObject(Context);
}
Modified: trunk/reactos/ntoskrnl/ob/obdir.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obdir.c?rev=25…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obdir.c (original)
+++ trunk/reactos/ntoskrnl/ob/obdir.c Mon Jan 15 23:24:40 2007
@@ -220,35 +220,49 @@
/* Set this entry as the first, to speed up incoming insertion */
if (AllocatedEntry != LookupBucket)
{
- /* Check if the directory was locked */
- if (!Context->DirectoryLocked)
+ /* Check if the directory was locked or convert the lock */
+ if ((Context->DirectoryLocked) ||
+ (ExConvertPushLockSharedToExclusive(&Directory->Lock)))
{
- /* Convert the lock from shared to exclusive */
- ExConvertPushLockSharedToExclusive(&Directory->Lock);
+ /* Set the Current Entry */
+ *AllocatedEntry = CurrentEntry->ChainLink;
+
+ /* Link to the old Hash Entry */
+ CurrentEntry->ChainLink = *LookupBucket;
+
+ /* Set the new Hash Entry */
+ *LookupBucket = CurrentEntry;
}
-
- /* Set the Current Entry */
- *AllocatedEntry = CurrentEntry->ChainLink;
-
- /* Link to the old Hash Entry */
- CurrentEntry->ChainLink = *LookupBucket;
-
- /* Set the new Hash Entry */
- *LookupBucket = CurrentEntry;
}
/* Save the found object */
FoundObject = CurrentEntry->Object;
- if (!FoundObject) goto Quickie;
-
+ goto Quickie;
+ }
+ else
+ {
+ /* Check if the directory was locked */
+ if (!Context->DirectoryLocked)
+ {
+ /* Release the lock */
+ ObpReleaseDirectoryLock(Directory, Context);
+ }
+
+ /* Check if we should scan the shadow directory */
+ if ((SearchShadow) && (Directory->DeviceMap))
+ {
+ /* FIXME: We don't support this yet */
+ KEBUGCHECK(0);
+ }
+ }
+
+Quickie:
+ /* Check if we inserted an object */
+ if (FoundObject)
+ {
/* Get the object name information */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(FoundObject);
- HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
- if (HeaderNameInfo)
- {
- /* Add a query reference */
- ObpIncrementQueryReference(ObjectHeader, HeaderNameInfo);
- }
+ ObpAcquireNameInformation(ObjectHeader);
/* Reference the object being looked up */
ObReferenceObject(FoundObject);
@@ -260,29 +274,17 @@
ObpReleaseDirectoryLock(Directory, Context);
}
}
- else
- {
- /* Check if the directory was locked */
- if (!Context->DirectoryLocked)
- {
- /* Release the lock */
- ObpReleaseDirectoryLock(Directory, Context);
- }
-
- /* Check if we should scan the shadow directory */
- if ((SearchShadow) && (Directory->DeviceMap))
- {
- /* FIXME: We don't support this yet */
- KEBUGCHECK(0);
- }
- }
-
-Quickie:
+
/* Check if we found an object already */
if (Context->Object)
{
/* We already did a lookup, so remove this object's query reference */
- //ObpDecrementQueryReference(Context->Object);
+ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Context->Object);
+ HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
+ ObpReleaseNameInformation(HeaderNameInfo);
+
+ /* Also dereference the object itself */
+ ObDereferenceObject(Context->Object);
}
/* Return the object we found */
@@ -354,17 +356,17 @@
*--*/
NTSTATUS
NTAPI
-NtOpenDirectoryObject (OUT PHANDLE DirectoryHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes)
+NtOpenDirectoryObject(OUT PHANDLE DirectoryHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes)
{
- HANDLE hDirectory;
+ HANDLE Directory;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
/* Check if we need to do any probing */
- if(PreviousMode != KernelMode)
+ if (PreviousMode != KernelMode)
{
_SEH_TRY
{
@@ -377,8 +379,6 @@
Status = _SEH_GetExceptionCode();
}
_SEH_END;
-
- /* If we failed, return the error */
if(!NT_SUCCESS(Status)) return Status;
}
@@ -389,13 +389,13 @@
NULL,
DesiredAccess,
NULL,
- &hDirectory);
- if(NT_SUCCESS(Status))
+ &Directory);
+ if (NT_SUCCESS(Status))
{
_SEH_TRY
{
/* Write back the handle to the caller */
- *DirectoryHandle = hDirectory;
+ *DirectoryHandle = Directory;
}
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{
@@ -476,10 +476,14 @@
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
UNICODE_STRING Name;
PWSTR p;
+ OBP_LOOKUP_CONTEXT LookupContext;
PAGED_CODE();
+ /* Initialize lookup */
+ ObpInitializeDirectoryLookup(&LookupContext);
+
/* Check if we need to do any probing */
- if(PreviousMode != KernelMode)
+ if (PreviousMode != KernelMode)
{
_SEH_TRY
{
@@ -491,7 +495,7 @@
if (!RestartScan) SkipEntries = *Context;
/* Probe the return length if the caller specified one */
- if(ReturnLength) ProbeForWriteUlong(ReturnLength);
+ if (ReturnLength) ProbeForWriteUlong(ReturnLength);
}
_SEH_HANDLE
{
@@ -499,8 +503,6 @@
Status = _SEH_GetExceptionCode();
}
_SEH_END;
-
- /* Return the exception to caller if we failed */
if(!NT_SUCCESS(Status)) return Status;
}
else if (!RestartScan)
@@ -530,6 +532,9 @@
ExFreePool(LocalBuffer);
return Status;
}
+
+ /* Lock directory in shared mode */
+ ObpAcquireDirectoryLockShared(Directory, &LookupContext);
/* Start at position 0 */
DirectoryInfo = (POBJECT_DIRECTORY_INFORMATION)LocalBuffer;
@@ -691,6 +696,9 @@
}
_SEH_END;
+ /* Unlock the directory */
+ ObpReleaseDirectoryLock(Directory, &LookupContext);
+
/* Dereference the directory and free our buffer */
ObDereferenceObject(Directory);
ExFreePool(LocalBuffer);
@@ -726,7 +734,7 @@
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
POBJECT_DIRECTORY Directory;
- HANDLE hDirectory;
+ HANDLE NewHandle;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
@@ -745,8 +753,6 @@
Status = _SEH_GetExceptionCode();
}
_SEH_END;
-
- /* If we failed, return the error */
if(!NT_SUCCESS(Status)) return Status;
}
@@ -760,30 +766,33 @@
0,
0,
(PVOID*)&Directory);
- if(NT_SUCCESS(Status))
- {
- /* Insert it into the handle table */
- Status = ObInsertObject((PVOID)Directory,
- NULL,
- DesiredAccess,
- 0,
- NULL,
- &hDirectory);
- if(NT_SUCCESS(Status))
- {
- _SEH_TRY
- {
- /* Return the handle back to the caller */
- *DirectoryHandle = hDirectory;
- }
- _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
- {
- /* Get the exception code */
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- }
- }
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Setup the object */
+ RtlZeroMemory(Directory, sizeof(OBJECT_DIRECTORY));
+ ExInitializePushLock((PULONG_PTR)&Directory->Lock);
+ Directory->SessionId = -1;
+
+ /* Insert it into the handle table */
+ Status = ObInsertObject((PVOID)Directory,
+ NULL,
+ DesiredAccess,
+ 0,
+ NULL,
+ &NewHandle);
+
+ /* Enter SEH to protect write */
+ _SEH_TRY
+ {
+ /* Return the handle back to the caller */
+ *DirectoryHandle = NewHandle;
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ /* Get the exception code */
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
/* Return status to caller */
return Status;
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 Mon Jan 15 23:24:40 2007
@@ -2693,7 +2693,6 @@
{
/* Display warning and break into debugger */
DPRINT1("OB: Attempting to insert existing object %08x\n", Object);
- KEBUGCHECK(0);
DbgBreakPoint();
/* Allow debugger to continue */
@@ -2703,22 +2702,11 @@
/* Get the create and name info, as well as the object type */
ObjectCreateInfo = ObjectHeader->ObjectCreateInfo;
- ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
+ ObjectNameInfo = ObpAcquireNameInformation(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;
- }
- }
+ ObjectName = NULL;
/* Check if this is an named object */
- ObjectName = NULL;
if ((ObjectNameInfo) && (ObjectNameInfo->Name.Buffer))
{
/* Get the object name */
@@ -2738,6 +2726,7 @@
{
/* Assume failure */
*Handle = NULL;
+ ObjectHeader->ObjectCreateInfo = NULL;
/* Create the handle */
Status = ObpCreateUnnamedHandle(Object,
@@ -2750,10 +2739,9 @@
/* Free the create information */
ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo);
- ObjectHeader->ObjectCreateInfo = NULL;
-
- /* Remove a query reference if we added one */
- if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
+
+ /* Release the object name information */
+ ObpReleaseNameInformation(ObjectNameInfo);
/* Remove the extra keep-alive reference */
ObDereferenceObject(Object);
@@ -2779,7 +2767,7 @@
if (!NT_SUCCESS(Status))
{
/* Fail */
- if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
+ ObpReleaseNameInformation(ObjectNameInfo);
ObDereferenceObject(Object);
return Status;
}
@@ -2793,7 +2781,7 @@
if (!NT_SUCCESS(Status))
{
/* Fail */
- if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
+ ObpReleaseNameInformation(ObjectNameInfo);
ObDereferenceObject(Object);
return Status;
}
@@ -2855,7 +2843,7 @@
ObpCleanupDirectoryLookup(&Context);
/* Remove query reference that we added */
- if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
+ ObpReleaseNameInformation(ObjectNameInfo);
/* Dereference the object and delete the access state */
ObDereferenceObject(Object);
@@ -2922,11 +2910,19 @@
/* Check if anything until now failed */
if (!NT_SUCCESS(Status))
{
- /* Cleanup lookup context */
+ /* Check if the directory was added */
+ if (Context.DirectoryLocked)
+ {
+ /* Weird case where we need to do a manual delete */
+ DPRINT1("Unhandled path\n");
+ KEBUGCHECK(0);
+ }
+
+ /* Cleanup the lookup */
ObpCleanupDirectoryLookup(&Context);
/* Remove query reference that we added */
- if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
+ ObpReleaseNameInformation(ObjectNameInfo);
/* Dereference the object and delete the access state */
ObDereferenceObject(Object);
@@ -2971,7 +2967,7 @@
}
/* Remove a query reference */
- if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
+ ObpReleaseNameInformation(ObjectNameInfo);
/* Remove the extra keep-alive reference */
ObDereferenceObject(Object);
@@ -3078,7 +3074,8 @@
SourceProcessHandle,
TargetProcessHandle);
- if((TargetHandle) && (PreviousMode != KernelMode))
+ /* Check if we have a target handle */
+ if ((TargetHandle) && (PreviousMode != KernelMode))
{
/* Enter SEH */
_SEH_TRY
@@ -3092,8 +3089,6 @@
Status = _SEH_GetExceptionCode();
}
_SEH_END;
-
- /* Fail if the pointer was invalid */
if (!NT_SUCCESS(Status)) return Status;
}
@@ -3168,7 +3163,7 @@
hTarget,
TargetProcessHandle,
Status);
- ObDereferenceObject(Target);
+ if (Target) ObDereferenceObject(Target);
ObDereferenceObject(SourceProcess);
return Status;
}
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 Mon Jan 15 23:24:40 2007
@@ -170,19 +170,8 @@
/* Get object structures */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
- ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
+ ObjectNameInfo = ObpAcquireNameInformation(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,
@@ -225,21 +214,14 @@
ObpDeleteSymbolicLinkName(Object);
}
- /* Add a query reference */
+ /* Check if the magic protection flag is set */
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 */
+ /* Remove protection flag */
InterlockedExchangeAdd((PLONG)&ObjectNameInfo->QueryReferences,
- 0xC0000000);
+ -0x40000000);
}
/* Get the directory */
@@ -254,13 +236,13 @@
ObpCleanupDirectoryLookup(&Context);
/* Remove another query reference since we added one on top */
- ObpDecrementQueryReference(ObjectNameInfo);
+ ObpReleaseNameInformation(ObjectNameInfo);
/* Check if we were inserted in a directory */
if (Directory)
{
/* We were, so first remove the extra reference we had added */
- ObpDecrementQueryReference(ObjectNameInfo);
+ ObpReleaseNameInformation(ObjectNameInfo);
/* Now dereference the object as well */
ObDereferenceObject(Object);
@@ -269,7 +251,7 @@
else
{
/* Remove the reference we added */
- if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
+ ObpReleaseNameInformation(ObjectNameInfo);
}
}
@@ -313,11 +295,15 @@
Status = STATUS_SUCCESS;
Object = NULL;
- /* Check if case-insensitivity is forced */
- if ((ObpCaseInsensitive) || (ObjectType->TypeInfo.CaseInsensitive))
- {
- /* Add the flag to disable case sensitivity */
- Attributes |= OBJ_CASE_INSENSITIVE;
+ /* Check if case-insensitivity is checked */
+ if (ObpCaseInsensitive)
+ {
+ /* Check if the object type requests this */
+ if (!(ObjectType) || (ObjectType->TypeInfo.CaseInsensitive))
+ {
+ /* Add the flag to disable case sensitivity */
+ Attributes |= OBJ_CASE_INSENSITIVE;
+ }
}
/* Check if this is a access checks are being forced */
Author: ion
Date: Mon Jan 15 21:37:53 2007
New Revision: 25467
URL: http://svn.reactos.org/svn/reactos?rev=25467&view=rev
Log:
[22 bugfixes]:
- ObpReferenceProcessObjectByHandle is always called with HandleInformation, remove this check.
- ObpReferenceProcessObjectByHandle already gets a process parameter, don't query the current one.
- ObpReferenceProcessObjectByHandle already gets a handle table, don't query the current one.
- ObpDecrementHandleCount shouldn't remove the object from the creator info.
- ObpDecrementHandleCount should clear the exclusive process if this is the last handle.
- Killing a protected handle should raise an exception if a debug port is connected, not an exception port.
- ObpIncrementHandleCount should support OBJ_FORCE_ACCESS_CHECK.
- ObpIncrementHandleCount needs to support ObDuplicateHandle.
- ObpIncrementHandleCount needs to support being called without an AccessState.
- Fix interlocked handle count accounting.
- Allow user-mode to create kernel-mode handles.
- Fix the way Additional reference bias is de-referenced during failures.
- Complete rundown in ObKillProcess.
- Send SourceProcess in ObDuplicateHandle.
- Assume initial failure and clear handle in ObDuplicateHandle.
- Don't leak object table references when failing in ObDuplicateHandle.
- Assume failure in ObOpenObjectByName.
- Don't leak buffer during failure in ObOpenObjectByName.
- Don't leak object reference durning failure in ObOpenObjecByName.
- Validate handle attributes in ObOpenObjectByPointer.
- Use RtlCopyMemory when possible to speed up.
Modified:
trunk/reactos/ntoskrnl/ob/obhandle.c
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 Mon Jan 15 21:37:53 2007
@@ -60,14 +60,14 @@
IN PHANDLE_TABLE HandleTable,
IN KPROCESSOR_MODE AccessMode,
OUT PVOID *Object,
- OUT POBJECT_HANDLE_INFORMATION HandleInformation)
+ OUT POBJECT_HANDLE_INFORMATION HandleInformation,
+ OUT PACCESS_MASK AuditMask)
{
PHANDLE_TABLE_ENTRY HandleEntry;
POBJECT_HEADER ObjectHeader;
ACCESS_MASK GrantedAccess;
ULONG Attributes;
- PEPROCESS CurrentProcess;
- PETHREAD CurrentThread;
+ PETHREAD Thread = PsGetCurrentThread();
NTSTATUS Status;
PAGED_CODE();
@@ -77,46 +77,40 @@
/* Check if the caller wants the current process */
if (Handle == NtCurrentProcess())
{
- /* Get the current process */
- CurrentProcess = PsGetCurrentProcess();
-
- /* Check if the caller wanted handle information */
- if (HandleInformation)
- {
- /* Return it */
- HandleInformation->HandleAttributes = 0;
- HandleInformation->GrantedAccess = Process->GrantedAccess;
- }
+ /* Return handle info */
+ HandleInformation->HandleAttributes = 0;
+ HandleInformation->GrantedAccess = Process->GrantedAccess;
+
+ /* No audit mask */
+ *AuditMask = 0;
/* Reference ourselves */
- ObjectHeader = OBJECT_TO_OBJECT_HEADER(CurrentProcess);
+ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Process);
InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1);
/* Return the pointer */
- *Object = CurrentProcess;
+ *Object = Process;
+ ASSERT(*Object != NULL);
return STATUS_SUCCESS;
}
/* Check if the caller wants the current thread */
if (Handle == NtCurrentThread())
{
- /* Get the current thread */
- CurrentThread = PsGetCurrentThread();
-
- /* Check if the caller wanted handle information */
- if (HandleInformation)
- {
- /* Return it */
- HandleInformation->HandleAttributes = 0;
- HandleInformation->GrantedAccess = CurrentThread->GrantedAccess;
- }
+ /* Return handle information */
+ HandleInformation->HandleAttributes = 0;
+ HandleInformation->GrantedAccess = Thread->GrantedAccess;
/* Reference ourselves */
- ObjectHeader = OBJECT_TO_OBJECT_HEADER(CurrentThread);
+ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Thread);
InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1);
+ /* No audit mask */
+ *AuditMask = 0;
+
/* Return the pointer */
- *Object = CurrentThread;
+ *Object = Thread;
+ ASSERT(*Object != NULL);
return STATUS_SUCCESS;
}
@@ -126,11 +120,6 @@
/* Use the kernel handle table and get the actual handle value */
Handle = ObKernelHandleToHandle(Handle);
HandleTable = ObpKernelHandleTable;
- }
- else
- {
- /* Otherwise use this process's handle table */
- HandleTable = PsGetCurrentProcess()->ObjectTable;
}
/* Enter a critical region while we touch the handle table */
@@ -156,6 +145,9 @@
/* Fill out the information */
HandleInformation->HandleAttributes = Attributes;
HandleInformation->GrantedAccess = GrantedAccess;
+
+ /* No audit mask (FIXME!) */
+ *AuditMask = 0;
/* Return the pointer */
*Object = &ObjectHeader->Body;
@@ -244,7 +236,7 @@
if (!HandleDatabase) return NULL;
/* Copy the old database */
- RtlMoveMemory(HandleDatabase, OldHandleDatabase, OldSize);
+ RtlCopyMemory(HandleDatabase, OldHandleDatabase, OldSize);
/* Check if we he had a single entry before */
if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS)
@@ -440,12 +432,12 @@
POBJECT_TYPE ObjectType;
LONG SystemHandleCount, ProcessHandleCount;
LONG NewCount;
- POBJECT_HEADER_CREATOR_INFO CreatorInfo;
KIRQL CalloutIrql;
POBJECT_HEADER_HANDLE_INFO HandleInfo;
POBJECT_HANDLE_COUNT_ENTRY HandleEntry;
POBJECT_HANDLE_COUNT_DATABASE HandleDatabase;
ULONG i;
+ PAGED_CODE();
/* Get the object type and header */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
@@ -467,17 +459,11 @@
/* Decrement the handle count */
NewCount = InterlockedDecrement(&ObjectHeader->HandleCount);
- /* Check if we're out of handles */
- if (!NewCount)
- {
- /* Get the creator info */
- CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader);
- if ((CreatorInfo) && !(IsListEmpty(&CreatorInfo->TypeList)))
- {
- /* Remove it from the list and re-initialize it */
- RemoveEntryList(&CreatorInfo->TypeList);
- InitializeListHead(&CreatorInfo->TypeList);
- }
+ /* Check if we're out of handles and this was an exclusive object */
+ if (!(NewCount) && (ObjectHeader->Flags & OB_FLAG_EXCLUSIVE))
+ {
+ /* Clear the exclusive flag */
+ OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = NULL;
}
/* Is the object type keeping track of handles? */
@@ -644,8 +630,8 @@
/* We are! Unlock the entry */
ExUnlockHandleTableEntry(HandleTable, HandleEntry);
- /* Make sure we have an exception port */
- if (PsGetCurrentProcess()->ExceptionPort)
+ /* Make sure we have a debug port */
+ if (PsGetCurrentProcess()->DebugPort)
{
/* Raise an exception */
return KeRaiseUserException(STATUS_HANDLE_NOT_CLOSABLE);
@@ -656,10 +642,11 @@
return STATUS_HANDLE_NOT_CLOSABLE;
}
}
-
- /* Otherwise, we are kernel mode, so unlock the entry and return */
- ExUnlockHandleTableEntry(HandleTable, HandleEntry);
- return STATUS_HANDLE_NOT_CLOSABLE;
+ else
+ {
+ /* Otherwise, bugcheck the OS */
+ KeBugCheckEx(0x8B, (ULONG_PTR)Handle, 0, 0, 0);
+ }
}
/* Destroy and unlock the handle entry */
@@ -727,6 +714,8 @@
BOOLEAN Exclusive = FALSE, NewObject;
POBJECT_HEADER_CREATOR_INFO CreatorInfo;
KIRQL CalloutIrql;
+ KPROCESSOR_MODE ProbeMode;
+ ULONG Total;
/* Get the object header and type */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
@@ -738,6 +727,18 @@
OpenReason,
ObjectHeader->HandleCount,
ObjectHeader->PointerCount);
+
+ /* Check if caller is forcing user mode */
+ if (HandleAttributes & OBJ_FORCE_ACCESS_CHECK)
+ {
+ /* Force it */
+ ProbeMode = UserMode;
+ }
+ else
+ {
+ /* Keep original setting */
+ ProbeMode = AccessMode;
+ }
/* Lock the object type */
ObpEnterObjectTypeMutex(ObjectType);
@@ -797,7 +798,8 @@
}
/* Check if we're opening an existing handle */
- if (OpenReason == ObOpenHandle)
+ if ((OpenReason == ObOpenHandle) ||
+ ((OpenReason == ObDuplicateHandle) && (AccessState)))
{
/* Validate the caller's access to this object */
if (!ObCheckObjectAccess(Object,
@@ -875,7 +877,10 @@
Status = ObjectType->TypeInfo.OpenProcedure(OpenReason,
Process,
Object,
- AccessState->PreviouslyGrantedAccess,
+ AccessState ?
+ AccessState->
+ PreviouslyGrantedAccess :
+ 0,
ProcessHandleCount);
ObpCalloutEnd(CalloutIrql, "Open", ObjectType, Object);
@@ -889,26 +894,30 @@
}
}
- /* Check if we have creator info */
- CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader);
- if (CreatorInfo)
- {
- /* We do, acquire the lock */
- ObpEnterObjectTypeMutex(ObjectType);
-
- /* Insert us on the list */
- InsertTailList(&ObjectType->TypeList, &CreatorInfo->TypeList);
-
- /* Release the lock */
- ObpLeaveObjectTypeMutex(ObjectType);
+ /* Check if this is a create operation */
+ if (OpenReason == ObCreateHandle)
+ {
+ /* Check if we have creator info */
+ CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader);
+ if (CreatorInfo)
+ {
+ /* We do, acquire the lock */
+ ObpEnterObjectTypeMutex(ObjectType);
+
+ /* Insert us on the list */
+ InsertTailList(&ObjectType->TypeList, &CreatorInfo->TypeList);
+
+ /* Release the lock */
+ ObpLeaveObjectTypeMutex(ObjectType);
+ }
}
/* Increase total number of handles */
- InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfHandles);
- if (ObjectType->TotalNumberOfHandles > ObjectType->HighWaterNumberOfHandles)
+ Total = InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfHandles);
+ if (Total > ObjectType->HighWaterNumberOfHandles)
{
/* Fixup count */
- ObjectType->HighWaterNumberOfHandles = ObjectType->TotalNumberOfHandles;
+ ObjectType->HighWaterNumberOfHandles = Total;
}
/* Trace call and return */
@@ -971,6 +980,7 @@
BOOLEAN Exclusive = FALSE, NewObject;
POBJECT_HEADER_CREATOR_INFO CreatorInfo;
KIRQL CalloutIrql;
+ ULONG Total;
/* Get the object header and type */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
@@ -1123,11 +1133,11 @@
}
/* Increase total number of handles */
- InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfHandles);
- if (ObjectType->TotalNumberOfHandles > ObjectType->HighWaterNumberOfHandles)
+ Total = InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfHandles);
+ if (Total > ObjectType->HighWaterNumberOfHandles)
{
/* Fixup count */
- ObjectType->HighWaterNumberOfHandles = ObjectType->TotalNumberOfHandles;
+ ObjectType->HighWaterNumberOfHandles = Total;
}
/* Trace call and return */
@@ -1208,7 +1218,7 @@
ObjectHeader->PointerCount);
/* Check if this is a kernel handle */
- if ((HandleAttributes & OBJ_KERNEL_HANDLE) && (AccessMode == KernelMode))
+ if (HandleAttributes & OBJ_KERNEL_HANDLE)
{
/* Set the handle table */
HandleTable = ObpKernelHandleTable;
@@ -1309,14 +1319,9 @@
}
/* Handle extra references */
- if (AdditionalReferences == 1)
- {
- /* Dereference the object once */
- ObDereferenceObject(Object);
- }
- else if (AdditionalReferences > 1)
- {
- /* Dereference it many times */
+ if (AdditionalReferences)
+ {
+ /* Dereference it as many times as required */
InterlockedExchangeAdd(&ObjectHeader->PointerCount,
-AdditionalReferences);
}
@@ -1413,7 +1418,7 @@
}
/* Check if this is a kernel handle */
- if ((HandleAttributes & OBJ_KERNEL_HANDLE) && (AccessMode == KernelMode))
+ if (HandleAttributes & OBJ_KERNEL_HANDLE)
{
/* Set the handle table */
HandleTable = ObpKernelHandleTable;
@@ -1508,12 +1513,6 @@
/* Make sure we got a handle */
if (Handle)
{
- /* Check if we have auxiliary data */
- if (AuxData)
- {
- /* FIXME: Change handle security */
- }
-
/* Check if this was a kernel handle */
if (KernelHandle) Handle = ObMarkHandleAsKernelHandle(Handle);
@@ -1573,16 +1572,18 @@
GrantedAccess);
/* Handle extra references */
- if (AdditionalReferences == 1)
- {
- /* Dereference the object once */
+ if (AdditionalReferences)
+ {
+ /* Check how many extra references were added */
+ if (AdditionalReferences > 1)
+ {
+ /* Dereference it many times */
+ InterlockedExchangeAdd(&ObjectHeader->PointerCount,
+ -(AdditionalReferences - 1));
+ }
+
+ /* Dereference the object one last time */
ObDereferenceObject(Object);
- }
- else if (AdditionalReferences > 1)
- {
- /* Dereference it many times */
- InterlockedExchangeAdd(&ObjectHeader->PointerCount,
- -AdditionalReferences);
}
/* Detach if necessary and fail */
@@ -1670,9 +1671,9 @@
/* Detach */
if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
- /* Check if this was a user-mode caller with a valid exception port */
+ /* Check if this was a user-mode caller with a valid debug port */
if ((AccessMode != KernelMode) &&
- (PsGetCurrentProcess()->ExceptionPort))
+ (PsGetCurrentProcess()->DebugPort))
{
/* Raise an exception */
Status = KeRaiseUserException(STATUS_INVALID_HANDLE);
@@ -1948,8 +1949,9 @@
BOOLEAN HardErrors;
PAGED_CODE();
- /* Wait for process rundown */
+ /* Wait for process rundown and then complete it */
ExWaitForRundownProtectionRelease(&Process->RundownProtect);
+ ExRundownCompleted(&Process->RundownProtect);
/* Get the object table */
HandleTable = Process->ObjectTable;
@@ -2007,6 +2009,7 @@
AUX_DATA AuxData;
PHANDLE_TABLE HandleTable;
OBJECT_HANDLE_INFORMATION HandleInformation;
+ ULONG AuditMask;
PAGED_CODE();
OBTRACE(OB_HANDLE_DEBUG,
"%s - Duplicating handle: %lx for %p into %p\n",
@@ -2015,6 +2018,9 @@
SourceProcess,
TargetProcess);
+ /* Assume failure */
+ if (TargetHandle) *TargetHandle = NULL;
+
/* Check if we're not duplicating the same access */
if (!(Options & DUPLICATE_SAME_ACCESS))
{
@@ -2029,11 +2035,12 @@
/* Reference the process object */
Status = ObpReferenceProcessObjectByHandle(SourceHandle,
- 0,
+ SourceProcess,
HandleTable,
PreviousMode,
&SourceObject,
- &HandleInformation);
+ &HandleInformation,
+ &AuditMask);
if (!NT_SUCCESS(Status))
{
/* Fail */
@@ -2191,6 +2198,10 @@
/* Now check if incrementing actually failed */
if (!NT_SUCCESS(Status))
{
+ /* Dereference handle tables */
+ ObDereferenceProcessHandleTable(SourceProcess);
+ ObDereferenceProcessHandleTable(TargetProcess);
+
/* Dereference the source object */
ObDereferenceObject(SourceObject);
return Status;
@@ -2283,11 +2294,13 @@
POB_TEMP_BUFFER TempBuffer;
PAGED_CODE();
+ /* Assume failure */
+ *Handle = NULL;
+
/* Check if we didn't get any Object Attributes */
if (!ObjectAttributes)
{
/* Fail with special status code */
- *Handle = NULL;
return STATUS_INVALID_PARAMETER;
}
@@ -2303,7 +2316,12 @@
TRUE,
&TempBuffer->ObjectCreateInfo,
&ObjectName);
- if (!NT_SUCCESS(Status)) return Status;
+ if (!NT_SUCCESS(Status))
+ {
+ /* Fail */
+ ExFreePool(TempBuffer);
+ return Status;
+ }
/* Check if we didn't get an access state */
if (!PassedAccessState)
@@ -2378,6 +2396,9 @@
/* Cleanup after lookup */
ObpCleanupDirectoryLookup(&TempBuffer->LookupContext);
+
+ /* Dereference the object */
+ ObDereferenceObject(Object);
}
else
{
@@ -2466,8 +2487,8 @@
AUX_DATA AuxData;
PAGED_CODE();
- /* Get the Header Info */
- Header = OBJECT_TO_OBJECT_HEADER(Object);
+ /* Assume failure */
+ *Handle = NULL;
/* Reference the object */
Status = ObReferenceObjectByPointer(Object,
@@ -2475,6 +2496,9 @@
ObjectType,
AccessMode);
if (!NT_SUCCESS(Status)) return Status;
+
+ /* Get the Header Info */
+ Header = OBJECT_TO_OBJECT_HEADER(Object);
/* Check if we didn't get an access state */
if (!PassedAccessState)
@@ -2491,6 +2515,20 @@
ObDereferenceObject(Object);
return Status;
}
+ }
+
+ /* Check if we have invalid object attributes */
+ if (Header->Type->TypeInfo.InvalidAttributes & HandleAttributes)
+ {
+ /* Delete the access state */
+ if (PassedAccessState == &AccessState)
+ {
+ SeDeleteAccessState(PassedAccessState);
+ }
+
+ /* Dereference the object */
+ ObDereferenceObject(Object);
+ return STATUS_INVALID_PARAMETER;
}
/* Create the handle */