mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
- Fix kmtest's inclusion of the NDK.
- Implement support for the Handle Count Database. - Don't do anything in IopCloseFile if this isn't the last handle for the process. - Fix definition of OBJECT_HANDLE_COUNT_DATABASE. svn path=/trunk/; revision=25382
This commit is contained in:
parent
a9e4074bd0
commit
a9b16dfb0e
4 changed files with 248 additions and 13 deletions
|
@ -28,12 +28,7 @@
|
|||
//#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
#include "ndk/obtypes.h"
|
||||
#include "ndk/obfuncs.h"
|
||||
|
||||
#include "ndk/ifssupp.h"
|
||||
#include "ndk/setypes.h"
|
||||
#include "ndk/sefuncs.h"
|
||||
#include "ntndk.h"
|
||||
|
||||
// I ment to make this test scalable, but for now
|
||||
// we work with two object types only
|
||||
|
|
|
@ -399,7 +399,7 @@ typedef struct _OBJECT_HANDLE_COUNT_ENTRY
|
|||
typedef struct _OBJECT_HANDLE_COUNT_DATABASE
|
||||
{
|
||||
ULONG CountEntries;
|
||||
POBJECT_HANDLE_COUNT_ENTRY HandleCountEntries[1];
|
||||
OBJECT_HANDLE_COUNT_ENTRY HandleCountEntries[1];
|
||||
} OBJECT_HANDLE_COUNT_DATABASE, *POBJECT_HANDLE_COUNT_DATABASE;
|
||||
|
||||
typedef struct _OBJECT_HEADER_HANDLE_INFO
|
||||
|
|
|
@ -1396,6 +1396,9 @@ IopCloseFile(IN PEPROCESS Process OPTIONAL,
|
|||
KIRQL OldIrql;
|
||||
IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);
|
||||
|
||||
/* If this isn't the last handle for the current process, quit */
|
||||
if (HandleCount != 1) return;
|
||||
|
||||
/* Check if the file is locked and has more then one handle opened */
|
||||
if ((FileObject->LockOperation) && (SystemHandleCount != 1))
|
||||
{
|
||||
|
|
|
@ -19,8 +19,178 @@
|
|||
|
||||
PHANDLE_TABLE ObpKernelHandleTable = NULL;
|
||||
|
||||
#define TAG_OB_HANDLE TAG('O', 'b', 'H', 'd')
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
POBJECT_HANDLE_COUNT_ENTRY
|
||||
NTAPI
|
||||
ObpInsertHandleCount(IN POBJECT_HEADER ObjectHeader)
|
||||
{
|
||||
POBJECT_HEADER_HANDLE_INFO HandleInfo;
|
||||
POBJECT_HANDLE_COUNT_ENTRY FreeEntry;
|
||||
POBJECT_HANDLE_COUNT_DATABASE HandleDatabase, OldHandleDatabase;
|
||||
ULONG i;
|
||||
ULONG Size, OldSize;
|
||||
OBJECT_HANDLE_COUNT_DATABASE SingleDatabase;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Get the handle info */
|
||||
HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader);
|
||||
if (!HandleInfo) return NULL;
|
||||
|
||||
/* Check if we only have one entry */
|
||||
if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS)
|
||||
{
|
||||
/* Fill out the single entry */
|
||||
SingleDatabase.CountEntries = 1;
|
||||
SingleDatabase.HandleCountEntries[0] = HandleInfo->SingleEntry;
|
||||
|
||||
/* Use this as the old size */
|
||||
OldHandleDatabase = &SingleDatabase;
|
||||
OldSize = sizeof(SingleDatabase);
|
||||
|
||||
/* Now we'll have two entries, and an entire DB */
|
||||
i = 2;
|
||||
Size = sizeof(OBJECT_HANDLE_COUNT_DATABASE) +
|
||||
sizeof(OBJECT_HANDLE_COUNT_ENTRY);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We already have a DB, get the information from it */
|
||||
OldHandleDatabase = HandleInfo->HandleCountDatabase;
|
||||
i = OldHandleDatabase->CountEntries;
|
||||
OldSize = sizeof(OBJECT_HANDLE_COUNT_DATABASE) +
|
||||
((i - 1) * sizeof(OBJECT_HANDLE_COUNT_ENTRY));
|
||||
|
||||
/* Add 4 more entries */
|
||||
i += 4;
|
||||
Size = OldSize += (4 * sizeof(OBJECT_HANDLE_COUNT_ENTRY));
|
||||
}
|
||||
|
||||
/* Allocate the DB */
|
||||
HandleDatabase = ExAllocatePoolWithTag(PagedPool, Size, TAG_OB_HANDLE);
|
||||
if (!HandleDatabase) return NULL;
|
||||
|
||||
/* Copy the old database */
|
||||
RtlMoveMemory(HandleDatabase, OldHandleDatabase, OldSize);
|
||||
|
||||
/* Check if we he had a single entry before */
|
||||
if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS)
|
||||
{
|
||||
/* Now we have more */
|
||||
ObjectHeader->Flags &= ~OB_FLAG_SINGLE_PROCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise we had a DB, free it */
|
||||
ExFreePool(OldHandleDatabase);
|
||||
}
|
||||
|
||||
/* Find the end of the copy and zero out the new data */
|
||||
FreeEntry = (PVOID)((ULONG_PTR)HandleDatabase + OldSize);
|
||||
RtlZeroMemory(FreeEntry, Size - OldSize);
|
||||
|
||||
/* Set the new information and return the free entry */
|
||||
HandleDatabase->CountEntries = i;
|
||||
HandleInfo->HandleCountDatabase = HandleDatabase;
|
||||
return FreeEntry;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ObpIncrementHandleDataBase(IN POBJECT_HEADER ObjectHeader,
|
||||
IN PEPROCESS Process,
|
||||
IN OUT PULONG NewProcessHandleCount)
|
||||
{
|
||||
POBJECT_HEADER_HANDLE_INFO HandleInfo;
|
||||
POBJECT_HANDLE_COUNT_ENTRY HandleEntry, FreeEntry = NULL;
|
||||
POBJECT_HANDLE_COUNT_DATABASE HandleDatabase;
|
||||
ULONG i;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Get the handle info and check if we only have one entry */
|
||||
HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader);
|
||||
if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS)
|
||||
{
|
||||
/* Check if the entry is free */
|
||||
if (!HandleInfo->SingleEntry.HandleCount)
|
||||
{
|
||||
/* Add ours */
|
||||
HandleInfo->SingleEntry.HandleCount = 1;
|
||||
HandleInfo->SingleEntry.Process = Process;
|
||||
|
||||
/* Return success and 1 handle */
|
||||
*NewProcessHandleCount = 1;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (HandleInfo->SingleEntry.Process == Process)
|
||||
{
|
||||
/* Busy entry, but same process */
|
||||
*NewProcessHandleCount = ++HandleInfo->SingleEntry.HandleCount;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Insert a new entry */
|
||||
FreeEntry = ObpInsertHandleCount(ObjectHeader);
|
||||
if (!FreeEntry) return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* Fill it out */
|
||||
FreeEntry->Process = Process;
|
||||
FreeEntry->HandleCount = 1;
|
||||
|
||||
/* Return success and 1 handle */
|
||||
*NewProcessHandleCount = 1;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* We have a database instead */
|
||||
HandleDatabase = HandleInfo->HandleCountDatabase;
|
||||
if (HandleDatabase)
|
||||
{
|
||||
/* Get the entries and loop them */
|
||||
i = HandleDatabase->CountEntries;
|
||||
HandleEntry = &HandleDatabase->HandleCountEntries[0];
|
||||
while (i)
|
||||
{
|
||||
/* Check if this is a match */
|
||||
if (HandleEntry->Process == Process)
|
||||
{
|
||||
/* Found it, get the process handle count */
|
||||
*NewProcessHandleCount = ++HandleEntry->HandleCount;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (!HandleEntry->HandleCount)
|
||||
{
|
||||
/* Found a free entry */
|
||||
FreeEntry = HandleEntry;
|
||||
}
|
||||
|
||||
/* Keep looping */
|
||||
HandleEntry++;
|
||||
i--;
|
||||
}
|
||||
|
||||
/* Check if we couldn't find a free entry */
|
||||
if (!FreeEntry)
|
||||
{
|
||||
/* Allocate one */
|
||||
FreeEntry = ObpInsertHandleCount(ObjectHeader);
|
||||
if (!FreeEntry) return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Fill out the entry */
|
||||
FreeEntry->Process = Process;
|
||||
FreeEntry->HandleCount = 1;
|
||||
*NewProcessHandleCount = 1;
|
||||
}
|
||||
|
||||
/* Return success if we got here */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ObpChargeQuotaForObject(IN POBJECT_HEADER ObjectHeader,
|
||||
|
@ -101,6 +271,10 @@ ObpDecrementHandleCount(IN PVOID ObjectBody,
|
|||
LONG NewCount;
|
||||
POBJECT_HEADER_CREATOR_INFO CreatorInfo;
|
||||
KIRQL CalloutIrql;
|
||||
POBJECT_HEADER_HANDLE_INFO HandleInfo;
|
||||
POBJECT_HANDLE_COUNT_ENTRY HandleEntry;
|
||||
POBJECT_HANDLE_COUNT_DATABASE HandleDatabase;
|
||||
ULONG i;
|
||||
|
||||
/* Get the object type and header */
|
||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
|
||||
|
@ -138,8 +312,53 @@ ObpDecrementHandleCount(IN PVOID ObjectBody,
|
|||
/* Is the object type keeping track of handles? */
|
||||
if (ObjectType->TypeInfo.MaintainHandleCount)
|
||||
{
|
||||
/* FIXME */
|
||||
DPRINT("Handle Database not yet implemented\n");
|
||||
/* Get handle information */
|
||||
HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader);
|
||||
|
||||
/* Check if there's only a single entry */
|
||||
if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS)
|
||||
{
|
||||
/* It should be us */
|
||||
ASSERT(HandleInfo->SingleEntry.Process == Process);
|
||||
ASSERT(HandleInfo->SingleEntry.HandleCount > 0);
|
||||
|
||||
/* Get the handle counts */
|
||||
ProcessHandleCount = HandleInfo->SingleEntry.HandleCount--;
|
||||
HandleEntry = &HandleInfo->SingleEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, get the database */
|
||||
HandleDatabase = HandleInfo->HandleCountDatabase;
|
||||
if (HandleDatabase)
|
||||
{
|
||||
/* Get the entries and loop them */
|
||||
i = HandleDatabase->CountEntries;
|
||||
HandleEntry = &HandleDatabase->HandleCountEntries[0];
|
||||
while (i)
|
||||
{
|
||||
/* Check if this is a match */
|
||||
if ((HandleEntry->HandleCount) &&
|
||||
(HandleEntry->Process == Process))
|
||||
{
|
||||
/* Found it, get the process handle count */
|
||||
ProcessHandleCount = HandleEntry->HandleCount--;
|
||||
}
|
||||
|
||||
/* Keep looping */
|
||||
HandleEntry++;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if this is the last handle */
|
||||
if (ProcessHandleCount == 1)
|
||||
{
|
||||
/* Then clear the entry */
|
||||
HandleEntry->Process = NULL;
|
||||
HandleEntry->HandleCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the lock */
|
||||
|
@ -461,8 +680,17 @@ ObpIncrementHandleCount(IN PVOID Object,
|
|||
/* Check if we have a handle database */
|
||||
if (ObjectType->TypeInfo.MaintainHandleCount)
|
||||
{
|
||||
/* FIXME: TODO */
|
||||
DPRINT("Handle DB not yet supported\n");
|
||||
/* Increment the handle database */
|
||||
Status = ObpIncrementHandleDataBase(ObjectHeader,
|
||||
Process,
|
||||
&ProcessHandleCount);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* FIXME: This should never happen for now */
|
||||
DPRINT1("Unhandled case\n");
|
||||
KEBUGCHECK(0);
|
||||
goto Quickie;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the lock */
|
||||
|
@ -672,8 +900,17 @@ ObpIncrementUnnamedHandleCount(IN PVOID Object,
|
|||
/* Check if we have a handle database */
|
||||
if (ObjectType->TypeInfo.MaintainHandleCount)
|
||||
{
|
||||
/* FIXME: TODO */
|
||||
DPRINT("Handle DB not yet supported\n");
|
||||
/* Increment the handle database */
|
||||
Status = ObpIncrementHandleDataBase(ObjectHeader,
|
||||
Process,
|
||||
&ProcessHandleCount);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* FIXME: This should never happen for now */
|
||||
DPRINT1("Unhandled case\n");
|
||||
KEBUGCHECK(0);
|
||||
goto Quickie;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the lock */
|
||||
|
|
Loading…
Reference in a new issue