forked from TeamTofuShop/segatools
176
fgohook/ftdi.c
176
fgohook/ftdi.c
@ -8,15 +8,22 @@
|
||||
The game queries the presence of the FTDI board itself, followed by a
|
||||
registry check to see which port number is assigned to the FTDI board.
|
||||
If these fail, the "CABINET LED" check on startup will always return "NG".
|
||||
|
||||
Credits:
|
||||
|
||||
OLEG
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <setupapi.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "fgohook/ftdi.h"
|
||||
|
||||
#include "hook/iohook.h"
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "hooklib/setupapi.h"
|
||||
|
||||
@ -24,10 +31,97 @@
|
||||
|
||||
static struct ftdi_config ftdi_cfg;
|
||||
|
||||
static HANDLE ftdi_fd;
|
||||
|
||||
HRESULT ftdi_hook_init(const struct ftdi_config *cfg)
|
||||
{
|
||||
static BOOL WINAPI hook_SetupDiGetDeviceRegistryPropertyA(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
uint32_t Property,
|
||||
uint32_t *PropertyRegDataType,
|
||||
void *PropertyBuffer,
|
||||
uint32_t PropertyBufferSize,
|
||||
uint32_t *RequiredSize
|
||||
);
|
||||
|
||||
static HKEY WINAPI hook_SetupDiOpenDevRegKey(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
uint32_t Scope,
|
||||
uint32_t HwProfile,
|
||||
uint32_t KeyType,
|
||||
REGSAM samDesired
|
||||
);
|
||||
|
||||
static LSTATUS WINAPI hook_RegQueryValueExA(
|
||||
HKEY handle,
|
||||
const char *name,
|
||||
void *reserved,
|
||||
uint32_t *type,
|
||||
void *bytes,
|
||||
uint32_t *nbytes);
|
||||
|
||||
static LSTATUS WINAPI hook_RegCloseKey(HKEY handle);
|
||||
|
||||
|
||||
static BOOL (WINAPI *next_SetupDiGetDeviceRegistryPropertyA)(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
uint32_t Property,
|
||||
uint32_t *PropertyRegDataType,
|
||||
void *PropertyBuffer,
|
||||
uint32_t PropertyBufferSize,
|
||||
uint32_t *RequiredSize
|
||||
);
|
||||
|
||||
static HKEY (WINAPI *next_SetupDiOpenDevRegKey)(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
uint32_t Scope,
|
||||
uint32_t HwProfile,
|
||||
uint32_t KeyType,
|
||||
REGSAM samDesired
|
||||
);
|
||||
|
||||
static LSTATUS (WINAPI *next_RegQueryValueExA)(
|
||||
HKEY handle,
|
||||
const char *name,
|
||||
void *reserved,
|
||||
uint32_t *type,
|
||||
void *bytes,
|
||||
uint32_t *nbytes);
|
||||
|
||||
static LSTATUS (WINAPI *next_RegCloseKey)(HKEY handle);
|
||||
|
||||
|
||||
static const struct hook_symbol setupapi_syms[] = {
|
||||
{
|
||||
.name = "SetupDiGetDeviceRegistryPropertyA",
|
||||
.patch = hook_SetupDiGetDeviceRegistryPropertyA,
|
||||
.link = (void *) &next_SetupDiGetDeviceRegistryPropertyA,
|
||||
}, {
|
||||
.name = "SetupDiOpenDevRegKey",
|
||||
.patch = hook_SetupDiOpenDevRegKey,
|
||||
.link = (void *) &next_SetupDiOpenDevRegKey,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct hook_symbol reg_syms[] = {
|
||||
{
|
||||
.name = "RegQueryValueExA",
|
||||
.patch = hook_RegQueryValueExA,
|
||||
.link = (void *) &next_RegQueryValueExA,
|
||||
}, {
|
||||
.name = "RegCloseKey",
|
||||
.patch = hook_RegCloseKey,
|
||||
.link = (void *) &next_RegCloseKey,
|
||||
}
|
||||
};
|
||||
|
||||
#define device_fake_key 0xDEADBEEF
|
||||
|
||||
static HANDLE ftdi_fd;
|
||||
static char port_name[8];
|
||||
|
||||
HRESULT ftdi_hook_init(const struct ftdi_config *cfg) {
|
||||
HRESULT hr;
|
||||
|
||||
assert(cfg != NULL);
|
||||
@ -36,6 +130,18 @@ HRESULT ftdi_hook_init(const struct ftdi_config *cfg)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"setupapi.dll",
|
||||
setupapi_syms,
|
||||
_countof(setupapi_syms));
|
||||
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"advapi32.dll",
|
||||
reg_syms,
|
||||
_countof(reg_syms));
|
||||
|
||||
memcpy(&ftdi_cfg, cfg, sizeof(*cfg));
|
||||
|
||||
hr = iohook_open_nul_fd(&ftdi_fd);
|
||||
@ -50,6 +156,68 @@ HRESULT ftdi_hook_init(const struct ftdi_config *cfg)
|
||||
return hr;
|
||||
}
|
||||
|
||||
sprintf(port_name, "COM%d", cfg->port_no);
|
||||
|
||||
dprintf("FTDI: Hook enabled.\n");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static BOOL WINAPI hook_SetupDiGetDeviceRegistryPropertyA(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
uint32_t Property,
|
||||
uint32_t *PropertyRegDataType,
|
||||
void *PropertyBuffer,
|
||||
uint32_t PropertyBufferSize,
|
||||
uint32_t *RequiredSize
|
||||
) {
|
||||
if (!PropertyBuffer || PropertyBufferSize == 0) {
|
||||
*RequiredSize = 16;
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*PropertyRegDataType = 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static HKEY WINAPI hook_SetupDiOpenDevRegKey(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
uint32_t Scope,
|
||||
uint32_t HwProfile,
|
||||
uint32_t KeyType,
|
||||
REGSAM samDesired
|
||||
) {
|
||||
return (HKEY) device_fake_key;
|
||||
}
|
||||
|
||||
static LSTATUS WINAPI hook_RegCloseKey(HKEY handle) {
|
||||
if (handle == (HKEY) device_fake_key)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
return next_RegCloseKey(handle);
|
||||
}
|
||||
|
||||
static LSTATUS WINAPI hook_RegQueryValueExA(
|
||||
HKEY handle,
|
||||
const char *name,
|
||||
void *reserved,
|
||||
uint32_t *type,
|
||||
void *bytes,
|
||||
uint32_t *nbytes) {
|
||||
if (handle == (HKEY) device_fake_key && !strcmp(name, "PortName")) {
|
||||
strcpy(bytes, port_name);
|
||||
*nbytes = 5;
|
||||
*type = 1;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
return next_RegQueryValueExA(
|
||||
handle,
|
||||
name,
|
||||
reserved,
|
||||
type,
|
||||
bytes,
|
||||
nbytes);
|
||||
}
|
||||
|
Reference in New Issue
Block a user