windows-nt/Source/XPSP1/NT/sdktools/pview/vastat.c
2020-09-26 16:20:57 +08:00

672 lines
17 KiB
C

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <pviewp.h>
#include <explode.h>
#define DEFAULT_INCR (64*1024)
LIST_ENTRY VaList;
typedef struct _VAINFO {
LIST_ENTRY Links;
LIST_ENTRY AllocationBaseHead;
MEMORY_BASIC_INFORMATION BasicInfo;
} VAINFO, *PVAINFO;
PVAINFO LastAllocationBase;
SIZE_T CommitedBytes;
SIZE_T ReservedBytes;
SIZE_T FreeBytes;
SIZE_T ImageCommitedBytes;
SIZE_T ImageReservedBytes;
SIZE_T ImageFreeBytes;
#define NOACCESS 0
#define READONLY 1
#define READWRITE 2
#define WRITECOPY 3
#define EXECUTE 4
#define EXECUTEREAD 5
#define EXECUTEREADWRITE 6
#define EXECUTEWRITECOPY 7
#define MAXPROTECT 8
ULONG_PTR MappedCommit[MAXPROTECT];
ULONG_PTR PrivateCommit[MAXPROTECT];
typedef struct _MODINFO {
PVOID BaseAddress;
SIZE_T VirtualSize;
ANSI_STRING Name;
ANSI_STRING FullName;
ULONG_PTR CommitVector[MAXPROTECT];
} MODINFO, *PMODINFO;
#define MODINFO_SIZE 64
ULONG ModInfoNext;
MODINFO ModInfo[MODINFO_SIZE];
MODINFO TotalModInfo;
PMODINFO
LocateModInfo(
PVOID Address
)
{
int i;
for (i=0;i<(int)ModInfoNext;i++){
if ( Address >= ModInfo[i].BaseAddress &&
Address <= (PVOID)((ULONG_PTR)ModInfo[i].BaseAddress+ModInfo[i].VirtualSize) ) {
return &ModInfo[i];
}
}
return NULL;
}
VOID
ComputeModInfo(
HWND hDlg,
HANDLE Process
)
{
PPEB Peb;
NTSTATUS Status;
PROCESS_BASIC_INFORMATION BasicInfo;
PLDR_DATA_TABLE_ENTRY LdrEntry;
LDR_DATA_TABLE_ENTRY LdrEntryData;
PLIST_ENTRY LdrHead,LdrNext;
PPEB_LDR_DATA Ldr;
UNICODE_STRING us;
int i,nIndex;
HWND ComboList;
HANDLE hFile;
HANDLE hMappedFile;
PIMAGE_DOS_HEADER DosHeader;
PIMAGE_NT_HEADERS FileHeader;
LPSTR p;
PVOID MappedAddress;
for (i=0;i<(int)ModInfoNext;i++){
if ( ModInfo[i].BaseAddress &&
ModInfo[i].BaseAddress != (PVOID) (-1) &&
ModInfo[i].Name.Buffer
) {
RtlFreeAnsiString(&ModInfo[i].Name);
}
}
ModInfoNext = 0;
RtlZeroMemory(ModInfo,sizeof(ModInfo));
RtlInitAnsiString(&TotalModInfo.Name," TotalImageCommit");
ComboList = GetDlgItem(hDlg, PXPLODE_IMAGE_COMMIT);
SendMessage(ComboList, CB_RESETCONTENT, 0, 0);
SendMessage(ComboList, CB_SETITEMDATA, 0L, 0L);
nIndex = (int)SendMessage(
ComboList,
CB_ADDSTRING,
0,
(LPARAM)TotalModInfo.Name.Buffer
);
SendMessage(
ComboList,
CB_SETITEMDATA,
nIndex,
(LPARAM)&TotalModInfo
);
Status = NtQueryInformationProcess(
Process,
ProcessBasicInformation,
&BasicInfo,
sizeof(BasicInfo),
NULL
);
if ( !NT_SUCCESS(Status) ) {
if ( Status == STATUS_INFO_LENGTH_MISMATCH ) {
Status = NtQueryInformationProcess(
Process,
ProcessBasicInformation,
&BasicInfo,
sizeof(BasicInfo)-4,
NULL
);
if ( !NT_SUCCESS(Status) ) {
return;
}
}
else {
return;
}
}
Peb = BasicInfo.PebBaseAddress;
//
// Ldr = Peb->Ldr
//
Status = NtReadVirtualMemory(
Process,
&Peb->Ldr,
&Ldr,
sizeof(Ldr),
NULL
);
if ( !NT_SUCCESS(Status) ) {
return;
}
LdrHead = &Ldr->InMemoryOrderModuleList;
//
// LdrNext = Head->Flink;
//
Status = NtReadVirtualMemory(
Process,
&LdrHead->Flink,
&LdrNext,
sizeof(LdrNext),
NULL
);
if ( !NT_SUCCESS(Status) ) {
return;
}
while ( LdrNext != LdrHead ) {
LdrEntry = CONTAINING_RECORD(LdrNext,LDR_DATA_TABLE_ENTRY,InMemoryOrderLinks);
Status = NtReadVirtualMemory(
Process,
LdrEntry,
&LdrEntryData,
sizeof(LdrEntryData),
NULL
);
if ( !NT_SUCCESS(Status) ) {
return;
}
ModInfo[ModInfoNext].BaseAddress = LdrEntryData.DllBase;
us.Length = LdrEntryData.BaseDllName.Length;
us.MaximumLength = LdrEntryData.BaseDllName.MaximumLength;
us.Buffer = LocalAlloc(LMEM_ZEROINIT,us.MaximumLength);
if ( !us.Buffer ) {
return;
}
Status = NtReadVirtualMemory(
Process,
LdrEntryData.BaseDllName.Buffer,
us.Buffer,
us.MaximumLength,
NULL
);
if ( !NT_SUCCESS(Status) ) {
return;
}
RtlUnicodeStringToAnsiString(
&ModInfo[ModInfoNext].Name,
&us,
TRUE
);
LocalFree(us.Buffer);
us.Length = LdrEntryData.FullDllName.Length;
us.MaximumLength = LdrEntryData.FullDllName.MaximumLength;
us.Buffer = LocalAlloc(LMEM_ZEROINIT,us.MaximumLength);
if ( !us.Buffer ) {
return;
}
Status = NtReadVirtualMemory(
Process,
LdrEntryData.FullDllName.Buffer,
us.Buffer,
us.MaximumLength,
NULL
);
if ( !NT_SUCCESS(Status) ) {
return;
}
RtlUnicodeStringToAnsiString(
&ModInfo[ModInfoNext].FullName,
&us,
TRUE
);
LocalFree(us.Buffer);
if ( p = strchr(ModInfo[ModInfoNext].FullName.Buffer,':') ) {
ModInfo[ModInfoNext].FullName.Buffer = p - 1;
}
hFile = CreateFile(
ModInfo[ModInfoNext].FullName.Buffer,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL
);
if ( hFile == INVALID_HANDLE_VALUE ) {
return;
}
hMappedFile = CreateFileMapping(
hFile,
NULL,
PAGE_READONLY,
0,
0,
NULL
);
CloseHandle(hFile);
if ( !hMappedFile ) {
return;
}
MappedAddress = MapViewOfFile(
hMappedFile,
FILE_MAP_READ,
0,
0,
0
);
CloseHandle(hMappedFile);
if ( !MappedAddress ) {
UnmapViewOfFile(MappedAddress);
return;
}
DosHeader = (PIMAGE_DOS_HEADER)MappedAddress;
if ( DosHeader->e_magic != IMAGE_DOS_SIGNATURE ) {
UnmapViewOfFile(MappedAddress);
return;
}
FileHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)DosHeader + DosHeader->e_lfanew);
if ( FileHeader->Signature != IMAGE_NT_SIGNATURE ) {
UnmapViewOfFile(MappedAddress);
return;
}
ModInfo[ModInfoNext].VirtualSize = FileHeader->OptionalHeader.SizeOfImage;
UnmapViewOfFile(MappedAddress);
nIndex = (int)SendMessage(
ComboList,
CB_ADDSTRING,
0,
(LPARAM)ModInfo[ModInfoNext].Name.Buffer
);
SendMessage(
ComboList,
CB_SETITEMDATA,
nIndex,
(LPARAM)&ModInfo[ModInfoNext]
);
ModInfoNext++;
ModInfo[ModInfoNext].BaseAddress = (PVOID) (-1);
LdrNext = LdrEntryData.InMemoryOrderLinks.Flink;
}
SendMessage(ComboList, CB_SETCURSEL, 0, 0);
}
ProtectionToIndex(
ULONG Protection
)
{
Protection &= ~PAGE_GUARD;
switch ( Protection ) {
case PAGE_NOACCESS:
return NOACCESS;
case PAGE_READONLY:
return READONLY;
case PAGE_READWRITE:
return READWRITE;
case PAGE_WRITECOPY:
return WRITECOPY;
case PAGE_EXECUTE:
return EXECUTE;
case PAGE_EXECUTE_READ:
return EXECUTEREAD;
case PAGE_EXECUTE_READWRITE:
return EXECUTEREADWRITE;
case PAGE_EXECUTE_WRITECOPY:
return EXECUTEWRITECOPY;
default:
printf("Unknown Protection 0x%lx\n",Protection);
return 0;
}
}
VOID
DumpImageCommit(
HWND hDlg,
PULONG_PTR CommitVector
)
{
SIZE_T TotalCommitCount;
ULONG i;
CHAR szTemp[80];
TotalCommitCount = 0;
for ( i=0;i<MAXPROTECT;i++){
TotalCommitCount += CommitVector[i];
}
wsprintf(szTemp,"%d Kb",TotalCommitCount/1024);
SetDlgItemText(
hDlg,
PXPLODE_TOTALIMAGE_COMMIT,
szTemp
);
wsprintf(szTemp,"%d Kb",CommitVector[NOACCESS]/1024);
SetDlgItemText(
hDlg,
PXPLODE_IMAGE_NOACCESS,
szTemp
);
wsprintf(szTemp,"%d Kb",CommitVector[READONLY]/1024);
SetDlgItemText(
hDlg,
PXPLODE_IMAGE_READONLY,
szTemp
);
wsprintf(szTemp,"%d Kb",CommitVector[READWRITE]/1024);
SetDlgItemText(
hDlg,
PXPLODE_IMAGE_READWRITE,
szTemp
);
wsprintf(szTemp,"%d Kb",CommitVector[WRITECOPY]/1024);
SetDlgItemText(
hDlg,
PXPLODE_IMAGE_WRITECOPY,
szTemp
);
wsprintf(szTemp,"%d Kb",
(CommitVector[EXECUTE] +
CommitVector[EXECUTEREAD] +
CommitVector[EXECUTEREADWRITE] +
CommitVector[EXECUTEWRITECOPY])/1024);
SetDlgItemText(
hDlg,
PXPLODE_IMAGE_EXECUTE,
szTemp
);
}
VOID
DumpMappedCommit(
HWND hDlg,
PULONG_PTR CommitVector
)
{
SIZE_T TotalCommitCount;
ULONG i;
CHAR szTemp[80];
TotalCommitCount = 0;
for ( i=0;i<MAXPROTECT;i++){
TotalCommitCount += CommitVector[i];
}
wsprintf(szTemp,"%d Kb",TotalCommitCount/1024);
SetDlgItemText(
hDlg,
PXPLODE_TOTALMAPPED_COMMIT,
szTemp
);
wsprintf(szTemp,"%d Kb",CommitVector[NOACCESS]/1024);
SetDlgItemText(
hDlg,
PXPLODE_MAPPED_NOACCESS,
szTemp
);
wsprintf(szTemp,"%d Kb",CommitVector[READONLY]/1024);
SetDlgItemText(
hDlg,
PXPLODE_MAPPED_READONLY,
szTemp
);
wsprintf(szTemp,"%d Kb",CommitVector[READWRITE]/1024);
SetDlgItemText(
hDlg,
PXPLODE_MAPPED_READWRITE,
szTemp
);
wsprintf(szTemp,"%d Kb",CommitVector[WRITECOPY]/1024);
SetDlgItemText(
hDlg,
PXPLODE_MAPPED_WRITECOPY,
szTemp
);
wsprintf(szTemp,"%d Kb",
(CommitVector[EXECUTE] +
CommitVector[EXECUTEREAD] +
CommitVector[EXECUTEREADWRITE] +
CommitVector[EXECUTEWRITECOPY])/1024);
SetDlgItemText(
hDlg,
PXPLODE_MAPPED_EXECUTE,
szTemp
);
}
VOID
DumpPrivateCommit(
HWND hDlg,
PULONG_PTR CommitVector
)
{
SIZE_T TotalCommitCount;
ULONG i;
CHAR szTemp[80];
TotalCommitCount = 0;
for ( i=0;i<MAXPROTECT;i++){
TotalCommitCount += CommitVector[i];
}
wsprintf(szTemp,"%d Kb",TotalCommitCount/1024);
SetDlgItemText(
hDlg,
PXPLODE_TOTALPRIVATE_COMMIT,
szTemp
);
wsprintf(szTemp,"%d Kb",CommitVector[NOACCESS]/1024);
SetDlgItemText(
hDlg,
PXPLODE_PRIVATE_NOACCESS,
szTemp
);
wsprintf(szTemp,"%d Kb",CommitVector[READONLY]/1024);
SetDlgItemText(
hDlg,
PXPLODE_PRIVATE_READONLY,
szTemp
);
wsprintf(szTemp,"%d Kb",CommitVector[READWRITE]/1024);
SetDlgItemText(
hDlg,
PXPLODE_PRIVATE_READWRITE,
szTemp
);
wsprintf(szTemp,"%d Kb",CommitVector[WRITECOPY]/1024);
SetDlgItemText(
hDlg,
PXPLODE_PRIVATE_WRITECOPY,
szTemp
);
wsprintf(szTemp,"%d Kb",
(CommitVector[EXECUTE] +
CommitVector[EXECUTEREAD] +
CommitVector[EXECUTEREADWRITE] +
CommitVector[EXECUTEWRITECOPY])/1024);
SetDlgItemText(
hDlg,
PXPLODE_PRIVATE_EXECUTE,
szTemp
);
}
VOID
CaptureVaSpace(
IN HANDLE Process
)
{
NTSTATUS Status;
PVOID BaseAddress;
PVAINFO VaInfo;
PMODINFO Mod;
ULONG_PTR SystemRangeStart;
Status = NtQuerySystemInformation(SystemRangeStartInformation,
&SystemRangeStart,
sizeof(SystemRangeStart),
NULL);
if (!NT_SUCCESS(Status)) {
return;
}
BaseAddress = NULL;
LastAllocationBase = NULL;
InitializeListHead(&VaList);
VaInfo = LocalAlloc(LMEM_ZEROINIT,sizeof(*VaInfo));
while ( (ULONG_PTR)BaseAddress < SystemRangeStart ) {
Status = NtQueryVirtualMemory(
Process,
BaseAddress,
MemoryBasicInformation,
&VaInfo->BasicInfo,
sizeof(VaInfo->BasicInfo),
NULL
);
if ( !NT_SUCCESS(Status) ) {
LocalFree(VaInfo);
return;
}
else {
switch (VaInfo->BasicInfo.State ) {
case MEM_COMMIT :
if ( VaInfo->BasicInfo.Type == MEM_IMAGE ) {
TotalModInfo.CommitVector[ProtectionToIndex(VaInfo->BasicInfo.Protect)] += VaInfo->BasicInfo.RegionSize;
Mod = LocateModInfo(BaseAddress);
if ( Mod ) {
Mod->CommitVector[ProtectionToIndex(VaInfo->BasicInfo.Protect)] += VaInfo->BasicInfo.RegionSize;
}
}
else {
if ( VaInfo->BasicInfo.Type == MEM_MAPPED ) {
MappedCommit[ProtectionToIndex(VaInfo->BasicInfo.Protect)] += VaInfo->BasicInfo.RegionSize;
}
else {
PrivateCommit[ProtectionToIndex(VaInfo->BasicInfo.Protect)] += VaInfo->BasicInfo.RegionSize;
}
}
break;
case MEM_RESERVE :
if ( VaInfo->BasicInfo.Type == MEM_IMAGE ) {
ImageReservedBytes += VaInfo->BasicInfo.RegionSize;
}
else {
ReservedBytes += VaInfo->BasicInfo.RegionSize;
}
break;
case MEM_FREE :
if ( VaInfo->BasicInfo.Type == MEM_IMAGE ) {
ImageFreeBytes += VaInfo->BasicInfo.RegionSize;
}
else {
FreeBytes += VaInfo->BasicInfo.RegionSize;
}
break;
}
BaseAddress = (PVOID)((ULONG_PTR)BaseAddress + VaInfo->BasicInfo.RegionSize);
}
}
}
BOOL
ComputeVaSpace(
HWND hDlg,
HANDLE hProcess
)
{
memset(TotalModInfo.CommitVector,0,sizeof(TotalModInfo.CommitVector));
memset(MappedCommit,0,sizeof(MappedCommit));
memset(PrivateCommit,0,sizeof(PrivateCommit));
ComputeModInfo(hDlg,hProcess);
if ( hProcess) {
CaptureVaSpace(hProcess);
}
DumpImageCommit(hDlg,&TotalModInfo.CommitVector[0]);
DumpMappedCommit(hDlg,MappedCommit);
DumpPrivateCommit(hDlg,PrivateCommit);
return TRUE;
}
VOID
UpdateImageCommit(
HWND hDlg
)
{
HWND ComboList;
int nIndex;
PMODINFO ModInfo;
ComboList = GetDlgItem(hDlg, PXPLODE_IMAGE_COMMIT);
nIndex = (int)SendMessage(ComboList, CB_GETCURSEL, 0, 0);
ModInfo = (PMODINFO)SendMessage(
ComboList,
CB_GETITEMDATA,
nIndex,
0
);
if ( ModInfo ) {
DumpImageCommit(hDlg,&ModInfo->CommitVector[0]);
}
}