-/* $Id: object.c,v 1.73 2003/12/30 18:52:05 fireball Exp $
+/* $Id$
*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/ob/object.c
- * PURPOSE: Implements generic object managment functions
- * PROGRAMMERS David Welch (welch@cwcom.net), Skywing (skywing@valhallalegends.com)
- * UPDATE HISTORY:
- * 10/06/98: Created
- * 09/13/03: Fixed various ObXxx routines to not call retention
- * checks directly at a raised IRQL.
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/ob/object.c
+ * PURPOSE: Implements generic object managment functions
+ *
+ * PROGRAMMERS: David Welch (welch@cwcom.net)
+ * Skywing (skywing@valhallalegends.com)
*/
/* INCLUDES *****************************************************************/
-#define NTOS_MODE_KERNEL
-#include <ntos.h>
-#include <roscfg.h>
-#include <internal/ob.h>
-#include <internal/ps.h>
-#include <internal/id.h>
-#include <internal/ke.h>
-
+#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
PVOID HEADER_TO_BODY(POBJECT_HEADER obj)
{
- return(((char*)obj)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER));
+ return(((char*)obj)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER));
}
POBJECT_HEADER BODY_TO_HEADER(PVOID body)
{
- PCOMMON_BODY_HEADER chdr = (PCOMMON_BODY_HEADER)body;
- return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type));
+ PCOMMON_BODY_HEADER chdr = (PCOMMON_BODY_HEADER)body;
+ return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type));
+}
+
+NTSTATUS
+ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN KPROCESSOR_MODE AccessMode,
+ IN POOL_TYPE PoolType,
+ IN BOOLEAN CaptureIfKernel,
+ OUT PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL,
+ OUT PUNICODE_STRING ObjectName OPTIONAL)
+{
+ OBJECT_ATTRIBUTES AttributesCopy;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ /* at least one output parameter must be != NULL! */
+ ASSERT(CapturedObjectAttributes != NULL || ObjectName != NULL);
+
+ if(ObjectAttributes == NULL)
+ {
+ /* we're going to return STATUS_SUCCESS! */
+ goto failbasiccleanup;
+ }
+
+ if(AccessMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForRead(ObjectAttributes,
+ sizeof(ObjectAttributes),
+ sizeof(ULONG));
+ /* make a copy on the stack */
+ AttributesCopy = *ObjectAttributes;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("ObpCaptureObjectAttributes failed to probe object attributes\n");
+ goto failbasiccleanup;
+ }
+ }
+ else if(!CaptureIfKernel)
+ {
+ if(ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
+ {
+ if(ObjectName != NULL)
+ {
+ /* we don't have to capture any memory, the caller considers the passed data
+ as valid */
+ if(ObjectAttributes->ObjectName != NULL)
+ {
+ *ObjectName = *ObjectAttributes->ObjectName;
+ }
+ else
+ {
+ ObjectName->Length = ObjectName->MaximumLength = 0;
+ ObjectName->Buffer = NULL;
+ }
+ }
+ if(CapturedObjectAttributes != NULL)
+ {
+ CapturedObjectAttributes->RootDirectory = ObjectAttributes->RootDirectory;
+ CapturedObjectAttributes->Attributes = ObjectAttributes->Attributes;
+ CapturedObjectAttributes->SecurityDescriptor = ObjectAttributes->SecurityDescriptor;
+ CapturedObjectAttributes->SecurityQualityOfService = ObjectAttributes->SecurityQualityOfService;
+ }
+
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto failbasiccleanup;
+ }
+ }
+ else
+ {
+ AttributesCopy = *ObjectAttributes;
+ }
+
+ /* if Length isn't as expected, bail with an invalid parameter status code so
+ the caller knows he passed garbage... */
+ if(AttributesCopy.Length != sizeof(OBJECT_ATTRIBUTES))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto failbasiccleanup;
+ }
+
+ if(CapturedObjectAttributes != NULL)
+ {
+ CapturedObjectAttributes->RootDirectory = AttributesCopy.RootDirectory;
+ CapturedObjectAttributes->Attributes = AttributesCopy.Attributes;
+
+ if(AttributesCopy.SecurityDescriptor != NULL)
+ {
+ Status = SeCaptureSecurityDescriptor(AttributesCopy.SecurityDescriptor,
+ AccessMode,
+ PoolType,
+ TRUE,
+ &CapturedObjectAttributes->SecurityDescriptor);
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unable to capture the security descriptor!!!\n");
+ goto failbasiccleanup;
+ }
+ }
+ else
+ {
+ CapturedObjectAttributes->SecurityDescriptor = NULL;
+ }
+
+ if(AttributesCopy.SecurityQualityOfService != NULL)
+ {
+ SECURITY_QUALITY_OF_SERVICE SafeQoS;
+
+ _SEH_TRY
+ {
+ ProbeForRead(AttributesCopy.SecurityQualityOfService,
+ sizeof(SECURITY_QUALITY_OF_SERVICE),
+ sizeof(ULONG));
+ SafeQoS = *(PSECURITY_QUALITY_OF_SERVICE)AttributesCopy.SecurityQualityOfService;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unable to capture QoS!!!\n");
+ goto failcleanupsdescriptor;
+ }
+
+ if(SafeQoS.Length != sizeof(SECURITY_QUALITY_OF_SERVICE))
+ {
+ DPRINT1("Unable to capture QoS, wrong size!!!\n");
+ Status = STATUS_INVALID_PARAMETER;
+ goto failcleanupsdescriptor;
+ }
+
+ CapturedObjectAttributes->SecurityQualityOfService = ExAllocatePool(PoolType,
+ sizeof(SECURITY_QUALITY_OF_SERVICE));
+ if(CapturedObjectAttributes->SecurityQualityOfService != NULL)
+ {
+ *CapturedObjectAttributes->SecurityQualityOfService = SafeQoS;
+ }
+ else
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto failcleanupsdescriptor;
+ }
+ }
+ else
+ {
+ CapturedObjectAttributes->SecurityQualityOfService = NULL;
+ }
+ }
+
+ if(ObjectName != NULL)
+ {
+ if(AttributesCopy.ObjectName != NULL)
+ {
+ UNICODE_STRING OriginalCopy;
+
+ if(AccessMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ /* probe the ObjectName structure and make a local stack copy of it */
+ ProbeForRead(AttributesCopy.ObjectName,
+ sizeof(UNICODE_STRING),
+ sizeof(ULONG));
+ OriginalCopy = *AttributesCopy.ObjectName;
+ if(OriginalCopy.Length > 0)
+ {
+ ProbeForRead(OriginalCopy.Buffer,
+ OriginalCopy.Length,
+ sizeof(WCHAR));
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(NT_SUCCESS(Status))
+ {
+ if(OriginalCopy.Length > 0)
+ {
+ ObjectName->MaximumLength = OriginalCopy.Length + sizeof(WCHAR);
+ ObjectName->Buffer = ExAllocatePool(PoolType,
+ ObjectName->MaximumLength);
+ if(ObjectName->Buffer != NULL)
+ {
+ _SEH_TRY
+ {
+ /* no need to probe OriginalCopy.Buffer again, we already did that
+ when capturing the UNICODE_STRING structure itself */
+ RtlCopyMemory(ObjectName->Buffer, OriginalCopy.Buffer, OriginalCopy.Length);
+ ObjectName->Buffer[OriginalCopy.Length / sizeof(WCHAR)] = L'\0';
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("ObpCaptureObjectAttributes failed to copy the unicode string!\n");
+ }
+ }
+ else
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ else if(AttributesCopy.RootDirectory != NULL /* && OriginalCopy.Length == 0 */)
+ {
+ /* if the caller specified a root directory, there must be an object name! */
+ Status = STATUS_OBJECT_NAME_INVALID;
+ }
+ }
+ else
+ {
+ DPRINT1("ObpCaptureObjectAttributes failed to probe the object name UNICODE_STRING structure!\n");
+ }
+ }
+ else /* AccessMode == KernelMode */
+ {
+ OriginalCopy = *AttributesCopy.ObjectName;
+
+ if(OriginalCopy.Length > 0)
+ {
+ ObjectName->MaximumLength = OriginalCopy.Length + sizeof(WCHAR);
+ ObjectName->Buffer = ExAllocatePool(PoolType,
+ ObjectName->MaximumLength);
+ if(ObjectName->Buffer != NULL)
+ {
+ RtlCopyMemory(ObjectName->Buffer, OriginalCopy.Buffer, OriginalCopy.Length);
+ ObjectName->Buffer[OriginalCopy.Length / sizeof(WCHAR)] = L'\0';
+ }
+ else
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ else if(AttributesCopy.RootDirectory != NULL /* && OriginalCopy.Length == 0 */)
+ {
+ /* if the caller specified a root directory, there must be an object name! */
+ Status = STATUS_OBJECT_NAME_INVALID;
+ }
+ }
+ }
+ else
+ {
+ ObjectName->Length = ObjectName->MaximumLength = 0;
+ ObjectName->Buffer = NULL;
+ }
+ }
+
+ if(!NT_SUCCESS(Status))
+ {
+ if(ObjectName->Buffer)
+ {
+ ExFreePool(ObjectName->Buffer);
+ }
+
+failcleanupsdescriptor:
+ if(CapturedObjectAttributes != NULL)
+ {
+ /* cleanup allocated resources */
+ SeReleaseSecurityDescriptor(CapturedObjectAttributes->SecurityDescriptor,
+ AccessMode,
+ TRUE);
+ }
+
+failbasiccleanup:
+ if(ObjectName != NULL)
+ {
+ ObjectName->Length = ObjectName->MaximumLength = 0;
+ ObjectName->Buffer = NULL;
+ }
+ if(CapturedObjectAttributes != NULL)
+ {
+ RtlZeroMemory(CapturedObjectAttributes, sizeof(CAPTURED_OBJECT_ATTRIBUTES));
+ }
+ }
+
+ return Status;
+}
+
+
+VOID
+ObpReleaseObjectAttributes(IN PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL,
+ IN PUNICODE_STRING ObjectName OPTIONAL,
+ IN KPROCESSOR_MODE AccessMode,
+ IN BOOLEAN CaptureIfKernel)
+{
+ /* WARNING - You need to pass the same parameters to this function as you passed
+ to ObpCaptureObjectAttributes() to avoid memory leaks */
+ if(AccessMode != KernelMode || CaptureIfKernel)
+ {
+ if(CapturedObjectAttributes != NULL)
+ {
+ if(CapturedObjectAttributes->SecurityDescriptor != NULL)
+ {
+ ExFreePool(CapturedObjectAttributes->SecurityDescriptor);
+ CapturedObjectAttributes->SecurityDescriptor = NULL;
+ }
+ if(CapturedObjectAttributes->SecurityQualityOfService != NULL)
+ {
+ ExFreePool(CapturedObjectAttributes->SecurityQualityOfService);
+ CapturedObjectAttributes->SecurityQualityOfService = NULL;
+ }
+ }
+ if(ObjectName != NULL &&
+ ObjectName->Length > 0)
+ {
+ ExFreePool(ObjectName->Buffer);
+ }
+ }
}
PUNICODE_STRING RemainingPath,
POBJECT_TYPE ObjectType)
{
- PVOID NextObject;
- PVOID CurrentObject;
- PVOID RootObject;
- POBJECT_HEADER CurrentHeader;
- NTSTATUS Status;
- PWSTR current;
- UNICODE_STRING PathString;
- ULONG Attributes;
- PUNICODE_STRING ObjectName;
+ PVOID NextObject;
+ PVOID CurrentObject;
+ PVOID RootObject;
+ POBJECT_HEADER CurrentHeader;
+ NTSTATUS Status;
+ PWSTR current;
+ UNICODE_STRING PathString;
+ ULONG Attributes;
+ PUNICODE_STRING ObjectName;
+
+ PAGED_CODE();
- DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
- "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
- DPRINT("ObjectAttributes->ObjectName %wZ\n",
- ObjectAttributes->ObjectName);
+ DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
+ "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
+ DPRINT("ObjectAttributes->ObjectName %wZ\n",
+ ObjectAttributes->ObjectName);
- RtlInitUnicodeString (RemainingPath, NULL);
+ RtlInitUnicodeString (RemainingPath, NULL);
- if (ObjectAttributes->RootDirectory == NULL)
- {
- ObReferenceObjectByPointer(NameSpaceRoot,
- DIRECTORY_TRAVERSE,
- NULL,
- UserMode);
- CurrentObject = NameSpaceRoot;
- }
- else
- {
- Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
- DIRECTORY_TRAVERSE,
- NULL,
- UserMode,
- &CurrentObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- }
+ if (ObjectAttributes->RootDirectory == NULL)
+ {
+ ObReferenceObjectByPointer(NameSpaceRoot,
+ DIRECTORY_TRAVERSE,
+ NULL,
+ UserMode);
+ CurrentObject = NameSpaceRoot;
+ }
+ else
+ {
+ Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
+ DIRECTORY_TRAVERSE,
+ NULL,
+ UserMode,
+ &CurrentObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
ObjectName = ObjectAttributes->ObjectName;
if (ObjectName->Length == 0 ||
current = PathString.Buffer;
- RootObject = CurrentObject;
- Attributes = ObjectAttributes->Attributes;
- if (ObjectType == ObSymbolicLinkType)
- Attributes |= OBJ_OPENLINK;
+ RootObject = CurrentObject;
+ Attributes = ObjectAttributes->Attributes;
+ if (ObjectType == ObSymbolicLinkType)
+ Attributes |= OBJ_OPENLINK;
- while (TRUE)
- {
+ while (TRUE)
+ {
DPRINT("current %S\n",current);
CurrentHeader = BODY_TO_HEADER(CurrentObject);
if (Status == STATUS_REPARSE)
{
/* reparse the object path */
- NextObject = RootObject;
+ NextObject = NameSpaceRoot;
current = PathString.Buffer;
ObReferenceObjectByPointer(NextObject,
}
ObDereferenceObject(CurrentObject);
CurrentObject = NextObject;
- }
-
- if (current)
- RtlCreateUnicodeString (RemainingPath, current);
- RtlFreeUnicodeString (&PathString);
- *ReturnedObject = CurrentObject;
-
- return(STATUS_SUCCESS);
+ }
+
+ if (current)
+ RtlpCreateUnicodeString (RemainingPath, current, NonPagedPool);
+ RtlFreeUnicodeString (&PathString);
+ *ReturnedObject = CurrentObject;
+
+ return STATUS_SUCCESS;
}
POBJECT_HEADER ObjectHeader;
ULONG LocalReturnLength;
NTSTATUS Status;
+
+ PAGED_CODE();
*ReturnLength = 0;
NTSTATUS Status;
BOOLEAN ObjectAttached = FALSE;
PWCHAR NamePtr;
-
- assert_irql(APC_LEVEL);
+ PSECURITY_DESCRIPTOR NewSecurityDescriptor = NULL;
+ SECURITY_SUBJECT_CONTEXT SubjectContext;
+
+ PAGED_CODE();
+
+ if(ObjectAttributesAccessMode == UserMode && ObjectAttributes != NULL)
+ {
+ Status = STATUS_SUCCESS;
+ _SEH_TRY
+ {
+ ProbeForRead(ObjectAttributes,
+ sizeof(OBJECT_ATTRIBUTES),
+ sizeof(ULONG));
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
DPRINT("ObCreateObject(Type %p ObjectAttributes %p, Object %p)\n",
Type, ObjectAttributes, Object);
+ if (Type == NULL)
+ {
+ DPRINT1("Invalid object type!\n");
+ return STATUS_INVALID_PARAMETER;
+ }
+
if (ObjectAttributes != NULL &&
ObjectAttributes->ObjectName != NULL &&
ObjectAttributes->ObjectName->Buffer != NULL)
NULL);
if (!NT_SUCCESS(Status))
{
- DPRINT("ObFindObject() failed! (Status 0x%x)\n", Status);
- return(Status);
+ DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status);
+ return Status;
}
}
else
Header = (POBJECT_HEADER)ExAllocatePoolWithTag(NonPagedPool,
OBJECT_ALLOC_SIZE(ObjectSize),
Type->Tag);
- if (Header == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
+ if (Header == NULL) {
+ DPRINT1("Not enough memory!\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory(Header, OBJECT_ALLOC_SIZE(ObjectSize));
/* Initialize the object header */
+ DPRINT("Initalizing header\n");
Header->HandleCount = 0;
Header->RefCount = 1;
Header->ObjectType = Type;
RtlInitUnicodeString(&(Header->Name),NULL);
+ DPRINT("Getting Parent and adding entry\n");
if (Parent != NULL)
{
ParentHeader = BODY_TO_HEADER(Parent);
ObjectAttached = TRUE;
}
- if ((Header->ObjectType != NULL) &&
- (Header->ObjectType->Create != NULL))
+ DPRINT("About to call Create Routine\n");
+ if (Header->ObjectType->Create != NULL)
{
DPRINT("Calling %x\n", Header->ObjectType->Create);
Status = Header->ObjectType->Create(HEADER_TO_BODY(Header),
RtlFreeUnicodeString(&Header->Name);
RtlFreeUnicodeString(&RemainingPath);
ExFreePool(Header);
- return(Status);
+ DPRINT("Create Failed\n");
+ return Status;
+ }
+ }
+ RtlFreeUnicodeString(&RemainingPath);
+
+ SeCaptureSubjectContext(&SubjectContext);
+
+ DPRINT("Security Assignment in progress\n");
+ /* Build the new security descriptor */
+ Status = SeAssignSecurity((ParentHeader != NULL) ? ParentHeader->SecurityDescriptor : NULL,
+ (ObjectAttributes != NULL) ? ObjectAttributes->SecurityDescriptor : NULL,
+ &NewSecurityDescriptor,
+ (Header->ObjectType == ObDirectoryType),
+ &SubjectContext,
+ Header->ObjectType->Mapping,
+ PagedPool);
+ if (NT_SUCCESS(Status))
+ {
+ DPRINT("NewSecurityDescriptor %p\n", NewSecurityDescriptor);
+
+ if (Header->ObjectType->Security != NULL)
+ {
+ /* Call the security method */
+ Status = Header->ObjectType->Security(HEADER_TO_BODY(Header),
+ AssignSecurityDescriptor,
+ 0,
+ NewSecurityDescriptor,
+ NULL);
+ }
+ else
+ {
+ /* Assign the security descriptor to the object header */
+ Status = ObpAddSecurityDescriptor(NewSecurityDescriptor,
+ &Header->SecurityDescriptor);
+ DPRINT("Object security descriptor %p\n", Header->SecurityDescriptor);
}
+
+ /* Release the new security descriptor */
+ SeDeassignSecurity(&NewSecurityDescriptor);
}
- RtlFreeUnicodeString( &RemainingPath );
+
+ DPRINT("Security Complete\n");
+ SeReleaseSubjectContext(&SubjectContext);
if (Object != NULL)
{
*Object = HEADER_TO_BODY(Header);
}
- return(STATUS_SUCCESS);
+ DPRINT("Sucess!\n");
+ return STATUS_SUCCESS;
}
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-ObReferenceObjectByPointer(IN PVOID Object,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_TYPE ObjectType,
- IN KPROCESSOR_MODE AccessMode)
/*
* FUNCTION: Increments the pointer reference count for a given object
* ARGUMENTS:
* ObjectType = Points to the object type structure
* AccessMode = Type of access check to perform
* RETURNS: Status
+ *
+ * @implemented
*/
+NTSTATUS STDCALL
+ObReferenceObjectByPointer(IN PVOID Object,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_TYPE ObjectType,
+ IN KPROCESSOR_MODE AccessMode)
{
POBJECT_HEADER Header;
+
+ /* NOTE: should be possible to reference an object above APC_LEVEL! */
DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
Object,ObjectType);
Header->ObjectType,
Header->ObjectType->TypeName.Buffer,
ObjectType,
- ObjectType->TypeName.Buffer);
+ ObjectType->TypeName.Buffer);
return(STATUS_UNSUCCESSFUL);
}
if (Header->ObjectType == PsProcessType)
{
NTSTATUS Status;
+ PAGED_CODE();
+
DPRINT("ObOpenObjectByPointer()\n");
Status = ObReferenceObjectByPointer(Object,
static NTSTATUS
-ObpPerformRetentionChecks(POBJECT_HEADER Header)
+ObpDeleteObject(POBJECT_HEADER Header)
{
- DPRINT("ObPerformRetentionChecks(Header %p)\n", Header);
+ DPRINT("ObpDeleteObject(Header %p)\n", Header);
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
{
- DPRINT("ObpPerformRetentionChecks called at an unsupported IRQL. Use ObpPerformRetentionChecksDpcLevel instead.\n");
+ DPRINT("ObpDeleteObject called at an unsupported IRQL. Use ObpDeleteObjectDpcLevel instead.\n");
KEBUGCHECK(0);
}
+ if (Header->SecurityDescriptor != NULL)
+ {
+ ObpRemoveSecurityDescriptor(Header->SecurityDescriptor);
+ }
+
if (Header->ObjectType != NULL &&
Header->ObjectType->Delete != NULL)
{
VOID STDCALL
-ObpPerformRetentionChecksWorkRoutine (IN PVOID Parameter)
+ObpDeleteObjectWorkRoutine (IN PVOID Parameter)
{
PRETENTION_CHECK_PARAMS Params = (PRETENTION_CHECK_PARAMS)Parameter;
/* ULONG Tag; */ /* See below */
- assert(Params);
- assert(KeGetCurrentIrql() == PASSIVE_LEVEL); /* We need PAGED_CODE somewhere... */
+ ASSERT(Params);
+ ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); /* We need PAGED_CODE somewhere... */
/* Turn this on when we have ExFreePoolWithTag
Tag = Params->ObjectHeader->ObjectType->Tag; */
- ObpPerformRetentionChecks(Params->ObjectHeader);
+ ObpDeleteObject(Params->ObjectHeader);
ExFreePool(Params);
/* ExFreePoolWithTag(Params, Tag); */
}
-static NTSTATUS
-ObpPerformRetentionChecksDpcLevel(IN POBJECT_HEADER ObjectHeader)
+STATIC NTSTATUS
+ObpDeleteObjectDpcLevel(IN POBJECT_HEADER ObjectHeader,
+ IN LONG OldRefCount)
{
if (ObjectHeader->RefCount < 0)
{
CPRINT("Object %p/%p has invalid reference count (%d)\n",
- ObjectHeader, HEADER_TO_BODY(ObjectHeader), ObjectHeader->RefCount);
+ ObjectHeader, HEADER_TO_BODY(ObjectHeader),
+ ObjectHeader->RefCount);
KEBUGCHECK(0);
}
if (ObjectHeader->HandleCount < 0)
{
CPRINT("Object %p/%p has invalid handle count (%d)\n",
- ObjectHeader, HEADER_TO_BODY(ObjectHeader), ObjectHeader->HandleCount);
+ ObjectHeader, HEADER_TO_BODY(ObjectHeader),
+ ObjectHeader->HandleCount);
KEBUGCHECK(0);
}
- if (ObjectHeader->RefCount == 0 &&
- ObjectHeader->HandleCount == 0 &&
- ObjectHeader->Permanent == FALSE)
+ if (ObjectHeader->CloseInProcess)
{
- if (ObjectHeader->CloseInProcess)
- {
- KEBUGCHECK(0);
- return STATUS_UNSUCCESSFUL;
- }
- ObjectHeader->CloseInProcess = TRUE;
-
- switch (KeGetCurrentIrql ())
- {
- case PASSIVE_LEVEL:
- return ObpPerformRetentionChecks (ObjectHeader);
-
- case APC_LEVEL:
- case DISPATCH_LEVEL:
- {
- PRETENTION_CHECK_PARAMS Params;
-
- /*
- * Can we get rid of this NonPagedPoolMustSucceed call and still be a
- * 'must succeed' function? I don't like to bugcheck on no memory!
- */
- Params = (PRETENTION_CHECK_PARAMS)ExAllocatePoolWithTag(NonPagedPoolMustSucceed,
- sizeof(RETENTION_CHECK_PARAMS),
- ObjectHeader->ObjectType->Tag);
- Params->ObjectHeader = ObjectHeader;
- ExInitializeWorkItem(&Params->WorkItem,
- ObpPerformRetentionChecksWorkRoutine,
- (PVOID)Params);
- ExQueueWorkItem(&Params->WorkItem,
- CriticalWorkQueue);
- }
- return STATUS_PENDING;
-
- default:
- DPRINT("ObpPerformRetentionChecksDpcLevel called at unsupported IRQL %u!\n",
- KeGetCurrentIrql());
- KEBUGCHECK(0);
- return STATUS_UNSUCCESSFUL;
- }
+ KEBUGCHECK(0);
+ return STATUS_UNSUCCESSFUL;
+ }
+ ObjectHeader->CloseInProcess = TRUE;
+
+ switch (KeGetCurrentIrql ())
+ {
+ case PASSIVE_LEVEL:
+ return ObpDeleteObject (ObjectHeader);
+
+ case APC_LEVEL:
+ case DISPATCH_LEVEL:
+ {
+ PRETENTION_CHECK_PARAMS Params;
+
+ /*
+ We use must succeed pool here because if the allocation fails
+ then we leak memory.
+ */
+ Params = (PRETENTION_CHECK_PARAMS)
+ ExAllocatePoolWithTag(NonPagedPoolMustSucceed,
+ sizeof(RETENTION_CHECK_PARAMS),
+ ObjectHeader->ObjectType->Tag);
+ Params->ObjectHeader = ObjectHeader;
+ ExInitializeWorkItem(&Params->WorkItem,
+ ObpDeleteObjectWorkRoutine,
+ (PVOID)Params);
+ ExQueueWorkItem(&Params->WorkItem,
+ CriticalWorkQueue);
+ }
+ return STATUS_PENDING;
+
+ default:
+ DPRINT("ObpDeleteObjectDpcLevel called at unsupported "
+ "IRQL %u!\n", KeGetCurrentIrql());
+ KEBUGCHECK(0);
+ return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
{
POBJECT_HEADER Header;
- assert(Object);
+ ASSERT(Object);
Header = BODY_TO_HEADER(Object);
+ /* No one should be referencing an object once we are deleting it. */
if (Header->CloseInProcess)
{
KEBUGCHECK(0);
}
- InterlockedIncrement(&Header->RefCount);
- ObpPerformRetentionChecksDpcLevel(Header);
+ (VOID)InterlockedIncrement(&Header->RefCount);
}
ObfDereferenceObject(IN PVOID Object)
{
POBJECT_HEADER Header;
- extern POBJECT_TYPE PsProcessType;
+ LONG NewRefCount;
+ BOOL Permanent;
+ ULONG HandleCount;
- assert(Object);
+ ASSERT(Object);
+ /* Extract the object header. */
Header = BODY_TO_HEADER(Object);
-
- if (Header->ObjectType == PsProcessType)
+ Permanent = Header->Permanent;
+ HandleCount = Header->HandleCount;
+
+ /*
+ Drop our reference and get the new count so we can tell if this was the
+ last reference.
+ */
+ NewRefCount = InterlockedDecrement(&Header->RefCount);
+ ASSERT(NewRefCount >= 0);
+
+ /* Check whether the object can now be deleted. */
+ if (NewRefCount == 0 &&
+ HandleCount == 0 &&
+ !Permanent)
{
- DPRINT("Deref p 0x%x with refcount %d type %x ",
- Object, Header->RefCount, PsProcessType);
- DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
+ ObpDeleteObjectDpcLevel(Header, NewRefCount);
}
-
- if (Header->ObjectType == PsThreadType)
- {
- DPRINT("Deref t 0x%x with refcount %d type %x ",
- Object, Header->RefCount, PsThreadType);
- DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
- }
-
- InterlockedDecrement(&Header->RefCount);
-
- ObpPerformRetentionChecksDpcLevel(Header);
}
ObGetObjectPointerCount(PVOID Object)
{
POBJECT_HEADER Header;
+
+ PAGED_CODE();
- assert(Object);
+ ASSERT(Object);
Header = BODY_TO_HEADER(Object);
- return(Header->RefCount);
+ return Header->RefCount;
}
ObGetObjectHandleCount(PVOID Object)
{
POBJECT_HEADER Header;
+
+ PAGED_CODE();
- assert(Object);
+ ASSERT(Object);
Header = BODY_TO_HEADER(Object);
- return(Header->HandleCount);
+ return Header->HandleCount;
}