From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/rtl/handle.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 private/ntos/rtl/handle.c (limited to 'private/ntos/rtl/handle.c') diff --git a/private/ntos/rtl/handle.c b/private/ntos/rtl/handle.c new file mode 100644 index 000000000..509fb4300 --- /dev/null +++ b/private/ntos/rtl/handle.c @@ -0,0 +1,228 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + handle.c + +Abstract: + + This module contains a simple handle allocator for use by the Local and + Global memory allocators. + +Author: + + Steve Wood (stevewo) 25-Jul-1991 + +Revision History: + +--*/ + +#include "ntrtlp.h" + +void +RtlInitializeHandleTable( + IN ULONG MaximumNumberOfHandles, + IN ULONG SizeOfHandleTableEntry, + OUT PRTL_HANDLE_TABLE HandleTable + ) +{ + RtlZeroMemory( HandleTable, sizeof( *HandleTable ) ); + HandleTable->MaximumNumberOfHandles = MaximumNumberOfHandles; + HandleTable->SizeOfHandleTableEntry = SizeOfHandleTableEntry; + + return; +} + +NTSTATUS +RtlDestroyHandleTable( + IN OUT PRTL_HANDLE_TABLE HandleTable + ) +{ + NTSTATUS Status; + PVOID BaseAddress; + ULONG ReserveSize; + + BaseAddress = HandleTable->CommittedHandles; + ReserveSize = (PUCHAR)(HandleTable->MaxReservedHandles) - + (PUCHAR)(HandleTable->CommittedHandles); + + Status = NtFreeVirtualMemory( NtCurrentProcess(), + &BaseAddress, + &ReserveSize, + MEM_RELEASE + ); + return Status; +} + +PRTL_HANDLE_TABLE_ENTRY +RtlAllocateHandle( + IN PRTL_HANDLE_TABLE HandleTable, + OUT PULONG HandleIndex OPTIONAL + ) +{ + NTSTATUS Status; + PVOID BaseAddress; + ULONG n, ReserveSize, CommitSize; + PRTL_HANDLE_TABLE_ENTRY p, *pp; + + if (HandleTable->FreeHandles == NULL) { + try { + if (HandleTable->UnCommittedHandles == NULL) { + ReserveSize = HandleTable->MaximumNumberOfHandles * + HandleTable->SizeOfHandleTableEntry; + BaseAddress = NULL; + Status = NtAllocateVirtualMemory( NtCurrentProcess(), + &BaseAddress, + 0, + &ReserveSize, + MEM_RESERVE, + PAGE_READWRITE + ); + + if (NT_SUCCESS( Status )) { + HandleTable->CommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)BaseAddress; + HandleTable->UnCommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)BaseAddress; + HandleTable->MaxReservedHandles = (PRTL_HANDLE_TABLE_ENTRY) + ((PCHAR)BaseAddress + ReserveSize); + } + } + else { + Status = STATUS_SUCCESS; + } + + + if (NT_SUCCESS( Status )) { + p = HandleTable->UnCommittedHandles; + if (p >= HandleTable->MaxReservedHandles) { + Status = STATUS_NO_MEMORY; + } + else { + CommitSize = PAGE_SIZE; + Status = NtAllocateVirtualMemory( NtCurrentProcess(), + (PVOID *)&p, + 0, + &CommitSize, + MEM_COMMIT, + PAGE_READWRITE + ); + if (NT_SUCCESS( Status )) { + HandleTable->UnCommittedHandles = (PRTL_HANDLE_TABLE_ENTRY) + ((PCH)p + CommitSize); + } + } + } + + } + except( EXCEPTION_EXECUTE_HANDLER ) { + Status = GetExceptionCode(); + } + + if (!NT_SUCCESS( Status )) { + return NULL; + } + + pp = &HandleTable->FreeHandles; + while (p < HandleTable->UnCommittedHandles) { + *pp = p; + pp = &p->NextFree; + p = (PRTL_HANDLE_TABLE_ENTRY)((PUCHAR)p + HandleTable->SizeOfHandleTableEntry); + } + } + + // + // Remove handle table entry from head of free list. + // + + p = HandleTable->FreeHandles; + HandleTable->FreeHandles = p->NextFree; + + // + // Clear free list link field, which also leaves the handle allocated bit + // clear. This allows the caller to mark it is allocated after they are + // done filling in their portion. + // + + p->NextFree = NULL; + + + // + // If requested, return the index of this handle table entry + // + if (ARGUMENT_PRESENT( HandleIndex )) { + *HandleIndex = ((ULONG)p - (ULONG)HandleTable->CommittedHandles) / HandleTable->SizeOfHandleTableEntry; + } + + // + // Return a pointer to the handle table entry. + // + + return p; +} + + +BOOLEAN +RtlFreeHandle( + IN PRTL_HANDLE_TABLE HandleTable, + IN PRTL_HANDLE_TABLE_ENTRY Handle + ) +{ +#if DBG + if (!RtlIsValidHandle( HandleTable, Handle )) { + DbgPrint( "RTL: RtlFreeHandle( %lx ) - invalid handle\n", Handle ); + if (NtCurrentPeb()->BeingDebugged) { + DbgBreakPoint(); + } + return FALSE; + } +#endif + + RtlZeroMemory( Handle, HandleTable->SizeOfHandleTableEntry ); + Handle->NextFree = HandleTable->FreeHandles; + HandleTable->FreeHandles = Handle; + return TRUE; +} + + + +BOOLEAN +RtlIsValidHandle( + IN PRTL_HANDLE_TABLE HandleTable, + IN PRTL_HANDLE_TABLE_ENTRY Handle + ) +{ + if (Handle == NULL || + Handle < HandleTable->CommittedHandles || + Handle >= HandleTable->UnCommittedHandles || + (ULONG)Handle & (HandleTable->SizeOfHandleTableEntry - 1) || + !(Handle->Flags & RTL_HANDLE_ALLOCATED) + ) { + return FALSE; + } + else { + return TRUE; + } +} + + +BOOLEAN +RtlIsValidIndexHandle( + IN PRTL_HANDLE_TABLE HandleTable, + IN ULONG HandleIndex, + OUT PRTL_HANDLE_TABLE_ENTRY *Handle + ) +{ + PRTL_HANDLE_TABLE_ENTRY p; + + p = (PRTL_HANDLE_TABLE_ENTRY) + ((PCHAR)HandleTable->CommittedHandles + (HandleIndex * HandleTable->SizeOfHandleTableEntry)); + + if (RtlIsValidHandle( HandleTable, p )) { + *Handle = p; + return TRUE; + } + else { + return FALSE; + } +} -- cgit v1.2.3