zoukankan      html  css  js  c++  java
  • 第14章 探索虚拟内存(2)

    14.4 确定地址空间的状态

    14.4.1 查询内存状态API 

    (1)VirtualQuery(Ex)函数

    参数

    描述

    HANDLE hProcess

    要查询的另一个进程的句柄。(注意,这个参数只有VirtualQueryEx才有,VirtualQuery只能查本进程的信息)

    LPCVOID pvAddress

    需要查询的虚拟内存地址

    PMEMORY_BASIC_INFORMATION pmbi

    返回的信息被放入该指针指向的MEMORY_BASIC_INFORMATION结构体。

    DWORD dwLength

    上述结构体的大小,表示返回时复制到上述结构体中的字节数。

    (2)MEMORY_BASIC_INFORMATION结构体

    字段

    描述

    BaseAddress

    这个值是VirtualQuery(Ex)第一个参数向下取整到页面的边界的值。如区域中的块,可以从AllocationBase开始以4KB倍数的偏移处作为其BaseAddress。

    AllocationBase

    标识出区域的基地址,该区域包含参数pvAddress所指向的地址。. VirtualAlloc分配的内存称为区域(Region),是一片连续的页.。Windows会以64KB为边界计算区域的起始地址,这里的64KB就是所谓的分配粒度,因此 AllocationBase正是一个区域(Region)的起始地址。

    AllocationProtect

    标识出在最开始预订区域时为该区域指定的保护属性

    RegionSize

    标识出区域的大小,以字节为单位。区域的起始地址为BaseAddress,区域中所有页面拥有相同的保护属性、状态及类型

    State

    标识出区域中页面的状态(MEM_FREE、MEM_RESERVE或MEM_COMMIT)

    如果为MEM_FREE,则AllocationBase、AllocationProtect、Protect及Type成员都没有意义。

    如果为MEM_RESERVE,那么Protect成员没有意义。

    Protect

    针对所有相邻页面(前提是其保护属性、状态和类型与其中包含 pvAddress参数中所指定地址的页面相同),标识出它们的保护属性(PAGE_*)

    Type

    标识出区域中页面的类型(MEM_IMAGE、MEM_MAPPED或MEM_PRIVATE)

    14.4.2 自定义的VMQuery(Ex)函数——得到更完整的内存信息

    (1)BOOL VMQuery(HANDLE hProcess,LPCVOID pvAddress,PVMQUERY pVMQ);

    (2)VMQUERY结构体

    字段

    描述

    备注

    PVOID pvRgnBaseAddress

    表示虚拟地址空间区域的起始地址,该区域包含了参数pvAddress所指定的地址

    DWORD dwRgnProtection

    表示在最开始预订地址空间区域时为该区域指定的保护属性(PAGE_*)

    SIZE_T RgnSize

    表示所预订区域的大小,以字节为单位

    DWORD dwRgnStorage

    表示用于区域中各块的物理存储器的类型。它可以是以下任一值:MEM_FREE、MEM_IMAGE、MEM_MAPPED或MEM_PRIVATE

    DWORD dwRgnBlocks

    表示区域中块的数量

    DWORD dwRgnGuardBlks

    表示区域中具有PAGE_GUARD保护属性标志的块的数量。通常这个值为0或1。如果为1,说明该区域是为了线程栈而预订的。

    BOOL bRgnIsAStack

    表示该区域是否包含线程栈。该值是通过近似猜测得到的,因为没有任何方法能百分百地肯定一个区域是否包含线程栈

    PVOID pvBlkBaseAddress

    表示块的起始地址,该块包含了参数pvAddress所指示的地址

    DWORD dwBlkProtection

    表示块的保护属性

    SIZE_T BlkSize

    表示块的大小,以字节为单位

    DWORD dwBlkStorage

    表示块的存储器类型。它可以是以下任一值:MEM_FREE、MEM_IMAGE、MEM_RESERVE、MEM_MAPPED或MEM_PRIVATE

    【VMMap程序】显示虚拟内存映射情况

     

    /*************************************************************************
    Module: VMMap.cpp
    Notices:Copyright(c) 2008 Jeffrey Richter & Christophe Nasarre
    *************************************************************************/
    
    #include "../../CommonFiles/CmnHdr.h"
    #include "../../CommonFiles/ToolHelp.h"
    #include "resource.h"
    #include "VMQuery.h"
    #include <Psapi.h>  //For GetMappedFileName函数
    #include <tchar.h>
    #include <strsafe.h>
    
    #pragma  comment(lib,"psapi")
    
    //////////////////////////////////////////////////////////////////////////
    DWORD g_dwProcessID = 0; //要遍历的进程
    BOOL  g_bExpandRegions = FALSE;
    CToolhelp g_toolhelp;
    //////////////////////////////////////////////////////////////////////////
    
    void CopyControlToClipboard(HWND hWnd){
        TCHAR szClipData[128 * 1024] = { 0 };
    
        int nCount = ListBox_GetCount(hWnd);
        for (int nNum = 0; nNum < nCount;nNum++){
            TCHAR szLine[1000];
            ListBox_GetText(hWnd, nNum, szLine);
            _tcscat_s(szClipData, _countof(szClipData), szLine);
            _tcscat_s(szClipData, _countof(szClipData), TEXT("
    "));
        }
    
        OpenClipboard(NULL);
        EmptyClipboard();
    
        //锁定内存块
        HGLOBAL hClipData = GlobalAlloc(GMEM_MOVEABLE |GMEM_ZEROINIT,
                                        sizeof(TCHAR)*(_tcslen(szClipData)+1));
        PTSTR  pClipData = (PTSTR)GlobalLock(hClipData);
        _tcscpy_s(pClipData, _tcslen(szClipData) + 1, szClipData);
    
    #ifdef UNICODE
        BOOL bOk = (hClipData == SetClipboardData(CF_UNICODETEXT,hClipData));
    #else
        BOOL bOk = (hClipData == SetClipboardData(CF_TEXT,hClipData));
    #endif
        CloseClipboard();
    
        if (!bOk){
            GlobalFree(hClipData);
            chMB("数据复制到剪贴板时出错!");
        }
    }
    //////////////////////////////////////////////////////////////////////////
    
    PCTSTR GetMemStorageText(DWORD dwStorage){
        PCTSTR p = TEXT("未知");
        switch (dwStorage){
            case MEM_FREE:        p = TEXT("空闲 "); break;
            case MEM_RESERVE:    p = TEXT("保留 "); break;
            case MEM_IMAGE:        p = TEXT("映像 "); break;
            case MEM_MAPPED:    p = TEXT("己映射"); break;
            case MEM_PRIVATE:   p = TEXT("私有 "); break;
        }
        return p;
    }
    //////////////////////////////////////////////////////////////////////////
    
    PTSTR GetProtectText(DWORD dwProtect, PTSTR szBuf, size_t chSize, BOOL bShowFlags){
    
        PCTSTR p = TEXT("未知");
        switch (dwProtect & ~(PAGE_GUARD | PAGE_NOCACHE | PAGE_WRITECOMBINE))
        {
            case PAGE_READONLY:            p = TEXT("-R--"); break;
            case PAGE_READWRITE:        p = TEXT("-RW-"); break;
            case PAGE_WRITECOPY:        p = TEXT("-RWC"); break;
            case PAGE_EXECUTE:            p = TEXT("E---"); break;
            case PAGE_EXECUTE_READ:        p = TEXT("ER--"); break;
            case PAGE_EXECUTE_READWRITE:p = TEXT("ERW-"); break;
            case PAGE_EXECUTE_WRITECOPY:p = TEXT("ERWC"); break;
            case PAGE_NOACCESS:            p = TEXT("----"); break;
        }
    
        _tcscpy_s(szBuf, chSize, p);
        if (bShowFlags){
            _tcscat_s(szBuf, chSize, TEXT(" "));
            _tcscat_s(szBuf, chSize, (dwProtect & PAGE_GUARD) ? TEXT("G") : TEXT("-"));
            _tcscat_s(szBuf, chSize, (dwProtect & PAGE_NOCACHE) ? TEXT("N") : TEXT("-"));
            _tcscat_s(szBuf, chSize, (dwProtect & PAGE_WRITECOMBINE) ? TEXT("W") : TEXT("-"));
        
        }
        return (szBuf);
    }
    //////////////////////////////////////////////////////////////////////////
    
    void ConstructRgnInfoLine(HANDLE hProcess, PVMQUERY pVMQ, PTSTR szLine, int cchMaxLen){
        
        StringCchPrintf(szLine, cchMaxLen, TEXT("%p	%s	%12u	"),
                        pVMQ->pvRgnBaseAddress,
                        GetMemStorageText(pVMQ->dwRgnStorage),
                        pVMQ->RgnSize);
    
        if (pVMQ->dwRgnStorage !=MEM_FREE){
            StringCchPrintf(_tcschr(szLine,0),cchMaxLen -_tcslen(szLine),
                            TEXT("%u	"),pVMQ->dwRgnBlocks);
            GetProtectText(pVMQ->dwRgnProtection, _tcschr(szLine, 0),
                           cchMaxLen - _tcslen(szLine), FALSE);
        
        } else{
            _tcscat_s(szLine, cchMaxLen, TEXT("	"));
        }
    
        _tcscat_s(szLine, cchMaxLen, TEXT("	"));
    
        //尝试获取区块的模块路径名称
        if ((pVMQ->dwRgnStorage != MEM_FREE)&&(pVMQ->pvRgnBaseAddress != NULL)){
            MODULEENTRY32 me = { sizeof(me) };
            if (g_toolhelp.ModuleFind(pVMQ->pvRgnBaseAddress,&me)){
                _tcscat_s(szLine, cchMaxLen, me.szExePath);        
            } else{
                int cchLen = _tcslen(szLine);
    
                //如果不是一个模块,查看一下是否是内存映射文件
                DWORD dwLen = GetMappedFileName(hProcess,
                                                pVMQ->pvRgnBaseAddress,            
                                                szLine + cchLen, cchMaxLen - cchLen);
                //注意:当GetMappedFileName调用失败时,会修改缓冲区中的内容
                if (dwLen == 0){
                    szLine[cchLen] = 0; 
                }
            }
        }
    
        if (pVMQ->bRgnIsAStack){
            _tcscat_s(szLine, cchMaxLen, TEXT("线程栈"));
        }
    }
    //////////////////////////////////////////////////////////////////////////
    
    //将区域中一个块的信息加入添加到列表框中
    void ConstructBlkInfoLine(PVMQUERY pVMQ, PTSTR szLine, int cchMaxLen){
        _stprintf_s(szLine, cchMaxLen, TEXT("   %p	%s	%12u	"), 
                    pVMQ->pvBlkBaseAddress,
                    GetMemStorageText(pVMQ->dwBlkStorage),
                    pVMQ->BlkSize);
    
        if (pVMQ->dwBlkStorage != MEM_FREE){
            //增加一个空的单元格(因为对于块来说,该列没有个数这列)
            _tcscat_s(szLine, cchMaxLen, TEXT("	"));
            GetProtectText(pVMQ->dwBlkProtection, _tcschr(szLine, 0),
                           cchMaxLen - _tcslen(szLine), TRUE);
        } else{
            _tcscat_s(szLine, cchMaxLen, TEXT("	"));
        }
        _tcscat_s(szLine, cchMaxLen, TEXT("	"));
    }
    //////////////////////////////////////////////////////////////////////////
    
    void Refresh(HWND hWndLB, DWORD dwProcessID, BOOL bExpandRegions){
        //删除列表框内容,并增加水平滚动条
        ListBox_ResetContent(hWndLB);
        ListBox_SetHorizontalExtent(hWndLB, 300 * LOWORD(GetDialogBaseUnits()));
    
        //判断进程是否仍在运行
        HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessID);
    
        if (hProcess == NULL){
            ListBox_AddString(hWndLB, TEXT("")); //增加空行(为了更好看一点)
            ListBox_AddString(hWndLB, TEXT("   指定的进程己经退出!"));
            return;
        }
    
        //抓取指定进程的快照
        g_toolhelp.CreateSnapshot(TH32CS_SNAPALL, dwProcessID);
    
        //遍历进程地址空间
        BOOL bOk = TRUE;
        PVOID pvAddress = NULL;
    
        SetWindowRedraw(hWndLB, FALSE); //遍历期间,禁止刷新列表框界面
        while (bOk){
            VMQUERY vmq;
            bOk = VMQuery(hProcess, pvAddress, &vmq);
    
            if (bOk){
                //为区域内的每个块创建一行来显示
                TCHAR szLine[1024];
                ConstructRgnInfoLine(hProcess, &vmq, szLine, _countof(szLine));
                ListBox_AddString(hWndLB, szLine);
    
                //如果需要展开块,更增加显示各块的信息
                if (bExpandRegions){
                    for (DWORD dwBlock = 0; bOk && (dwBlock < vmq.dwRgnBlocks);dwBlock++){
                    
                        ConstructBlkInfoLine(&vmq, szLine, _countof(szLine));
                        ListBox_AddString(hWndLB, szLine);
    
                        //获取下一个区域的地址(注意,不是块)
                        pvAddress = ((PBYTE)pvAddress + vmq.BlkSize);
                        if (dwBlock<vmq.dwRgnBlocks-1){
                            //区域的最后一个块不需要查询
                            bOk = VMQuery(hProcess, pvAddress, &vmq);
                        }
                    }
                }
    
                //获取下一个区域(注意是区域,不是区域内的块)
                pvAddress = ((PBYTE)vmq.pvRgnBaseAddress + vmq.RgnSize);
            }
        }
    
        SetWindowRedraw(hWndLB, TRUE);  //遍历完成,刷新列表框界面
        CloseHandle(hProcess);
    }
    
    //////////////////////////////////////////////////////////////////////////
    void Dlg_OnSize(HWND hWnd, UINT state, int cx, int cy){
        //将列表框铺满客户区
        SetWindowPos(GetDlgItem(hWnd, IDC_LISTBOX), NULL, 0, 0, cx, cy,SWP_NOZORDER);
    }
    
    //////////////////////////////////////////////////////////////////////////
    void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtrl, UINT codeNotity)
    {
        switch (id)
        {
        case IDCANCEL:
            EndDialog(hwnd, id);
            break;
    
        case ID_REFRESH:
            Refresh(GetDlgItem(hwnd, IDC_LISTBOX), g_dwProcessID, g_bExpandRegions);
            break;
    
        case ID_EXPANDREGIONS:
            g_bExpandRegions = !g_bExpandRegions;
            Refresh(GetDlgItem(hwnd, IDC_LISTBOX), g_dwProcessID, g_bExpandRegions);
            break;
    
        case ID_COPYTOCLIPBOARD:
            CopyControlToClipboard(GetDlgItem(hwnd, IDC_LISTBOX));
            break;
        }
    }
    
    //////////////////////////////////////////////////////////////////////////
    BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
    {
        chSETDLGICONS(hwnd, IDI_VMMAP);
    
        //在标题栏中正在分析的是哪个进程
        TCHAR szCaption[MAX_PATH * 2];
        GetWindowText(hwnd, szCaption, _countof(szCaption));
    
        g_toolhelp.CreateSnapshot(TH32CS_SNAPALL, g_dwProcessID);
        PROCESSENTRY32 pe = { sizeof(pe) };
        StringCchPrintf(&szCaption[_tcslen(szCaption)], _countof(szCaption) - _tcslen(szCaption),
                        TEXT("(PID=%u "%s")"),
                        g_dwProcessID,
                        g_toolhelp.ProcessFind(g_dwProcessID, &pe) ? pe.szExeFile : TEXT("未知"));
        SetWindowText(hwnd, szCaption);
    
        //默认显示方式为最大化
        ShowWindow(hwnd, SW_MAXIMIZE);
    
        //设置列表框各列的宽度
        int  aTabs[5];
        aTabs[0] = 48;
        aTabs[1] = aTabs[0] + 40;
        aTabs[2] = aTabs[1] + 52;//Count
        aTabs[3] = aTabs[2] + 12;//flags
        aTabs[4] = aTabs[3] + 20;//描述
    
        ListBox_SetTabStops(GetDlgItem(hwnd, IDC_LISTBOX), _countof(aTabs), aTabs);
    
        //强制刷新列表框
        Refresh(GetDlgItem(hwnd,IDC_LISTBOX),g_dwProcessID,g_bExpandRegions);
        return (TRUE);
    }
    
    //////////////////////////////////////////////////////////////////////////
    INT_PTR WINAPI Dlg_Proc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam){
        switch (uMsg)
        {
            chHANDLE_DLGMSG(hDlg, WM_INITDIALOG, Dlg_OnInitDialog);
            chHANDLE_DLGMSG(hDlg, WM_COMMAND, Dlg_OnCommand);
            chHANDLE_DLGMSG(hDlg, WM_SIZE, Dlg_OnSize);
        }
        return (FALSE);
    }
    
    //////////////////////////////////////////////////////////////////////////
    int WINAPI _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
    {
        CToolhelp::EnablePrivilege(SE_DEBUG_NAME, TRUE);
    
        g_dwProcessID = _ttoi(lpCmdLine);
        if (g_dwProcessID == 0){
            g_dwProcessID = GetCurrentProcessId();
        }
        DialogBox(hInstance, MAKEINTRESOURCE(IDD_VMMAP), NULL, Dlg_Proc);
        CToolhelp::EnablePrivilege(SE_DEBUG_NAME, FALSE);
    }

    //VMQuery.h

    /*************************************************************************
    Module: VMQuery.h
    Notices:Copyright(c) 2008 Jeffrey Richter & Christophe Nasarre
    *************************************************************************/
    #pragma once
    #include <windows.h>
    
    //////////////////////////////////////////////////////////////////////////
    typedef struct{
        //区域信息
        PVOID    pvRgnBaseAddress;
        DWORD    dwRgnProtection; //PAGE_*
        SIZE_T    RgnSize;
        DWORD   dwRgnStorage;    //MEM_*:Free,Image,Mapped,Private
        DWORD   dwRgnBlocks;
        DWORD   dwRgnGuardBlks;  //If>0,表示区域包含线程栈
        BOOL    bRgnIsAStack;    //TRUE:区域包含线程栈
    
        //块信息
        PVOID    pvBlkBaseAddress;
        DWORD    dwBlkProtection;  //PAGE_*
        SIZE_T  BlkSize;
        DWORD   dwBlkStorage;     //MEM_*:Free,Reserve,Image,Mapped,Private
    }VMQUERY, *PVMQUERY;
    
    //////////////////////////////////////////////////////////////////////////
    
    BOOL VMQuery(HANDLE hProcess, LPCVOID pvAddress, PVMQUERY pVMQ);
    
    
    ///////////////////////////////文件结束///////////////////////////////////

    //VMQuery.cpp

    /*************************************************************************
    Module: VMQuery.cpp
    Notices:Copyright(c) 2008 Jeffrey Richter & Christophe Nasarre
    *************************************************************************/
    
    #include "../../CommonFiles/CmnHdr.h"
    #include "VMQuery.h"
    
    //////////////////////////////////////////////////////////////////////////
    //Helper 结构体
    typedef struct{
        SIZE_T    RgnSize;
        DWORD   dwRgnStorage;    //MEM_*:Free,Image,Mapped,Private
        DWORD   dwRgnBlocks;
        DWORD   dwRgnGuardBlks;  //If>0,表示区域包含线程栈
        BOOL    bRgnIsAStack;    //TRUE:区域包含线程栈
    }VMQUERY_HELP,*PVMQUERY_HELP;
    //////////////////////////////////////////////////////////////////////////
    
    //全局变量用来保存CPU分配粒度
    static DWORD gs_dwAllocGran = 0;
    //////////////////////////////////////////////////////////////////////////
    
    //遍历一个区域中所有的块,并将汇总信息通过VMQUERY_HELP返回
    static BOOL VMQueryHelp(HANDLE hProcess, LPCVOID pvAddress, VMQUERY_HELP* pVMQHelp){
        ZeroMemory(pVMQHelp, sizeof(*pVMQHelp));
        
        //获得区域信息
        MEMORY_BASIC_INFORMATION  mbi;
        BOOL bOk = (sizeof(mbi) == 
                    VirtualQueryEx(hProcess, pvAddress, &mbi, sizeof(mbi)));
        if (!bOk){
            return bOk;  //错误的内存地址,返回FALSE
        }
    
        pVMQHelp->dwRgnStorage = mbi.Type;
    
        //从区域起始地址开始遍历
        PVOID pvRgnBaseAddress = mbi.AllocationBase;//(这里是不会变的)
    
        //块的地址指针,先指向第1个块
        PVOID pvAddressBlk = pvRgnBaseAddress;
        for (;;){
            //获得当前块的信息
            bOk = (VirtualQueryEx(hProcess, pvAddressBlk, &mbi,
                sizeof(mbi))==sizeof(mbi));
    
            if (!bOk)
                break;  //无法获得信息,则退出循环
    
            //块是否在同一个区域?
            if (mbi.AllocationBase != pvRgnBaseAddress)
                break;   //如果是下一个区域中的块,则退出循环
    
            //己经获得了区域中的一个块
            pVMQHelp->dwRgnBlocks++;   //找到一个块,块数加1
            pVMQHelp->RgnSize += mbi.RegionSize; //将块大小累加到区域大小
    
            //如果块具有PAGE_GUARD属性,则计数加1
            if ((mbi.Protect & PAGE_GUARD) == PAGE_GUARD)
                pVMQHelp->dwRgnGuardBlks++;
    
            //判断区域的物理存储器类型,因为块可能从MEM_IMAGE转为MEM_PRIVATE
            //或从MEM_MAPPED转为MEM_PRIVATE;而MEM_PRIVATE总是可以被MEM_IMAGE
            //或MEM_MAPPED重写。
            if (pVMQHelp->dwRgnStorage == MEM_PRIVATE)
                pVMQHelp->dwRgnStorage = mbi.Type;
    
            //获取一下个块的地址
            pvAddressBlk = (PVOID)((PBYTE)pvAddressBlk + mbi.RegionSize);
        }
    
        //最后检查区域是否包含有线程栈
        pVMQHelp->bRgnIsAStack = (pVMQHelp->dwRgnGuardBlks > 0);
        return (TRUE);
    }
    //////////////////////////////////////////////////////////////////////////
    
    BOOL VMQuery(HANDLE hProcess, LPCVOID pvAddress, PVMQUERY pVMQ){
        if (gs_dwAllocGran ==0){
            //第1次调用时,先获取CPU分配粒度
            SYSTEM_INFO  sinf;
            GetSystemInfo(&sinf);
            gs_dwAllocGran = sinf.dwAllocationGranularity;
        }
    
        ZeroMemory(pVMQ, sizeof(*pVMQ));//初始化VMQUERY结构体
    
        //通过传入的pvAddress获得MEMORY_BASIC_INFORMATION信息
        MEMORY_BASIC_INFORMATION mbi;
        BOOL bOk = (VirtualQueryEx(hProcess, pvAddress, &mbi, sizeof(mbi))
                    == sizeof(mbi));
    
        if (!bOk){
            return (bOk);   //错误的内存地址,返回失败
        }
    
        //首先,填充块字段
        switch (mbi.State) //3种状态:FREE、RESERVE和COMMIT
        {
            case MEM_FREE:  //空闲块
                pVMQ->pvBlkBaseAddress = NULL;
                pVMQ->BlkSize = 0;
                pVMQ->dwBlkProtection = 0;
                pVMQ->dwBlkStorage = MEM_FREE;
                break;
    
            case MEM_RESERVE: //保留,(未提交到该块存储器里)
                pVMQ->pvBlkBaseAddress = mbi.BaseAddress;
                pVMQ->BlkSize = mbi.RegionSize;
    
                //对于一个未提交的块,mbi.Protect是无效的。所以可以让
                //块的属性继承自区域的保护属性
                pVMQ->dwBlkProtection = mbi.AllocationProtect;
                pVMQ->dwBlkStorage = MEM_RESERVE;
                break;
    
            case MEM_COMMIT: //己提交块
                pVMQ->pvBlkBaseAddress = mbi.BaseAddress;
                pVMQ->BlkSize = mbi.RegionSize;
                pVMQ->dwBlkProtection = mbi.Protect;
                pVMQ->dwBlkStorage = mbi.Type;
                break;
    
            default:
                DebugBreak();
                break;
        }
    
        //然后,填充区域字段
        VMQUERY_HELP VMQHelp;
        switch (mbi.State)
        {
            case MEM_FREE: //空闲
                pVMQ->pvRgnBaseAddress = mbi.BaseAddress;
                pVMQ->dwRgnProtection = mbi.AllocationProtect;
                pVMQ->RgnSize = mbi.RegionSize;
                pVMQ->dwRgnStorage = MEM_FREE;
                pVMQ->dwRgnBlocks = 0;
                pVMQ->dwRgnGuardBlks = 0; //1为线程栈所预订
                pVMQ->bRgnIsAStack = FALSE;
                break;
    
            case MEM_RESERVE:
                pVMQ->pvRgnBaseAddress = mbi.AllocationBase; //这里与上面的块是不同的。
                pVMQ->dwRgnProtection = mbi.AllocationProtect;
    
                //迭代,通过所有块属性来推荐整个区域的属性
                VMQueryHelp(hProcess, pvAddress, &VMQHelp);
                pVMQ->RgnSize = VMQHelp.RgnSize;
                pVMQ->dwRgnStorage = VMQHelp.dwRgnStorage;
                pVMQ->dwRgnBlocks = VMQHelp.dwRgnBlocks;
                pVMQ->dwRgnGuardBlks = VMQHelp.dwRgnGuardBlks;
                pVMQ->bRgnIsAStack = VMQHelp.bRgnIsAStack;        
                break;
    
            case MEM_COMMIT: //己提交
                pVMQ->pvRgnBaseAddress = mbi.AllocationBase; //这里与上面的块是不同的。
                pVMQ->dwRgnProtection = mbi.AllocationProtect;
    
                //迭代,通过所有块属性来推荐整个区域的属性
                VMQueryHelp(hProcess, pvAddress, &VMQHelp);
                pVMQ->RgnSize = VMQHelp.RgnSize;
                pVMQ->dwRgnStorage = VMQHelp.dwRgnStorage;
                pVMQ->dwRgnBlocks = VMQHelp.dwRgnBlocks;
                pVMQ->dwRgnGuardBlks = VMQHelp.dwRgnGuardBlks;
                pVMQ->bRgnIsAStack = VMQHelp.bRgnIsAStack;
                break;
    
            default:
                DebugBreak();
                break;
        }
    
        return bOk;
    }
    ////////////////////////////////////文件结束////////////////////////////////

    //resource.h

    //{{NO_DEPENDENCIES}}
    // Microsoft Visual C++ 生成的包含文件。
    // 供 14_VMMap.rc 使用
    //
    #define IDD_VMMAP                       100
    #define IDC_LISTBOX                     101
    #define IDI_VMMAP                       102
    #define IDR_MENU1                       102
    #define IDR_VMMAP                       103
    #define ID_REFRESH                      40001
    #define ID_EXPANDREGIONS                40002
    #define ID_COPYTOCLIPBOARD              40003
    
    // Next default values for new objects
    // 
    #ifdef APSTUDIO_INVOKED
    #ifndef APSTUDIO_READONLY_SYMBOLS
    #define _APS_NEXT_RESOURCE_VALUE        104
    #define _APS_NEXT_COMMAND_VALUE         40001
    #define _APS_NEXT_CONTROL_VALUE         1001
    #define _APS_NEXT_SYMED_VALUE           101
    #endif
    #endif

    //VMMap.rc

    // Microsoft Visual C++ generated resource script.
    //
    #include "resource.h"
    
    #define APSTUDIO_READONLY_SYMBOLS
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 2 resource.
    //
    #include "winres.h"
    
    /////////////////////////////////////////////////////////////////////////////
    #undef APSTUDIO_READONLY_SYMBOLS
    
    /////////////////////////////////////////////////////////////////////////////
    // 中文(简体,中国) resources
    
    #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
    LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
    
    #ifdef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // TEXTINCLUDE
    //
    
    1 TEXTINCLUDE 
    BEGIN
        "resource.h"
    END
    
    2 TEXTINCLUDE 
    BEGIN
        "#include ""winres.h""
    "
        ""
    END
    
    3 TEXTINCLUDE 
    BEGIN
        "
    "
        ""
    END
    
    #endif    // APSTUDIO_INVOKED
    
    
    /////////////////////////////////////////////////////////////////////////////
    //
    // Dialog
    //
    
    IDD_VMMAP DIALOGEX 0, 0, 337, 250
    STYLE DS_SETFONT | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
    CAPTION "虚拟内存映射"
    MENU IDR_VMMAP
    FONT 10, "宋体", 400, 0, 0x86
    BEGIN
        LISTBOX         IDC_LISTBOX,0,0,334,248,LBS_USETABSTOPS | LBS_NOINTEGRALHEIGHT | NOT WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_GROUP | WS_TABSTOP
    END
    
    
    /////////////////////////////////////////////////////////////////////////////
    //
    // DESIGNINFO
    //
    
    #ifdef APSTUDIO_INVOKED
    GUIDELINES DESIGNINFO
    BEGIN
        IDD_VMMAP, DIALOG
        BEGIN
            RIGHTMARGIN, 250
        END
    END
    #endif    // APSTUDIO_INVOKED
    
    
    /////////////////////////////////////////////////////////////////////////////
    //
    // Menu
    //
    
    IDR_VMMAP MENU
    BEGIN
        MENUITEM "刷新(&R)!",                     ID_REFRESH
        MENUITEM "展开区域(&E)!",                   ID_EXPANDREGIONS
        MENUITEM "复制(&C)!",                     ID_COPYTOCLIPBOARD
    END
    
    
    /////////////////////////////////////////////////////////////////////////////
    //
    // Icon
    //
    
    // Icon with lowest ID value placed first to ensure application icon
    // remains consistent on all systems.
    IDI_VMMAP               ICON                    "VMMap.ico"
    #endif    // 中文(简体,中国) resources
    /////////////////////////////////////////////////////////////////////////////
    
    
    
    #ifndef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 3 resource.
    //
    
    
    /////////////////////////////////////////////////////////////////////////////
    #endif    // not APSTUDIO_INVOKED
  • 相关阅读:
    【原创】【js】screenLeft screenTop screenX screenY属性的有效性和兼容性研究
    兼容兼容兼容:浏览器兼容性大集合
    Vue 打包成APP后首屏出现白屏问题
    uniapp 安卓app端本地打包错误: Not found -1,6 at view.umd.min.js:1
    uniapp 下获取cid
    uniapp fill abort statuscode:-1
    Vuex刷新时数据会消失,那如何解决?为什么还要使用Vuex
    vue 安装失败;vue不是内部或外部命令
    js 文件下载,多个文件下载,pdf下载
    uni-App 去掉顶部导航栏
  • 原文地址:https://www.cnblogs.com/5iedu/p/4853561.html
Copyright © 2011-2022 走看看