- Implement dynamic allocation of handle entry pages in RtlAllocateHandle
- Fix a possible NULL pointer dereference

svn path=/trunk/; revision=57942
This commit is contained in:
Timo Kreuzer 2012-12-18 10:10:34 +00:00
parent 2cdf5f5ce0
commit be5ff02f5e

View file

@ -60,66 +60,89 @@ RtlAllocateHandle(
PRTL_HANDLE_TABLE HandleTable, PRTL_HANDLE_TABLE HandleTable,
PULONG Index) PULONG Index)
{ {
PRTL_HANDLE_TABLE_ENTRY *pp_new, *pph, ph; PRTL_HANDLE_TABLE_ENTRY CurrentEntry, NextEntry;
NTSTATUS Status; NTSTATUS Status;
PRTL_HANDLE_TABLE_ENTRY retval; PRTL_HANDLE_TABLE_ENTRY HandleEntry;
PVOID ArrayPointer; PVOID ArrayPointer;
SIZE_T ArraySize; SIZE_T ArraySize;
ULONG i, NumberOfEntries;
pp_new = &HandleTable->FreeHandles; /* Check if we are out of free handles entries */
if (HandleTable->FreeHandles == NULL) if (HandleTable->FreeHandles == NULL)
{ {
/* no free handle available */ /* Check if we don't have uncomitted handle entries yet */
if (HandleTable->UnCommittedHandles == NULL) if (HandleTable->UnCommittedHandles == NULL)
{ {
/* allocate handle array */ /* Use the maximum number of handle entries */
ArraySize = HandleTable->SizeOfHandleTableEntry * HandleTable->MaximumNumberOfHandles; ArraySize = HandleTable->SizeOfHandleTableEntry * HandleTable->MaximumNumberOfHandles;
ArrayPointer = NULL; ArrayPointer = NULL;
/* FIXME - only reserve handles here! */ /* Reserve memory */
Status = NtAllocateVirtualMemory(NtCurrentProcess(), Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
(PVOID*)&ArrayPointer, &ArrayPointer,
0, 0,
&ArraySize, &ArraySize,
MEM_RESERVE | MEM_COMMIT, MEM_RESERVE,
PAGE_READWRITE); PAGE_READWRITE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
return NULL; return NULL;
/* update handle array pointers */ /* 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;
HandleTable->UnCommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer; 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 */ /* 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;
/* build free list in handle array */ /* Update handle array pointers */
ph = HandleTable->FreeHandles; HandleTable->FreeHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer;
pph = pp_new; HandleTable->CommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer;
while (ph < HandleTable->MaxReservedHandles) 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; /* Calculate the address of the next handle entry */
pph = &ph->NextFree; NextEntry = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)CurrentEntry +
ph = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)ph + HandleTable->SizeOfHandleTableEntry); 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 */ /* remove handle from free list */
retval = *pp_new; HandleEntry = HandleTable->FreeHandles;
*pp_new = retval->NextFree; HandleTable->FreeHandles = HandleEntry->NextFree;
retval->NextFree = NULL; HandleEntry->NextFree = NULL;
if (Index) if (Index)
{ {
*Index = ((ULONG)((ULONG_PTR)retval - (ULONG_PTR)HandleTable->CommittedHandles) / *Index = ((ULONG)((ULONG_PTR)HandleEntry - (ULONG_PTR)HandleTable->CommittedHandles) /
HandleTable->SizeOfHandleTableEntry); HandleTable->SizeOfHandleTableEntry);
} }
return retval; return HandleEntry;
} }