0x01 相关API
1.QueryWorkingSet
得到刚加入指定进程工作集的页信息
BOOL QueryWorkingSet( HANDLE hProcess , PVOID pv , DWORD cb );
参数:
hProcess - [in]进程句柄。句柄必须有PROCESS_QUERY_INFORMATION和PROCESS_VM_READ权限。 pv - [out]指向接收信息的存储的指针。 cb - [in]pv存储的大小,字节为单位。
返回值
成功返回非零值。失败返回0。可调用GetLastError得到错误信息。
2.GetWsChanges
检索自上次调用此函数或InitializeProcessForWsWatch函数以来已添加到指定进程的工作集的页面的信息 。
BOOL WINAPI GetWsChanges( _In_HANDLE hProcess, _Out_ PPSAPI_WS_WATCH_INFORMATION lpWatchInfo, _In_ DWORD cb );
参数:
hProcess [in]处理过程的句柄。该句柄必须具有PROCESS_QUERY_INFORMATION 访问权限。有关更多信息,请参阅 进程安全和访问权限。 lpWatchInfo [out]指向用户分配的缓冲区的指针,该缓冲区接收PSAPI_WS_WATCH_INFORMATION结构数组 。该数组以FaultingPc成员为NULL 的结构终止。 cb [in]lpWatchInfo缓冲区的大小,以字节为单位。
返回值:
如果函数成功,则返回值为非零。
如果函数失败,返回值为零。要获得扩展错误信息,可调用 GetLastError。
如果 lpWatchInfo缓冲区不足以包含所有工作集合更改记录,则GetLastError返回 ERROR_INSUFFICIENT_BUFFER ; 缓冲区返回空。为缓冲区重新分配一个更大的内存块并再次调用。
3.EmptyWorkingSet
从指定进程的工作集中删除尽可能多的页面。
BOOL WINAPI EmptyWorkingSet( _In_ HANDLE hProcess );
参数:
hProcess [in] 处理过程的句柄。该句柄必须具有PROCESS_QUERY_INFORMATION或PROCESS_QUERY_LIMITED_INFORMATION访问权限和PROCESS_SET_QUOTA访问权限。
返回值:
如果函数成功,则返回值为非零。
如果函数失败,返回值为零。要获得扩展错误信息,可调用 GetLastError。
// WorkingSet.cpp : 定义控制台应用程序的入口点。
// http://www.howsoftworks.net/windows/system-services/queryworkingset.html
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <fstream>
#include "psapi.h"
#define MAX_NUM 10000
#pragma comment ( lib, "psapi.lib" )
using namespace std;
ofstream fout("WorkingSetInformation.txt");
void ShowErrorMessage()
{
DWORD dwErrorCode = GetLastError();
HLOCAL hLocal = NULL;
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL,
dwErrorCode,
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(PTSTR)&hLocal,
0,
NULL
);
fout << ' ' << "ErrorCode : " << dwErrorCode << endl;
fout << ' ' << "ErrorMessage : " << (char*)hLocal << endl;
LocalFree(hLocal);
}
int main()
{
//get notepad's PID from "Windows task maganent"
DWORD dwProcessId = 10084; //change it
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (InitializeProcessForWsWatch(hProcess))
{
/******************************
* QueryWorkingSet
*******************************/
PVOID pv[MAX_NUM] = { 0 };
if (!QueryWorkingSet(hProcess, pv, sizeof(pv)))
{
fout << "QueryWorkingSet Failed!" << endl;
ShowErrorMessage();
}
else
{
for (unsigned int i = 0; i < MAX_NUM; i++)
{
if (pv[i] != NULL)
{
if (i == 0)
fout << "TotalNum : " << hex << pv[i] << endl;
else
fout << ' ' << i << " pv : " << hex << pv[i] << endl;
}
else
{
break;
}
}
}
fout << endl << endl;
/******************************
* GetWsChanges
*******************************/
cout << "5 Second Wait" << endl;
Sleep(5000);
PSAPI_WS_WATCH_INFORMATION WatchInfo[MAX_NUM] = { 0 };
if (!GetWsChanges(hProcess, WatchInfo, sizeof(WatchInfo)))
{
fout << "GetWsChanges Failed!" << endl;
ShowErrorMessage();
}
else
{
for (unsigned int i = 0; i < MAX_NUM; i++)
{
if (WatchInfo[i].FaultingPc != NULL || WatchInfo[i].FaultingVa != NULL)
{
fout << "Pc指针 : " << WatchInfo[i].FaultingPc << endl;
fout << "Va缓冲区大小 : " << WatchInfo[i].FaultingVa << endl << endl;
}
else
{
break;
}
}
}
fout << endl << endl;
/******************************
* EmptyWorkingSet
*******************************/
if (!EmptyWorkingSet(hProcess))
{
fout << "EmptyWorkingSet Failed!" << endl;
ShowErrorMessage();
}
else
{
PVOID pv[MAX_NUM] = { 0 };
if (!QueryWorkingSet(hProcess, pv, sizeof(pv)))
{
fout << "EmptyWorkingSet Failed!" << endl;
ShowErrorMessage();
}
else
{
for (unsigned int i = 0; i < MAX_NUM; i++)
{
if (pv[i] != NULL)
{
if (i == 0)
fout << "TotalNum : " << hex << pv[i] << endl;
else
fout << ' ' << i << " pv : " << hex << pv[i] << endl;
}
else
{
break;
}
}
}
}
}
CloseHandle(hProcess);
return 0;
}