| 397 | |
| 398 | for (ULONG_PTR BaseAddress = BasePage; BaseAddress <= LastPage; BaseAddress += PageSize) |
| 399 | UnmapViewOfFile2(hProcess, (PVOID)BaseAddress, MEM_PRESERVE_PLACEHOLDER); |
| 400 | |
| 401 | if (dwFreeType == MEM_DECOMMIT) |
| 402 | return TRUE; |
| 403 | |
| 404 | BOOL Status; |
| 405 | VirtualFreeEx(hProcess, lpAddress, dwSize, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); |
| 406 | AcquireSRWLockExclusive(&XwpMappableLock); |
| 407 | Status = VirtualFreeEx(hProcess, lpAddress, 0, MEM_RELEASE); |
| 408 | if (Status) |
| 409 | XwpMappables.erase((ULONG_PTR)AllocationBase); |
| 410 | ReleaseSRWLockExclusive(&XwpMappableLock); |
| 411 | return Status; |
| 412 | } |
| 413 | |
| 414 | return VirtualFreeEx(hProcess, lpAddress, dwSize, dwFreeType); |
| 415 | } |
| 416 | |
| 417 | EXTERN_C BOOL __stdcall EraVirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType) |
| 418 | { |
| 419 | return EraVirtualFreeEx(GetCurrentProcess(), lpAddress, dwSize, dwFreeType); |
| 420 | } |
| 421 | |
| 422 | EXTERN_C SIZE_T __stdcall EraVirtualQueryEx(HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, |
| 423 | SIZE_T dwLength) |
| 424 | { |
| 425 | LPVOID AllocationBase; |
| 426 | MAPPABLE_MEM Mappable; |
| 427 | |
| 428 | if (!lpBuffer || dwLength < sizeof(*lpBuffer)) |
| 429 | return 0; |
| 430 | |
| 431 | AcquireSRWLockShared(&XwpMappableLock); |
| 432 | AllocationBase = MappableQuery(lpAddress, &Mappable); |
| 433 | ReleaseSRWLockShared(&XwpMappableLock); |
| 434 | |
| 435 | // Mappable memory requires special handling because of placeholder splits. |
| 436 | // VirtualQuery will normally only report on pages that belong to the same allocation. |
| 437 | if (AllocationBase) |
| 438 | { |
| 439 | MEMORY_BASIC_INFORMATION Region; |
| 440 | ULONG_PTR PageSize = Mappable.Is4MBPages ? PAGE_SIZE_2MB : PAGE_SIZE_4KB; |
| 441 | ULONG_PTR BasePage = (ULONG_PTR)lpAddress & ~(PageSize - 1); |
| 442 | ULONG_PTR ByteSize = Mappable.RegionSize - ((ULONG_PTR)BasePage - (ULONG_PTR)AllocationBase); |
| 443 | ULONG_PTR LastPage = ((ULONG_PTR)lpAddress + ByteSize) & ~(PageSize - 1); |
| 444 | |
| 445 | if (!VirtualQueryEx(hProcess, (LPCVOID)BasePage, &Region, sizeof(Region))) |
| 446 | return 0; |
| 447 | |
| 448 | lpBuffer->BaseAddress = (PVOID)BasePage; |
| 449 | lpBuffer->AllocationBase = AllocationBase; |
| 450 | lpBuffer->AllocationProtect = Region.AllocationProtect; |
| 451 | lpBuffer->PartitionId = Region.PartitionId; |
| 452 | lpBuffer->RegionSize = PageSize; |
| 453 | lpBuffer->State = Region.State; |
| 454 | lpBuffer->Protect = Region.Protect; |
| 455 | lpBuffer->Type = Region.Type; |
| 456 |
no test coverage detected