Author: ion
Date: Mon Jan 8 11:03:47 2007
New Revision: 25372
URL: http://svn.reactos.org/svn/reactos?rev=25372&view=rev
Log:
- 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.
Modified:
trunk/reactos/include/ndk/iotypes.h
trunk/reactos/include/ndk/obtypes.h
trunk/reactos/ntoskrnl/include/internal/ob.h
trunk/reactos/ntoskrnl/ob/obhandle.c
trunk/reactos/ntoskrnl/ob/obname.c
trunk/reactos/ntoskrnl/ob/obref.c
Modified: trunk/reactos/include/ndk/iotypes.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/iotypes.h?rev=…
==============================================================================
--- trunk/reactos/include/ndk/iotypes.h (original)
+++ trunk/reactos/include/ndk/iotypes.h Mon Jan 8 11:03:47 2007
@@ -23,9 +23,7 @@
// Dependencies
//
#include <umtypes.h>
-#if !defined(_NTIFS_)
-typedef PVOID PFS_FILTER_CALLBACKS;
-#endif
+#include <ifssupp.h>
//
// I/O Completion Access Rights
Modified: trunk/reactos/include/ndk/obtypes.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/obtypes.h?rev=…
==============================================================================
--- trunk/reactos/include/ndk/obtypes.h (original)
+++ trunk/reactos/include/ndk/obtypes.h Mon Jan 8 11:03:47 2007
@@ -23,16 +23,14 @@
// Dependencies
//
#include <umtypes.h>
-
-//
-// If the IFS wasn't included, define this here
-//
-#ifndef EX_PUSH_LOCK
-#define EX_PUSH_LOCK ULONG_PTR
-#endif
+#ifndef NTOS_MODE_USER
+#include <extypes.h>
+#endif
+
+#undef NTDDI_VERSION
+#define NTDDI_VERSION NTDDI_WS03SP1
#ifdef NTOS_MODE_USER
-
//
// Definitions for Object Creation
//
@@ -86,6 +84,7 @@
#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)
@@ -106,6 +105,11 @@
((POBJECT_HEADER_CREATOR_INFO)(!((h)->Flags & \
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 @@
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;
Modified: trunk/reactos/ntoskrnl/include/internal/ob.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ob.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ob.h Mon Jan 8 11:03:47 2007
@@ -81,6 +81,18 @@
} 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
//
BOOLEAN
@@ -152,18 +164,18 @@
//
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 KPROCESSOR_MODE AccessMode,
+ IN OUT PVOID ParseContext,
+ IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
+ IN PVOID InsertObject,
IN PACCESS_STATE AccessState,
- IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
- IN PVOID ParseContext,
- IN PVOID Insert
+ IN POBP_LOOKUP_CONTEXT LookupContext,
+ OUT PVOID *FoundObject
);
//
@@ -268,6 +280,12 @@
);
VOID
+FASTCALL
+ObfDereferenceDeviceMap(
+ IN PVOID DeviceMap
+);
+
+VOID
NTAPI
ObInheritDeviceMap(
IN PEPROCESS Parent,
@@ -314,14 +332,50 @@
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
);
//
Modified: trunk/reactos/ntoskrnl/ob/obhandle.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obhandle.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obhandle.c (original)
+++ trunk/reactos/ntoskrnl/ob/obhandle.c Mon Jan 8 11:03:47 2007
@@ -24,7 +24,8 @@
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 @@
/* 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 @@
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 @@
/* 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 @@
}
}
+ /* 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 @@
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 @@
POBJECT_TYPE ObjectType;
POBJECT_HEADER ObjectHeader;
ACCESS_MASK GrantedAccess;
+ KIRQL CalloutIrql;
PAGED_CODE();
/* Get the object data */
@@ -212,15 +228,20 @@
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 @@
}
else
{
- /* Return the error isntead */
+ /* Return the error instead */
return STATUS_HANDLE_NOT_CLOSABLE;
}
}
@@ -258,9 +279,6 @@
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 @@
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,8 +353,59 @@
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 @@
&Status))
{
/* Access was denied, so fail */
- return Status;
+ goto Quickie;
}
}
else if (OpenReason == ObCreateHandle)
@@ -365,30 +438,82 @@
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 @@
OpenReason,
ObjectHeader->HandleCount,
ObjectHeader->PointerCount);
- return STATUS_SUCCESS;
+ return Status;
+
+Quickie:
+ /* Release lock and return */
+ ObpLeaveObjectTypeMutex(ObjectType);
+ return Status;
}
/*++
@@ -439,6 +569,10 @@
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,8 +588,59 @@
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 @@
&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 */
+ 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(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 @@
*
* @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 @@
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 @@
{
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 */
@@ -1502,12 +1730,18 @@
*Handle = NULL;
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 @@
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 @@
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 @@
PassedAccessState,
0,
HandleAttributes,
+ NULL,
AccessMode,
NULL,
Handle);
@@ -1747,39 +2002,70 @@
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;
+ PUNICODE_STRING ObjectName;
+ PVOID InsertObject;
+ PSECURITY_DESCRIPTOR ParentDescriptor = NULL;
+ BOOLEAN SdAllocated = FALSE;
+ POBJECT_HEADER_NAME_INFO ObjectNameInfo;
+ OBP_LOOKUP_CONTEXT Context;
+ ACCESS_STATE LocalAccessState;
+ AUX_DATA AuxData;
+ OB_OPEN_REASON OpenReason;
+ KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS, RealStatus;
- PSECURITY_DESCRIPTOR DirectorySd = NULL;
- BOOLEAN SdAllocated;
- OBP_LOOKUP_CONTEXT Context;
- POBJECT_HEADER_NAME_INFO ObjectNameInfo;
- ACCESS_STATE AccessState;
- AUX_DATA AuxData;
- BOOLEAN IsNamed = FALSE;
- OB_OPEN_REASON OpenReason = ObCreateHandle;
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 @@
/* 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 @@
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 @@
}
/* 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 @@
{
/* 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 @@
TRUE);
/* Clear the current one */
- PassedAccessState->SecurityDescriptor =
- ObjectCreateInfo->SecurityDescriptor = NULL;
+ AccessState->SecurityDescriptor =
+ ObjectCreateInfo->SecurityDescriptor = NULL;
}
}
@@ -1941,10 +2251,10 @@
/* 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,33 +2271,28 @@
* 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);
- }
-
- /* Remove the extra keep-alive reference */
- if (Handle) ObDereferenceObject(Object);
+ if (ObjectName) ObpDeleteNameCheck(Object);
+ }
/* Check our final status */
if (!NT_SUCCESS(Status))
@@ -1997,12 +2302,17 @@
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,
Modified: trunk/reactos/ntoskrnl/ob/obname.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obname.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obname.c (original)
+++ trunk/reactos/ntoskrnl/ob/obname.c Mon Jan 8 11:03:47 2007
@@ -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 @@
(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 @@
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 @@
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 @@
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 @@
/* 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 @@
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;
Modified: trunk/reactos/ntoskrnl/ob/obref.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obref.c?rev=25…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obref.c (original)
+++ trunk/reactos/ntoskrnl/ob/obref.c Mon Jan 8 11:03:47 2007
@@ -369,21 +369,21 @@
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,10 +391,17 @@
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 @@
/* 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 */
Author: ion
Date: Mon Jan 8 10:54:57 2007
New Revision: 25371
URL: http://svn.reactos.org/svn/reactos?rev=25371&view=rev
Log:
- Changes to lookup context set-up as place-holder and compatibility for future patch. Only configure the lookup context once, outside the initial loop, instead of configuring it with the same settings at each iteration.
Modified:
trunk/reactos/ntoskrnl/ob/obinit.c
Modified: trunk/reactos/ntoskrnl/ob/obinit.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obinit.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obinit.c (original)
+++ trunk/reactos/ntoskrnl/ob/obinit.c Mon Jan 8 10:54:57 2007
@@ -12,11 +12,9 @@
#include <ntoskrnl.h>
#define NDEBUG
-#include <internal/debug.h>
-
-#if defined (ALLOC_PRAGMA)
-#pragma alloc_text(INIT, ObInit)
-#endif
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
GENERIC_MAPPING ObpTypeMapping =
{
@@ -280,6 +278,10 @@
Status = NtClose(Handle);
if (!NT_SUCCESS(Status)) return FALSE;
+ Context.Object = NULL;
+ Context.Directory = ObpTypeDirectoryObject;
+ Context.DirectoryLocked = TRUE;
+
/* Loop the object types */
ListHead = &ObTypeObjectType->TypeList;
NextEntry = ListHead->Flink;
@@ -297,10 +299,6 @@
/* Make sure we have a name, and aren't inserted yet */
if ((NameInfo) && !(NameInfo->Directory))
{
- /* Set up the context for the insert */
- Context.Directory = ObpTypeDirectoryObject;
- Context.DirectoryLocked = TRUE;
-
/* Do the initial lookup to setup the context */
if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject,
&NameInfo->Name,
@@ -319,6 +317,8 @@
NextEntry = NextEntry->Flink;
}
+ Context.Object = NULL;
+
/* Initialize DOS Devices Directory and related Symbolic Links */
Status = ObpCreateDosDevicesDirectory();
if (!NT_SUCCESS(Status)) return FALSE;
Author: ion
Date: Mon Jan 8 10:53:50 2007
New Revision: 25370
URL: http://svn.reactos.org/svn/reactos?rev=25370&view=rev
Log:
- Validate lookup context in ObpInsertEntryDirectory.
- Read actual ObpLUIDDeviceMapsEnable variable do determine if shadow-searching is enabled in ObpLookupEntryDirectory.
- Currently disable all directory locking code (it was never used anyways) in ObpLookupEntryDirectory.
- Update ObpLookupEntryDirectory with placeholder code/branches for future patch implementing directory locks.
Modified:
trunk/reactos/ntoskrnl/ob/obdir.c
Modified: trunk/reactos/ntoskrnl/ob/obdir.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obdir.c?rev=25…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obdir.c (original)
+++ trunk/reactos/ntoskrnl/ob/obdir.c Mon Jan 8 10:53:50 2007
@@ -13,11 +13,11 @@
/* INCLUDES ***************************************************************/
-#define NTDDI_VERSION NTDDI_WS03
#include <ntoskrnl.h>
#define NDEBUG
-#include <internal/debug.h>
-
+#include <debug.h>
+
+BOOLEAN ObpLUIDDeviceMapsEnabled;
POBJECT_TYPE ObDirectoryType = NULL;
/* PRIVATE FUNCTIONS ******************************************************/
@@ -53,6 +53,18 @@
/* Make sure we have a name */
ASSERT(ObjectHeader->NameInfoOffset != 0);
+
+ /* Validate the context */
+ if ((Context->Object) ||
+ !(Context->DirectoryLocked) ||
+ (Parent != Context->Directory))
+ {
+ /* Invalid context */
+ DPRINT1("OB: ObpInsertEntryDirectory - invalid context %p %ld\n",
+ Context, Context->DirectoryLocked);
+ KEBUGCHECK(0);
+ return FALSE;
+ }
/* Allocate a new Directory Entry */
NewEntry = ExAllocatePoolWithTag(PagedPool,
@@ -116,6 +128,7 @@
{
BOOLEAN CaseInsensitive = FALSE;
POBJECT_HEADER_NAME_INFO HeaderNameInfo;
+ POBJECT_HEADER ObjectHeader;
ULONG HashValue;
ULONG HashIndex;
LONG TotalChars;
@@ -127,8 +140,8 @@
PWSTR Buffer;
PAGED_CODE();
- /* Always disable this until we have DOS Device Maps */
- SearchShadow = FALSE;
+ /* Check if we should search the shadow directory */
+ if (!ObpLUIDDeviceMapsEnabled) SearchShadow = FALSE;
/* Fail if we don't have a directory or name */
if (!(Directory) || !(Name)) goto Quickie;
@@ -137,11 +150,11 @@
TotalChars = Name->Length / sizeof(WCHAR);
Buffer = Name->Buffer;
+ /* Set up case-sensitivity */
+ if (Attributes & OBJ_CASE_INSENSITIVE) CaseInsensitive = TRUE;
+
/* 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--)
@@ -172,9 +185,7 @@
/* Check if the directory is already locked */
if (!Context->DirectoryLocked)
{
- /* Lock it */
- KeEnterCriticalRegion();
- ExAcquireResourceSharedLite(&Directory->Lock, TRUE);
+
}
/* Start looping */
@@ -184,10 +195,11 @@
if (CurrentEntry->HashValue == HashValue)
{
/* Make sure that it has a name */
- ASSERT(OBJECT_TO_OBJECT_HEADER(CurrentEntry->Object)->NameInfoOffset != 0);
+ ObjectHeader = OBJECT_TO_OBJECT_HEADER(CurrentEntry->Object);
/* Get the name information */
- HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(OBJECT_TO_OBJECT_HEADER(CurrentEntry->Object));
+ ASSERT(ObjectHeader->NameInfoOffset != 0);
+ HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
/* Do the names match? */
if ((Name->Length == HeaderNameInfo->Name.Length) &&
@@ -207,6 +219,11 @@
/* Set this entry as the first, to speed up incoming insertion */
if (AllocatedEntry != LookupBucket)
{
+ /* Check if the directory was locked */
+ if (!Context->DirectoryLocked)
+ {
+ }
+
/* Set the Current Entry */
*AllocatedEntry = CurrentEntry->ChainLink;
@@ -220,17 +237,42 @@
/* Save the found object */
FoundObject = CurrentEntry->Object;
if (!FoundObject) goto Quickie;
- }
-
- /* Check if the directory was unlocked (which means we locked it) */
- if (!Context->DirectoryLocked)
- {
- /* Lock it */
- ExReleaseResourceLite(&Directory->Lock);
- KeLeaveCriticalRegion();
+
+ /* Get the object name information */
+ ObjectHeader = OBJECT_TO_OBJECT_HEADER(FoundObject);
+ HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
+
+ /* Reference the object being looked up */
+ //ObReferenceObject(FoundObject);
+
+ /* Check if the directory was locked */
+ if (!Context->DirectoryLocked)
+ {
+ }
+ }
+ else
+ {
+ /* Check if the directory was locked */
+ if (!Context->DirectoryLocked)
+ {
+ }
+
+ /* Check if we should scan the shadow directory */
+ if ((SearchShadow) && (Directory->DeviceMap))
+ {
+ /* FIXME: We don't support this yet */
+ KEBUGCHECK(0);
+ }
}
Quickie:
+ /* Check if we found an object already */
+ if (Context->Object)
+ {
+ /* We already did a lookup, so remove this object's query reference */
+ //ObpRemoveQueryReference(Context->Object);
+ }
+
/* Return the object we found */
Context->Object = FoundObject;
return FoundObject;
Author: ion
Date: Mon Jan 8 10:51:07 2007
New Revision: 25369
URL: http://svn.reactos.org/svn/reactos?rev=25369&view=rev
Log:
- Set an invalid pointer as the object header's type when freeing it, to detect invalid usage.
- Optimize type mutex acquisition in ObpDeleteObject. Also optimize freeing of the unicode_String containing the name. Also add callout checks/protection during the security and delete procedure callouts.
- Acquire object type mutex during modification of the OB_FLAG_PERMANENT flag in ObpSetPermanentObject.
- Initialize default QueryReferences field to 1 during object allocation.
- Support undocumented 0x10000 object attribute flag used in Windows 2003 SP1 and higher to protect objects from user-mode access (such as PhysicalMemory).
- Use InterlockedIncrements for ObjectType accounting outside the type lock.
- Clear the lookup context's object pointer for future use.
Modified:
trunk/reactos/ntoskrnl/ob/oblife.c
Modified: trunk/reactos/ntoskrnl/ob/oblife.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/oblife.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/oblife.c (original)
+++ trunk/reactos/ntoskrnl/ob/oblife.c Mon Jan 8 10:51:07 2007
@@ -107,9 +107,6 @@
/* Add the SD charge too */
if (Header->Flags & OB_FLAG_SECURITY) PagedPoolCharge += 2048;
}
-
- /* FIXME: Should be returning quota */
- DPRINT("Quotas: %lx %lx\n", PagedPoolCharge, NonPagedPoolCharge);
}
}
@@ -128,6 +125,9 @@
ExFreePool(NameInfo->Name.Buffer);
NameInfo->Name.Buffer = NULL;
}
+
+ /* Catch invalid access */
+ Header->Type = (POBJECT_TYPE)0xBAADB0B0;
/* Free the object using the same allocation tag */
ExFreePoolWithTag(HeaderLocation, ObjectType->Key);
@@ -142,6 +142,7 @@
POBJECT_TYPE ObjectType;
POBJECT_HEADER_NAME_INFO NameInfo;
POBJECT_HEADER_CREATOR_INFO CreatorInfo;
+ KIRQL CalloutIrql;
PAGED_CODE();
/* Get the header and type */
@@ -152,33 +153,32 @@
NameInfo = OBJECT_HEADER_TO_NAME_INFO(Header);
CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(Header);
- /* Lock the object type */
- ObpEnterObjectTypeMutex(ObjectType);
-
/* Check if the object is on a type list */
if ((CreatorInfo) && !(IsListEmpty(&CreatorInfo->TypeList)))
{
+ /* Lock the object type */
+ ObpEnterObjectTypeMutex(ObjectType);
+
/* Remove the object from the type list */
RemoveEntryList(&CreatorInfo->TypeList);
- }
-
- /* Release the lock */
- ObpLeaveObjectTypeMutex(ObjectType);
+
+ /* Release the lock */
+ ObpLeaveObjectTypeMutex(ObjectType);
+ }
/* Check if we have a name */
if ((NameInfo) && (NameInfo->Name.Buffer))
{
/* Free it */
ExFreePool(NameInfo->Name.Buffer);
-
- /* Clean up the string so we don't try this again */
- RtlInitUnicodeString(&NameInfo->Name, NULL);
+ RtlInitEmptyUnicodeString(&NameInfo->Name, NULL, 0);
}
/* Check if we have a security descriptor */
if (Header->SecurityDescriptor)
{
/* Call the security procedure to delete it */
+ ObpCalloutStart(&CalloutIrql);
ObjectType->TypeInfo.SecurityProcedure(Object,
DeleteSecurityDescriptor,
0,
@@ -187,13 +187,16 @@
&Header->SecurityDescriptor,
0,
NULL);
+ ObpCalloutEnd(CalloutIrql, "Security", ObjectType, Object);
}
/* Check if we have a delete procedure */
if (ObjectType->TypeInfo.DeleteProcedure)
{
/* Call it */
+ ObpCalloutStart(&CalloutIrql);
ObjectType->TypeInfo.DeleteProcedure(Object);
+ ObpCalloutEnd(CalloutIrql, "Delete", ObjectType, Object);
}
/* Now de-allocate all object members */
@@ -256,15 +259,26 @@
/* Get the header */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
+
+ /* Acquire object type lock */
+ ObpEnterObjectTypeMutex(ObjectHeader->Type);
+
+ /* Check what we're doing to it */
if (Permanent)
{
/* Set it to permanent */
ObjectHeader->Flags |= OB_FLAG_PERMANENT;
+
+ /* Release the lock */
+ ObpLeaveObjectTypeMutex(ObjectHeader->Type);
}
else
{
/* Remove the flag */
ObjectHeader->Flags &= ~OB_FLAG_PERMANENT;
+
+ /* Release the lock */
+ ObpLeaveObjectTypeMutex(ObjectHeader->Type);
/* Check if we should delete the object now */
ObpDeleteNameCheck(ObjectBody);
@@ -623,9 +637,10 @@
Header = ExAllocatePoolWithTag(PoolType, FinalSize + ObjectSize, Tag);
if (!Header) return STATUS_INSUFFICIENT_RESOURCES;
- /* Initialize quota info */
+ /* Check if we have a quota header */
if (QuotaSize)
{
+ /* Initialize quota info */
QuotaInfo = (POBJECT_HEADER_QUOTA_INFO)Header;
QuotaInfo->PagedPoolCharge = ObjectCreateInfo->PagedPoolCharge;
QuotaInfo->NonPagedPoolCharge = ObjectCreateInfo->NonPagedPoolCharge;
@@ -634,26 +649,41 @@
Header = (POBJECT_HEADER)(QuotaInfo + 1);
}
- /* Initialize Handle Info */
+ /* Check if we have a handle database header */
if (HandleSize)
{
+ /* Initialize Handle Info */
HandleInfo = (POBJECT_HEADER_HANDLE_INFO)Header;
HandleInfo->SingleEntry.HandleCount = 0;
Header = (POBJECT_HEADER)(HandleInfo + 1);
}
- /* Initialize the Object Name Info */
+ /* Check if we have a name header */
if (NameSize)
{
+ /* Initialize the Object Name Info */
NameInfo = (POBJECT_HEADER_NAME_INFO)Header;
NameInfo->Name = *ObjectName;
NameInfo->Directory = NULL;
+ NameInfo->QueryReferences = 1;
+
+ /* Check if this is a call with the special protection flag */
+ if ((PreviousMode == KernelMode) &&
+ (ObjectCreateInfo) &&
+ (ObjectCreateInfo->Attributes & 0x10000))
+ {
+ /* Set flag which will make the object protected from user-mode */
+ NameInfo->QueryReferences |= 0x40000000;
+ }
+
+ /* Set the header pointer */
Header = (POBJECT_HEADER)(NameInfo + 1);
}
- /* Initialize Creator Info */
+ /* Check if we have a creator header */
if (CreatorSize)
{
+ /* Initialize Creator Info */
CreatorInfo = (POBJECT_HEADER_CREATOR_INFO)Header;
CreatorInfo->CreatorBackTraceIndex = 0;
CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcessId();
@@ -739,7 +769,7 @@
if (ObjectType)
{
/* Increase the number of objects of this type */
- ObjectType->TotalNumberOfObjects++;
+ InterlockedIncrement(&ObjectType->TotalNumberOfObjects);
/* Update the high water */
ObjectType->HighWaterNumberOfObjects = max(ObjectType->
@@ -774,8 +804,6 @@
POBJECT_CREATE_INFORMATION ObjectCreateInfo;
UNICODE_STRING ObjectName;
POBJECT_HEADER Header;
- DPRINT("ObCreateObject(Type %p ObjectAttributes %p, Object %p)\n",
- Type, ObjectAttributes, Object);
/* Allocate a capture buffer */
ObjectCreateInfo = ObpAllocateCapturedAttributes(LookasideCreateInfoList);
@@ -898,6 +926,8 @@
if (*p++ == OBJ_NAME_PATH_SEPARATOR) return STATUS_OBJECT_NAME_INVALID;
}
+ Context.Object = NULL;
+
/* Check if we've already created the directory of types */
if (ObpTypeDirectoryObject)
{
@@ -911,6 +941,7 @@
&Context))
{
/* We have already created it, so fail */
+ Context.Object = NULL;
return STATUS_OBJECT_NAME_COLLISION;
}
}
@@ -922,6 +953,7 @@
if (!ObjectName.Buffer)
{
/* Out of memory, fail */
+ Context.Object = NULL;
return STATUS_INSUFFICIENT_RESOURCES;
}
@@ -938,6 +970,8 @@
(POBJECT_HEADER*)&Header);
if (!NT_SUCCESS(Status))
{
+ Context.Object = NULL;
+
/* Free the name and fail */
ExFreePool(ObjectName.Buffer);
return Status;
@@ -1067,12 +1101,15 @@
ObReferenceObject(ObpTypeDirectoryObject);
}
+ Context.Object = NULL;
+
/* Return the object type and success */
*ObjectType = LocalObjectType;
return STATUS_SUCCESS;
}
/* If we got here, then we failed */
+ Context.Object = NULL;
return STATUS_INSUFFICIENT_RESOURCES;
}
@@ -1094,6 +1131,8 @@
NTAPI
ObMakeTemporaryObject(IN PVOID ObjectBody)
{
+ PAGED_CODE();
+
/* Call the internal API */
ObpSetPermanentObject(ObjectBody, FALSE);
}