mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[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. svn path=/trunk/; revision=25469
This commit is contained in:
parent
4e9c7cf7e4
commit
d591f751c7
5 changed files with 277 additions and 161 deletions
|
@ -27,6 +27,121 @@ CmiGetLinkTarget(PEREGISTRY_HIVE RegistryHive,
|
|||
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 @@ CmFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
|
|||
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)
|
||||
|
|
|
@ -15,48 +15,58 @@
|
|||
#define OBP_LOCK_STATE_RELEASED 0xEEEE1234
|
||||
#define OBP_LOCK_STATE_INITIALIZED 0xFFFF1234
|
||||
|
||||
ULONG
|
||||
POBJECT_HEADER_NAME_INFO
|
||||
FORCEINLINE
|
||||
ObpIncrementQueryReference(IN POBJECT_HEADER ObjectHeader,
|
||||
IN POBJECT_HEADER_NAME_INFO ObjectNameInfo)
|
||||
ObpAcquireNameInformation(IN POBJECT_HEADER ObjectHeader)
|
||||
{
|
||||
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((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);
|
||||
}
|
||||
/* Make sure we have name information at all */
|
||||
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
|
||||
if (!ObjectNameInfo) return NULL;
|
||||
|
||||
/* Done looping */
|
||||
NewValue = ObjectNameInfo->QueryReferences;
|
||||
break;
|
||||
}
|
||||
/* Get the number of references */
|
||||
References = ObjectNameInfo->QueryReferences;
|
||||
for (;;)
|
||||
{
|
||||
/* Check if the count is 0 and fail if so */
|
||||
if (!References) return NULL;
|
||||
|
||||
/* Increment the number of references */
|
||||
NewValue = InterlockedCompareExchange((PLONG)&ObjectNameInfo->
|
||||
QueryReferences,
|
||||
References + 1,
|
||||
References);
|
||||
if (NewValue == References) break;
|
||||
|
||||
/* We failed, try again */
|
||||
References = NewValue;
|
||||
}
|
||||
|
||||
/* Return the number of references */
|
||||
return 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
|
||||
ObpDecrementQueryReference(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo)
|
||||
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 @@ ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context)
|
|||
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 @@ ObpCleanupDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context)
|
|||
{
|
||||
/* Release the lock */
|
||||
ObpReleaseDirectoryLock(Context->Directory, Context);
|
||||
Context->Directory = NULL;
|
||||
Context->DirectoryLocked = FALSE;
|
||||
}
|
||||
|
||||
/* Clear the context */
|
||||
Context->Directory = NULL;
|
||||
Context->DirectoryLocked = FALSE;
|
||||
ObpReleaseLookupContextObject(Context);
|
||||
}
|
||||
|
||||
|
|
|
@ -220,45 +220,24 @@ ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory,
|
|||
/* 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;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Reference the object being looked up */
|
||||
ObReferenceObject(FoundObject);
|
||||
|
||||
/* Check if the directory was locked */
|
||||
if (!Context->DirectoryLocked)
|
||||
{
|
||||
/* Release the lock */
|
||||
ObpReleaseDirectoryLock(Directory, Context);
|
||||
}
|
||||
goto Quickie;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -278,11 +257,34 @@ ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory,
|
|||
}
|
||||
|
||||
Quickie:
|
||||
/* Check if we inserted an object */
|
||||
if (FoundObject)
|
||||
{
|
||||
/* Get the object name information */
|
||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(FoundObject);
|
||||
ObpAcquireNameInformation(ObjectHeader);
|
||||
|
||||
/* Reference the object being looked up */
|
||||
ObReferenceObject(FoundObject);
|
||||
|
||||
/* Check if the directory was locked */
|
||||
if (!Context->DirectoryLocked)
|
||||
{
|
||||
/* Release the lock */
|
||||
ObpReleaseDirectoryLock(Directory, Context);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 @@ ObpDeleteEntryDirectory(POBP_LOOKUP_CONTEXT Context)
|
|||
*--*/
|
||||
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 @@ NtOpenDirectoryObject (OUT PHANDLE DirectoryHandle,
|
|||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
/* If we failed, return the error */
|
||||
if(!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
|
@ -389,13 +389,13 @@ NtOpenDirectoryObject (OUT PHANDLE DirectoryHandle,
|
|||
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 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
|
|||
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 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
|
|||
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 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
|
|||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
/* Return the exception to caller if we failed */
|
||||
if(!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
else if (!RestartScan)
|
||||
|
@ -531,6 +533,9 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
|
|||
return Status;
|
||||
}
|
||||
|
||||
/* Lock directory in shared mode */
|
||||
ObpAcquireDirectoryLockShared(Directory, &LookupContext);
|
||||
|
||||
/* Start at position 0 */
|
||||
DirectoryInfo = (POBJECT_DIRECTORY_INFORMATION)LocalBuffer;
|
||||
TotalLength = sizeof(OBJECT_DIRECTORY_INFORMATION);
|
||||
|
@ -691,6 +696,9 @@ Quickie:
|
|||
}
|
||||
_SEH_END;
|
||||
|
||||
/* Unlock the directory */
|
||||
ObpReleaseDirectoryLock(Directory, &LookupContext);
|
||||
|
||||
/* Dereference the directory and free our buffer */
|
||||
ObDereferenceObject(Directory);
|
||||
ExFreePool(LocalBuffer);
|
||||
|
@ -726,7 +734,7 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
|
|||
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 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
|
|||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
/* If we failed, return the error */
|
||||
if(!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
|
@ -760,30 +766,33 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
|
|||
0,
|
||||
0,
|
||||
(PVOID*)&Directory);
|
||||
if(NT_SUCCESS(Status))
|
||||
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
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
/* 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;
|
||||
|
|
|
@ -2693,7 +2693,6 @@ ObInsertObject(IN PVOID Object,
|
|||
{
|
||||
/* 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 @@ ObInsertObject(IN PVOID Object,
|
|||
|
||||
/* 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 @@ ObInsertObject(IN PVOID Object,
|
|||
{
|
||||
/* Assume failure */
|
||||
*Handle = NULL;
|
||||
ObjectHeader->ObjectCreateInfo = NULL;
|
||||
|
||||
/* Create the handle */
|
||||
Status = ObpCreateUnnamedHandle(Object,
|
||||
|
@ -2750,10 +2739,9 @@ ObInsertObject(IN PVOID Object,
|
|||
|
||||
/* 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 @@ ObInsertObject(IN PVOID Object,
|
|||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail */
|
||||
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
|
||||
ObpReleaseNameInformation(ObjectNameInfo);
|
||||
ObDereferenceObject(Object);
|
||||
return Status;
|
||||
}
|
||||
|
@ -2793,7 +2781,7 @@ ObInsertObject(IN PVOID Object,
|
|||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail */
|
||||
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
|
||||
ObpReleaseNameInformation(ObjectNameInfo);
|
||||
ObDereferenceObject(Object);
|
||||
return Status;
|
||||
}
|
||||
|
@ -2855,7 +2843,7 @@ ObInsertObject(IN PVOID Object,
|
|||
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 @@ ObInsertObject(IN PVOID Object,
|
|||
/* 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 @@ ObInsertObject(IN PVOID Object,
|
|||
}
|
||||
|
||||
/* Remove a query reference */
|
||||
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
|
||||
ObpReleaseNameInformation(ObjectNameInfo);
|
||||
|
||||
/* Remove the extra keep-alive reference */
|
||||
ObDereferenceObject(Object);
|
||||
|
@ -3078,7 +3074,8 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle,
|
|||
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 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle,
|
|||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
/* Fail if the pointer was invalid */
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
|
@ -3168,7 +3163,7 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle,
|
|||
hTarget,
|
||||
TargetProcessHandle,
|
||||
Status);
|
||||
ObDereferenceObject(Target);
|
||||
if (Target) ObDereferenceObject(Target);
|
||||
ObDereferenceObject(SourceProcess);
|
||||
return Status;
|
||||
}
|
||||
|
|
|
@ -170,20 +170,9 @@ ObpDeleteNameCheck(IN PVOID Object)
|
|||
|
||||
/* 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,
|
||||
* and if the object isn't a permanent object.
|
||||
|
@ -225,21 +214,14 @@ ObpDeleteNameCheck(IN PVOID Object)
|
|||
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 */
|
||||
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
|
||||
if ((ObjectNameInfo) &&
|
||||
(ObjectNameInfo->QueryReferences & 0x40000000))
|
||||
{
|
||||
/* Add deletion flag */
|
||||
/* Remove protection flag */
|
||||
InterlockedExchangeAdd((PLONG)&ObjectNameInfo->QueryReferences,
|
||||
0xC0000000);
|
||||
-0x40000000);
|
||||
}
|
||||
|
||||
/* Get the directory */
|
||||
|
@ -254,13 +236,13 @@ ObpDeleteNameCheck(IN PVOID Object)
|
|||
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 @@ ObpDeleteNameCheck(IN PVOID Object)
|
|||
else
|
||||
{
|
||||
/* Remove the reference we added */
|
||||
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
|
||||
ObpReleaseNameInformation(ObjectNameInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,11 +295,15 @@ ObpLookupObjectName(IN HANDLE RootHandle,
|
|||
Status = STATUS_SUCCESS;
|
||||
Object = NULL;
|
||||
|
||||
/* Check if case-insensitivity is forced */
|
||||
if ((ObpCaseInsensitive) || (ObjectType->TypeInfo.CaseInsensitive))
|
||||
/* Check if case-insensitivity is checked */
|
||||
if (ObpCaseInsensitive)
|
||||
{
|
||||
/* Add the flag to disable case sensitivity */
|
||||
Attributes |= OBJ_CASE_INSENSITIVE;
|
||||
/* 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 */
|
||||
|
|
Loading…
Reference in a new issue