Ok... Let's hook the GetDeviceData too ^^. About the glitch, yes. That's why I try to make the calls thread safe before trying any other raw game call. I traced the whole function above the one sending the skill in order to understand what drives the send.
I reached this part of the code :
Code:
/* if the jump occurs you skip the send of the skill
0088B10B mov edx,eax
0088B10D and edx,7
0088B110 mov cl,dl
0088B112 shr bl,cl
0088B114 test bl,1
0088B117 je 0088B1E7
*/
But I have no clue about what this test is really...
edit : Argh this stupid double post automerge again...
Failed to hook GetDeviceData()... Can't understand what happens here. Before I hook anything the normal call of GetDeviceData() is always performed with specific device through a specific callstack. But at the exact moment I hook the function, an unexpected call to my newly hooked function is performed through this crazy callstack with an unexpected unkown device and the game, (not my hooked function currently doing nothing else than recalling the original function), simply crash because it doesn't handle this case (unknown device return).
The unexpected callstack just right before calling GetDeviceData()
Code:
> game.bin!005f32af()
[Les frames ci-dessous sont peut-être incorrects et/ou manquants, aucun symbole chargé pour game.bin]
user32.dll!_UserCallWinProcCheckWow@32() + 0x10e octets
0018fc40()
ntdll.dll!_KiUserCallbackDispatcher@12() + 0x2e octets
game.bin!0078da6c()
game.bin!005ef361()
game.bin!004ffab5()
game.bin!00502634()
game.bin!0065b5cc()
game.bin!0050539a()
ntdll.dll!_NtQueryInformationProcess@20() + 0x12 octets
ntdll.dll!_RtlEncodePointer@4() + 0x17 octets
game.bin!00550047()
And the code supposed to work...
Code:
// DInputHook.cpp*: définit le point d'entrée pour l'application console.
//
#define _CRT_SECURE_NO_WARNINGS
#define DIRECTINPUT_VERSION 0x0800
#include <Windows.h>
#include <cstdio>
#include <time.h>
#include <dinput.h>
DWORD WINAPI HookThread();
DWORD WINAPI UnhookThread();
void add_log(char* format, ...);
void *SetDetour(BYTE *source, const BYTE *destination, unsigned int length);
void UnSetDetour(BYTE *source, const BYTE *destination, unsigned int length, BYTE *tunnel);
HRESULT __stdcall hkGetDeviceState(LPDIRECTINPUTDEVICE lpDevice, DWORD cbData, LPVOID lpvData);
typedef HRESULT(__stdcall* GetDeviceState_t)(LPDIRECTINPUTDEVICE, DWORD, LPVOID);
HRESULT hkGetDeviceData(LPDIRECTINPUTDEVICE lpDevice, DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags);
typedef HRESULT(__stdcall* GetDeviceData_t)(LPDIRECTINPUTDEVICE, DWORD, LPDIDEVICEOBJECTDATA, LPDWORD, DWORD);
GetDeviceState_t pGetDeviceState;
GetDeviceData_t pGetDeviceData;
HMODULE hModDInput8 = NULL;
FARPROC dwGetDeviceState = NULL;
FARPROC dwGetDeviceData = NULL;
FARPROC dwDirectInput8Create = NULL;
HANDLE tmpHandle = NULL;
bool Freeze = false;
bool ShouldExitThread = false;
BOOL WINAPI DllMain(HINSTANCE hinstDll,DWORD Reason,LPVOID Reserved)
{
switch(Reason)
{
case DLL_PROCESS_ATTACH:
add_log("==========LOG START==========");
add_log("DLL Attached");
add_log("Creating Thread...");
tmpHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&HookThread, 0, 0, 0);
if (!tmpHandle)
{
add_log("ThreadCreation Failed!");
}
break;
case DLL_PROCESS_DETACH:
ShouldExitThread = true;
Sleep(1000);
UnhookThread();
add_log("DLL Detached");
add_log("==========LOG END==========\n\n\n");
break;
}
return 1;
}
DWORD WINAPI HookThread(void)
{
add_log("Thread Created");
while (!hModDInput8)
{
add_log("Searching dinput8.dll...");
hModDInput8 = GetModuleHandle(L"dinput8.dll");
Sleep(100);
}
add_log("Found dinput8.dll: %x !", hModDInput8);
while (!dwDirectInput8Create)
{
add_log("Searching GetDeviceState...");
dwDirectInput8Create = GetProcAddress(hModDInput8, "DirectInput8Create");
Sleep(100);
}
add_log("Found DirectInput8Create: %x !", dwDirectInput8Create);
dwGetDeviceState = (FARPROC) ((DWORD)dwDirectInput8Create - 0x62B1);// C34CC8E - C3469DD
add_log("GetDeviceState is here (DirectInput8Create - 0x62B1): %x", dwGetDeviceState);
add_log("Hooking GetDeviceState...");
pGetDeviceState = (GetDeviceState_t) SetDetour((PBYTE) dwGetDeviceState, (PBYTE) hkGetDeviceState, 5);
add_log("Hooked GetDeviceState - Detour : %x - New: %x !", pGetDeviceState, hkGetDeviceState);
dwGetDeviceData = (FARPROC) ((DWORD)dwDirectInput8Create - 0x60E7);// C34CC8E - C346BA7
add_log("GetDeviceData is here (DirectInput8Create - 0x60E7): %x", dwGetDeviceData);
add_log("Hooking GetDeviceData...");
pGetDeviceData = (GetDeviceData_t) SetDetour((PBYTE) dwGetDeviceData, (PBYTE) hkGetDeviceData, 5);
add_log("Hooked GetDeviceData - Detour : %x - New: %x !", pGetDeviceData, hkGetDeviceData);
while (!ShouldExitThread)
{
if( GetAsyncKeyState( VK_F12 ) &1 )
{
Freeze = !Freeze;
Sleep(500);
}
Sleep(10);
}
return 0;
}
DWORD WINAPI UnhookThread(void)
{
UnSetDetour((BYTE *)dwGetDeviceState, (BYTE *)hkGetDeviceState, 5, (BYTE *)pGetDeviceState);
add_log("Unhooked GetDeviceState - Detour : %x - New: %x !", hkGetDeviceState, pGetDeviceState);
pGetDeviceState = NULL;
UnSetDetour((BYTE *)dwGetDeviceData, (BYTE *)hkGetDeviceData, 5, (BYTE *)pGetDeviceData);
add_log("Unhooked GetDeviceData - Detour : %x - New: %x !", hkGetDeviceData, pGetDeviceData);
pGetDeviceData = NULL;
return S_OK; // exit current thread
}
void add_log(char* format, ...)
{
HANDLE filehandle;
DWORD dwReadBytes;
char buffer[2048];
char writebuffer[2048];
va_list args;
va_start(args, format);
vsprintf (buffer, format, args);
filehandle = CreateFile(L"Log.txt", GENERIC_WRITE, 0, 0, OPEN_ALWAYS, 0, 0);
SetFilePointer(filehandle, 0, 0, FILE_END);
char date[18];
_strdate(date);
date[8] = ' ';
_strtime(date+9);
sprintf_s(writebuffer, 2048, "Log Added (%s): %s\r\n", date, buffer);
WriteFile(filehandle, writebuffer, strlen(writebuffer), &dwReadBytes, 0);
CloseHandle(filehandle);
}
void *SetDetour(BYTE *source, const BYTE *destination, unsigned int length)
{
unsigned int const jmpLength(5);
unsigned int const nopOpcode(0x90);
unsigned int const jmpOpcode(0xE9);
if (length < jmpLength)
length = jmpLength; // Make sure the patch's length is long enough to hold a 32bit JMP.
unsigned int tunnelLength = length + jmpLength;
BYTE *tunnel = new BYTE[tunnelLength]; // Create a body for the "tunnel" function.
FillMemory(tunnel, tunnelLength, 0);
DWORD oldProtection(NULL); // Old page protection.
VirtualProtect(source, length, PAGE_EXECUTE_READWRITE, &oldProtection);
memcpy(tunnel, source, length);
FillMemory(source, length, nopOpcode);// erase source opcode
source[0] = jmpOpcode;
tunnel[length] = jmpOpcode;
*(DWORD*)(source + 1) = (DWORD)(destination - source) - jmpLength; // JMP Offset 1
*(DWORD*)(tunnel + 1 + length) = (DWORD)(source - tunnel) - jmpLength; // JMP Offset 2
VirtualProtect(source, length, oldProtection, &oldProtection);
return tunnel;
}
void UnSetDetour(BYTE *source, const BYTE *destination, unsigned int length, BYTE *tunnel)
{
unsigned int const jmpLength(5);
unsigned int const nopOpcode(0x90);
unsigned int const jmpOpcode(0xE9);
if (length < jmpLength)
length = jmpLength; // Make sure the patch's length is long enough to hold a 32bit JMP.
unsigned int tunnelLength = length + jmpLength;
DWORD oldProtection(NULL); // Old page protection.
VirtualProtect(source, length, PAGE_EXECUTE_READWRITE, &oldProtection);
memcpy(source, tunnel, length);// copy back the original opcode
VirtualProtect(source, length, oldProtection, &oldProtection);
delete[] tunnel;
}
HRESULT __stdcall hkGetDeviceState(LPDIRECTINPUTDEVICE lpDevice, DWORD cbData, LPVOID lpvData)
{
static BYTE buffer[256];
HRESULT temp = DI_OK;
temp = pGetDeviceState(lpDevice, cbData, lpvData); // original code
if(cbData != 256)
return temp;
{
for (DWORD i = 0; i < 256; ++i)
{
if(((BYTE*)lpvData)[i]!=buffer[i])
add_log("Key 0x%X %s", i, (((BYTE*)lpvData)[i]&0x80) ? "pressed" : "released");
}
}
memcpy(buffer, lpvData, cbData);
return temp;
}
HRESULT hkGetDeviceData(LPDIRECTINPUTDEVICE lpDevice, DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags)
{
HRESULT temp = DI_OK;
temp = pGetDeviceData(lpDevice, cbObjectData, rgdod, pdwInOut, dwFlags); // original code
// if (temp == DI_OK)
// {
// for(DWORD i = 0; i < *pdwInOut; ++i)
// {
// if (rgdod[i].dwData & 0x80) // only key-down events are reported
// {
// add_log("Key 0x%X %s", rgdod[i].dwOfs, (rgdod[i].dwData & 0x80) ? "pressed" : "released");
// }
// }
// }
return temp;
}
Honestly these hook failures start to make me really sick... I just simply don't understand wtf happens. I feel like loosing my few free time for... nothing exept headaches -_-.