Hook DirectInput->CreateDevice->GetDeviceData解决方案

 

已解决,来人散分了,Hook DirectInput->CreateDevice->GetDeviceData
在一款使用DirectInput的3D游戏里面,通过Hook DirectInput8Create函数,CreateDevice方法,取得了GetDeviceData函数指针,在GetDeviceData里面已经可以取得键盘输入的数据(程序未使用GetDeviceState获得数据)

C/C++ code

HRESULT CHook::MyGetDeviceData(LPVOID *ppvOut, DWORD cbObjectData, LPDIDEVICEOBJECTDATA didod, LPDWORD pdwInOut, DWORD dwFlags)
{
    HRESULT hr = CGetDeviceData::Real(ppvOut, cbObjectData, didod, pdwInOut, dwFlags);
    if(SUCCEEDED(hr))
    {
        for(DWORD i = 0; i < *pdwInOut; i++)
        {
            if(didod[i].dwOfs == DIK_CAPSLOCK)
            {
                if(didod[i].dwData & 0x80)
                {
                    m_TurnLeft = !m_TurnLeft;
                    didod[i].dwOfs = m_TurnLeft ? DIK_A : DIK_D;
                }
                else
                    didod[i].dwOfs = m_TurnLeft ? DIK_A : DIK_D;
            }
        }
    }
    return hr;
}


函数是通过定义的基类CGetDeviceData的纯虚函数MyGetDeviceData进入的,现在的问题是:
只有部分键可以修改,例如DIK_I键,打开物品栏,直接写成

C/C++ code

HRESULT CHook::MyGetDeviceData(LPVOID *ppvOut, DWORD cbObjectData, LPDIDEVICEOBJECTDATA didod, LPDWORD pdwInOut, DWORD dwFlags)
{
    HRESULT hr = CGetDeviceData::Real(ppvOut, cbObjectData, didod, pdwInOut, dwFlags);
    if(SUCCEEDED(hr))
    {
        for(DWORD i = 0; i < *pdwInOut; i++)
        {
            if(didod[i].dwOfs == DIK_I)
            {
                didod[i].dwOfs = DIK_L;
            }
        }
    }
    return hr;
}


并不能打开L键的功能,仍然打开I对应的功能(关于这一点不能理解,例如我修改A=D,D=A可以倒转A、D键位),还有我键盘没有SCROLL键,这个键在这个游戏中是录像的功能,我修改HOME键指向SCROLL也没有效果(断点确实修改了)。
在X64 win7系统,不能写驱动实现。

还有如何在MyGetDeviceData添加按键?

附上基类CGetDeviceData代码

C/C++ code

// CGetDeviceData
typedef HRESULT (WINAPI *lpGetDeviceData)(LPVOID *ppvOut, DWORD cbObjectData, LPDIDEVICEOBJECTDATA didod, LPDWORD pdwInOut, DWORD dwFlags);
class CGetDeviceData
{
private:
    static CGetDeviceData* m_this;
    static HRESULT WINAPI _MyGetDeviceData(LPVOID *ppvOut, DWORD cbObjectData, LPDIDEVICEOBJECTDATA didod, LPDWORD pdwInOut, DWORD dwFlags){
        return m_this->MyGetDeviceData(ppvOut, cbObjectData, didod, pdwInOut, dwFlags);
    };
public:
    lpGetDeviceData Real;
    virtual HRESULT MyGetDeviceData(LPVOID *ppvOut, DWORD cbObjectData, LPDIDEVICEOBJECTDATA didod, LPDWORD pdwInOut, DWORD dwFlags) = 0;
    void Init(LPVOID *lplpDirectInputDevice){
        ULONG* vptr = *(*(ULONG***)lplpDirectInputDevice);
        Real = (lpGetDeviceData)vptr[10];
        vptr[10] = (ULONG)_MyGetDeviceData;
    };
    CGetDeviceData(){
        m_this = this;
        Real = NULL;
    };
};
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是代码形式的电话线路图状态: ``` @startuml title Telephone State Diagram [*] --> Idle : Initial State Idle --> Dialing : Off Hook Event Dialing --> Connecting : Valid Number Event Dialing --> Disconnected : Invalid/Wrong Number Event Connecting --> TimeOut : Timeout Event Connecting --> Connected : Called Phone Answers Event Ringing --> Connected : Called Phone Answers Event Connected --> Idle : On Hook Event Connected --> Busy Tone : Line Busy Event Connected --> TimeOut : Timeout Event Connected --> Disconnected : Timeout Event Connected --> Ringing : Play Message Event @enduml ``` 解释一下: - 初始状态为空闲状态(`[*] --> Idle : Initial State`)。 - 当电话机摘机时,电话状态从空闲状态转入拨号状态(`Idle --> Dialing : Off Hook Event`)。 - 当拨号有效号码时,电话状态从拨号状态转入连接状态(`Dialing --> Connecting : Valid Number Event`)。 - 当拨号号码无效或错误时,电话状态从拨号状态转入未连接状态(`Dialing --> Disconnected : Invalid/Wrong Number Event`)。 - 当连接超时时,电话连接状态从连接状态转入超时状态(`Connecting --> TimeOut : Timeout Event`)。 - 当被拨打的电话接听时,电话连接状态从连接状态或响铃状态转入已连接状态(`Connecting --> Connected : Called Phone Answers Event` 或 `Ringing --> Connected : Called Phone Answers Event`)。 - 当已连接状态的电话机挂机时,电话状态从已连接状态转入空闲状态(`Connected --> Idle : On Hook Event`)。 - 当已连接状态的电话线路忙碌时,电话状态从已连接状态转入忙音状态(`Connected --> Busy Tone : Line Busy Event`)。 - 当已连接状态的电话连接超时时,电话状态从已连接状态转入未连接状态(`Connected --> TimeOut : Timeout Event`)。 - 当已连接状态的电话播放信息时,电话状态从已连接状态转入响铃状态(`Connected --> Ringing : Play Message Event`)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值