/* * 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 #define NDEBUG #include /* 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 uncommitted 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 */