65.9K
CodeProject 正在变化。 阅读更多。
Home

CProcessData:一个模板类,用于简化进程间的 SendMessage 调用

starIconstarIconstarIconstarIconstarIcon

5.00/5 (39投票s)

2005年6月10日

1分钟阅读

viewsIcon

136552

downloadIcon

1355

CProcessData是一个模板类,可以轻松地使用在不同进程中分配的数据,并且在进行进程间SendMessage/PostMessage调用时非常有用。

概述

CProcessData是一个模板类,可以轻松地使用在不同进程中分配的数据,并且在进行进程间SendMessage/PostMessage调用时非常有用。

示例场景 - 1

假设你要向另一个进程中的日期/时间选择器控件发送DTM_SETSYSTEMTIME消息。

未使用CProcessData

SYSTEMTIME systim;
//Populate systim

HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
LPVOID lpData = VirtualAllocEx(hProc, NULL, 
    sizeof SYSTEMTIME, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProc, lpData, (LPCVOID)&systim, 
    sizeof SYSTEMTIME, NULL);            

DWORD dwResult = (DWORD)::SendMessage(hwnd, 
    DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&lpData);

if(dwResult == 0)
{
    DWORD err = GetLastError();
    //...
}

VirtualFreeEx(hProc, lpData, NULL, MEM_RELEASE);
CloseHandle(hProc);

使用CProcessData

SYSTEMTIME systim;
//Populate systim

CProcessData<SYSTEMTIME> data(pid);
data.WriteData(systim);

DWORD dwResult = (DWORD)::SendMessage(hwnd, 
    DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)data.GetData());
    
if(dwResult == 0)
{
    DWORD err = GetLastError();
    //...
}

请注意,你不仅节省了代码行数,而且避免了忘记释放分配的内存或关闭进程句柄的风险。

示例场景 - 2

假设你要从另一个进程中的工具栏控件中检索工具栏信息。

未使用CProcessData

HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
LPVOID lpData = VirtualAllocEx(hProc, NULL, 
    sizeof TBBUTTON, MEM_COMMIT, PAGE_READWRITE);      

::SendMessage(hwnd, TB_GETBUTTON, index, (LPARAM)lpData);

TBBUTTON tb;
ReadProcessMemory(hProc, lpData,(LPVOID)&tb, 
    sizeof TBBUTTON, NULL)

CUSTOMDATA cus;
ReadProcessMemory(hProc, (LPCVOID)tb.dwData, (LPVOID)&cus, 
    sizeof CUSTOMDATA, NULL)

VirtualFreeEx(hProc,lpData,NULL,MEM_RELEASE);
CloseHandle(hProc);

使用CProcessData

CProcessData<TBBUTTON> data(pid);

::SendMessage(hwnd, TB_GETBUTTON, index, 
    (LPARAM)data.GetData());

TBBUTTON tb;
data.ReadData(&tb);    

CUSTOMDATA cus;
data.ReadData<CUSTOMDATA>(&cus,(LPCVOID)tb.dwData);

很不错,对吧?

类参考

构造函数

CProcessData(DWORD dwProcessId = 0, DWORD dwDesiredAccess = PROCESS_ALL_ACCESS, DWORD flAllocationType = MEM_COMMIT, DWORD flProtect = PAGE_READWRITE)

如果你传入dwProcessId为0,则使用当前进程Id。对于其他参数,请参阅MSDN文档中的OpenProcessVirtualAllocEx

WriteData

BOOL WriteData(const T& data)

WriteDatadata复制到目标进程的内存中

ReadData

BOOL ReadData(T* data)

ReadData从目标进程的内存中读取数据到data中。

ReadData (模板版本)

template<typename TSUBTYPE> BOOL ReadData(TSUBTYPE* data, LPCVOID lpData)

模板化的ReadData,用于从目标进程中位于特定内存地址读取特定数据类型。

完整源代码

[列表已格式化以适应600像素的宽度。实际源代码(作为下载提供)已格式化为更宽的屏幕]

/*
    Author  :    Nishant Sivakumar
    Date    :    June 9, 2005
    Info    :    Template class that makes it easy to use data allocated
                 in a different process. Useful when making inter-process
                 SendMessage/PostMessage calls.            
    Contact :    nish#voidnish.com
*/

//ProcessData.h

#pragma once

template<typename T> class CProcessData
{
public:    
    /*
        If you pass in a dwProcessId of 0, the current process Id is used.
        For the other arguments, see MSDN documentation for OpenProcess and
        VirtualAllocEx.
    */
    CProcessData(DWORD dwProcessId = 0, 
        DWORD dwDesiredAccess = PROCESS_ALL_ACCESS,
        DWORD flAllocationType = MEM_COMMIT, DWORD flProtect = PAGE_READWRITE)
    {
        m_hProcess = OpenProcess(dwDesiredAccess, FALSE, 
            dwProcessId ? dwProcessId : GetCurrentProcessId());
        ASSERT(m_hProcess);
        if(m_hProcess)
        {
            m_lpData = VirtualAllocEx(m_hProcess, NULL, sizeof T, 
                flAllocationType, flProtect);
            ASSERT(m_lpData);
        }
    }

    ~CProcessData()
    {
        if(m_hProcess)
        {            
            if(m_lpData)
            {
                VirtualFreeEx(m_hProcess, m_lpData, NULL, MEM_RELEASE);
            }
            CloseHandle(m_hProcess);
        }
    }

    //WriteData is used to copy data to memory in the foreign process
    BOOL WriteData(const T& data)
    {
        return (m_hProcess && m_lpData) ? WriteProcessMemory(
            m_hProcess, m_lpData, 
            (LPCVOID)&data, sizeof T, NULL) : FALSE;
    }

    //ReadData reads back data from memory in the foreign process
    BOOL ReadData(T* data)
    {
        return (m_hProcess && m_lpData) ? ReadProcessMemory(
            m_hProcess, m_lpData, 
            (LPVOID)data, sizeof T, NULL) : FALSE;
    }

    //Templated ReadData that's used to read a specific data type from
    //a memory address located in the foreign process
    template<typename TSUBTYPE> BOOL ReadData(
        TSUBTYPE* data, LPCVOID lpData)
    {
        return m_hProcess ? ReadProcessMemory(m_hProcess, lpData, 
            (LPVOID)data, sizeof TSUBTYPE, NULL) : FALSE;
    }

    //Gets the address of the allocated memory in the foreign process
    const T* GetData()
    {
        return (m_hProcess && m_lpData) ? (T*)m_lpData : NULL;
    }
private:
    T m_Data;
    HANDLE m_hProcess;
    LPVOID m_lpData;
};

历史

  • 2005年6月16日:修复了析构函数中的一个小错误。(VirtualFreeExCloseHandle的顺序错误)
  • 2005年6月10日:文章首次发布。
  • 2005年6月9日:类编写完成。
© . All rights reserved.