| 565 | } |
| 566 | |
| 567 | static PDETOUR_TRAMPOLINE DetourAllocTrampoline(PUCHAR pTarget) { |
| 568 | PDETOUR_TRAMPOLINE pTrampoline = nullptr; |
| 569 | |
| 570 | // Insure that there is a default region. |
| 571 | if (s_pRegion == nullptr && s_pRegions != nullptr) { |
| 572 | s_pRegion = s_pRegions; |
| 573 | } |
| 574 | |
| 575 | // First check the default region for an valid free block. |
| 576 | if (s_pRegion != nullptr && s_pRegion->pFree != nullptr) { |
| 577 | |
| 578 | found_region: |
| 579 | pTrampoline = s_pRegion->pFree; |
| 580 | s_pRegion->pFree = (PDETOUR_TRAMPOLINE)pTrampoline->pRemain; |
| 581 | memset(pTrampoline, 0xcc, sizeof(*pTrampoline)); |
| 582 | return pTrampoline; |
| 583 | } |
| 584 | |
| 585 | // Then check the existing regions for a valid free block. |
| 586 | for (s_pRegion = s_pRegions; s_pRegion != nullptr; s_pRegion = s_pRegion->pNext) { |
| 587 | if (s_pRegion != nullptr && s_pRegion->pFree != nullptr) { |
| 588 | goto found_region; |
| 589 | } |
| 590 | } |
| 591 | |
| 592 | // We need to allocate a new region. |
| 593 | |
| 594 | // Round pTarget down to 64KB block. |
| 595 | // /RTCc RuntimeChecks breaks PtrToUlong. |
| 596 | pTarget = pTarget - (ULONG)((ULONG_PTR)pTarget & 0xffff); |
| 597 | |
| 598 | PVOID pNewlyAllocated = DetourAllocTrampolineAllocateNew(pTarget, nullptr, nullptr); |
| 599 | if (pNewlyAllocated != nullptr) { |
| 600 | s_pRegion = (DETOUR_REGION*)pNewlyAllocated; |
| 601 | s_pRegion->Signature = DETOUR_REGION_SIGNATURE; |
| 602 | s_pRegion->pFree = NULL; |
| 603 | s_pRegion->pNext = s_pRegions; |
| 604 | s_pRegions = s_pRegion; |
| 605 | LogDebug(" Allocated region %p..%p\n\n", |
| 606 | s_pRegion, ((PUCHAR)s_pRegion) + DETOUR_REGION_SIZE - 1); |
| 607 | |
| 608 | // Put everything but the first trampoline on the free list. |
| 609 | PUCHAR pFree = NULL; |
| 610 | pTrampoline = ((PDETOUR_TRAMPOLINE)s_pRegion) + 1; |
| 611 | for (int i = DETOUR_TRAMPOLINES_PER_REGION - 1; i > 1; i--) { |
| 612 | pTrampoline[i].pRemain = pFree; |
| 613 | pFree = (PUCHAR)&pTrampoline[i]; |
| 614 | } |
| 615 | s_pRegion->pFree = (PDETOUR_TRAMPOLINE)pFree; |
| 616 | goto found_region; |
| 617 | } |
| 618 | |
| 619 | LogError("Couldn't find available memory region!\n"); |
| 620 | return nullptr; |
| 621 | } |
| 622 | |
| 623 | static bool DetourIsRegionEmpty(PDETOUR_REGION pRegion) { |
| 624 | // Stop if the region isn't a region (this would be bad). |
no test coverage detected