已解决,来人散分了,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;
};
};