函數(shù)功能描述:查詢地址空間中內(nèi)存地址的信息。
函數(shù)原型:
DWORD VirtualQueryEx( HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, DWORD dwLength );
參數(shù):
hProcess 進(jìn)程句柄。
LpAddress 查詢內(nèi)存的地址。
LpBuffer 指向MEMORY_BASIC_INFORMATION結(jié)構(gòu)的指針,用于接收內(nèi)存信息。
DwLength MEMORY_BASIC_INFORMATION結(jié)構(gòu)的大小。
返回值:
函數(shù)寫入lpBuffer的字節(jié)數(shù),如果不等于sizeof(MEMORY_BASIC_INFORMATION)表示失敗。
備注:
MEMORY_BASIC_INFORMATION在WinNT.h中定義如下:
typedef struct _MEMORY_BASIC_INFORMATION {
PVOID BaseAddress; // 區(qū)域基地址。
PVOID AllocationBase; // 分配基地址。
DWORD AllocationProtect; // 區(qū)域被初次保留時(shí)賦予的保護(hù)屬性。
SIZE_T RegionSize; // 區(qū)域大小(以字節(jié)為計(jì)量單位)。
DWORD State; // 狀態(tài)(MEM_FREE、MEM_RESERVE或 MEM_COMMIT)。
DWORD Protect; // 保護(hù)屬性。
DWORD Type; // 類型。
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
成員解釋:
BaseAddress 與LpAddress參數(shù)的值相同,但是四舍五入為頁(yè)面的邊界值。
AllocationBase 指明用VirtualAlloc函數(shù)分配內(nèi)存區(qū)域的基地址。LpAddress
在該區(qū)域之內(nèi)。
AllocationProtect 指明該地址空間區(qū)域被初次保留時(shí)賦予該區(qū)域的保護(hù)屬性。
PAGE_READONLY 只讀屬性,如果試圖進(jìn)行寫操作,將引發(fā)訪問違規(guī)。如果系統(tǒng)
區(qū)分只讀、執(zhí)行兩種屬性,那么試圖在該區(qū)域執(zhí)行代碼也將引
發(fā)訪問違規(guī)。
PAGE_READWRITE 允許讀寫。
PAGE_EXECUTE 只允許執(zhí)行代碼,對(duì)該區(qū)域試圖進(jìn)行讀寫操作將引發(fā)訪問違規(guī)。
PAGE_EXECUTE_READ 允許執(zhí)行和讀取。
PAGE_EXECUTE_READWRITE 允許讀寫和執(zhí)行代碼。
PAGE_EXECUTE_WRITECOPY 對(duì)于該地址空間的區(qū)域,不管執(zhí)行什么操作,都不會(huì)引發(fā)訪問違
規(guī)。如果試圖在該頁(yè)面上的內(nèi)存中進(jìn)行寫入操作,就會(huì)將它自己
的私有頁(yè)面(受頁(yè)文件的支持)拷貝賦予該進(jìn)程。
PAGE_GUARD 在頁(yè)面上寫入一個(gè)字節(jié)時(shí)使應(yīng)用程序收到一個(gè)通知(通過一個(gè)異
常條件)。該標(biāo)志有一些非常巧妙的用法。Windows 2000在創(chuàng)建
線程堆棧時(shí)使用該標(biāo)志。
PAGE_NOACCESS 禁止一切訪問。
PAGE_NOCACHE 停用已提交頁(yè)面的高速緩存。一般情況下最好不要使用該標(biāo)志,
因?yàn)樗饕枪┬枰幚韮?nèi)存緩沖區(qū)的硬件設(shè)備驅(qū)動(dòng)程序的開發(fā)
人員使用的。
RegionSize 用于指明內(nèi)存塊從基地址即BaseAddress開始的所有頁(yè)面的大
?。ㄒ宰止?jié)為計(jì)量單位)這些頁(yè)面與含有用LpAddress參數(shù)設(shè)
定的地址的頁(yè)面擁有相同的保護(hù)屬性、狀態(tài)和類型。
State 用于指明所有相鄰頁(yè)面的狀態(tài)。
MEM_COMMIT 指明已分配物理內(nèi)存或者系統(tǒng)頁(yè)文件。
MEM_FREE 空閑狀態(tài)。該區(qū)域的虛擬地址不受任何內(nèi)存的支持。該地址空間沒
有被保留。改狀態(tài)下AllocationBase、AllocationProtect、Protect
和Type等成員均未定義。
MEM_RESERVE 指明頁(yè)面被保留,但是沒有分配任何物理內(nèi)存。該狀態(tài)下Protect成
員未定。
Protect 用于指明所有相鄰頁(yè)面(內(nèi)存塊)的保護(hù)屬性。這些頁(yè)面與含有
擁有相同的保屬性、狀態(tài)和類型。意義同AllocationProtect。
Type 用于指明支持所有相鄰頁(yè)面的物理存儲(chǔ)器的類型(MEM_IMAGE,
MEM_MAPPED或MEM_PRIVATE)。這些相鄰頁(yè)面擁有相同的保護(hù)屬
性、狀態(tài)和類型。如果是Windows 98,那么這個(gè)成員將總是
MEM_PRIVATE 。
MEM_IMAGE 指明該區(qū)域的虛擬地址原先受內(nèi)存映射的映像文件(如.exe或DLL
文件)的支持,但也許不再受映像文件的支持。例如,當(dāng)寫入模塊
映像中的全局變量時(shí),“寫入時(shí)拷貝”的機(jī)制將由頁(yè)文件來支持特
定的頁(yè)面,而不是受原始映像文件的支持。
MEM_MAPPED 該區(qū)域的虛擬地址原先是受內(nèi)存映射的數(shù)據(jù)文件的支持,但也許不
再受數(shù)據(jù)文件的支持。例如,數(shù)據(jù)文件可以使用“寫入時(shí)拷貝”的
保護(hù)屬性來映射。對(duì)文件的任何寫入操作都將導(dǎo)致頁(yè)文件而不是原
始數(shù)據(jù)支持特定的頁(yè)面。
MEM_PRIVATE 指明該內(nèi)存區(qū)域是私有的。不被其他進(jìn)程共享。
#include "stdafx.h"
#include <windows.h>
#include <TCHAR.H>
BOOL ShowProcMemInfo(DWORD dwPID);
int _tmain(int argc, char* argv[])
{
ShowProcMemInfo( GetCurrentProcessId() );
return 0;
}
// 顯示一個(gè)進(jìn)程的內(nèi)存狀態(tài) dwPID為進(jìn)程ID
BOOL ShowProcMemInfo(DWORD dwPID)
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,
FALSE,
dwPID);
if(hProcess == NULL)
return FALSE;
MEMORY_BASIC_INFORMATION mbi;
PBYTE pAddress = NULL;
TCHAR szInfo[200] = _T("BaseAddr Size Type State Protect \n");
_tprintf(szInfo);
while(TRUE)
{
if(VirtualQueryEx(hProcess, pAddress, &mbi, sizeof(mbi)) != sizeof(mbi))
{
break;
}
if((mbi.AllocationBase != mbi.BaseAddress) && (mbi.State != MEM_FREE))
{
_stprintf(szInfo, _T(" %08X %8dK "),
mbi.BaseAddress,
mbi.RegionSize>>10);
}
else
{
_stprintf(szInfo, _T("%08X %8dK "),
mbi.BaseAddress,
mbi.RegionSize>>10);
}
PCTSTR pStr = _T("");
switch(mbi.Type)
{
case MEM_IMAGE: pStr = _T("MEM_IMAGE "); break;
case MEM_MAPPED: pStr = _T("MEM_MAPPED "); break;
case MEM_PRIVATE: pStr = _T("MEM_PRIVATE"); break;
default: pStr = _T("-----------"); break;
}
_tcscat(szInfo, pStr);
_tcscat(szInfo, _T(" "));
switch(mbi.State)
{
case MEM_COMMIT: pStr = _T("MEM_COMMIT "); break;
case MEM_RESERVE: pStr = _T("MEM_RESERVE"); break;
case MEM_FREE: pStr = _T("MEM_FREE "); break;
default: pStr = _T("-----------"); break;
}
_tcscat(szInfo, pStr);
_tcscat(szInfo, _T(" "));
switch(mbi.AllocationProtect)
{
case PAGE_READONLY: pStr = _T("PAGE_READONLY "); break;
case PAGE_READWRITE: pStr = _T("PAGE_READWRITE "); break;
case PAGE_WRITECOPY: pStr = _T("PAGE_WRITECOPY "); break;
case PAGE_EXECUTE: pStr = _T("PAGE_EXECUTE "); break;
case PAGE_EXECUTE_READ: pStr = _T("PAGE_EXECUTE_READ "); break;
case PAGE_EXECUTE_READWRITE: pStr = _T("PAGE_EXECUTE_READWRITE"); break;
case PAGE_EXECUTE_WRITECOPY: pStr = _T("PAGE_EXECUTE_WRITECOPY"); break;
case PAGE_GUARD: pStr = _T("PAGE_GUARD "); break;
case PAGE_NOACCESS: pStr = _T("PAGE_NOACCESS "); break;
case PAGE_NOCACHE: pStr = _T("PAGE_NOCACHE "); break;
default: pStr = _T("----------------------"); break;
}
_tcscat(szInfo, pStr);
_tcscat(szInfo, _T("\n"));
_tprintf(szInfo);
pAddress = ((PBYTE)mbi.BaseAddress + mbi.RegionSize);
}
CloseHandle(hProcess);
return TRUE;
}