From 74332efe6339ddea22da872ff5e389172e77bf82 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Mon, 8 Jan 2007 08:03:47 +0000 Subject: [PATCH] - Fix ObReferenceObjectByName to do proper name validation checks. - Fix ObReferenceObjectByName to call ObpCheckObjectReference before allowing the caller to obtain the reference. - Rename ObFindObject to ObpLookupObjectName and shuffle parameters around and add some placeholder code that resets the object pointer of the lookup context. - Modify ObpChargeQuotaForObject to also return if this is a new object. - Modify ObpDecrementHandleCount to detect when objects with a handle database are being used. Also protect close callout with checks. Protect ObpCloseHAndleTableEntry's callouts with checks as well. - Update logic of ObpIncrementHandleCount and ObpIncrementUnnamedHandleCount to handle currently exclusive objects as well as new handles with OBJ_EXCLUSIVE. Also detect objects that require handle databases and protect callouts. - Support CreatorInfo and the TypeList in ObpIncrementHandleCount. Also update the TotalNumberOfHandles in the object type properly. - Fixup object type lock usage in these routines. - Do proper invalid attributes check in ObOpenObjectByName, and also use a buffer from the pool instead of the stack. - Make ObInsertObject detect invalid object insertions and change some parameter names and checks. - Add stub code to validate the access mask in ObInsertObject. Proper initailize some lookup variables before starting lookup. - Add detection for symbolic link inserts which require some handling code later on. - Free the create information at the right moment isntead of too late. - Add some missing Ob functions, flags and types to the NDK. Fix OBJECT_DIRECTORY structure to use EX_PUSH_LOCK for locks, not ERESOURCE. svn path=/trunk/; revision=25372 --- reactos/include/ndk/iotypes.h | 4 +- reactos/include/ndk/obtypes.h | 22 +- reactos/ntoskrnl/include/internal/ob.h | 70 ++- reactos/ntoskrnl/ob/obhandle.c | 608 +++++++++++++++++++------ reactos/ntoskrnl/ob/obname.c | 37 +- reactos/ntoskrnl/ob/obref.c | 63 ++- 6 files changed, 597 insertions(+), 207 deletions(-) diff --git a/reactos/include/ndk/iotypes.h b/reactos/include/ndk/iotypes.h index d0fe92cda55..5217162f463 100644 --- a/reactos/include/ndk/iotypes.h +++ b/reactos/include/ndk/iotypes.h @@ -23,9 +23,7 @@ Author: // Dependencies // #include -#if !defined(_NTIFS_) -typedef PVOID PFS_FILTER_CALLBACKS; -#endif +#include // // I/O Completion Access Rights diff --git a/reactos/include/ndk/obtypes.h b/reactos/include/ndk/obtypes.h index 72d50affa6b..a794077f47b 100644 --- a/reactos/include/ndk/obtypes.h +++ b/reactos/include/ndk/obtypes.h @@ -23,16 +23,14 @@ Author: // Dependencies // #include - -// -// If the IFS wasn't included, define this here -// -#ifndef EX_PUSH_LOCK -#define EX_PUSH_LOCK ULONG_PTR +#ifndef NTOS_MODE_USER +#include #endif -#ifdef NTOS_MODE_USER +#undef NTDDI_VERSION +#define NTDDI_VERSION NTDDI_WS03SP1 +#ifdef NTOS_MODE_USER // // Definitions for Object Creation // @@ -86,6 +84,7 @@ Author: #define OB_FLAG_PERMANENT 0x10 #define OB_FLAG_SECURITY 0x20 #define OB_FLAG_SINGLE_PROCESS 0x40 +#define OB_FLAG_DEFER_DELETE 0x80 #define OBJECT_TO_OBJECT_HEADER(o) \ CONTAINING_RECORD((o), OBJECT_HEADER, Body) @@ -107,6 +106,11 @@ Author: OB_FLAG_CREATOR_INFO) ? NULL: ((PCHAR)(h) - \ sizeof(OBJECT_HEADER_CREATOR_INFO)))) +#define OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(h) \ + ((!((h)->Flags & OB_FLAG_EXCLUSIVE)) ? \ + NULL: (((POBJECT_HEADER_QUOTA_INFO)((PCHAR)(h) - \ + (h)->QuotaInfoOffset))->ExclusiveProcess)) + // // Reasons for Open Callback // @@ -359,8 +363,8 @@ typedef struct _OBJECT_DIRECTORY struct _OBJECT_DIRECTORY_ENTRY *HashBuckets[NUMBER_HASH_BUCKETS]; #if (NTDDI_VERSION < NTDDI_WINXP) ERESOURCE Lock; -#elif (NTDDI_VERSION >= NTDDI_WINXP) - ERESOURCE Lock; // FIXME: HACKHACK, SHOULD BE EX_PUSH_LOCK +#else + EX_PUSH_LOCK Lock; #endif #if (NTDDI_VERSION < NTDDI_WINXP) BOOLEAN CurrentEntryValid; diff --git a/reactos/ntoskrnl/include/internal/ob.h b/reactos/ntoskrnl/include/internal/ob.h index 2762164fc79..f8a2f21ccc6 100644 --- a/reactos/ntoskrnl/include/internal/ob.h +++ b/reactos/ntoskrnl/include/internal/ob.h @@ -80,6 +80,18 @@ typedef struct _OBP_CLOSE_HANDLE_CONTEXT KPROCESSOR_MODE AccessMode; } OBP_CLOSE_HANDLE_CONTEXT, *POBP_CLOSE_HANDLE_CONTEXT; +// +// Private Temporary Buffer for Lookup Routines +// +#define TAG_OB_TEMP_STORAGE TAG('O', 'b', 'S', 't') +typedef struct _OB_TEMP_BUFFER +{ + ACCESS_STATE LocalAccessState; + OBJECT_CREATE_INFORMATION ObjectCreateInfo; + OBP_LOOKUP_CONTEXT LookupContext; + AUX_DATA AuxData; +} OB_TEMP_BUFFER, *POB_TEMP_BUFFER; + // // Directory Namespace Functions // @@ -152,18 +164,18 @@ ObKillProcess( // NTSTATUS NTAPI -ObFindObject( +ObpLookupObjectName( IN HANDLE RootHandle, IN PUNICODE_STRING ObjectName, IN ULONG Attributes, - IN KPROCESSOR_MODE PreviousMode, - IN PVOID *ReturnedObject, IN POBJECT_TYPE ObjectType, - IN POBP_LOOKUP_CONTEXT Context, - IN PACCESS_STATE AccessState, + IN KPROCESSOR_MODE AccessMode, + IN OUT PVOID ParseContext, IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, - IN PVOID ParseContext, - IN PVOID Insert + IN PVOID InsertObject, + IN PACCESS_STATE AccessState, + IN POBP_LOOKUP_CONTEXT LookupContext, + OUT PVOID *FoundObject ); // @@ -267,6 +279,12 @@ ObDereferenceDeviceMap( IN PEPROCESS Process ); +VOID +FASTCALL +ObfDereferenceDeviceMap( + IN PVOID DeviceMap +); + VOID NTAPI ObInheritDeviceMap( @@ -314,16 +332,52 @@ ObpDereferenceCachedSecurityDescriptor( IN PSECURITY_DESCRIPTOR SecurityDescriptor ); +// +// Object Security Routines +// BOOLEAN NTAPI ObCheckObjectAccess( IN PVOID Object, IN OUT PACCESS_STATE AccessState, - IN BOOLEAN Unknown, + IN BOOLEAN LockHeld, IN KPROCESSOR_MODE AccessMode, OUT PNTSTATUS ReturnedStatus ); +BOOLEAN +NTAPI +ObCheckCreateObjectAccess( + IN PVOID Object, + IN ACCESS_MASK CreateAccess, + IN PACCESS_STATE AccessState, + IN PUNICODE_STRING ComponentName, + IN BOOLEAN LockHeld, + IN KPROCESSOR_MODE AccessMode, + OUT PNTSTATUS AccessStatus +); + +BOOLEAN +NTAPI +ObpCheckTraverseAccess( + IN PVOID Object, + IN ACCESS_MASK TraverseAccess, + IN PACCESS_STATE AccessState OPTIONAL, + IN BOOLEAN LockHeld, + IN KPROCESSOR_MODE AccessMode, + OUT PNTSTATUS AccessStatus +); + +BOOLEAN +NTAPI +ObpCheckObjectReference( + IN PVOID Object, + IN OUT PACCESS_STATE AccessState, + IN BOOLEAN LockHeld, + IN KPROCESSOR_MODE AccessMode, + OUT PNTSTATUS AccessStatus +); + // // Executive Fast Referencing Functions // diff --git a/reactos/ntoskrnl/ob/obhandle.c b/reactos/ntoskrnl/ob/obhandle.c index 85b0271c4eb..f4ea0dc6132 100644 --- a/reactos/ntoskrnl/ob/obhandle.c +++ b/reactos/ntoskrnl/ob/obhandle.c @@ -24,7 +24,8 @@ PHANDLE_TABLE ObpKernelHandleTable = NULL; NTSTATUS NTAPI ObpChargeQuotaForObject(IN POBJECT_HEADER ObjectHeader, - IN POBJECT_TYPE ObjectType) + IN POBJECT_TYPE ObjectType, + OUT PBOOLEAN NewObject) { POBJECT_HEADER_QUOTA_INFO ObjectQuota; ULONG PagedPoolCharge, NonPagedPoolCharge; @@ -32,10 +33,14 @@ ObpChargeQuotaForObject(IN POBJECT_HEADER ObjectHeader, /* Get quota information */ ObjectQuota = OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader); + *NewObject = FALSE; /* Check if this is a new object */ if (ObjectHeader->Flags & OB_FLAG_CREATE_INFO) { + /* Set the flag */ + *NewObject = TRUE; + /* Remove the flag */ ObjectHeader->Flags &= ~ OB_FLAG_CREATE_INFO; if (ObjectQuota) @@ -95,6 +100,7 @@ ObpDecrementHandleCount(IN PVOID ObjectBody, LONG SystemHandleCount, ProcessHandleCount; LONG NewCount; POBJECT_HEADER_CREATOR_INFO CreatorInfo; + KIRQL CalloutIrql; /* Get the object type and header */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody); @@ -109,7 +115,7 @@ ObpDecrementHandleCount(IN PVOID ObjectBody, /* Lock the object type */ ObpEnterObjectTypeMutex(ObjectType); - /* FIXME: The process handle count should be in the Handle DB. Investigate */ + /* Set default counts */ SystemHandleCount = ObjectHeader->HandleCount; ProcessHandleCount = 0; @@ -129,6 +135,13 @@ ObpDecrementHandleCount(IN PVOID ObjectBody, } } + /* Is the object type keeping track of handles? */ + if (ObjectType->TypeInfo.MaintainHandleCount) + { + /* FIXME */ + DPRINT("Handle Database not yet implemented\n"); + } + /* Release the lock */ ObpLeaveObjectTypeMutex(ObjectType); @@ -136,11 +149,13 @@ ObpDecrementHandleCount(IN PVOID ObjectBody, if (ObjectType->TypeInfo.CloseProcedure) { /* Call it */ + ObpCalloutStart(&CalloutIrql); ObjectType->TypeInfo.CloseProcedure(Process, ObjectBody, GrantedAccess, ProcessHandleCount, SystemHandleCount); + ObpCalloutEnd(CalloutIrql, "Close", ObjectType, ObjectBody); } /* Check if we should delete the object */ @@ -193,6 +208,7 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable, POBJECT_TYPE ObjectType; POBJECT_HEADER ObjectHeader; ACCESS_MASK GrantedAccess; + KIRQL CalloutIrql; PAGED_CODE(); /* Get the object data */ @@ -212,15 +228,20 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable, if (ObjectType->TypeInfo.OkayToCloseProcedure) { /* Call it and check if it's not letting us close it */ + ObpCalloutStart(&CalloutIrql); if (!ObjectType->TypeInfo.OkayToCloseProcedure(PsGetCurrentProcess(), Body, Handle, AccessMode)) { /* Fail */ + ObpCalloutEnd(CalloutIrql, "NtClose", ObjectType, Body); ExUnlockHandleTableEntry(HandleTable, HandleEntry); return STATUS_HANDLE_NOT_CLOSABLE; } + + /* Success, validate callout retrn */ + ObpCalloutEnd(CalloutIrql, "NtClose", ObjectType, Body); } /* The callback allowed us to close it, but does the handle itself? */ @@ -241,7 +262,7 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable, } else { - /* Return the error isntead */ + /* Return the error instead */ return STATUS_HANDLE_NOT_CLOSABLE; } } @@ -258,9 +279,6 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable, ObpDecrementHandleCount(Body, PsGetCurrentProcess(), GrantedAccess); /* Dereference the object as well */ - ASSERT(ObjectHeader->Type); - ASSERT(ObjectHeader->PointerCount != 0xCCCCCCCC); - ObDereferenceObject(Body); /* Return to caller */ @@ -315,6 +333,10 @@ ObpIncrementHandleCount(IN PVOID Object, POBJECT_TYPE ObjectType; ULONG ProcessHandleCount; NTSTATUS Status; + PEPROCESS ExclusiveProcess; + BOOLEAN Exclusive = FALSE, NewObject; + POBJECT_HEADER_CREATOR_INFO CreatorInfo; + KIRQL CalloutIrql; /* Get the object header and type */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); @@ -331,9 +353,60 @@ ObpIncrementHandleCount(IN PVOID Object, ObpEnterObjectTypeMutex(ObjectType); /* Charge quota and remove the creator info flag */ - Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType); + Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType, &NewObject); if (!NT_SUCCESS(Status)) return Status; + /* Check if the open is exclusive */ + if (HandleAttributes & OBJ_EXCLUSIVE) + { + /* Check if the object allows this, or if the inherit flag was given */ + if ((HandleAttributes & OBJ_INHERIT) || + !(ObjectHeader->Flags & OB_FLAG_EXCLUSIVE)) + { + /* Incorrect attempt */ + DPRINT1("Failing here\n"); + Status = STATUS_INVALID_PARAMETER; + goto Quickie; + } + + /* Check if we have access to it */ + ExclusiveProcess = OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader); + if ((!(ExclusiveProcess) && (ObjectHeader->HandleCount)) || + ((ExclusiveProcess) && (ExclusiveProcess != PsGetCurrentProcess()))) + { + /* This isn't the right process */ + Status = STATUS_ACCESS_DENIED; + goto Quickie; + } + + /* Now you got exclusive access */ + Exclusive = TRUE; + } + else if ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE) && + (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader))) + { + /* Caller didn't want exclusive access, but the object is exclusive */ + Status = STATUS_ACCESS_DENIED; + goto Quickie; + } + + /* + * Check if this is an object that went from 0 handles back to existence, + * but doesn't have an open procedure, only a close procedure. This means + * that it will never realize that the object is back alive, so we must + * fail the request. + */ + if (!(ObjectHeader->HandleCount) && + !(NewObject) && + (ObjectType->TypeInfo.MaintainHandleCount) && + !(ObjectType->TypeInfo.OpenProcedure) && + (ObjectType->TypeInfo.CloseProcedure)) + { + /* Fail */ + Status = STATUS_UNSUCCESSFUL; + goto Quickie; + } + /* Check if we're opening an existing handle */ if (OpenReason == ObOpenHandle) { @@ -345,7 +418,7 @@ ObpIncrementHandleCount(IN PVOID Object, &Status)) { /* Access was denied, so fail */ - return Status; + goto Quickie; } } else if (OpenReason == ObCreateHandle) @@ -365,30 +438,82 @@ ObpIncrementHandleCount(IN PVOID Object, RtlMapGenericMask(&AccessState->RemainingDesiredAccess, &ObjectType->TypeInfo.GenericMapping); } + + /* Check if the caller is trying to access system security */ + if (AccessState->RemainingDesiredAccess & ACCESS_SYSTEM_SECURITY) + { + /* FIXME: TODO */ + DPRINT1("ACCESS_SYSTEM_SECURITY not validated!\n"); + } + } + + /* Check if this is an exclusive handle */ + if (Exclusive) + { + /* Save the owner process */ + OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = Process; } /* Increase the handle count */ InterlockedIncrement(&ObjectHeader->HandleCount); + ProcessHandleCount = 0; + + /* Check if we have a handle database */ + if (ObjectType->TypeInfo.MaintainHandleCount) + { + /* FIXME: TODO */ + DPRINT("Handle DB not yet supported\n"); + } /* Release the lock */ ObpLeaveObjectTypeMutex(ObjectType); - /* FIXME: Use the Handle Database */ - ProcessHandleCount = 0; - /* Check if we have an open procedure */ + Status = STATUS_SUCCESS; if (ObjectType->TypeInfo.OpenProcedure) { /* Call it */ - ObjectType->TypeInfo.OpenProcedure(OpenReason, - Process, - Object, - AccessState->PreviouslyGrantedAccess, - ProcessHandleCount); + ObpCalloutStart(&CalloutIrql); + Status = ObjectType->TypeInfo.OpenProcedure(OpenReason, + Process, + Object, + AccessState->PreviouslyGrantedAccess, + ProcessHandleCount); + ObpCalloutEnd(CalloutIrql, "Open", ObjectType, Object); + + /* Check if the open procedure failed */ + if (!NT_SUCCESS(Status)) + { + /* FIXME: This should never happen for now */ + DPRINT1("Unhandled case\n"); + KEBUGCHECK(0); + return Status; + } + } + + /* 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) + { + /* Fixup count */ + ObjectType->HighWaterNumberOfHandles = ObjectType->TotalNumberOfHandles; + } + + /* Trace call and return */ OBTRACE(OB_HANDLE_DEBUG, "%s - Incremented count for: %p. Reason: %lx HC LC %lx %lx\n", __FUNCTION__, @@ -396,7 +521,12 @@ ObpIncrementHandleCount(IN PVOID Object, OpenReason, ObjectHeader->HandleCount, ObjectHeader->PointerCount); - return STATUS_SUCCESS; + return Status; + +Quickie: + /* Release lock and return */ + ObpLeaveObjectTypeMutex(ObjectType); + return Status; } /*++ @@ -439,6 +569,10 @@ ObpIncrementUnnamedHandleCount(IN PVOID Object, POBJECT_TYPE ObjectType; ULONG ProcessHandleCount; NTSTATUS Status; + PEPROCESS ExclusiveProcess; + BOOLEAN Exclusive = FALSE, NewObject; + POBJECT_HEADER_CREATOR_INFO CreatorInfo; + KIRQL CalloutIrql; /* Get the object header and type */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); @@ -454,9 +588,60 @@ ObpIncrementUnnamedHandleCount(IN PVOID Object, ObpEnterObjectTypeMutex(ObjectType); /* Charge quota and remove the creator info flag */ - Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType); + Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType, &NewObject); if (!NT_SUCCESS(Status)) return Status; + /* Check if the open is exclusive */ + if (HandleAttributes & OBJ_EXCLUSIVE) + { + /* Check if the object allows this, or if the inherit flag was given */ + if ((HandleAttributes & OBJ_INHERIT) || + !(ObjectHeader->Flags & OB_FLAG_EXCLUSIVE)) + { + /* Incorrect attempt */ + DPRINT1("failing here\n"); + Status = STATUS_INVALID_PARAMETER; + goto Quickie; + } + + /* Check if we have access to it */ + ExclusiveProcess = OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader); + if ((!(ExclusiveProcess) && (ObjectHeader->HandleCount)) || + ((ExclusiveProcess) && (ExclusiveProcess != PsGetCurrentProcess()))) + { + /* This isn't the right process */ + Status = STATUS_ACCESS_DENIED; + goto Quickie; + } + + /* Now you got exclusive access */ + Exclusive = TRUE; + } + else if ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE) && + (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader))) + { + /* Caller didn't want exclusive access, but the object is exclusive */ + Status = STATUS_ACCESS_DENIED; + goto Quickie; + } + + /* + * Check if this is an object that went from 0 handles back to existence, + * but doesn't have an open procedure, only a close procedure. This means + * that it will never realize that the object is back alive, so we must + * fail the request. + */ + if (!(ObjectHeader->HandleCount) && + !(NewObject) && + (ObjectType->TypeInfo.MaintainHandleCount) && + !(ObjectType->TypeInfo.OpenProcedure) && + (ObjectType->TypeInfo.CloseProcedure)) + { + /* Fail */ + Status = STATUS_UNSUCCESSFUL; + goto Quickie; + } + /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */ if (*DesiredAccess & MAXIMUM_ALLOWED) { @@ -473,35 +658,85 @@ ObpIncrementUnnamedHandleCount(IN PVOID Object, &ObjectType->TypeInfo.GenericMapping); } + /* Check if this is an exclusive handle */ + if (Exclusive) + { + /* Save the owner process */ + OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = Process; + } + /* Increase the handle count */ InterlockedIncrement(&ObjectHeader->HandleCount); - - /* Release the object type */ - ObpLeaveObjectTypeMutex(ObjectType); - - /* FIXME: Use the Handle Database */ ProcessHandleCount = 0; + /* Check if we have a handle database */ + if (ObjectType->TypeInfo.MaintainHandleCount) + { + /* FIXME: TODO */ + DPRINT("Handle DB not yet supported\n"); + } + + /* Release the lock */ + ObpLeaveObjectTypeMutex(ObjectType); + /* Check if we have an open procedure */ + Status = STATUS_SUCCESS; if (ObjectType->TypeInfo.OpenProcedure) { /* Call it */ - ObjectType->TypeInfo.OpenProcedure(ObCreateHandle, - Process, - Object, - *DesiredAccess, - ProcessHandleCount); + ObpCalloutStart(&CalloutIrql); + Status = ObjectType->TypeInfo.OpenProcedure(ObCreateHandle, + Process, + Object, + *DesiredAccess, + ProcessHandleCount); + ObpCalloutEnd(CalloutIrql, "Open", ObjectType, Object); + + /* Check if the open procedure failed */ + if (!NT_SUCCESS(Status)) + { + /* FIXME: This should never happen for now */ + DPRINT1("Unhandled case\n"); + KEBUGCHECK(0); + return Status; + } + } + + /* 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) + { + /* Fixup count */ + ObjectType->HighWaterNumberOfHandles = ObjectType->TotalNumberOfHandles; + } + + /* Trace call and return */ OBTRACE(OB_HANDLE_DEBUG, "%s - Incremented count for: %p. UNNAMED HC LC %lx %lx\n", __FUNCTION__, Object, ObjectHeader->HandleCount, ObjectHeader->PointerCount); - return STATUS_SUCCESS; + return Status; + +Quickie: + /* Release lock and return */ + ObpLeaveObjectTypeMutex(ObjectType); + return Status; } /*++ @@ -709,12 +944,7 @@ ObpCreateUnnamedHandle(IN PVOID Object, * * @return . * -* @remarks Gloomy says OpenReason is "enables Security" if == 1. -* since this function *has* to call ObpIncrementHandleCount, -* which needs to somehow know the OpenReason, and since -* ObOpenHandle == 1, I'm guessing this is actually the -* OpenReason. Also makes sense since this function is shared -* by Duplication, Creation and Opening.. +* @remarks Cleans up the Lookup Context on success. * *--*/ NTSTATUS @@ -725,6 +955,7 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason, IN PACCESS_STATE AccessState, IN ULONG AdditionalReferences, IN ULONG HandleAttributes, + IN POBP_LOOKUP_CONTEXT Context, IN KPROCESSOR_MODE AccessMode, OUT PVOID *ReturnedObject, OUT PHANDLE ReturnedHandle) @@ -1485,14 +1716,11 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, { PVOID Object = NULL; UNICODE_STRING ObjectName; - OBJECT_CREATE_INFORMATION ObjectCreateInfo; NTSTATUS Status; - OBP_LOOKUP_CONTEXT Context; POBJECT_HEADER ObjectHeader; - AUX_DATA AuxData; PGENERIC_MAPPING GenericMapping = NULL; - ACCESS_STATE AccessState; OB_OPEN_REASON OpenReason; + POB_TEMP_BUFFER TempBuffer; PAGED_CODE(); /* Check if we didn't get any Object Attributes */ @@ -1503,11 +1731,17 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, return STATUS_INVALID_PARAMETER; } + /* Allocate the temporary buffer */ + TempBuffer = ExAllocatePoolWithTag(NonPagedPool, + sizeof(OB_TEMP_BUFFER), + TAG_OB_TEMP_STORAGE); + if (!TempBuffer) return STATUS_INSUFFICIENT_RESOURCES; + /* Capture all the info */ Status = ObpCaptureObjectAttributes(ObjectAttributes, AccessMode, TRUE, - &ObjectCreateInfo, + &TempBuffer->ObjectCreateInfo, &ObjectName); if (!NT_SUCCESS(Status)) return Status; @@ -1518,35 +1752,40 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, if (ObjectType) GenericMapping = &ObjectType->TypeInfo.GenericMapping; /* Use our built-in access state */ - PassedAccessState = &AccessState; - Status = SeCreateAccessState(&AccessState, - &AuxData, + PassedAccessState = &TempBuffer->LocalAccessState; + Status = SeCreateAccessState(&TempBuffer->LocalAccessState, + &TempBuffer->AuxData, DesiredAccess, GenericMapping); if (!NT_SUCCESS(Status)) goto Quickie; } /* Get the security descriptor */ - if (ObjectCreateInfo.SecurityDescriptor) + if (TempBuffer->ObjectCreateInfo.SecurityDescriptor) { /* Save it in the access state */ PassedAccessState->SecurityDescriptor = - ObjectCreateInfo.SecurityDescriptor; + TempBuffer->ObjectCreateInfo.SecurityDescriptor; } /* Now do the lookup */ - Status = ObFindObject(ObjectCreateInfo.RootDirectory, - &ObjectName, - ObjectCreateInfo.Attributes, - AccessMode, - &Object, - ObjectType, - &Context, - PassedAccessState, - ObjectCreateInfo.SecurityQos, - ParseContext, - NULL); - if (!NT_SUCCESS(Status)) goto Cleanup; + Status = ObpLookupObjectName(TempBuffer->ObjectCreateInfo.RootDirectory, + &ObjectName, + TempBuffer->ObjectCreateInfo.Attributes, + ObjectType, + AccessMode, + ParseContext, + TempBuffer->ObjectCreateInfo.SecurityQos, + NULL, + PassedAccessState, + &TempBuffer->LookupContext, + &Object); + if (!NT_SUCCESS(Status)) + { + /* Cleanup after lookup */ + TempBuffer->LookupContext.Object = NULL; + goto Cleanup; + } /* Check if this object has create information */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); @@ -1570,29 +1809,44 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, OpenReason = ObOpenHandle; } - /* Create the actual handle now */ - Status = ObpCreateHandle(OpenReason, - Object, - ObjectType, - PassedAccessState, - 0, - ObjectCreateInfo.Attributes, - AccessMode, - NULL, - Handle); - if (!NT_SUCCESS(Status)) ObDereferenceObject(Object); + /* Check if we have invalid object attributes */ + if (ObjectHeader->Type->TypeInfo.InvalidAttributes & + TempBuffer->ObjectCreateInfo.Attributes) + { + /* Set failure code */ + Status = STATUS_INVALID_PARAMETER; + TempBuffer->LookupContext.Object = NULL; + } + else + { + /* Create the actual handle now */ + Status = ObpCreateHandle(OpenReason, + Object, + ObjectType, + PassedAccessState, + 0, + TempBuffer->ObjectCreateInfo.Attributes, + &TempBuffer->LookupContext, + AccessMode, + NULL, + Handle); + if (!NT_SUCCESS(Status)) ObDereferenceObject(Object); + } Cleanup: /* Delete the access state */ - if (PassedAccessState == &AccessState) + if (PassedAccessState == &TempBuffer->LocalAccessState) { SeDeleteAccessState(PassedAccessState); } - /* Release the object attributes and return status */ Quickie: - ObpReleaseCapturedAttributes(&ObjectCreateInfo); + /* Release the object attributes and temporary buffer */ + ObpReleaseCapturedAttributes(&TempBuffer->ObjectCreateInfo); if (ObjectName.Buffer) ObpReleaseCapturedName(&ObjectName); + ExFreePool(TempBuffer); + + /* Return status */ OBTRACE(OB_HANDLE_DEBUG, "%s - returning Object %p with PC S: %lx %lx\n", __FUNCTION__, @@ -1684,6 +1938,7 @@ ObOpenObjectByPointer(IN PVOID Object, PassedAccessState, 0, HandleAttributes, + NULL, AccessMode, NULL, Handle); @@ -1747,39 +2002,70 @@ ObFindHandleForObject(IN PEPROCESS Process, NTSTATUS NTAPI ObInsertObject(IN PVOID Object, - IN PACCESS_STATE PassedAccessState OPTIONAL, + IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, - IN ULONG AdditionalReferences, - OUT PVOID *ReferencedObject OPTIONAL, + IN ULONG ObjectPointerBias, + OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle) { POBJECT_CREATE_INFORMATION ObjectCreateInfo; - POBJECT_HEADER Header; + POBJECT_HEADER ObjectHeader; POBJECT_TYPE ObjectType; - PVOID FoundObject = Object; - POBJECT_HEADER FoundHeader = NULL; - NTSTATUS Status = STATUS_SUCCESS, RealStatus; - PSECURITY_DESCRIPTOR DirectorySd = NULL; - BOOLEAN SdAllocated; - OBP_LOOKUP_CONTEXT Context; + PUNICODE_STRING ObjectName; + PVOID InsertObject; + PSECURITY_DESCRIPTOR ParentDescriptor = NULL; + BOOLEAN SdAllocated = FALSE; POBJECT_HEADER_NAME_INFO ObjectNameInfo; - ACCESS_STATE AccessState; + OBP_LOOKUP_CONTEXT Context; + ACCESS_STATE LocalAccessState; AUX_DATA AuxData; - BOOLEAN IsNamed = FALSE; - OB_OPEN_REASON OpenReason = ObCreateHandle; + OB_OPEN_REASON OpenReason; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS, RealStatus; PAGED_CODE(); - /* Get the Header and Create Info */ - Header = OBJECT_TO_OBJECT_HEADER(Object); - ObjectCreateInfo = Header->ObjectCreateInfo; - ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(Header); - ObjectType = Header->Type; + /* Get the Header */ + ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); + + /* Detect invalid insert */ + if (!(ObjectHeader->Flags & OB_FLAG_CREATE_INFO)) + { + /* Display warning and break into debugger */ + DPRINT1("OB: Attempting to insert existing object %08x\n", Object); + KEBUGCHECK(0); + DbgBreakPoint(); + + /* Allow debugger to continue */ + ObDereferenceObject(Object); + return STATUS_INVALID_PARAMETER; + } + + /* Get the create and name info, as well as the object type */ + ObjectCreateInfo = ObjectHeader->ObjectCreateInfo; + ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); + ObjectType = ObjectHeader->Type; + /* Check if this is an named object */ - if ((ObjectNameInfo) && (ObjectNameInfo->Name.Buffer)) IsNamed = TRUE; + ObjectName = NULL; + if ((ObjectNameInfo) && (ObjectNameInfo->Name.Buffer)) + { + /* Get the object name */ + ObjectName = &ObjectNameInfo->Name; + } + + /* Sanity check, but broken on ROS due to Cm */ +#if 0 + ASSERT((Handle) || + ((ObjectPointerBias == 0) && + (ObjectName == NULL) && + (ObjectType->TypeInfo.SecurityRequired) && + (NewObject == NULL))); +#endif /* Check if the object is unnamed and also doesn't have security */ - if ((!ObjectType->TypeInfo.SecurityRequired) && !(IsNamed)) + PreviousMode = KeGetPreviousMode(); + if (!(ObjectType->TypeInfo.SecurityRequired) && !(ObjectName)) { /* ReactOS HACK */ if (Handle) @@ -1790,16 +2076,17 @@ ObInsertObject(IN PVOID Object, /* Create the handle */ Status = ObpCreateUnnamedHandle(Object, DesiredAccess, - AdditionalReferences + 1, + ObjectPointerBias + 1, ObjectCreateInfo->Attributes, - ExGetPreviousMode(), - ReferencedObject, + PreviousMode, + NewObject, Handle); } /* Free the create information */ ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo); - Header->ObjectCreateInfo = NULL; + ObjectHeader->ObjectCreateInfo = NULL; + /* Remove the extra keep-alive reference */ if (Handle) ObDereferenceObject(Object); @@ -1808,17 +2095,17 @@ ObInsertObject(IN PVOID Object, OBTRACE(OB_HANDLE_DEBUG, "%s - returning Object with PC S: %lx %lx\n", __FUNCTION__, - OBJECT_TO_OBJECT_HEADER(Object)->PointerCount, + ObjectHeader->PointerCount, Status); return Status; } /* Check if we didn't get an access state */ - if (!PassedAccessState) + if (!AccessState) { /* Use our built-in access state */ - PassedAccessState = &AccessState; - Status = SeCreateAccessState(&AccessState, + AccessState = &LocalAccessState; + Status = SeCreateAccessState(&LocalAccessState, &AuxData, DesiredAccess, &ObjectType->TypeInfo.GenericMapping); @@ -1831,37 +2118,50 @@ ObInsertObject(IN PVOID Object, } /* Save the security descriptor */ - PassedAccessState->SecurityDescriptor = - ObjectCreateInfo->SecurityDescriptor; + AccessState->SecurityDescriptor = ObjectCreateInfo->SecurityDescriptor; + + /* Validate the access mask */ + Status = STATUS_SUCCESS;//ObpValidateAccessMask(AccessState); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ObDereferenceObject(Object); + return Status; + } + + /* Setup a lookup context */ + Context.Object = NULL; + InsertObject = Object; + OpenReason = ObCreateHandle; /* Check if the object is named */ - if (IsNamed) + if (ObjectName) { /* Look it up */ - Status = ObFindObject(ObjectCreateInfo->RootDirectory, - &ObjectNameInfo->Name, - ObjectCreateInfo->Attributes, - (Header->Flags & OB_FLAG_KERNEL_MODE) ? - KernelMode : UserMode, - &FoundObject, - ObjectType, - &Context, - PassedAccessState, - ObjectCreateInfo->SecurityQos, - ObjectCreateInfo->ParseContext, - Object); + Status = ObpLookupObjectName(ObjectCreateInfo->RootDirectory, + ObjectName, + ObjectCreateInfo->Attributes, + ObjectType, + (ObjectHeader->Flags & OB_FLAG_KERNEL_MODE) ? + KernelMode : UserMode, + ObjectCreateInfo->ParseContext, + ObjectCreateInfo->SecurityQos, + Object, + AccessState, + &Context, + &InsertObject); + /* Check if we found an object that doesn't match the one requested */ - if ((NT_SUCCESS(Status)) && (FoundObject) && (Object != FoundObject)) + if ((NT_SUCCESS(Status)) && (InsertObject) && (Object != InsertObject)) { /* This means we're opening an object, not creating a new one */ - FoundHeader = OBJECT_TO_OBJECT_HEADER(FoundObject); OpenReason = ObOpenHandle; /* Make sure the caller said it's OK to do this */ if (ObjectCreateInfo->Attributes & OBJ_OPENIF) { /* He did, but did he want this type? */ - if (ObjectType != FoundHeader->Type) + if (ObjectType != OBJECT_TO_OBJECT_HEADER(InsertObject)->Type) { /* Wrong type, so fail */ Status = STATUS_OBJECT_TYPE_MISMATCH; @@ -1884,43 +2184,53 @@ ObInsertObject(IN PVOID Object, { /* We failed, dereference the object and delete the access state */ ObDereferenceObject(Object); - if (PassedAccessState == &AccessState) + if (AccessState == &LocalAccessState) { /* We used a local one; delete it */ - SeDeleteAccessState(PassedAccessState); + SeDeleteAccessState(AccessState); } /* Return failure code */ return Status; } + else + { + /* Check if this is a symbolic link */ + if (ObjectType == ObSymbolicLinkType) + { + /* Create the internal name */ + DPRINT("FIXME: Created link!\n"); + //ObpCreateSymbolicLinkName(FoundObject); + } + } } /* Now check if this object is being created */ - if (FoundObject == Object) + if (InsertObject == Object) { /* Check if it's named or forces security */ - if ((IsNamed) || (ObjectType->TypeInfo.SecurityRequired)) + if ((ObjectName) || (ObjectType->TypeInfo.SecurityRequired)) { /* Make sure it's inserted into an object directory */ if ((ObjectNameInfo) && (ObjectNameInfo->Directory)) { /* Get the current descriptor */ ObGetObjectSecurity(ObjectNameInfo->Directory, - &DirectorySd, + &ParentDescriptor, &SdAllocated); } /* Now assign it */ - Status = ObAssignSecurity(PassedAccessState, - DirectorySd, + Status = ObAssignSecurity(AccessState, + ParentDescriptor, Object, ObjectType); /* Check if we captured one */ - if (DirectorySd) + if (ParentDescriptor) { /* We did, release it */ - ObReleaseObjectSecurity(DirectorySd, SdAllocated); + ObReleaseObjectSecurity(ParentDescriptor, SdAllocated); } else if (NT_SUCCESS(Status)) { @@ -1930,8 +2240,8 @@ ObInsertObject(IN PVOID Object, TRUE); /* Clear the current one */ - PassedAccessState->SecurityDescriptor = - ObjectCreateInfo->SecurityDescriptor = NULL; + AccessState->SecurityDescriptor = + ObjectCreateInfo->SecurityDescriptor = NULL; } } @@ -1941,10 +2251,10 @@ ObInsertObject(IN PVOID Object, /* We failed, dereference the object and delete the access state */ KEBUGCHECK(0); ObDereferenceObject(Object); - if (PassedAccessState == &AccessState) + if (AccessState == &LocalAccessState) { /* We used a local one; delete it */ - SeDeleteAccessState(PassedAccessState); + SeDeleteAccessState(AccessState); } /* Return failure code */ @@ -1961,34 +2271,29 @@ ObInsertObject(IN PVOID Object, * a handle if Handle is NULL when the Registry Code calls it, because * the registry code totally bastardizes the Ob and needs to be fixed */ + ObjectHeader->ObjectCreateInfo = NULL; if (Handle) { /* Create the handle */ Status = ObpCreateHandle(OpenReason, - FoundObject, + InsertObject, NULL, - PassedAccessState, - AdditionalReferences + 1, + AccessState, + ObjectPointerBias + 1, ObjectCreateInfo->Attributes, - ExGetPreviousMode(), - ReferencedObject, + &Context, + PreviousMode, + NewObject, Handle); } - /* We can delete the Create Info now */ - Header->ObjectCreateInfo = NULL; - ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo); - /* Check if creating the handle failed */ if (!NT_SUCCESS(Status)) { /* If the object had a name, backout everything */ - if (IsNamed) ObpDeleteNameCheck(Object); + if (ObjectName) ObpDeleteNameCheck(Object); } - /* Remove the extra keep-alive reference */ - if (Handle) ObDereferenceObject(Object); - /* Check our final status */ if (!NT_SUCCESS(Status)) { @@ -1997,12 +2302,17 @@ ObInsertObject(IN PVOID Object, RealStatus = Status; } - /* Check if we created our own access state */ - if (PassedAccessState == &AccessState) - { - /* We used a local one; delete it */ - SeDeleteAccessState(PassedAccessState); - } + + + + /* Remove the extra keep-alive reference */ + if (Handle) ObDereferenceObject(Object); + + /* We can delete the Create Info now */ + ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo); + + /* Check if we created our own access state and delete it if so */ + if (AccessState == &LocalAccessState) SeDeleteAccessState(AccessState); /* Return status code */ OBTRACE(OB_HANDLE_DEBUG, diff --git a/reactos/ntoskrnl/ob/obname.c b/reactos/ntoskrnl/ob/obname.c index aa3d9a8c754..ecbbbe72c21 100644 --- a/reactos/ntoskrnl/ob/obname.c +++ b/reactos/ntoskrnl/ob/obname.c @@ -14,8 +14,9 @@ #define NTDDI_VERSION NTDDI_WINXP #include #define NDEBUG -#include +#include +BOOLEAN ObpCaseInsensitive = TRUE; POBJECT_DIRECTORY NameSpaceRoot = NULL; POBJECT_DIRECTORY ObpTypeDirectoryObject = NULL; @@ -181,6 +182,8 @@ ObpDeleteNameCheck(IN PVOID Object) (ObjectNameInfo->Name.Length) && !(ObjectHeader->Flags & OB_FLAG_PERMANENT)) { + Context.Object = NULL; + /* Make sure it's still inserted */ Context.Directory = ObjectNameInfo->Directory; Context.DirectoryLocked = TRUE; @@ -220,6 +223,8 @@ ObpDeleteNameCheck(IN PVOID Object) ExFreePool(ObjectNameInfo->Name.Buffer); RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, NULL, 0); + Context.Object = NULL; + /* Clear the current directory and de-reference it */ Directory = ObjectNameInfo->Directory; ObjectNameInfo->Directory = NULL; @@ -237,17 +242,17 @@ ObpDeleteNameCheck(IN PVOID Object) NTSTATUS NTAPI -ObFindObject(IN HANDLE RootHandle, - IN PUNICODE_STRING ObjectName, - IN ULONG Attributes, - IN KPROCESSOR_MODE AccessMode, - IN PVOID *ReturnedObject, - IN POBJECT_TYPE ObjectType, - IN POBP_LOOKUP_CONTEXT Context, - IN PACCESS_STATE AccessState, - IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, - IN OUT PVOID ParseContext, - OUT PVOID ExpectedObject) +ObpLookupObjectName(IN HANDLE RootHandle, + IN PUNICODE_STRING ObjectName, + IN ULONG Attributes, + IN POBJECT_TYPE ObjectType, + IN KPROCESSOR_MODE AccessMode, + IN OUT PVOID ParseContext, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, + IN PVOID ExpectedObject, + IN PACCESS_STATE AccessState, + IN POBP_LOOKUP_CONTEXT Context, + OUT PVOID *ReturnedObject) { PVOID RootDirectory; PVOID CurrentDirectory = NULL; @@ -500,7 +505,7 @@ ReparseNewDir: ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(CurrentHeader); /* Copy the Name */ - RtlCopyMemory(NewName, PartName.Buffer, PartName.MaximumLength); + RtlMoveMemory(NewName, PartName.Buffer, PartName.MaximumLength); /* Free old name */ if (ObjectNameInfo->Name.Buffer) ExFreePool(ObjectNameInfo->Name.Buffer); @@ -526,7 +531,7 @@ Reparse: /* We found it, so now get its header */ CurrentHeader = OBJECT_TO_OBJECT_HEADER(CurrentObject); - /* + /* * Check for a parse Procedure, but don't bother to parse for an insert * unless it's a Symbolic Link, in which case we MUST parse */ @@ -674,9 +679,9 @@ Reparse: NTSTATUS NTAPI -ObQueryNameString(IN PVOID Object, +ObQueryNameString(IN PVOID Object, OUT POBJECT_NAME_INFORMATION ObjectNameInfo, - IN ULONG Length, + IN ULONG Length, OUT PULONG ReturnLength) { POBJECT_HEADER_NAME_INFO LocalInfo; diff --git a/reactos/ntoskrnl/ob/obref.c b/reactos/ntoskrnl/ob/obref.c index 0432345edce..eeabc23e942 100644 --- a/reactos/ntoskrnl/ob/obref.c +++ b/reactos/ntoskrnl/ob/obref.c @@ -369,21 +369,21 @@ ObReferenceObjectByPointer(IN PVOID Object, return STATUS_OBJECT_TYPE_MISMATCH; } - /* Oncrement the reference count and return success */ + /* Increment the reference count and return success */ InterlockedIncrement(&Header->PointerCount); return STATUS_SUCCESS; } NTSTATUS NTAPI -ObReferenceObjectByName(PUNICODE_STRING ObjectPath, - ULONG Attributes, - PACCESS_STATE PassedAccessState, - ACCESS_MASK DesiredAccess, - POBJECT_TYPE ObjectType, - KPROCESSOR_MODE AccessMode, - PVOID ParseContext, - PVOID* ObjectPtr) +ObReferenceObjectByName(IN PUNICODE_STRING ObjectPath, + IN ULONG Attributes, + IN PACCESS_STATE PassedAccessState, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_TYPE ObjectType, + IN KPROCESSOR_MODE AccessMode, + IN OUT PVOID ParseContext, + OUT PVOID* ObjectPtr) { PVOID Object = NULL; UNICODE_STRING ObjectName; @@ -391,11 +391,18 @@ ObReferenceObjectByName(PUNICODE_STRING ObjectPath, OBP_LOOKUP_CONTEXT Context; AUX_DATA AuxData; ACCESS_STATE AccessState; + PAGED_CODE(); + + /* Fail quickly */ + if (!ObjectPath) return STATUS_OBJECT_NAME_INVALID; /* Capture the name */ Status = ObpCaptureObjectName(&ObjectName, ObjectPath, AccessMode, TRUE); if (!NT_SUCCESS(Status)) return Status; + /* We also need a valid name after capture */ + if (!ObjectName.Length) return STATUS_OBJECT_NAME_INVALID; + /* Check if we didn't get an access state */ if (!PassedAccessState) { @@ -410,21 +417,33 @@ ObReferenceObjectByName(PUNICODE_STRING ObjectPath, /* Find the object */ *ObjectPtr = NULL; - Status = ObFindObject(NULL, - &ObjectName, - Attributes, - AccessMode, - &Object, - ObjectType, - &Context, - PassedAccessState, - NULL, - ParseContext, - NULL); + Status = ObpLookupObjectName(NULL, + &ObjectName, + Attributes, + ObjectType, + AccessMode, + ParseContext, + NULL, + NULL, + PassedAccessState, + &Context, + &Object); + Context.Object = NULL; + + /* Check if the lookup succeeded */ if (NT_SUCCESS(Status)) { - /* Return the object */ - *ObjectPtr = Object; + /* Check if access is allowed */ + if (ObpCheckObjectReference(Object, + PassedAccessState, + FALSE, + AccessMode, + &Status)) + { + /* Return the object */ + Status = STATUS_SUCCESS; + *ObjectPtr = Object; + } } /* Free the access state */