26 #define MAX_HEAPS 1000
27 #define WS_REQUEST_COUNT (PAGE_SIZE / sizeof(MEMORY_WORKING_SET_EX_INFORMATION))
46 _In_ ULONG Protection,
47 _Out_writes_(17) PWSTR String
59 if (Protection & PAGE_NOACCESS)
61 else if (Protection & PAGE_READONLY)
63 else if (Protection & PAGE_READWRITE)
65 else if (Protection & PAGE_WRITECOPY)
67 else if (Protection & PAGE_EXECUTE)
69 else if (Protection & PAGE_EXECUTE_READ)
71 else if (Protection & PAGE_EXECUTE_READWRITE)
73 else if (Protection & PAGE_EXECUTE_WRITECOPY)
81 string += base.
Length /
sizeof(WCHAR);
83 if (Protection & PAGE_GUARD)
85 memcpy(
string, L
"+G", 2 * 2);
89 if (Protection & PAGE_NOCACHE)
91 memcpy(
string, L
"+NC", 3 * 2);
95 if (Protection & PAGE_WRITECOMBINE)
97 memcpy(
string, L
"+WCM", 4 * 2);
108 if (State & MEM_COMMIT)
110 else if (State & MEM_RESERVE)
112 else if (State & MEM_FREE)
122 if (Type & MEM_PRIVATE)
124 else if (Type & MEM_MAPPED)
126 else if (Type & MEM_IMAGE)
162 static LONG NTAPI PhpMemoryItemCompareFunction(
177 PLIST_ENTRY listEntry;
180 listEntry = List->ListHead.Flink;
182 while (listEntry != &List->ListHead)
184 memoryItem = CONTAINING_RECORD(listEntry,
PH_MEMORY_ITEM, ListEntry);
185 listEntry = listEntry->Flink;
246 _In_ BOOLEAN GoToAllocationBase,
270 _In_ HANDLE ProcessHandle
278 BOOLEAN isWow64 =
FALSE;
281 PLIST_ENTRY listEntry;
291 return STATUS_NOT_FOUND;
299 PROCESS_BASIC_INFORMATION basicInfo;
301 PVOID processHeapsPtr;
306 ULONG processHeapsPtr32;
307 ULONG *processHeaps32;
316 &numberOfHeaps,
sizeof(ULONG), NULL)) && numberOfHeaps <
MAX_HEAPS)
318 processHeaps = PhAllocate(numberOfHeaps *
sizeof(PVOID));
322 &processHeapsPtr,
sizeof(PVOID), NULL)) &&
325 processHeaps, numberOfHeaps *
sizeof(PVOID), NULL)))
327 for (i = 0; i < numberOfHeaps; i++)
330 memoryItem->
u.
Heap.Index = i;
346 &numberOfHeaps,
sizeof(ULONG), NULL)) && numberOfHeaps <
MAX_HEAPS)
348 processHeaps32 = PhAllocate(numberOfHeaps *
sizeof(ULONG));
352 &processHeapsPtr32,
sizeof(ULONG), NULL)) &&
354 (PVOID)processHeapsPtr32,
355 processHeaps32, numberOfHeaps *
sizeof(ULONG), NULL)))
357 for (i = 0; i < numberOfHeaps; i++)
360 memoryItem->
u.
Heap.Index = i;
385 NtClose(threadHandle);
398 bytesRead ==
sizeof(NT_TIB))
400 if ((ULONG_PTR)ntTib.StackLimit < (ULONG_PTR)ntTib.StackBase)
407 if (isWow64 && ntTib.ExceptionList)
409 ULONG teb32 = (ULONG)ntTib.ExceptionList;
416 bytesRead ==
sizeof(NT_TIB32))
418 if (ntTib32.StackLimit < ntTib32.StackBase)
431 for (listEntry = List->ListHead.Flink; listEntry != &List->ListHead; listEntry = listEntry->Flink)
433 memoryItem = CONTAINING_RECORD(listEntry,
PH_MEMORY_ITEM, ListEntry);
455 if (memoryItem->
State & MEM_COMMIT)
460 buffer,
sizeof(buffer), NULL)))
462 PVOID candidateHeap = NULL;
463 ULONG candidateHeap32 = 0;
472 candidateHeap = heapSegment->
Heap;
474 candidateHeap32 = heapSegment32->Heap;
482 candidateHeap = heapSegment->
Heap;
484 candidateHeap32 = heapSegment32->Heap;
491 if (heapMemoryItem && heapMemoryItem->
BaseAddress == candidateHeap &&
499 else if (candidateHeap32)
503 if (heapMemoryItem && heapMemoryItem->
BaseAddress == (PVOID)candidateHeap32 &&
517 return STATUS_SUCCESS;
522 _In_ HANDLE ProcessHandle
525 PLIST_ENTRY listEntry;
531 return STATUS_NO_MEMORY;
533 for (listEntry = List->ListHead.Flink; listEntry != &List->ListHead; listEntry = listEntry->Flink)
536 ULONG_PTR virtualAddress;
537 SIZE_T remainingPages;
541 if (!(memoryItem->
State & MEM_COMMIT))
544 virtualAddress = (ULONG_PTR)memoryItem->
BaseAddress;
547 while (remainingPages != 0)
551 for (i = 0; i < requestPages; i++)
566 for (i = 0; i < requestPages; i++)
586 remainingPages -= requestPages;
592 return STATUS_SUCCESS;
597 _In_ HANDLE ProcessHandle
613 if (!memoryItem || virtualAddress < (ULONG_PTR)memoryItem->
BaseAddress ||
634 return STATUS_SUCCESS;
644 HANDLE processHandle;
645 ULONG_PTR allocationGranularity;
646 PVOID baseAddress = (PVOID)0;
647 MEMORY_BASIC_INFORMATION basicInfo;
678 sizeof(MEMORY_BASIC_INFORMATION),
684 if (basicInfo.State & MEM_FREE)
695 if (basicInfo.AllocationBase == basicInfo.BaseAddress)
696 allocationBaseItem = memoryItem;
700 if (basicInfo.State & MEM_COMMIT)
704 if (basicInfo.Type & MEM_PRIVATE)
711 if (basicInfo.State & MEM_FREE)
713 if ((ULONG_PTR)basicInfo.BaseAddress & (allocationGranularity - 1))
715 ULONG_PTR nextAllocationBase;
716 ULONG_PTR potentialUnusableSize;
720 nextAllocationBase =
ALIGN_UP_BY(basicInfo.BaseAddress, allocationGranularity);
721 potentialUnusableSize = nextAllocationBase - (ULONG_PTR)basicInfo.BaseAddress;
729 if (nextAllocationBase < (ULONG_PTR)basicInfo.BaseAddress + basicInfo.RegionSize)
733 memoryItem->
RegionSize = potentialUnusableSize;
737 otherMemoryItem->
BaseAddress = (PVOID)nextAllocationBase;
739 otherMemoryItem->
RegionSize = basicInfo.RegionSize - potentialUnusableSize;
745 previousMemoryItem = otherMemoryItem;
751 previousMemoryItem = memoryItem;
768 NtClose(processHandle);
770 return STATUS_SUCCESS;