From: Timo Kreuzer Date: Tue, 18 Dec 2012 10:10:34 +0000 (+0000) Subject: [RTL] X-Git-Tag: backups/ros-csrss@60644~104^2~90 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=be5ff02f5e65b0736b675c79812aa84dac23b979;ds=sidebyside [RTL] - Implement dynamic allocation of handle entry pages in RtlAllocateHandle - Fix a possible NULL pointer dereference svn path=/trunk/; revision=57942 --- diff --git a/reactos/lib/rtl/handle.c b/reactos/lib/rtl/handle.c index 4209a0033b7..7e884dc12b6 100644 --- a/reactos/lib/rtl/handle.c +++ b/reactos/lib/rtl/handle.c @@ -60,66 +60,89 @@ RtlAllocateHandle( PRTL_HANDLE_TABLE HandleTable, PULONG Index) { - PRTL_HANDLE_TABLE_ENTRY *pp_new, *pph, ph; + PRTL_HANDLE_TABLE_ENTRY CurrentEntry, NextEntry; NTSTATUS Status; - PRTL_HANDLE_TABLE_ENTRY retval; + PRTL_HANDLE_TABLE_ENTRY HandleEntry; PVOID ArrayPointer; SIZE_T ArraySize; + ULONG i, NumberOfEntries; - pp_new = &HandleTable->FreeHandles; - + /* Check if we are out of free handles entries */ if (HandleTable->FreeHandles == NULL) { - /* no free handle available */ + /* Check if we don't have uncomitted handle entries yet */ if (HandleTable->UnCommittedHandles == NULL) { - /* allocate handle array */ + /* Use the maximum number of handle entries */ ArraySize = HandleTable->SizeOfHandleTableEntry * HandleTable->MaximumNumberOfHandles; ArrayPointer = NULL; - /* FIXME - only reserve handles here! */ - Status = NtAllocateVirtualMemory(NtCurrentProcess(), - (PVOID*)&ArrayPointer, + /* Reserve memory */ + Status = ZwAllocateVirtualMemory(NtCurrentProcess(), + &ArrayPointer, 0, &ArraySize, - MEM_RESERVE | MEM_COMMIT, + MEM_RESERVE, PAGE_READWRITE); if (!NT_SUCCESS(Status)) return NULL; - /* update handle array pointers */ - HandleTable->FreeHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer; - HandleTable->MaxReservedHandles = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)ArrayPointer + ArraySize); - HandleTable->CommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer; + /* Update handle array pointers */ HandleTable->UnCommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer; + HandleTable->MaxReservedHandles = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)ArrayPointer + ArraySize); } - /* FIXME - should check if handles need to be committed */ - - /* build free list in handle array */ - ph = HandleTable->FreeHandles; - pph = pp_new; - while (ph < HandleTable->MaxReservedHandles) + /* 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->CommittedHandles = (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++) { - *pph = ph; - pph = &ph->NextFree; - ph = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)ph + HandleTable->SizeOfHandleTableEntry); + /* 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; } - *pph = 0; + + /* CurrentEntry now points to the last entry, terminate the list here */ + CurrentEntry->NextFree = NULL; } /* remove handle from free list */ - retval = *pp_new; - *pp_new = retval->NextFree; - retval->NextFree = NULL; + HandleEntry = HandleTable->FreeHandles; + HandleTable->FreeHandles = HandleEntry->NextFree; + HandleEntry->NextFree = NULL; if (Index) { - *Index = ((ULONG)((ULONG_PTR)retval - (ULONG_PTR)HandleTable->CommittedHandles) / + *Index = ((ULONG)((ULONG_PTR)HandleEntry - (ULONG_PTR)HandleTable->CommittedHandles) / HandleTable->SizeOfHandleTableEntry); } - return retval; + return HandleEntry; }