summaryrefslogtreecommitdiffstats
path: root/private/ntos/rtl/handle.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/rtl/handle.c')
-rw-r--r--private/ntos/rtl/handle.c228
1 files changed, 228 insertions, 0 deletions
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;
+ }
+}