函數功能描述:查詢地址空間中內存地址的信息。
函數原型:
DWORD VirtualQueryEx( HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, DWORD dwLength );
參數:
hProcess 進程句柄。
LpAddress 查詢內存的地址。
LpBuffer 指向MEMORY_BASIC_INFORMATION結構的指針,用于接收內存信息。
DwLength MEMORY_BASIC_INFORMATION結構的大小。
返回值:
函數寫入lpBuffer的字節數,如果不等于sizeof(MEMORY_BASIC_INFORMATION)表示失敗。
備注:
MEMORY_BASIC_INFORMATION在WinNT.h中定義如下:
typedef struct _MEMORY_BASIC_INFORMATION {
PVOID BaseAddress; // 區域基地址。
PVOID AllocationBase; // 分配基地址。
DWORD AllocationProtect; // 區域被初次保留時賦予的保護屬性。
SIZE_T RegionSize; // 區域大小(以字節為計量單位)。
DWORD State; // 狀態(MEM_FREE、MEM_RESERVE或 MEM_COMMIT)。
DWORD Protect; // 保護屬性。
DWORD Type; // 類型。
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
成員解釋:
BaseAddress 與LpAddress參數的值相同,但是四舍五入為頁面的邊界值。
AllocationBase 指明用VirtualAlloc函數分配內存區域的基地址。LpAddress
在該區域之內。
AllocationProtect 指明該地址空間區域被初次保留時賦予該區域的保護屬性。
PAGE_READONLY 只讀屬性,如果試圖進行寫操作,將引發訪問違規。如果系統
區分只讀、執行兩種屬性,那么試圖在該區域執行代碼也將引
發訪問違規。
PAGE_READWRITE 允許讀寫。
PAGE_EXECUTE 只允許執行代碼,對該區域試圖進行讀寫操作將引發訪問違規。
PAGE_EXECUTE_READ 允許執行和讀取。
PAGE_EXECUTE_READWRITE 允許讀寫和執行代碼。
PAGE_EXECUTE_WRITECOPY 對于該地址空間的區域,不管執行什么操作,都不會引發訪問違
規。如果試圖在該頁面上的內存中進行寫入操作,就會將它自己
的私有頁面(受頁文件的支持)拷貝賦予該進程。
PAGE_GUARD 在頁面上寫入一個字節時使應用程序收到一個通知(通過一個異
常條件)。該標志有一些非常巧妙的用法。Windows 2000在創建
線程堆棧時使用該標志。
PAGE_NOACCESS 禁止一切訪問。
PAGE_NOCACHE 停用已提交頁面的高速緩存。一般情況下最好不要使用該標志,
因為它主要是供需要處理內存緩沖區的硬件設備驅動程序的開發
人員使用的。
RegionSize 用于指明內存塊從基地址即BaseAddress開始的所有頁面的大
小(以字節為計量單位)這些頁面與含有用LpAddress參數設
定的地址的頁面擁有相同的保護屬性、狀態和類型。
State 用于指明所有相鄰頁面的狀態。
MEM_COMMIT 指明已分配物理內存或者系統頁文件。
MEM_FREE 空閑狀態。該區域的虛擬地址不受任何內存的支持。該地址空間沒
有被保留。改狀態下AllocationBase、AllocationProtect、Protect
和Type等成員均未定義。
MEM_RESERVE 指明頁面被保留,但是沒有分配任何物理內存。該狀態下Protect成
員未定。
Protect 用于指明所有相鄰頁面(內存塊)的保護屬性。這些頁面與含有
擁有相同的保屬性、狀態和類型。意義同AllocationProtect。
Type 用于指明支持所有相鄰頁面的物理存儲器的類型(MEM_IMAGE,
MEM_MAPPED或MEM_PRIVATE)。這些相鄰頁面擁有相同的保護屬
性、狀態和類型。如果是Windows 98,那么這個成員將總是
MEM_PRIVATE 。
MEM_IMAGE 指明該區域的虛擬地址原先受內存映射的映像文件(如.exe或DLL
文件)的支持,但也許不再受映像文件的支持。例如,當寫入模塊
映像中的全局變量時,“寫入時拷貝”的機制將由頁文件來支持特
定的頁面,而不是受原始映像文件的支持。
MEM_MAPPED 該區域的虛擬地址原先是受內存映射的數據文件的支持,但也許不
再受數據文件的支持。例如,數據文件可以使用“寫入時拷貝”的
保護屬性來映射。對文件的任何寫入操作都將導致頁文件而不是原
始數據支持特定的頁面。
MEM_PRIVATE 指明該內存區域是私有的。不被其他進程共享。
#include "stdafx.h"
#include <windows.h>
#include <TCHAR.H>
BOOL ShowProcMemInfo(DWORD dwPID);
int _tmain(int argc, char* argv[])
{
ShowProcMemInfo( GetCurrentProcessId() );
return 0;
}
// 顯示一個進程的內存狀態 dwPID為進程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;
}