mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 13:06:34 +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);
|
PUNICODE_STRING TargetPath);
|
||||||
|
|
||||||
/* FUNCTONS *****************************************************************/
|
/* 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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
CmFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
|
CmFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
|
||||||
|
@ -137,9 +252,10 @@ CmFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
|
||||||
if (End != NULL) *End = 0;
|
if (End != NULL) *End = 0;
|
||||||
|
|
||||||
RtlInitUnicodeString(&StartUs, Start);
|
RtlInitUnicodeString(&StartUs, Start);
|
||||||
|
ObpInitializeDirectoryLookup(&Context);
|
||||||
Context.DirectoryLocked = TRUE;
|
Context.DirectoryLocked = TRUE;
|
||||||
Context.Directory = CurrentObject;
|
Context.Directory = CurrentObject;
|
||||||
FoundObject = ObpLookupEntryDirectory(CurrentObject, &StartUs, Attributes, FALSE, &Context);
|
FoundObject = CmpLookupEntryDirectory(CurrentObject, &StartUs, Attributes, FALSE, &Context);
|
||||||
if (FoundObject == NULL)
|
if (FoundObject == NULL)
|
||||||
{
|
{
|
||||||
if (End != NULL)
|
if (End != NULL)
|
||||||
|
|
|
@ -15,48 +15,58 @@
|
||||||
#define OBP_LOCK_STATE_RELEASED 0xEEEE1234
|
#define OBP_LOCK_STATE_RELEASED 0xEEEE1234
|
||||||
#define OBP_LOCK_STATE_INITIALIZED 0xFFFF1234
|
#define OBP_LOCK_STATE_INITIALIZED 0xFFFF1234
|
||||||
|
|
||||||
ULONG
|
POBJECT_HEADER_NAME_INFO
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
ObpIncrementQueryReference(IN POBJECT_HEADER ObjectHeader,
|
ObpAcquireNameInformation(IN POBJECT_HEADER ObjectHeader)
|
||||||
IN POBJECT_HEADER_NAME_INFO ObjectNameInfo)
|
|
||||||
{
|
{
|
||||||
|
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
|
||||||
ULONG NewValue, References;
|
ULONG NewValue, References;
|
||||||
|
|
||||||
/* Get the number of references */
|
/* Make sure we have name information at all */
|
||||||
NewValue = ObjectNameInfo->QueryReferences;
|
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
|
||||||
while ((NewValue != 0) && (References = NewValue))
|
if (!ObjectNameInfo) 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 */
|
/* Get the number of references */
|
||||||
NewValue = ObjectNameInfo->QueryReferences;
|
References = ObjectNameInfo->QueryReferences;
|
||||||
break;
|
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 */
|
/* Check for magic flag */
|
||||||
return NewValue;
|
if (ObjectNameInfo->QueryReferences & 0x80000000)
|
||||||
|
{
|
||||||
|
/* FIXME: Unhandled*/
|
||||||
|
DbgPrint("OB: Unhandled path\n");
|
||||||
|
KEBUGCHECK(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the name information */
|
||||||
|
return ObjectNameInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
ObpDecrementQueryReference(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo)
|
ObpReleaseNameInformation(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo)
|
||||||
{
|
{
|
||||||
POBJECT_DIRECTORY Directory;
|
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 */
|
/* 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 */
|
/* Check if we have a name */
|
||||||
if (HeaderNameInfo->Name.Buffer)
|
if (HeaderNameInfo->Name.Buffer)
|
||||||
|
@ -149,8 +159,8 @@ ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context)
|
||||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Context->Object);
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Context->Object);
|
||||||
HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
|
HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
|
||||||
|
|
||||||
/* Check if we do have name information */
|
/* release the name information */
|
||||||
if (HeaderNameInfo) ObpDecrementQueryReference(HeaderNameInfo);
|
ObpReleaseNameInformation(HeaderNameInfo);
|
||||||
|
|
||||||
/* Dereference the object */
|
/* Dereference the object */
|
||||||
ObDereferenceObject(Context->Object);
|
ObDereferenceObject(Context->Object);
|
||||||
|
@ -167,11 +177,11 @@ ObpCleanupDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context)
|
||||||
{
|
{
|
||||||
/* Release the lock */
|
/* Release the lock */
|
||||||
ObpReleaseDirectoryLock(Context->Directory, Context);
|
ObpReleaseDirectoryLock(Context->Directory, Context);
|
||||||
|
Context->Directory = NULL;
|
||||||
|
Context->DirectoryLocked = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear the context */
|
/* Clear the context */
|
||||||
Context->Directory = NULL;
|
|
||||||
Context->DirectoryLocked = FALSE;
|
|
||||||
ObpReleaseLookupContextObject(Context);
|
ObpReleaseLookupContextObject(Context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -220,45 +220,24 @@ ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory,
|
||||||
/* Set this entry as the first, to speed up incoming insertion */
|
/* Set this entry as the first, to speed up incoming insertion */
|
||||||
if (AllocatedEntry != LookupBucket)
|
if (AllocatedEntry != LookupBucket)
|
||||||
{
|
{
|
||||||
/* Check if the directory was locked */
|
/* Check if the directory was locked or convert the lock */
|
||||||
if (!Context->DirectoryLocked)
|
if ((Context->DirectoryLocked) ||
|
||||||
|
(ExConvertPushLockSharedToExclusive(&Directory->Lock)))
|
||||||
{
|
{
|
||||||
/* Convert the lock from shared to exclusive */
|
/* Set the Current Entry */
|
||||||
ExConvertPushLockSharedToExclusive(&Directory->Lock);
|
*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 */
|
/* Save the found object */
|
||||||
FoundObject = CurrentEntry->Object;
|
FoundObject = CurrentEntry->Object;
|
||||||
if (!FoundObject) goto Quickie;
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -278,11 +257,34 @@ ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory,
|
||||||
}
|
}
|
||||||
|
|
||||||
Quickie:
|
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 */
|
/* Check if we found an object already */
|
||||||
if (Context->Object)
|
if (Context->Object)
|
||||||
{
|
{
|
||||||
/* We already did a lookup, so remove this object's query reference */
|
/* 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 */
|
/* Return the object we found */
|
||||||
|
@ -354,17 +356,17 @@ ObpDeleteEntryDirectory(POBP_LOOKUP_CONTEXT Context)
|
||||||
*--*/
|
*--*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
NtOpenDirectoryObject (OUT PHANDLE DirectoryHandle,
|
NtOpenDirectoryObject(OUT PHANDLE DirectoryHandle,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
||||||
{
|
{
|
||||||
HANDLE hDirectory;
|
HANDLE Directory;
|
||||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Check if we need to do any probing */
|
/* Check if we need to do any probing */
|
||||||
if(PreviousMode != KernelMode)
|
if (PreviousMode != KernelMode)
|
||||||
{
|
{
|
||||||
_SEH_TRY
|
_SEH_TRY
|
||||||
{
|
{
|
||||||
|
@ -377,8 +379,6 @@ NtOpenDirectoryObject (OUT PHANDLE DirectoryHandle,
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
}
|
||||||
_SEH_END;
|
_SEH_END;
|
||||||
|
|
||||||
/* If we failed, return the error */
|
|
||||||
if(!NT_SUCCESS(Status)) return Status;
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,13 +389,13 @@ NtOpenDirectoryObject (OUT PHANDLE DirectoryHandle,
|
||||||
NULL,
|
NULL,
|
||||||
DesiredAccess,
|
DesiredAccess,
|
||||||
NULL,
|
NULL,
|
||||||
&hDirectory);
|
&Directory);
|
||||||
if(NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
_SEH_TRY
|
_SEH_TRY
|
||||||
{
|
{
|
||||||
/* Write back the handle to the caller */
|
/* Write back the handle to the caller */
|
||||||
*DirectoryHandle = hDirectory;
|
*DirectoryHandle = Directory;
|
||||||
}
|
}
|
||||||
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
|
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
|
||||||
{
|
{
|
||||||
|
@ -476,10 +476,14 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
|
||||||
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
|
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
|
||||||
UNICODE_STRING Name;
|
UNICODE_STRING Name;
|
||||||
PWSTR p;
|
PWSTR p;
|
||||||
|
OBP_LOOKUP_CONTEXT LookupContext;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Initialize lookup */
|
||||||
|
ObpInitializeDirectoryLookup(&LookupContext);
|
||||||
|
|
||||||
/* Check if we need to do any probing */
|
/* Check if we need to do any probing */
|
||||||
if(PreviousMode != KernelMode)
|
if (PreviousMode != KernelMode)
|
||||||
{
|
{
|
||||||
_SEH_TRY
|
_SEH_TRY
|
||||||
{
|
{
|
||||||
|
@ -491,7 +495,7 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
|
||||||
if (!RestartScan) SkipEntries = *Context;
|
if (!RestartScan) SkipEntries = *Context;
|
||||||
|
|
||||||
/* Probe the return length if the caller specified one */
|
/* Probe the return length if the caller specified one */
|
||||||
if(ReturnLength) ProbeForWriteUlong(ReturnLength);
|
if (ReturnLength) ProbeForWriteUlong(ReturnLength);
|
||||||
}
|
}
|
||||||
_SEH_HANDLE
|
_SEH_HANDLE
|
||||||
{
|
{
|
||||||
|
@ -499,8 +503,6 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
}
|
||||||
_SEH_END;
|
_SEH_END;
|
||||||
|
|
||||||
/* Return the exception to caller if we failed */
|
|
||||||
if(!NT_SUCCESS(Status)) return Status;
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
}
|
||||||
else if (!RestartScan)
|
else if (!RestartScan)
|
||||||
|
@ -531,6 +533,9 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Lock directory in shared mode */
|
||||||
|
ObpAcquireDirectoryLockShared(Directory, &LookupContext);
|
||||||
|
|
||||||
/* Start at position 0 */
|
/* Start at position 0 */
|
||||||
DirectoryInfo = (POBJECT_DIRECTORY_INFORMATION)LocalBuffer;
|
DirectoryInfo = (POBJECT_DIRECTORY_INFORMATION)LocalBuffer;
|
||||||
TotalLength = sizeof(OBJECT_DIRECTORY_INFORMATION);
|
TotalLength = sizeof(OBJECT_DIRECTORY_INFORMATION);
|
||||||
|
@ -691,6 +696,9 @@ Quickie:
|
||||||
}
|
}
|
||||||
_SEH_END;
|
_SEH_END;
|
||||||
|
|
||||||
|
/* Unlock the directory */
|
||||||
|
ObpReleaseDirectoryLock(Directory, &LookupContext);
|
||||||
|
|
||||||
/* Dereference the directory and free our buffer */
|
/* Dereference the directory and free our buffer */
|
||||||
ObDereferenceObject(Directory);
|
ObDereferenceObject(Directory);
|
||||||
ExFreePool(LocalBuffer);
|
ExFreePool(LocalBuffer);
|
||||||
|
@ -726,7 +734,7 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
||||||
{
|
{
|
||||||
POBJECT_DIRECTORY Directory;
|
POBJECT_DIRECTORY Directory;
|
||||||
HANDLE hDirectory;
|
HANDLE NewHandle;
|
||||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
@ -745,8 +753,6 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
}
|
||||||
_SEH_END;
|
_SEH_END;
|
||||||
|
|
||||||
/* If we failed, return the error */
|
|
||||||
if(!NT_SUCCESS(Status)) return Status;
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -760,30 +766,33 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
(PVOID*)&Directory);
|
(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 */
|
/* Return the handle back to the caller */
|
||||||
Status = ObInsertObject((PVOID)Directory,
|
*DirectoryHandle = NewHandle;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
|
||||||
|
{
|
||||||
|
/* Get the exception code */
|
||||||
|
Status = _SEH_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH_END;
|
||||||
|
|
||||||
/* Return status to caller */
|
/* Return status to caller */
|
||||||
return Status;
|
return Status;
|
||||||
|
|
|
@ -2693,7 +2693,6 @@ ObInsertObject(IN PVOID Object,
|
||||||
{
|
{
|
||||||
/* Display warning and break into debugger */
|
/* Display warning and break into debugger */
|
||||||
DPRINT1("OB: Attempting to insert existing object %08x\n", Object);
|
DPRINT1("OB: Attempting to insert existing object %08x\n", Object);
|
||||||
KEBUGCHECK(0);
|
|
||||||
DbgBreakPoint();
|
DbgBreakPoint();
|
||||||
|
|
||||||
/* Allow debugger to continue */
|
/* Allow debugger to continue */
|
||||||
|
@ -2703,22 +2702,11 @@ ObInsertObject(IN PVOID Object,
|
||||||
|
|
||||||
/* Get the create and name info, as well as the object type */
|
/* Get the create and name info, as well as the object type */
|
||||||
ObjectCreateInfo = ObjectHeader->ObjectCreateInfo;
|
ObjectCreateInfo = ObjectHeader->ObjectCreateInfo;
|
||||||
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
|
ObjectNameInfo = ObpAcquireNameInformation(ObjectHeader);
|
||||||
ObjectType = ObjectHeader->Type;
|
ObjectType = ObjectHeader->Type;
|
||||||
|
ObjectName = NULL;
|
||||||
/* 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 */
|
/* Check if this is an named object */
|
||||||
ObjectName = NULL;
|
|
||||||
if ((ObjectNameInfo) && (ObjectNameInfo->Name.Buffer))
|
if ((ObjectNameInfo) && (ObjectNameInfo->Name.Buffer))
|
||||||
{
|
{
|
||||||
/* Get the object name */
|
/* Get the object name */
|
||||||
|
@ -2738,6 +2726,7 @@ ObInsertObject(IN PVOID Object,
|
||||||
{
|
{
|
||||||
/* Assume failure */
|
/* Assume failure */
|
||||||
*Handle = NULL;
|
*Handle = NULL;
|
||||||
|
ObjectHeader->ObjectCreateInfo = NULL;
|
||||||
|
|
||||||
/* Create the handle */
|
/* Create the handle */
|
||||||
Status = ObpCreateUnnamedHandle(Object,
|
Status = ObpCreateUnnamedHandle(Object,
|
||||||
|
@ -2750,10 +2739,9 @@ ObInsertObject(IN PVOID Object,
|
||||||
|
|
||||||
/* Free the create information */
|
/* Free the create information */
|
||||||
ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo);
|
ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo);
|
||||||
ObjectHeader->ObjectCreateInfo = NULL;
|
|
||||||
|
|
||||||
/* Remove a query reference if we added one */
|
/* Release the object name information */
|
||||||
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
|
ObpReleaseNameInformation(ObjectNameInfo);
|
||||||
|
|
||||||
/* Remove the extra keep-alive reference */
|
/* Remove the extra keep-alive reference */
|
||||||
ObDereferenceObject(Object);
|
ObDereferenceObject(Object);
|
||||||
|
@ -2779,7 +2767,7 @@ ObInsertObject(IN PVOID Object,
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Fail */
|
/* Fail */
|
||||||
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
|
ObpReleaseNameInformation(ObjectNameInfo);
|
||||||
ObDereferenceObject(Object);
|
ObDereferenceObject(Object);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -2793,7 +2781,7 @@ ObInsertObject(IN PVOID Object,
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Fail */
|
/* Fail */
|
||||||
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
|
ObpReleaseNameInformation(ObjectNameInfo);
|
||||||
ObDereferenceObject(Object);
|
ObDereferenceObject(Object);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -2855,7 +2843,7 @@ ObInsertObject(IN PVOID Object,
|
||||||
ObpCleanupDirectoryLookup(&Context);
|
ObpCleanupDirectoryLookup(&Context);
|
||||||
|
|
||||||
/* Remove query reference that we added */
|
/* Remove query reference that we added */
|
||||||
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
|
ObpReleaseNameInformation(ObjectNameInfo);
|
||||||
|
|
||||||
/* Dereference the object and delete the access state */
|
/* Dereference the object and delete the access state */
|
||||||
ObDereferenceObject(Object);
|
ObDereferenceObject(Object);
|
||||||
|
@ -2922,11 +2910,19 @@ ObInsertObject(IN PVOID Object,
|
||||||
/* Check if anything until now failed */
|
/* Check if anything until now failed */
|
||||||
if (!NT_SUCCESS(Status))
|
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);
|
ObpCleanupDirectoryLookup(&Context);
|
||||||
|
|
||||||
/* Remove query reference that we added */
|
/* Remove query reference that we added */
|
||||||
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
|
ObpReleaseNameInformation(ObjectNameInfo);
|
||||||
|
|
||||||
/* Dereference the object and delete the access state */
|
/* Dereference the object and delete the access state */
|
||||||
ObDereferenceObject(Object);
|
ObDereferenceObject(Object);
|
||||||
|
@ -2971,7 +2967,7 @@ ObInsertObject(IN PVOID Object,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove a query reference */
|
/* Remove a query reference */
|
||||||
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
|
ObpReleaseNameInformation(ObjectNameInfo);
|
||||||
|
|
||||||
/* Remove the extra keep-alive reference */
|
/* Remove the extra keep-alive reference */
|
||||||
ObDereferenceObject(Object);
|
ObDereferenceObject(Object);
|
||||||
|
@ -3078,7 +3074,8 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle,
|
||||||
SourceProcessHandle,
|
SourceProcessHandle,
|
||||||
TargetProcessHandle);
|
TargetProcessHandle);
|
||||||
|
|
||||||
if((TargetHandle) && (PreviousMode != KernelMode))
|
/* Check if we have a target handle */
|
||||||
|
if ((TargetHandle) && (PreviousMode != KernelMode))
|
||||||
{
|
{
|
||||||
/* Enter SEH */
|
/* Enter SEH */
|
||||||
_SEH_TRY
|
_SEH_TRY
|
||||||
|
@ -3092,8 +3089,6 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle,
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
}
|
||||||
_SEH_END;
|
_SEH_END;
|
||||||
|
|
||||||
/* Fail if the pointer was invalid */
|
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3168,7 +3163,7 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle,
|
||||||
hTarget,
|
hTarget,
|
||||||
TargetProcessHandle,
|
TargetProcessHandle,
|
||||||
Status);
|
Status);
|
||||||
ObDereferenceObject(Target);
|
if (Target) ObDereferenceObject(Target);
|
||||||
ObDereferenceObject(SourceProcess);
|
ObDereferenceObject(SourceProcess);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,20 +170,9 @@ ObpDeleteNameCheck(IN PVOID Object)
|
||||||
|
|
||||||
/* Get object structures */
|
/* Get object structures */
|
||||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
||||||
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
|
ObjectNameInfo = ObpAcquireNameInformation(ObjectHeader);
|
||||||
ObjectType = ObjectHeader->Type;
|
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,
|
* Check if the handle count is 0, if the object is named,
|
||||||
* and if the object isn't a permanent object.
|
* and if the object isn't a permanent object.
|
||||||
|
@ -225,21 +214,14 @@ ObpDeleteNameCheck(IN PVOID Object)
|
||||||
ObpDeleteSymbolicLinkName(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 */
|
/* Check if the magic protection flag is set */
|
||||||
|
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
|
||||||
if ((ObjectNameInfo) &&
|
if ((ObjectNameInfo) &&
|
||||||
(ObjectNameInfo->QueryReferences & 0x40000000))
|
(ObjectNameInfo->QueryReferences & 0x40000000))
|
||||||
{
|
{
|
||||||
/* Add deletion flag */
|
/* Remove protection flag */
|
||||||
InterlockedExchangeAdd((PLONG)&ObjectNameInfo->QueryReferences,
|
InterlockedExchangeAdd((PLONG)&ObjectNameInfo->QueryReferences,
|
||||||
0xC0000000);
|
-0x40000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the directory */
|
/* Get the directory */
|
||||||
|
@ -254,13 +236,13 @@ ObpDeleteNameCheck(IN PVOID Object)
|
||||||
ObpCleanupDirectoryLookup(&Context);
|
ObpCleanupDirectoryLookup(&Context);
|
||||||
|
|
||||||
/* Remove another query reference since we added one on top */
|
/* Remove another query reference since we added one on top */
|
||||||
ObpDecrementQueryReference(ObjectNameInfo);
|
ObpReleaseNameInformation(ObjectNameInfo);
|
||||||
|
|
||||||
/* Check if we were inserted in a directory */
|
/* Check if we were inserted in a directory */
|
||||||
if (Directory)
|
if (Directory)
|
||||||
{
|
{
|
||||||
/* We were, so first remove the extra reference we had added */
|
/* We were, so first remove the extra reference we had added */
|
||||||
ObpDecrementQueryReference(ObjectNameInfo);
|
ObpReleaseNameInformation(ObjectNameInfo);
|
||||||
|
|
||||||
/* Now dereference the object as well */
|
/* Now dereference the object as well */
|
||||||
ObDereferenceObject(Object);
|
ObDereferenceObject(Object);
|
||||||
|
@ -269,7 +251,7 @@ ObpDeleteNameCheck(IN PVOID Object)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Remove the reference we added */
|
/* Remove the reference we added */
|
||||||
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
|
ObpReleaseNameInformation(ObjectNameInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,11 +295,15 @@ ObpLookupObjectName(IN HANDLE RootHandle,
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
Object = NULL;
|
Object = NULL;
|
||||||
|
|
||||||
/* Check if case-insensitivity is forced */
|
/* Check if case-insensitivity is checked */
|
||||||
if ((ObpCaseInsensitive) || (ObjectType->TypeInfo.CaseInsensitive))
|
if (ObpCaseInsensitive)
|
||||||
{
|
{
|
||||||
/* Add the flag to disable case sensitivity */
|
/* Check if the object type requests this */
|
||||||
Attributes |= OBJ_CASE_INSENSITIVE;
|
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 */
|
/* Check if this is a access checks are being forced */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue