static VOID GdiPoolDeleteSection(PGDI_POOL pPool, PGDI_POOL_SECTION pSection) { NTSTATUS status; SIZE_T cjSize = 0; /* Should not have any allocations */ if (pSection->cAllocCount != 0) { DPRINT1("There are %lu allocations left, section=%p, pool=%p\n", pSection->cAllocCount, pSection, pPool); DBG_DUMP_EVENT_LIST(&pPool->slhLog); ASSERT(FALSE); } /* Release the virtual memory */ status = ZwFreeVirtualMemory(NtCurrentProcess(), &pSection->pvBaseAddress, &cjSize, MEM_RELEASE); ASSERT(NT_SUCCESS(status)); /* Free the section object */ EngFreeMem(pSection); }
VOID NTAPI DbgDumpLockedGdiHandles() { #if 0 ULONG i; for (i = RESERVE_ENTRIES_COUNT; i < GDI_HANDLE_COUNT; i++) { PENTRY pentry = &gpentHmgr[i]; if (pentry->Objt) { POBJ pobj = pentry->einfo.pobj; if (pobj->cExclusiveLock > 0) { DPRINT1("Locked object: %lx, type = %lx. allocated from:\n", i, pentry->Objt); DBG_DUMP_EVENT_LIST(&pobj->slhLog); } } } #endif }
PVOID NTAPI GdiPoolAllocate( PGDI_POOL pPool) { PGDI_POOL_SECTION pSection; ULONG ulIndex, cjOffset, ulPageBit; PLIST_ENTRY ple; PVOID pvAlloc, pvBaseAddress; SIZE_T cjSize; NTSTATUS status; /* Disable APCs and acquire the pool lock */ KeEnterCriticalRegion(); ExAcquirePushLockExclusive(&pPool->pushlock); /* Check if we have a ready section */ if (!IsListEmpty(&pPool->leReadyList)) { /* Get a free section */ ple = pPool->leReadyList.Flink; pSection = CONTAINING_RECORD(ple, GDI_POOL_SECTION, leReadyLink); if (pSection->cAllocCount >= pPool->cSlotsPerSection) { DPRINT1("pSection->cAllocCount=%lu, pPool->cSlotsPerSection=%lu\n", pSection->cAllocCount, pPool->cSlotsPerSection); DBG_DUMP_EVENT_LIST(&pPool->slhLog); ASSERT(FALSE); } ASSERT(pSection->cAllocCount < pPool->cSlotsPerSection); } else { /* No, check if we have something on the empty list */ if (!IsListEmpty(&pPool->leEmptyList)) { /* Yes, remove it from the empty list */ ple = RemoveHeadList(&pPool->leEmptyList); pSection = CONTAINING_RECORD(ple, GDI_POOL_SECTION, leInUseLink); pPool->cEmptySections--; ASSERT(pSection->cAllocCount == 0); } else { /* No, allocate a new section */ pSection = GdiPoolAllocateSection(pPool); if (!pSection) { DPRINT1("Couldn't allocate a section\n"); pvAlloc = NULL; goto done; } } /* Insert it into the in-use and ready list */ InsertHeadList(&pPool->leInUseList, &pSection->leInUseLink); InsertHeadList(&pPool->leReadyList, &pSection->leReadyLink); } /* Find and set a single bit */ ulIndex = RtlFindClearBitsAndSet(&pSection->bitmap, 1, 0); ASSERT(ulIndex != MAXULONG); /* Calculate the allocation address */ cjOffset = ulIndex * pPool->cjAllocSize; pvAlloc = (PVOID)((ULONG_PTR)pSection->pvBaseAddress + cjOffset); /* Check if memory is comitted */ ulPageBit = 1 << (cjOffset / PAGE_SIZE); ulPageBit |= 1 << ((cjOffset + pPool->cjAllocSize - 1) / PAGE_SIZE); if ((pSection->ulCommitBitmap & ulPageBit) != ulPageBit) { /* Commit the pages */ pvBaseAddress = PAGE_ALIGN(pvAlloc); cjSize = ADDRESS_AND_SIZE_TO_SPAN_PAGES(pvAlloc, pPool->cjAllocSize) * PAGE_SIZE; status = ZwAllocateVirtualMemory(NtCurrentProcess(), &pvBaseAddress, 0, &cjSize, MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(status)) { pvAlloc = NULL; goto done; } pSection->ulCommitBitmap |= ulPageBit; } /* Increase alloc count */ pSection->cAllocCount++; ASSERT(RtlNumberOfSetBits(&pSection->bitmap) == pSection->cAllocCount); DBG_LOGEVENT(&pPool->slhLog, EVENT_ALLOCATE, pvAlloc); /* Check if section is now busy */ if (pSection->cAllocCount == pPool->cSlotsPerSection) { /* Remove the section from the ready list */ RemoveEntryList(&pSection->leReadyLink); } done: /* Release the pool lock and enable APCs */ ExReleasePushLockExclusive(&pPool->pushlock); KeLeaveCriticalRegion(); DPRINT("GdiPoolallocate: %p\n", pvAlloc); return pvAlloc; }