mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-29 04:13:32 +00:00
- 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
This commit is contained in:
@@ -23,9 +23,7 @@ Author:
|
||||
// Dependencies
|
||||
//
|
||||
#include <umtypes.h>
|
||||
#if !defined(_NTIFS_)
|
||||
typedef PVOID PFS_FILTER_CALLBACKS;
|
||||
#endif
|
||||
#include <ifssupp.h>
|
||||
|
||||
//
|
||||
// I/O Completion Access Rights
|
||||
|
||||
@@ -23,16 +23,14 @@ Author:
|
||||
// Dependencies
|
||||
//
|
||||
#include <umtypes.h>
|
||||
|
||||
//
|
||||
// If the IFS wasn't included, define this here
|
||||
//
|
||||
#ifndef EX_PUSH_LOCK
|
||||
#define EX_PUSH_LOCK ULONG_PTR
|
||||
#ifndef NTOS_MODE_USER
|
||||
#include <extypes.h>
|
||||
#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;
|
||||
|
||||
@@ -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
|
||||
//
|
||||
|
||||
+459
-149
@@ -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 <FILLMEIN>.
|
||||
*
|
||||
* @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,
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
#define NTDDI_VERSION NTDDI_WINXP
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
#include <debug.h>
|
||||
|
||||
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;
|
||||
|
||||
+41
-22
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user