mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
233 lines
6.4 KiB
C
233 lines
6.4 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS system libraries
|
|
* PURPOSE: Handle table
|
|
* FILE: lib/rtl/handle.c
|
|
* PROGRAMMER: Eric Kohl
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include <rtl.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* GLOBALS ******************************************************************/
|
|
|
|
VOID
|
|
NTAPI
|
|
RtlInitializeHandleTable(
|
|
ULONG TableSize,
|
|
ULONG HandleSize,
|
|
PRTL_HANDLE_TABLE HandleTable)
|
|
{
|
|
/* Initialize handle table */
|
|
memset(HandleTable, 0, sizeof(RTL_HANDLE_TABLE));
|
|
HandleTable->MaximumNumberOfHandles = TableSize;
|
|
HandleTable->SizeOfHandleTableEntry = HandleSize;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID
|
|
NTAPI
|
|
RtlDestroyHandleTable(
|
|
PRTL_HANDLE_TABLE HandleTable)
|
|
{
|
|
PVOID ArrayPointer;
|
|
SIZE_T ArraySize = 0;
|
|
|
|
/* free handle array */
|
|
if (HandleTable->CommittedHandles)
|
|
{
|
|
ArrayPointer = (PVOID)HandleTable->CommittedHandles;
|
|
NtFreeVirtualMemory(NtCurrentProcess(),
|
|
&ArrayPointer,
|
|
&ArraySize,
|
|
MEM_RELEASE);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
PRTL_HANDLE_TABLE_ENTRY
|
|
NTAPI
|
|
RtlAllocateHandle(
|
|
PRTL_HANDLE_TABLE HandleTable,
|
|
PULONG Index)
|
|
{
|
|
PRTL_HANDLE_TABLE_ENTRY CurrentEntry, NextEntry;
|
|
NTSTATUS Status;
|
|
PRTL_HANDLE_TABLE_ENTRY HandleEntry;
|
|
PVOID ArrayPointer;
|
|
SIZE_T ArraySize;
|
|
ULONG i, NumberOfEntries;
|
|
|
|
/* Check if we are out of free handles entries */
|
|
if (HandleTable->FreeHandles == NULL)
|
|
{
|
|
/* Check if we don't have uncomitted handle entries yet */
|
|
if (HandleTable->UnCommittedHandles == NULL)
|
|
{
|
|
/* Use the maximum number of handle entries */
|
|
ArraySize = HandleTable->SizeOfHandleTableEntry * HandleTable->MaximumNumberOfHandles;
|
|
ArrayPointer = NULL;
|
|
|
|
/* Reserve memory */
|
|
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
|
|
&ArrayPointer,
|
|
0,
|
|
&ArraySize,
|
|
MEM_RESERVE,
|
|
PAGE_READWRITE);
|
|
if (!NT_SUCCESS(Status))
|
|
return NULL;
|
|
|
|
/* Update handle array pointers */
|
|
HandleTable->CommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer;
|
|
HandleTable->UnCommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer;
|
|
HandleTable->MaxReservedHandles = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)ArrayPointer + ArraySize);
|
|
}
|
|
|
|
/* Commit one reserved handle entry page */
|
|
ArraySize = PAGE_SIZE;
|
|
ArrayPointer = HandleTable->UnCommittedHandles;
|
|
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
|
|
&ArrayPointer,
|
|
0,
|
|
&ArraySize,
|
|
MEM_COMMIT,
|
|
PAGE_READWRITE);
|
|
if (!NT_SUCCESS(Status))
|
|
return NULL;
|
|
|
|
/* Update handle array pointers */
|
|
HandleTable->FreeHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer;
|
|
HandleTable->UnCommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)ArrayPointer + ArraySize);
|
|
|
|
/* Calculate the number of entries we can store in the array */
|
|
NumberOfEntries = ArraySize / HandleTable->SizeOfHandleTableEntry;
|
|
|
|
/* Loop all entries, except the last one */
|
|
CurrentEntry = HandleTable->FreeHandles;
|
|
for (i = 0; i < NumberOfEntries - 1; i++)
|
|
{
|
|
/* Calculate the address of the next handle entry */
|
|
NextEntry = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)CurrentEntry +
|
|
HandleTable->SizeOfHandleTableEntry);
|
|
|
|
/* Link the next entry */
|
|
CurrentEntry->NextFree = NextEntry;
|
|
|
|
/* Continue with the next entry */
|
|
CurrentEntry = NextEntry;
|
|
}
|
|
|
|
/* CurrentEntry now points to the last entry, terminate the list here */
|
|
CurrentEntry->NextFree = NULL;
|
|
}
|
|
|
|
/* remove handle from free list */
|
|
HandleEntry = HandleTable->FreeHandles;
|
|
HandleTable->FreeHandles = HandleEntry->NextFree;
|
|
HandleEntry->NextFree = NULL;
|
|
|
|
if (Index)
|
|
{
|
|
*Index = ((ULONG)((ULONG_PTR)HandleEntry - (ULONG_PTR)HandleTable->CommittedHandles) /
|
|
HandleTable->SizeOfHandleTableEntry);
|
|
}
|
|
|
|
return HandleEntry;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOLEAN
|
|
NTAPI
|
|
RtlFreeHandle(
|
|
PRTL_HANDLE_TABLE HandleTable,
|
|
PRTL_HANDLE_TABLE_ENTRY Handle)
|
|
{
|
|
#if DBG
|
|
/* check if handle is valid */
|
|
if (!RtlIsValidHandle(HandleTable, Handle))
|
|
{
|
|
DPRINT1("Invalid Handle! HandleTable=0x%p, Handle=0x%p, Handle->Flags=0x%x\n",
|
|
HandleTable, Handle, Handle ? Handle->Flags : 0);
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
/* clear handle */
|
|
memset(Handle, 0, HandleTable->SizeOfHandleTableEntry);
|
|
|
|
/* add handle to free list */
|
|
Handle->NextFree = HandleTable->FreeHandles;
|
|
HandleTable->FreeHandles = Handle;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOLEAN
|
|
NTAPI
|
|
RtlIsValidHandle(
|
|
PRTL_HANDLE_TABLE HandleTable,
|
|
PRTL_HANDLE_TABLE_ENTRY Handle)
|
|
{
|
|
if ((HandleTable != NULL)
|
|
&& (Handle >= HandleTable->CommittedHandles)
|
|
&& (Handle < HandleTable->MaxReservedHandles)
|
|
&& (Handle->Flags & RTL_HANDLE_VALID))
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOLEAN
|
|
NTAPI
|
|
RtlIsValidIndexHandle(
|
|
IN PRTL_HANDLE_TABLE HandleTable,
|
|
IN ULONG Index,
|
|
OUT PRTL_HANDLE_TABLE_ENTRY *Handle)
|
|
{
|
|
PRTL_HANDLE_TABLE_ENTRY InternalHandle;
|
|
|
|
DPRINT("RtlIsValidIndexHandle(HandleTable %p Index 0x%lx Handle %p)\n", HandleTable, Index, Handle);
|
|
|
|
if (HandleTable == NULL)
|
|
return FALSE;
|
|
|
|
DPRINT("Handles %p HandleSize 0x%lx\n",
|
|
HandleTable->CommittedHandles, HandleTable->SizeOfHandleTableEntry);
|
|
|
|
InternalHandle = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)HandleTable->CommittedHandles +
|
|
(HandleTable->SizeOfHandleTableEntry * Index));
|
|
if (!RtlIsValidHandle(HandleTable, InternalHandle))
|
|
return FALSE;
|
|
|
|
DPRINT("InternalHandle %p\n", InternalHandle);
|
|
|
|
if (Handle != NULL)
|
|
*Handle = InternalHandle;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* EOF */
|