mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
Issue a work item only if an object will be deleted.
Fixes bug #14. svn path=/trunk/; revision=6469
This commit is contained in:
parent
d6e366fb65
commit
bd908afdf1
1 changed files with 90 additions and 75 deletions
|
@ -1,4 +1,4 @@
|
|||
/* $Id: object.c,v 1.70 2003/10/04 20:26:45 ekohl Exp $
|
||||
/* $Id: object.c,v 1.71 2003/10/30 21:34:54 ekohl Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -25,6 +25,13 @@
|
|||
#include <internal/debug.h>
|
||||
|
||||
|
||||
typedef struct _RETENTION_CHECK_PARAMS
|
||||
{
|
||||
WORK_QUEUE_ITEM WorkItem;
|
||||
POBJECT_HEADER ObjectHeader;
|
||||
} RETENTION_CHECK_PARAMS, *PRETENTION_CHECK_PARAMS;
|
||||
|
||||
|
||||
/* FUNCTIONS ************************************************************/
|
||||
|
||||
PVOID HEADER_TO_BODY(POBJECT_HEADER obj)
|
||||
|
@ -472,8 +479,8 @@ ObReferenceObjectByPointer(IN PVOID Object,
|
|||
{
|
||||
POBJECT_HEADER Header;
|
||||
|
||||
// DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
|
||||
// Object,ObjectType);
|
||||
DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
|
||||
Object,ObjectType);
|
||||
|
||||
Header = BODY_TO_HEADER(Object);
|
||||
|
||||
|
@ -559,64 +566,34 @@ ObOpenObjectByPointer(IN POBJECT Object,
|
|||
static NTSTATUS
|
||||
ObpPerformRetentionChecks(POBJECT_HEADER Header)
|
||||
{
|
||||
// DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
|
||||
// Header,Header->RefCount,Header->HandleCount);
|
||||
if(KeGetCurrentIrql() != PASSIVE_LEVEL)
|
||||
{
|
||||
DPRINT("ObpPerformRetentionChecks called at an unsupported IRQL. Use ObpPerformRetentionChecksDpcLevel instead.\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
DPRINT("ObPerformRetentionChecks(Header %p)\n", Header);
|
||||
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
|
||||
{
|
||||
DPRINT("ObpPerformRetentionChecks called at an unsupported IRQL. Use ObpPerformRetentionChecksDpcLevel instead.\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
|
||||
if (Header->RefCount < 0)
|
||||
if (Header->ObjectType != NULL &&
|
||||
Header->ObjectType->Delete != NULL)
|
||||
{
|
||||
CPRINT("Object %x/%x has invalid reference count (%d)\n",
|
||||
Header, HEADER_TO_BODY(Header), Header->RefCount);
|
||||
KEBUGCHECK(0);
|
||||
Header->ObjectType->Delete(HEADER_TO_BODY(Header));
|
||||
}
|
||||
if (Header->HandleCount < 0)
|
||||
|
||||
if (Header->Name.Buffer != NULL)
|
||||
{
|
||||
CPRINT("Object %x/%x has invalid handle count (%d)\n",
|
||||
Header, HEADER_TO_BODY(Header), Header->HandleCount);
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
if (Header->RefCount == 0 &&
|
||||
Header->HandleCount == 0 &&
|
||||
Header->Permanent == FALSE)
|
||||
{
|
||||
if (Header->CloseInProcess)
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
Header->CloseInProcess = TRUE;
|
||||
if (Header->ObjectType != NULL &&
|
||||
Header->ObjectType->Delete != NULL)
|
||||
{
|
||||
Header->ObjectType->Delete(HEADER_TO_BODY(Header));
|
||||
}
|
||||
if (Header->Name.Buffer != NULL)
|
||||
{
|
||||
ObpRemoveEntryDirectory(Header);
|
||||
RtlFreeUnicodeString(&Header->Name);
|
||||
}
|
||||
DPRINT("ObPerformRetentionChecks() = Freeing object\n");
|
||||
ExFreePool(Header);
|
||||
ObpRemoveEntryDirectory(Header);
|
||||
RtlFreeUnicodeString(&Header->Name);
|
||||
}
|
||||
|
||||
DPRINT("ObPerformRetentionChecks() = Freeing object\n");
|
||||
ExFreePool(Header);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
typedef struct _RETENTION_CHECK_PARAMS {
|
||||
WORK_QUEUE_ITEM WorkItem;
|
||||
POBJECT_HEADER ObjectHeader;
|
||||
} RETENTION_CHECK_PARAMS, *PRETENTION_CHECK_PARAMS;
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
ObpPerformRetentionChecksWorkRoutine(
|
||||
IN PVOID Parameter
|
||||
)
|
||||
VOID STDCALL
|
||||
ObpPerformRetentionChecksWorkRoutine (IN PVOID Parameter)
|
||||
{
|
||||
PRETENTION_CHECK_PARAMS Params = (PRETENTION_CHECK_PARAMS)Parameter;
|
||||
/* ULONG Tag; */ /* See below */
|
||||
|
@ -631,33 +608,70 @@ ObpPerformRetentionChecksWorkRoutine(
|
|||
/* ExFreePoolWithTag(Params, Tag); */
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
ObpPerformRetentionChecksDpcLevel(IN POBJECT_HEADER ObjectHeader)
|
||||
{
|
||||
switch(KeGetCurrentIrql()) {
|
||||
if (ObjectHeader->RefCount < 0)
|
||||
{
|
||||
CPRINT("Object %p/%p has invalid reference count (%d)\n",
|
||||
ObjectHeader, HEADER_TO_BODY(ObjectHeader), ObjectHeader->RefCount);
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
case PASSIVE_LEVEL:
|
||||
return ObpPerformRetentionChecks(ObjectHeader);
|
||||
if (ObjectHeader->HandleCount < 0)
|
||||
{
|
||||
CPRINT("Object %p/%p has invalid handle count (%d)\n",
|
||||
ObjectHeader, HEADER_TO_BODY(ObjectHeader), ObjectHeader->HandleCount);
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
case APC_LEVEL:
|
||||
case DISPATCH_LEVEL:
|
||||
{
|
||||
/* Can we get rid of this NonPagedPoolMustSucceed call and still be a 'must succeed' function? I don't like to bugcheck on no memory! */
|
||||
PRETENTION_CHECK_PARAMS 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;
|
||||
if (ObjectHeader->RefCount == 0 &&
|
||||
ObjectHeader->HandleCount == 0 &&
|
||||
ObjectHeader->Permanent == FALSE)
|
||||
{
|
||||
if (ObjectHeader->CloseInProcess)
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
ObjectHeader->CloseInProcess = TRUE;
|
||||
|
||||
default:
|
||||
DPRINT("ObpPerformRetentionChecksDpcLevel called at unsupported IRQL %u!\n", KeGetCurrentIrql());
|
||||
KEBUGCHECK(0);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -687,9 +701,9 @@ ObfReferenceObject(IN PVOID Object)
|
|||
Header = BODY_TO_HEADER(Object);
|
||||
|
||||
if (Header->CloseInProcess)
|
||||
{
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
InterlockedIncrement(&Header->RefCount);
|
||||
|
||||
ObpPerformRetentionChecksDpcLevel(Header);
|
||||
|
@ -728,15 +742,16 @@ ObfDereferenceObject(IN PVOID Object)
|
|||
Object, Header->RefCount, PsProcessType);
|
||||
DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue