Bemanitools v5.26 release

This commit is contained in:
icex2
2019-09-27 22:36:50 +02:00
commit cbd7720349
718 changed files with 62731 additions and 0 deletions
+31
View File
@@ -0,0 +1,31 @@
avsdlls += iidxhook8
ldflags_iidxhook8 := \
-liphlpapi \
-lsetupapi \
-lcfgmgr32 \
-lmf \
-lmfplat \
-lole32 \
deplibs_iidxhook8 := \
avs \
libs_iidxhook8 := \
iidxhook-util \
acioemu \
iidxio \
hook \
hooklib \
cconfig \
util \
eamio \
src_iidxhook8 := \
bi2a.c \
bio2.c \
cam.c \
config-cam.c \
config-io.c \
dllmain.c \
setupapi.c \
+251
View File
@@ -0,0 +1,251 @@
#define LOG_MODULE "bio2emu-bi2a"
#include "iidxhook8/bi2a.h"
#include <windows.h> /* for _BitScanForward */
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "acioemu/emu.h"
#include "bemanitools/iidxio.h"
static int get_default_slider_valid(size_t idx);
static void bio2_emu_bi2a_cmd_send_version(const struct ac_io_message *req);
static void bio2_emu_bi2a_send_state(const struct ac_io_message *req);
static void bio2_emu_bi2a_send_empty(const struct ac_io_message *req);
static void bio2_emu_bi2a_send_status(const struct ac_io_message *req, uint8_t status);
static struct ac_io_emu *bi2a_bio2;
static int default_sliders[5];
static bool poll_delay;
int get_default_slider_valid(size_t idx) {
if (default_sliders[idx] >= 0 && default_sliders[idx] <= 15) {
return 1;
} else {
return 0;
}
}
void bio2_emu_bi2a_init(struct ac_io_emu *bio2_emu, bool disable_poll_limiter)
{
FILE* f;
bi2a_bio2 = bio2_emu;
poll_delay = !disable_poll_limiter;
if (!poll_delay) {
log_warning("bio2_emu_bi2a_init: poll_delay has been disabled");
}
for (size_t i = 0; i < 5; ++i) {
default_sliders[i] = -1;
}
f = fopen("vefx.txt", "r");
if (f) {
fscanf(f, "%d %d %d %d %d", &default_sliders[0], &default_sliders[1], &default_sliders[2], &default_sliders[3], &default_sliders[4]);
fclose(f);
}
}
void bio2_emu_bi2a_dispatch_request(const struct ac_io_message *req)
{
uint16_t cmd_code;
cmd_code = ac_io_u16(req->cmd.code);
switch (cmd_code) {
case BIO2_BI2A_CMD_UNK_0100:
case BIO2_BI2A_CMD_UNK_0120:
log_misc("BIO2_BI2A_CMD_UNK_%04X(%d)", cmd_code, req->addr);
bio2_emu_bi2a_send_status(req, 0x00);
break;
case BIO2_BI2A_CMD_POLL:
// log_misc("BIO2_BI2A_CMD_POLL");
bio2_emu_bi2a_send_state(req);
break;
case AC_IO_CMD_GET_VERSION:
log_misc("BIO2_CMD_GET_VERSION(%d)", req->addr);
bio2_emu_bi2a_cmd_send_version(req);
break;
case AC_IO_CMD_START_UP:
log_misc("BIO2_CMD_START_UP(%d)", req->addr);
bio2_emu_bi2a_send_status(req, 0x00);
break;
case AC_IO_CMD_KEEPALIVE:
log_misc("BIO2_CMD_KEEPALIVE(%d)", req->addr);
bio2_emu_bi2a_send_empty(req);
break;
default:
log_warning("Unknown BIO2 message %04x on BI2A node, addr=%d", cmd_code, req->addr);
break;
}
}
static void bio2_emu_bi2a_cmd_send_version(const struct ac_io_message *req)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = sizeof(resp.cmd.version);
resp.cmd.version.type = ac_io_u32(AC_IO_NODE_TYPE_BI2A);
resp.cmd.version.flag = 0x00;
resp.cmd.version.major = 0x04;
resp.cmd.version.minor = 0x00;
resp.cmd.version.revision = 0x04;
memcpy(resp.cmd.version.product_code, "BI2A",
sizeof(resp.cmd.version.product_code));
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
ac_io_emu_response_push(bi2a_bio2, &resp, 0);
}
static void bio2_emu_bi2a_send_empty(const struct ac_io_message *req)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = 0;
ac_io_emu_response_push(bi2a_bio2, &resp, 0);
}
static void bio2_emu_bi2a_send_status(const struct ac_io_message *req, uint8_t status)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = sizeof(resp.cmd.status);
resp.cmd.status = status;
ac_io_emu_response_push(bi2a_bio2, &resp, 0);
}
static void bio2_emu_bi2a_send_state(const struct ac_io_message *req)
{
struct ac_io_message resp;
struct bio2_bi2a_state *body;
struct bio2_bi2a_state_in *req_bi2a;
uint8_t input_sys = 0;
uint8_t input_panel = 0;
uint16_t input_keys = 0;
struct {
uint8_t panel_lights;
uint16_t deck_lights;
uint8_t top_lamps;
} packed_lights;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = sizeof(struct bio2_bi2a_state);
req_bi2a = (struct bio2_bi2a_state_in*)req->cmd.raw;
packed_lights.panel_lights = 0;
for (size_t i = 0; i < 4; ++i) {
if (req_bi2a->PANEL[i].l_state) {
packed_lights.panel_lights |= (1 << i);
}
}
packed_lights.deck_lights = 0;
for (size_t i = 0; i < 14; ++i) {
if (req_bi2a->DECKSW[i].l_state) {
packed_lights.deck_lights |= (1 << i);
}
}
packed_lights.top_lamps = 0;
for (size_t i = 0; i < 4; ++i) {
if (req_bi2a->SPOTLIGHT1[i].l_state) {
packed_lights.top_lamps |= (1 << i);
}
}
for (size_t i = 0; i < 4; ++i) {
if (req_bi2a->SPOTLIGHT2[i].l_state) {
packed_lights.top_lamps |= (1 << (i + 4));
}
}
iidx_io_ep1_set_deck_lights(packed_lights.deck_lights);
iidx_io_ep1_set_panel_lights(packed_lights.panel_lights);
iidx_io_ep1_set_top_lamps(packed_lights.top_lamps);
iidx_io_ep1_set_top_neons(req_bi2a->NEONLAMP.l_state);
if (!iidx_io_ep1_send()) {
log_warning("BIO2: iidx_io_ep1_send error");
return bio2_emu_bi2a_send_status(req, 0);
}
if (!iidx_io_ep3_write_16seg((const char*) req_bi2a->SEG16)) {
log_warning("BIO2: iidx_io_ep3_write_16seg error");
return bio2_emu_bi2a_send_status(req, 0);
}
body = (struct bio2_bi2a_state *)&resp.cmd.raw;
memset(body, 0, sizeof(struct bio2_bi2a_state));
// IIDX25 polls really really fast, this limits it to 1000Hz
if (poll_delay) {
Sleep(1);
}
if (!iidx_io_ep2_recv()) {
log_warning("BIO2: iidx_io_ep2_recv error");
return bio2_emu_bi2a_send_status(req, 0);
}
body->TURNTABLE1 = iidx_io_ep2_get_turntable(0);
body->TURNTABLE2 = iidx_io_ep2_get_turntable(1);
body->SLIDER1.s_val = get_default_slider_valid(0) ? default_sliders[0] : iidx_io_ep2_get_slider(0);
body->SLIDER2.s_val = get_default_slider_valid(1) ? default_sliders[1] : iidx_io_ep2_get_slider(1);
body->SLIDER3.s_val = get_default_slider_valid(2) ? default_sliders[2] : iidx_io_ep2_get_slider(2);
body->SLIDER4.s_val = get_default_slider_valid(3) ? default_sliders[3] : iidx_io_ep2_get_slider(3);
body->SLIDER5.s_val = get_default_slider_valid(4) ? default_sliders[4] : iidx_io_ep2_get_slider(4);
input_keys = iidx_io_ep2_get_keys();
input_sys = iidx_io_ep2_get_sys();
input_panel = iidx_io_ep2_get_panel();
body->P1SW1.b_val = (input_keys >> IIDX_IO_KEY_P1_1) & 1;
body->P1SW2.b_val = (input_keys >> IIDX_IO_KEY_P1_2) & 1;
body->P1SW3.b_val = (input_keys >> IIDX_IO_KEY_P1_3) & 1;
body->P1SW4.b_val = (input_keys >> IIDX_IO_KEY_P1_4) & 1;
body->P1SW5.b_val = (input_keys >> IIDX_IO_KEY_P1_5) & 1;
body->P1SW6.b_val = (input_keys >> IIDX_IO_KEY_P1_6) & 1;
body->P1SW7.b_val = (input_keys >> IIDX_IO_KEY_P1_7) & 1;
body->P2SW1.b_val = (input_keys >> IIDX_IO_KEY_P2_1) & 1;
body->P2SW2.b_val = (input_keys >> IIDX_IO_KEY_P2_2) & 1;
body->P2SW3.b_val = (input_keys >> IIDX_IO_KEY_P2_3) & 1;
body->P2SW4.b_val = (input_keys >> IIDX_IO_KEY_P2_4) & 1;
body->P2SW5.b_val = (input_keys >> IIDX_IO_KEY_P2_5) & 1;
body->P2SW6.b_val = (input_keys >> IIDX_IO_KEY_P2_6) & 1;
body->P2SW7.b_val = (input_keys >> IIDX_IO_KEY_P2_7) & 1;
body->PANEL.y_start1 = (input_panel >> IIDX_IO_PANEL_P1_START) & 1;
body->PANEL.y_start2 = (input_panel >> IIDX_IO_PANEL_P2_START) & 1;
body->PANEL.y_vefx = (input_panel >> IIDX_IO_PANEL_VEFX) & 1;
body->PANEL.y_effect = (input_panel >> IIDX_IO_PANEL_EFFECT) & 1;
body->SYSTEM.v_test = (input_sys >> IIDX_IO_SYS_TEST) & 1;
body->SYSTEM.v_service = (input_sys >> IIDX_IO_SYS_SERVICE) & 1;
body->SYSTEM.v_coin = (input_sys >> IIDX_IO_SYS_COIN) & 1;
ac_io_emu_response_push(bi2a_bio2, &resp, 0);
}
+115
View File
@@ -0,0 +1,115 @@
#ifndef IIDXHOOK_BI2A_H
#define IIDXHOOK_BI2A_H
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include "acioemu/emu.h"
enum bio2_bi2a_cmd {
// Custom Stuff
BIO2_BI2A_CMD_UNK_0100 = 0x0100,
BIO2_BI2A_CMD_UNK_0120 = 0x0120,
BIO2_BI2A_CMD_POLL = 0x0152,
};
#pragma pack(push, 1)
struct _slider {
uint8_t s_unk : 4;
uint8_t s_val : 4;
};
struct _system {
uint8_t v_unk1 : 1;
uint8_t v_coin : 1;
uint8_t v_service : 1;
uint8_t v_test : 1;
uint8_t v_unk2 : 4;
};
struct _button {
uint8_t b_unk : 7;
uint8_t b_val : 1;
};
struct _panel {
uint8_t y_unk : 4;
uint8_t y_effect : 1;
uint8_t y_vefx : 1;
uint8_t y_start2 : 1;
uint8_t y_start1 : 1;
};
struct bio2_bi2a_state {
struct _slider SLIDER1;
struct _system SYSTEM;
struct _slider SLIDER2;
uint8_t UNK1;
struct _slider SLIDER3;
uint8_t UNK2;
struct _slider SLIDER4;
struct _slider SLIDER5;
uint8_t UNK3; // coin mech?
struct _panel PANEL;
uint8_t UNK4;
uint8_t UNK5;
uint8_t UNK6;
uint8_t UNK7;
uint8_t UNK8;
uint8_t UNK9;
uint8_t TURNTABLE1;
uint8_t TURNTABLE2;
struct _button P1SW1;
uint8_t UNK11;
struct _button P1SW2;
uint8_t UNK12;
struct _button P1SW3;
uint8_t UNK13;
struct _button P1SW4;
uint8_t UNK14;
struct _button P1SW5;
uint8_t UNK15;
struct _button P1SW6;
uint8_t UNK16;
struct _button P1SW7;
uint8_t UNK17;
struct _button P2SW1;
uint8_t UNK21;
struct _button P2SW2;
uint8_t UNK22;
struct _button P2SW3;
uint8_t UNK23;
struct _button P2SW4;
uint8_t UNK24;
struct _button P2SW5;
uint8_t UNK25;
struct _button P2SW6;
uint8_t UNK26;
struct _button P2SW7;
uint8_t UNK27;
};
struct _light {
uint8_t l_unk : 7;
uint8_t l_state : 1;
};
struct bio2_bi2a_state_in {
struct _light UNK1[3];
struct _light PANEL[4];
struct _light DECKSW[14];
uint8_t UNK2[2];
uint8_t SEG16[9];
struct _light SPOTLIGHT1[4];
struct _light NEONLAMP;
struct _light SPOTLIGHT2[4];
uint8_t UNK3[7];
};
_Static_assert(sizeof(struct bio2_bi2a_state_in) == 48, "bio2_bi2a_state_in is the wrong size");
#pragma pack(pop)
void bio2_emu_bi2a_init(struct ac_io_emu *in, bool disable_poll_limiter);
void bio2_emu_bi2a_dispatch_request(const struct ac_io_message *req);
#endif
+81
View File
@@ -0,0 +1,81 @@
#include <windows.h>
#include <ntdef.h>
#include <devioctl.h>
#include <ntddser.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "acioemu/addr.h"
#include "acioemu/emu.h"
#include "hook/iohook.h"
#include "iidxhook8/bi2a.h"
#include "imports/avs.h"
#include "util/defs.h"
#include "util/iobuf.h"
#include "util/log.h"
#include "util/str.h"
static struct ac_io_emu bio2_emu;
void bio2_port_init(bool disable_poll_limiter)
{
// yes I'm using acio
// they use the same framing
ac_io_emu_init(&bio2_emu, L"COM4");
bio2_emu_bi2a_init(&bio2_emu, disable_poll_limiter);
}
void bio2_port_fini(void)
{
ac_io_emu_fini(&bio2_emu);
}
HRESULT bio2_port_dispatch_irp(struct irp *irp)
{
const struct ac_io_message *msg;
HRESULT hr;
log_assert(irp != NULL);
if (!ac_io_emu_match_irp(&bio2_emu, irp)) {
return irp_invoke_next(irp);
}
for (;;) {
hr = ac_io_emu_dispatch_irp(&bio2_emu, irp);
if (hr != S_OK) {
return hr;
}
msg = ac_io_emu_request_peek(&bio2_emu);
switch (msg->addr) {
case 0:
ac_io_emu_cmd_assign_addrs(&bio2_emu, msg, 1);
break;
case 1:
bio2_emu_bi2a_dispatch_request(msg);
break;
case AC_IO_BROADCAST:
log_warning("Broadcast(?) message on IIDX BIO2 bus?");
break;
default:
log_warning("BIO2 message on unhandled bus address: %d", msg->addr);
break;
}
ac_io_emu_request_pop(&bio2_emu);
}
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef IIDXHOOK_BIO2_H
#define IIDXHOOK_BIO2_H
#include <windows.h>
#include <stdbool.h>
#include "hook/iohook.h"
void bio2_port_init(bool disable_poll_limiter);
void bio2_port_fini(void);
HRESULT bio2_port_dispatch_irp(struct irp *irp);
#endif
+731
View File
@@ -0,0 +1,731 @@
#define LOG_MODULE "cam-hook"
#include <initguid.h>
#include <windows.h>
#include <mfobjects.h>
#include <mfidl.h>
#include <mfapi.h>
#include <setupapi.h>
#include <cfgmgr32.h>
#include <stdio.h>
#include "hook/com-proxy.h"
#include "hook/table.h"
#include "iidxhook8/cam.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
#include "util/time.h"
#define CAMERA_DATA_STRING_SIZE 0x100
EXTERN_GUID(MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, 0xc60ac5fe, 0x252a, 0x478f, 0xa0, 0xef, 0xbc, 0x8f, 0xa5, 0xf7, 0xca, 0xd3);
EXTERN_GUID(MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID, 0x8ac3587a, 0x4ae7, 0x42d8, 0x99, 0xe0, 0x0a, 0x60, 0x13, 0xee, 0xf9, 0x0f);
EXTERN_GUID(MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, 0x58f0aad8, 0x22bf, 0x4f8a, 0xbb, 0x3d, 0xd2, 0xc4, 0x97, 0x8c, 0x6e, 0x2f);
// define ourselves cause mingw has these wrong
struct CameraData {
bool setup;
char name[CAMERA_DATA_STRING_SIZE];
char deviceInstancePath[CAMERA_DATA_STRING_SIZE];
wchar_t deviceSymbolicLink[CAMERA_DATA_STRING_SIZE];
char extra_upper[CAMERA_DATA_STRING_SIZE];
int address;
char parent_name[CAMERA_DATA_STRING_SIZE];
char parent_deviceInstancePath[CAMERA_DATA_STRING_SIZE];
int parent_address;
};
static struct CameraData camData[2];
static CONFIGRET my_CM_Locate_DevNodeA(
PDEVINST pdnDevInst,
DEVINSTID_A pDeviceID,
ULONG ulFlags
);
static CONFIGRET my_CM_Get_Parent(
PDEVINST pdnDevInst,
DEVINST dnDevInst,
ULONG ulFlags
);
static CONFIGRET my_CM_Get_Device_IDA(
DEVINST dnDevInst,
PSTR Buffer,
ULONG BufferLen,
ULONG ulFlags
);
static CONFIGRET(*real_CM_Locate_DevNodeA)(
PDEVINST pdnDevInst,
DEVINSTID_A pDeviceID,
ULONG ulFlags
);
static CONFIGRET(*real_CM_Get_Parent)(
PDEVINST pdnDevInst,
DEVINST dnDevInst,
ULONG ulFlags
);
static CONFIGRET(*real_CM_Get_Device_IDA)(
DEVINST dnDevInst,
PSTR Buffer,
ULONG BufferLen,
ULONG ulFlags
);
static HRESULT my_MFEnumDeviceSources(
IMFAttributes *pAttributes,
IMFActivate ***pppSourceActivate,
UINT32 *pcSourceActivate
);
static HRESULT (*real_MFEnumDeviceSources)(
IMFAttributes *pAttributes,
IMFActivate ***pppSourceActivate,
UINT32 *pcSourceActivate
);
static BOOL my_SetupDiDestroyDeviceInfoList(
HDEVINFO DeviceInfoSet
);
static BOOL (*real_SetupDiDestroyDeviceInfoList)(
HDEVINFO DeviceInfoSet
);
static BOOL my_SetupDiEnumDeviceInfo(
HDEVINFO DeviceInfoSet,
DWORD MemberIndex,
PSP_DEVINFO_DATA DeviceInfoData
);
static BOOL (*real_SetupDiEnumDeviceInfo)(
HDEVINFO DeviceInfoSet,
DWORD MemberIndex,
PSP_DEVINFO_DATA DeviceInfoData
);
static BOOL my_SetupDiGetDeviceRegistryPropertyA(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Property,
PDWORD PropertyRegDataType,
PBYTE PropertyBuffer,
DWORD PropertyBufferSize,
PDWORD RequiredSize
);
static BOOL (*real_SetupDiGetDeviceRegistryPropertyA)(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Property,
PDWORD PropertyRegDataType,
PBYTE PropertyBuffer,
DWORD PropertyBufferSize,
PDWORD RequiredSize
);
static HDEVINFO my_SetupDiGetClassDevsA(
CONST GUID *ClassGuid,
PCSTR Enumerator,
HWND hwndParent,
DWORD Flags
);
static HDEVINFO(*real_SetupDiGetClassDevsA)(
CONST GUID *ClassGuid,
PCSTR Enumerator,
HWND hwndParent,
DWORD Flags
);
static const struct hook_symbol iidxhook5_cfgmgr32_syms[] = {
{
.name = "CM_Locate_DevNodeA",
.patch = my_CM_Locate_DevNodeA,
.link = (void **) &real_CM_Locate_DevNodeA
},
{
.name = "CM_Get_Parent",
.patch = my_CM_Get_Parent,
.link = (void **) &real_CM_Get_Parent
},
{
.name = "CM_Get_Device_IDA",
.patch = my_CM_Get_Device_IDA,
.link = (void **) &real_CM_Get_Device_IDA
},
{
.name = "SetupDiDestroyDeviceInfoList",
.patch = my_SetupDiDestroyDeviceInfoList,
.link = (void **) &real_SetupDiDestroyDeviceInfoList
},
{
.name = "SetupDiEnumDeviceInfo",
.patch = my_SetupDiEnumDeviceInfo,
.link = (void **) &real_SetupDiEnumDeviceInfo
},
{
.name = "SetupDiGetDeviceRegistryPropertyA",
.patch = my_SetupDiGetDeviceRegistryPropertyA,
.link = (void **) &real_SetupDiGetDeviceRegistryPropertyA
},
{
.name = "SetupDiGetClassDevsA",
.patch = my_SetupDiGetClassDevsA,
.link = (void **) &real_SetupDiGetClassDevsA
},
};
static const struct hook_symbol iidxhook5_mf_syms[] = {
{
.name = "MFEnumDeviceSources",
.patch = my_MFEnumDeviceSources,
.link = (void **) &real_MFEnumDeviceSources
},
};
#define CUSTOM_DEV_NODE1 0x04040004
#define CUSTOM_DEV_NODE2 0x04040008
#define CUSTOM_DEV_PARENT_NODE1 0x04040014
#define CUSTOM_DEV_PARENT_NODE2 0x04040018
static CONFIGRET my_CM_Locate_DevNodeA(
PDEVINST pdnDevInst,
DEVINSTID_A pDeviceID,
ULONG ulFlags
){
log_info("Inside: %s", __FUNCTION__);
char builtString1[CAMERA_DATA_STRING_SIZE] = {0};
char builtString2[CAMERA_DATA_STRING_SIZE] = {0};
if (camData[0].setup) {
snprintf(builtString1, CAMERA_DATA_STRING_SIZE, "USB\\VID_288C&PID_0002&MI_00\\%s", camData[0].extra_upper);
if(camData[1].setup) {
snprintf(builtString2, CAMERA_DATA_STRING_SIZE, "USB\\VID_288C&PID_0002&MI_00\\%s", camData[1].extra_upper);
}
} else if(camData[1].setup) {
snprintf(builtString1, CAMERA_DATA_STRING_SIZE, "USB\\VID_288C&PID_0002&MI_00\\%s", camData[1].extra_upper);
}
if (pdnDevInst) {
if (strcmp(pDeviceID, builtString1) == 0) {
log_info("Injecting custom device 1");
*pdnDevInst = CUSTOM_DEV_NODE1;
return CR_SUCCESS;
}
if (strcmp(pDeviceID, builtString2) == 0) {
log_info("Injecting custom device 2");
*pdnDevInst = CUSTOM_DEV_NODE2;
return CR_SUCCESS;
}
}
return real_CM_Locate_DevNodeA(pdnDevInst, pDeviceID, ulFlags);
}
static CONFIGRET my_CM_Get_Parent(
PDEVINST pdnDevInst,
DEVINST dnDevInst,
ULONG ulFlags
){
log_info("Inside: %s", __FUNCTION__);
if (pdnDevInst) {
if (dnDevInst == CUSTOM_DEV_NODE1) {
log_info("Injecting custom parent 1");
*pdnDevInst = CUSTOM_DEV_PARENT_NODE1;
return CR_SUCCESS;
}
if (dnDevInst == CUSTOM_DEV_NODE2) {
log_info("Injecting custom parent 2");
*pdnDevInst = CUSTOM_DEV_PARENT_NODE2;
return CR_SUCCESS;
}
}
return real_CM_Get_Parent(pdnDevInst, dnDevInst, ulFlags);
}
static CONFIGRET my_CM_Get_Device_IDA(
DEVINST dnDevInst,
PSTR Buffer,
ULONG BufferLen,
ULONG ulFlags
){
log_info("Inside: %s", __FUNCTION__);
if (Buffer) {
if (dnDevInst == CUSTOM_DEV_PARENT_NODE1) {
log_info("Injecting custom parent 1 ID");
strncpy(Buffer, "USB\\VEN_1022&DEV_7908", BufferLen);
Buffer[BufferLen - 1] = '\0';
log_info("%s", Buffer);
return CR_SUCCESS;
}
if (dnDevInst == CUSTOM_DEV_PARENT_NODE2) {
log_info("Injecting custom parent 2 ID");
strncpy(Buffer, "USB\\VEN_1022&DEV_7914", BufferLen);
Buffer[BufferLen - 1] = '\0';
log_info("%s", Buffer);
return CR_SUCCESS;
}
}
return real_CM_Get_Device_IDA(dnDevInst, Buffer, BufferLen, ulFlags);
}
static HRESULT (STDCALL *real_GetAllocatedString)(
IMFActivate* self,
REFGUID guidKey,
LPWSTR *ppwszValue,
UINT32 *pcchLength);
HRESULT my_GetAllocatedString(
IMFActivate* self,
REFGUID guidKey,
LPWSTR *ppwszValue,
UINT32 *pcchLength
){
HRESULT ret;
log_info("Inside: %s", __FUNCTION__);
// should probably check GUID, oh well
ret = real_GetAllocatedString(self, guidKey, ppwszValue, pcchLength);
log_info("Obtained: %ls", *ppwszValue);
wchar_t *pwc = NULL;
if (camData[0].setup) {
pwc = wcsstr(*ppwszValue, camData[0].deviceSymbolicLink);
}
if (camData[1].setup) {
if (!pwc) {
pwc = wcsstr(*ppwszValue, camData[1].deviceSymbolicLink);
}
}
if (pwc){
// \\?\usb#vid_288c&pid_0002&mi_00
pwc[12] = L'2';
pwc[13] = L'8';
pwc[14] = L'8';
pwc[15] = L'c';
pwc[21] = L'0';
pwc[22] = L'0';
pwc[23] = L'0';
pwc[24] = L'2';
pwc[29] = L'0';
pwc[30] = L'0';
log_info("Replaced: %ls", *ppwszValue);
}
return ret;
}
static HRESULT my_MFEnumDeviceSources(
IMFAttributes *pAttributes,
IMFActivate ***pppSourceActivate,
UINT32 *pcSourceActivate
){
IMFActivate *api;
IMFActivateVtbl *api_vtbl;
struct com_proxy *api_proxy;
UINT32 nsrcs;
HRESULT ret;
log_info("Inside: %s", __FUNCTION__);
ret = real_MFEnumDeviceSources(pAttributes, pppSourceActivate, pcSourceActivate);
nsrcs = *pcSourceActivate;
for (UINT32 i = 0; i < nsrcs; ++i) {
api = (*pppSourceActivate)[i];
api_proxy = com_proxy_wrap(api, sizeof(*api->lpVtbl));
api_vtbl = api_proxy->vptr;
real_GetAllocatedString = api_vtbl->GetAllocatedString;
api_vtbl->GetAllocatedString = my_GetAllocatedString;
(*pppSourceActivate)[i] = (IMFActivate *)api_proxy;
}
return ret;
}
#define CUSTOM_DEVICE_HANDLE (void*)0x04041110
static HDEVINFO RealReplacedHandle;
static BOOL my_SetupDiDestroyDeviceInfoList(
HDEVINFO DeviceInfoSet
){
if (DeviceInfoSet == CUSTOM_DEVICE_HANDLE){
log_info("Inside: %s", __FUNCTION__);
DeviceInfoSet = RealReplacedHandle;
RealReplacedHandle = NULL;
return real_SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
return real_SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
static BOOL my_SetupDiEnumDeviceInfo(
HDEVINFO DeviceInfoSet,
DWORD MemberIndex,
PSP_DEVINFO_DATA DeviceInfoData
){
if (DeviceInfoSet == CUSTOM_DEVICE_HANDLE) {
// log_info("Inside: %s", __FUNCTION__);
return real_SetupDiEnumDeviceInfo(RealReplacedHandle, MemberIndex, DeviceInfoData);
}
return real_SetupDiEnumDeviceInfo(DeviceInfoSet, MemberIndex, DeviceInfoData);
}
static BOOL my_SetupDiGetDeviceRegistryPropertyA(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Property,
PDWORD PropertyRegDataType,
PBYTE PropertyBuffer,
DWORD PropertyBufferSize,
PDWORD RequiredSize
){
if (DeviceInfoSet == CUSTOM_DEVICE_HANDLE) {
BOOL ret = real_SetupDiGetDeviceRegistryPropertyA(RealReplacedHandle, DeviceInfoData, Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, RequiredSize);
if (Property == SPDRP_DEVICEDESC) {
if (PropertyBuffer){
if (camData[0].setup) {
if (strcmp((char*)PropertyBuffer, camData[0].parent_name) == 0) {
log_info("%s: replacing %s", __FUNCTION__, camData[0].parent_name);
strncpy((char*)PropertyBuffer, "USB Composite Device", PropertyBufferSize);
}
}
if (camData[1].setup) {
if (strcmp((char*)PropertyBuffer, camData[1].parent_name) == 0) {
log_info("%s: replacing %s", __FUNCTION__, camData[1].parent_name);
strncpy((char*)PropertyBuffer, "USB Composite Device", PropertyBufferSize);
}
}
}
return ret;
} else if (Property == SPDRP_ADDRESS) {
if (PropertyBuffer){
int addr = *(int*)PropertyBuffer;
if (camData[0].setup) {
if (addr == camData[0].parent_address) {
log_info("%s: replacing addr1", __FUNCTION__);
*(int*)PropertyBuffer = 1;
} else if (camData[1].setup) {
if (addr == camData[1].parent_address) {
log_info("%s: replacing addr7", __FUNCTION__);
*(int*)PropertyBuffer = 7;
}
}
} else if (camData[1].setup) {
if (addr == camData[1].parent_address) {
log_info("%s: replacing addr1 (alt)", __FUNCTION__);
*(int*)PropertyBuffer = 1;
}
}
}
return ret;
}
}
return real_SetupDiGetDeviceRegistryPropertyA(DeviceInfoSet, DeviceInfoData, Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, RequiredSize);
}
static HDEVINFO my_SetupDiGetClassDevsA(
CONST GUID *ClassGuid,
PCSTR Enumerator,
HWND hwndParent,
DWORD Flags
){
if (ClassGuid == NULL && Enumerator != NULL && hwndParent == NULL && Flags == (DIGCF_PRESENT | DIGCF_ALLCLASSES)) {
if (RealReplacedHandle) {
log_info("Replacement handle is already set?");
}
if (strcmp(Enumerator, "USB") == 0) {
log_info("Inside: %s", __FUNCTION__);
RealReplacedHandle = real_SetupDiGetClassDevsA(ClassGuid, Enumerator, hwndParent, Flags);
if (RealReplacedHandle == INVALID_HANDLE_VALUE) {
return INVALID_HANDLE_VALUE;
}
return CUSTOM_DEVICE_HANDLE;
}
}
return real_SetupDiGetClassDevsA(ClassGuid, Enumerator, hwndParent, Flags);
}
bool check_four(const char inA[4], const char inB[4]) {
return (*(uint32_t*)inA == *(uint32_t*)inB);
}
char* grab_next_camera_id(char* buffer, size_t bsz) {
static size_t gotten = 0;
IMFAttributes *pAttributes = NULL;
IMFActivate **ppDevices = NULL;
buffer[0] = '\0';
HRESULT hr = MFCreateAttributes(&pAttributes, 1);
if (FAILED(hr)) {
log_info("MFCreateAttributes failed: %ld", hr);
goto done;
}
hr = pAttributes->lpVtbl->SetGUID(pAttributes, &MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, &MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
if (FAILED(hr)) {
log_info("SetGUID failed: %ld", hr);
goto done;
}
UINT32 count;
hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count);
if (FAILED(hr)) {
log_info("MFEnumDeviceSources failed: %ld", hr);
goto done;
}
if (count <= gotten) {
log_info("gotten failed: %d < %d", count, (int)gotten);
// not enough remaining
goto done;
}
wchar_t wSymLink[CAMERA_DATA_STRING_SIZE];
UINT32 sz;
hr = ppDevices[gotten]->lpVtbl->GetString(ppDevices[gotten], &MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, wSymLink, CAMERA_DATA_STRING_SIZE, &sz);
if (FAILED(hr)) {
log_info("GetString failed: %ld", hr);
goto done;
}
log_info("Detected webcam: %s\n", buffer);
wcstombs(buffer, wSymLink, bsz);
++gotten;
done:
if (pAttributes) {
pAttributes->lpVtbl->Release(pAttributes);
}
for (DWORD i = 0; i < count; i++) {
if (ppDevices != NULL && ppDevices[i]) {
ppDevices[i]->lpVtbl->Release(ppDevices[i]);
}
}
CoTaskMemFree(ppDevices);
return buffer;
}
bool convert_sym_to_path(const char* sym, char* path) {
HDEVINFO DeviceInfoSet = SetupDiCreateDeviceInfoList(NULL, NULL);
if (DeviceInfoSet == INVALID_HANDLE_VALUE) {
log_info("Could not open SetupDiCreateDeviceInfoList\n");
return 0;
}
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = {0};
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
if (!SetupDiOpenDeviceInterfaceA(DeviceInfoSet, sym, 0, &DeviceInterfaceData)) {
log_info("Could not SetupDiOpenDeviceInterfaceA\n");
return 0;
}
SP_DEVINFO_DATA DeviceInfoData = {0};
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (!SetupDiGetDeviceInterfaceDetailA(DeviceInfoSet, &DeviceInterfaceData, NULL, 0, NULL, &DeviceInfoData)) {
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
log_info("Could not SetupDiGetDeviceInterfaceDetailA\n");
return 0;
}
}
DWORD sz;
if (!SetupDiGetDeviceInstanceIdA(DeviceInfoSet, &DeviceInfoData, path, CAMERA_DATA_STRING_SIZE, &sz)){
log_info("Could not SetupDiGetDeviceInstanceIdA\n");
return 0;
}
if (DeviceInfoSet != INVALID_HANDLE_VALUE){
if (!SetupDiDeleteDeviceInterfaceData(DeviceInfoSet, &DeviceInterfaceData)){
log_info("Could not SetupDiDeleteDeviceInterfaceData\n");
return 0;
}
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
return 1;
}
void strtolower(char* str) {
for (size_t i = 0; str[i]; i++){
str[i] = tolower(str[i]);
}
}
bool convert_path_to_fakesym(const char* path, wchar_t* sym, char* extra_o) {
char root[16] = {0};
char vidstr[16] = {0};
char pidstr[16] = {0};
char mistr[16] = {0};
char extra[64] = {0};
sscanf(path, "%[^\\]\\%[^&]&%[^&]&%[^\\]\\%s", root, vidstr, pidstr, mistr, extra);
strcpy(extra_o, extra);
strtolower(root);
strtolower(vidstr);
strtolower(pidstr);
strtolower(mistr);
strtolower(extra);
swprintf(sym, CAMERA_DATA_STRING_SIZE, L"\\\\?\\%S#%S&%S&%S#%S", root, vidstr, pidstr, mistr, extra);
return true;
}
void fill_cam_struct(struct CameraData* data, const char* devid)
{
char buffer[CAMERA_DATA_STRING_SIZE];
data->setup = false;
if (!devid || strlen(devid) == 0) {
devid = grab_next_camera_id(buffer, CAMERA_DATA_STRING_SIZE);
}
if (!devid || strlen(devid) == 0) {
// no more cameras remain?
return;
}
if (strlen(devid) >= CAMERA_DATA_STRING_SIZE) {
// error probably log something?
return;
}
// detect input type
if (check_four(devid, "\\\\?\\")) {
// SYMBOLIC_LINK
if (!convert_sym_to_path(devid, data->deviceInstancePath)){
log_info("Could not convert %s to path", devid);
return;
}
} else if (check_four(devid, "USB\\")) {
// Device instance path
strcpy(data->deviceInstancePath, devid);
// continue
} else {
// UNKNOWN ENTRY
log_info("UNK: %s", devid);
log_info("Please enter the device instance path");
return;
}
if (!convert_path_to_fakesym(data->deviceInstancePath, data->deviceSymbolicLink, data->extra_upper)){
log_info("Could not convert %s to sym", data->deviceInstancePath);
return;
}
log_info("dev path: %s", data->deviceInstancePath);
// locate device nodes
DEVINST dnDevInst;
DEVINST parentDev;
CONFIGRET cmret;
cmret = CM_Locate_DevNodeA(&dnDevInst, data->deviceInstancePath, CM_LOCATE_DEVNODE_NORMAL);
if (cmret != CR_SUCCESS) {
log_info("CM_Locate_DevNodeA fail: %s", data->deviceInstancePath);
return;
}
cmret = CM_Get_Parent(&parentDev, dnDevInst, 0);
if (cmret != CR_SUCCESS) {
log_info("CM_Get_Parent fail: %s", data->deviceInstancePath);
return;
}
cmret = CM_Get_Device_IDA(parentDev, data->parent_deviceInstancePath, CAMERA_DATA_STRING_SIZE, 0);
if (cmret != CR_SUCCESS) {
log_info("CM_Get_Device_IDA parent fail: %s", data->deviceInstancePath);
return;
}
ULONG szAddr;
ULONG szDesc;
szAddr = 4;
szDesc = CAMERA_DATA_STRING_SIZE;
cmret = CM_Get_DevNode_Registry_PropertyA(dnDevInst, CM_DRP_ADDRESS, NULL, &data->address, &szAddr, 0);
if (cmret != CR_SUCCESS) {
log_info("CM_Get_DevNode_Registry_PropertyA fail: %s", data->deviceInstancePath);
return;
}
cmret = CM_Get_DevNode_Registry_PropertyA(dnDevInst, CM_DRP_DEVICEDESC, NULL, &data->name, &szDesc, 0);
if (cmret != CR_SUCCESS) {
log_info("CM_Get_DevNode_Registry_PropertyA fail: %s", data->deviceInstancePath);
return;
}
szAddr = 4;
szDesc = CAMERA_DATA_STRING_SIZE;
cmret = CM_Get_DevNode_Registry_PropertyA(parentDev, CM_DRP_ADDRESS, NULL, &data->parent_address, &szAddr, 0);
if (cmret != CR_SUCCESS) {
log_info("CM_Get_DevNode_Registry_PropertyA parent fail: %s", data->deviceInstancePath);
return;
}
cmret = CM_Get_DevNode_Registry_PropertyA(parentDev, CM_DRP_DEVICEDESC, NULL, &data->parent_name, &szDesc, 0);
if (cmret != CR_SUCCESS) {
log_info("CM_Get_DevNode_Registry_PropertyA parent fail: %s", data->deviceInstancePath);
return;
}
log_info("Found %s @ %d", data->name, data->address);
log_info("Parent %s @ %d", data->parent_name, data->parent_address);
data->setup = true;
}
void cam_hook_init(const char* devID1, const char* devID2)
{
// fill before applying hooks
fill_cam_struct(&camData[0], devID1);
fill_cam_struct(&camData[1], devID2);
if (camData[0].setup || camData[1].setup) {
hook_table_apply(
NULL,
"setupapi.dll",
iidxhook5_cfgmgr32_syms,
lengthof(iidxhook5_cfgmgr32_syms));
hook_table_apply(
NULL,
"Mf.dll",
iidxhook5_mf_syms,
lengthof(iidxhook5_mf_syms));
log_info("Inserted cam hooks");
} else {
log_info("No cams detected, not hooking");
}
}
+6
View File
@@ -0,0 +1,6 @@
#ifndef IIDXHOOK5_CAM_H
#define IIDXHOOK5_CAM_H
void cam_hook_init(const char* devID1, const char* devID2);
#endif
+61
View File
@@ -0,0 +1,61 @@
#include "cconfig/cconfig-util.h"
#include "iidxhook8/config-cam.h"
#include "util/log.h"
#define IIDXHOOK8_CONFIG_CAM_DISABLE_EMU_KEY "cam.disable_emu"
#define IIDXHOOK8_CONFIG_CAM_DEVICE_ID1_KEY "cam.device_id1"
#define IIDXHOOK8_CONFIG_CAM_DEVICE_ID2_KEY "cam.device_id2"
#define IIDXHOOK8_CONFIG_CAM_DEFAULT_DISABLE_EMU_VALUE false
#define IIDXHOOK8_CONFIG_CAM_DEFAULT_DEVICE_ID1_VALUE ""
#define IIDXHOOK8_CONFIG_CAM_DEFAULT_DEVICE_ID2_VALUE ""
void iidxhook8_config_cam_init(struct cconfig* config)
{
cconfig_util_set_bool(config,
IIDXHOOK8_CONFIG_CAM_DISABLE_EMU_KEY,
IIDXHOOK8_CONFIG_CAM_DEFAULT_DISABLE_EMU_VALUE,
"Disables the camera emulation");
cconfig_util_set_str(config,
IIDXHOOK8_CONFIG_CAM_DEVICE_ID1_KEY,
IIDXHOOK8_CONFIG_CAM_DEFAULT_DEVICE_ID1_VALUE,
"Override camera device ID 1 detection (copy from device manager, do "
"not escape)");
cconfig_util_set_str(config,
IIDXHOOK8_CONFIG_CAM_DEVICE_ID2_KEY,
IIDXHOOK8_CONFIG_CAM_DEFAULT_DEVICE_ID2_VALUE,
"Override camera device ID 2 detection (copy from device manager, do "
"not escape)");
}
void iidxhook8_config_cam_get(struct iidxhook8_config_cam* config_cam,
struct cconfig* config)
{
if (!cconfig_util_get_bool(config, IIDXHOOK8_CONFIG_CAM_DISABLE_EMU_KEY,
&config_cam->disable_emu,
IIDXHOOK8_CONFIG_CAM_DEFAULT_DISABLE_EMU_VALUE)) {
log_warning("Invalid value for key '%s' specified, fallback "
"to default '%d'", IIDXHOOK8_CONFIG_CAM_DISABLE_EMU_KEY,
IIDXHOOK8_CONFIG_CAM_DEFAULT_DISABLE_EMU_VALUE);
}
if (!cconfig_util_get_str(config, IIDXHOOK8_CONFIG_CAM_DEVICE_ID1_KEY,
config_cam->device_id1, sizeof(config_cam->device_id1) - 1,
IIDXHOOK8_CONFIG_CAM_DEFAULT_DEVICE_ID1_VALUE)) {
log_warning("Invalid value for key '%s' specified, fallback "
"to default '%s'", IIDXHOOK8_CONFIG_CAM_DEVICE_ID1_KEY,
IIDXHOOK8_CONFIG_CAM_DEFAULT_DEVICE_ID1_VALUE);
}
if (!cconfig_util_get_str(config, IIDXHOOK8_CONFIG_CAM_DEVICE_ID2_KEY,
config_cam->device_id2, sizeof(config_cam->device_id2) - 1,
IIDXHOOK8_CONFIG_CAM_DEFAULT_DEVICE_ID2_VALUE)) {
log_warning("Invalid value for key '%s' specified, fallback "
"to default '%s'", IIDXHOOK8_CONFIG_CAM_DEVICE_ID2_KEY,
IIDXHOOK8_CONFIG_CAM_DEFAULT_DEVICE_ID2_VALUE);
}
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef IIDXHOOK8_CONFIG_CAM_H
#define IIDXHOOK8_CONFIG_CAM_H
#include <windows.h>
#include "cconfig/cconfig.h"
struct iidxhook8_config_cam {
bool disable_emu;
char device_id1[MAX_PATH];
char device_id2[MAX_PATH];
};
void iidxhook8_config_cam_init(struct cconfig* config);
void iidxhook8_config_cam_get(struct iidxhook8_config_cam* config_cam,
struct cconfig* config);
#endif
+63
View File
@@ -0,0 +1,63 @@
#include "cconfig/cconfig-util.h"
#include "iidxhook8/config-io.h"
#include "util/log.h"
#define IIDXHOOK8_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY "io.disable_card_reader_emu"
#define IIDXHOOK8_CONFIG_IO_DISABLE_BIO2_EMU_KEY "io.disable_bio2_emu"
#define IIDXHOOK8_CONFIG_IO_DISABLE_POLL_LIMITER_KEY "io.disable_poll_limiter"
#define IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE false
#define IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE false
#define IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE false
void iidxhook8_config_io_init(struct cconfig* config)
{
cconfig_util_set_bool(config,
IIDXHOOK8_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY,
IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE,
"Disable card reader emulation and enable usage of real card reader "
"hardware on COM0 (for games supporting slotted readers)");
cconfig_util_set_bool(config,
IIDXHOOK8_CONFIG_IO_DISABLE_BIO2_EMU_KEY,
IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE,
"Disable BIO2 emulation and enable usage of real BIO2 hardware");
cconfig_util_set_bool(config,
IIDXHOOK8_CONFIG_IO_DISABLE_POLL_LIMITER_KEY,
IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE,
"Disables the poll limiter, warning very high CPU usage may arise");
}
void iidxhook8_config_io_get(struct iidxhook8_config_io* config_io,
struct cconfig* config)
{
if (!cconfig_util_get_bool(config,
IIDXHOOK8_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY,
&config_io->disable_card_reader_emu,
IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE)) {
log_warning("Invalid value for key '%s' specified, fallback "
"to default '%d'", IIDXHOOK8_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY,
IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE);
}
if (!cconfig_util_get_bool(config,
IIDXHOOK8_CONFIG_IO_DISABLE_BIO2_EMU_KEY,
&config_io->disable_bio2_emu,
IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE)) {
log_warning("Invalid value for key '%s' specified, fallback "
"to default '%d'", IIDXHOOK8_CONFIG_IO_DISABLE_BIO2_EMU_KEY,
IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE);
}
if (!cconfig_util_get_bool(config,
IIDXHOOK8_CONFIG_IO_DISABLE_POLL_LIMITER_KEY,
&config_io->disable_poll_limiter,
IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE)) {
log_warning("Invalid value for key '%s' specified, fallback "
"to default '%d'", IIDXHOOK8_CONFIG_IO_DISABLE_POLL_LIMITER_KEY,
IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE);
}
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef IIDXHOOK8_CONFIG_IO_H
#define IIDXHOOK8_CONFIG_IO_H
#include <windows.h>
#include "cconfig/cconfig.h"
struct iidxhook8_config_io {
bool disable_card_reader_emu;
bool disable_bio2_emu;
bool disable_poll_limiter;
};
void iidxhook8_config_io_init(struct cconfig* config);
void iidxhook8_config_io_get(struct iidxhook8_config_io* config_io,
struct cconfig* config);
#endif
+194
View File
@@ -0,0 +1,194 @@
#include <windows.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "bemanitools/eamio.h"
#include "bemanitools/iidxio.h"
#include "cconfig/cconfig-hook.h"
#include "hooklib/acp.h"
#include "hooklib/adapter.h"
#include "hooklib/app.h"
#include "hooklib/rs232.h"
#include "hooklib/setupapi.h"
#include "iidxhook-util/acio.h"
#include "iidxhook-util/config-gfx.h"
#include "iidxhook-util/d3d9.h"
#include "iidxhook-util/log-server.h"
#include "iidxhook8/bio2.h"
#include "iidxhook8/cam.h"
#include "iidxhook8/config-cam.h"
#include "iidxhook8/config-io.h"
#include "iidxhook8/setupapi.h"
#include "iidxhook8/cam.h"
#include "imports/avs.h"
#include "util/log.h"
#include "util/str.h"
#include "util/thread.h"
#define IIDXHOOK8_INFO_HEADER \
"iidxhook for Cannon Ballers" \
", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) "\n"
#define IIDXHOOK8_CMD_USAGE \
"Usage: launcher.exe -K iidxhook8.dll <bm2dx.dll> [options...]"
static const irp_handler_t iidxhook_handlers[] = {
iidxhook_util_acio_dispatch_irp,
bio2_port_dispatch_irp,
};
struct iidxhook8_config_io iidxhook8_config_io;
static bool my_dll_entry_init(char *sidcode, struct property_node *param)
{
struct cconfig* config;
struct iidxhook_config_gfx config_gfx;
struct iidxhook8_config_cam config_cam;
// log_server_init is not required anymore
log_info("-------------------------------------------------------------");
log_info("--------------- Begin iidxhook dll_entry_init ---------------");
log_info("-------------------------------------------------------------");
config = cconfig_init();
iidxhook_config_gfx_init(config);
iidxhook8_config_cam_init(config);
iidxhook8_config_io_init(config);
if (!cconfig_hook_config_init(config, IIDXHOOK8_INFO_HEADER "\n" IIDXHOOK8_CMD_USAGE, CCONFIG_CMD_USAGE_OUT_DBG)) {
cconfig_finit(config);
log_server_fini();
exit(EXIT_FAILURE);
}
iidxhook_config_gfx_get(&config_gfx, config);
iidxhook8_config_cam_get(&config_cam, config);
iidxhook8_config_io_get(&iidxhook8_config_io, config);
cconfig_finit(config);
log_info(IIDXHOOK8_INFO_HEADER);
log_info("Initializing iidxhook...");
if (config_gfx.windowed) {
d3d9_set_windowed(config_gfx.framed, config_gfx.window_width,
config_gfx.window_height);
}
if (config_gfx.pci_id_pid != 0 && config_gfx.pci_id_vid != 0) {
d3d9_set_pci_id(config_gfx.pci_id_pid, config_gfx.pci_id_vid);
}
if (config_gfx.frame_rate_limit > 0) {
d3d9_set_frame_rate_limit(config_gfx.frame_rate_limit);
}
if (config_gfx.scale_back_buffer_width > 0 && config_gfx.scale_back_buffer_height > 0) {
d3d9_scale_back_buffer(config_gfx.scale_back_buffer_width, config_gfx.scale_back_buffer_height,
config_gfx.scale_back_buffer_filter);
}
/* Start up IIDXIO.DLL */
if (!iidxhook8_config_io.disable_bio2_emu) {
log_info("Starting IIDX IO backend");
iidx_io_set_loggers(log_impl_misc, log_impl_info, log_impl_warning,
log_impl_fatal);
if (!iidx_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
log_fatal("Initializing IIDX IO backend failed");
}
}
/* Start up EAMIO.DLL */
if (!iidxhook8_config_io.disable_card_reader_emu) {
log_misc("Initializing card reader backend");
eam_io_set_loggers(log_impl_misc, log_impl_info, log_impl_warning,
log_impl_fatal);
if (!eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
log_fatal("Initializing card reader backend failed");
}
}
/* iohooks are okay, even if emu is diabled since the fake handlers won't be used */
/* Set up IO emulation hooks _after_ IO API setup to allow
API implementations with real IO devices */
iohook_init(iidxhook_handlers, lengthof(iidxhook_handlers));
rs232_hook_init();
if (!iidxhook8_config_io.disable_bio2_emu) {
bio2_port_init(iidxhook8_config_io.disable_poll_limiter);
setupapi_hook_init();
}
if (!iidxhook8_config_io.disable_card_reader_emu) {
iidxhook_util_acio_init(false);
}
// camera hooks
if (!config_cam.disable_emu) {
cam_hook_init(config_cam.device_id1, config_cam.device_id2);
}
log_info("-------------------------------------------------------------");
log_info("---------------- End iidxhook dll_entry_init ----------------");
log_info("-------------------------------------------------------------");
return app_hook_invoke_init(sidcode, param);
}
static bool my_dll_entry_main(void)
{
bool result;
result = app_hook_invoke_main();
if (!iidxhook8_config_io.disable_card_reader_emu) {
log_misc("Shutting down card reader backend");
eam_io_fini();
}
if (!iidxhook8_config_io.disable_bio2_emu) {
log_misc("Shutting down IIDX IO backend");
iidx_io_fini();
}
return result;
}
/**
* Hook library Resort Anthem onwards
*/
BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx)
{
if (reason != DLL_PROCESS_ATTACH) {
goto end;
}
log_to_external(
log_body_misc,
log_body_info,
log_body_warning,
log_body_fatal);
app_hook_init(my_dll_entry_init, my_dll_entry_main);
acp_hook_init();
adapter_hook_init();
d3d9_hook_init();
end:
return TRUE;
}
+4
View File
@@ -0,0 +1,4 @@
LIBRARY iidxhook8
EXPORTS
DllMain@12 @1 NONAME
+287
View File
@@ -0,0 +1,287 @@
#define LOG_MODULE "setupapi-hook"
#include <windows.h>
#include <setupapi.h>
#include <initguid.h>
#include "hook/table.h"
#include "iidxhook8/setupapi.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
#include "util/time.h"
static BOOL my_SetupDiDestroyDeviceInfoList(
HDEVINFO DeviceInfoSet
);
static BOOL (*real_SetupDiDestroyDeviceInfoList)(
HDEVINFO DeviceInfoSet
);
static BOOL my_SetupDiEnumDeviceInfo(
HDEVINFO DeviceInfoSet,
DWORD MemberIndex,
PSP_DEVINFO_DATA DeviceInfoData
);
static BOOL (*real_SetupDiEnumDeviceInfo)(
HDEVINFO DeviceInfoSet,
DWORD MemberIndex,
PSP_DEVINFO_DATA DeviceInfoData
);
static HKEY my_SetupDiOpenDevRegKey(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Scope,
DWORD HwProfile,
DWORD KeyType,
REGSAM samDesired
);
static HKEY (*real_SetupDiOpenDevRegKey)(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Scope,
DWORD HwProfile,
DWORD KeyType,
REGSAM samDesired
);
static BOOL my_SetupDiGetDeviceRegistryPropertyA(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Property,
PDWORD PropertyRegDataType,
PBYTE PropertyBuffer,
DWORD PropertyBufferSize,
PDWORD RequiredSize
);
static BOOL (*real_SetupDiGetDeviceRegistryPropertyA)(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Property,
PDWORD PropertyRegDataType,
PBYTE PropertyBuffer,
DWORD PropertyBufferSize,
PDWORD RequiredSize
);
static BOOL my_SetupDiGetDeviceInfoListDetailA(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_LIST_DETAIL_DATA_A DeviceInfoSetDetailData
);
static BOOL (*real_SetupDiGetDeviceInfoListDetailA)(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_LIST_DETAIL_DATA_A DeviceInfoSetDetailData
);
static HDEVINFO my_SetupDiGetClassDevsA(
CONST GUID *ClassGuid,
PCSTR Enumerator,
HWND hwndParent,
DWORD Flags
);
static HDEVINFO(*real_SetupDiGetClassDevsA)(
CONST GUID *ClassGuid,
PCSTR Enumerator,
HWND hwndParent,
DWORD Flags
);
static const struct hook_symbol iidxhook5_setupapi_syms[] = {
{
.name = "SetupDiDestroyDeviceInfoList",
.patch = my_SetupDiDestroyDeviceInfoList,
.link = (void **) &real_SetupDiDestroyDeviceInfoList
},
{
.name = "SetupDiEnumDeviceInfo",
.patch = my_SetupDiEnumDeviceInfo,
.link = (void **) &real_SetupDiEnumDeviceInfo
},
{
.name = "SetupDiOpenDevRegKey",
.patch = my_SetupDiOpenDevRegKey,
.link = (void **) &real_SetupDiOpenDevRegKey
},
{
.name = "SetupDiGetDeviceRegistryPropertyA",
.patch = my_SetupDiGetDeviceRegistryPropertyA,
.link = (void **) &real_SetupDiGetDeviceRegistryPropertyA
},
{
.name = "SetupDiGetDeviceInfoListDetailA",
.patch = my_SetupDiGetDeviceInfoListDetailA,
.link = (void **) &real_SetupDiGetDeviceInfoListDetailA
},
{
.name = "SetupDiGetClassDevsA",
.patch = my_SetupDiGetClassDevsA,
.link = (void **) &real_SetupDiGetClassDevsA
},
};
static LSTATUS my_RegQueryValueExA(
HKEY hKey,
LPCSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
);
static LSTATUS (*real_RegQueryValueExA)(
HKEY hKey,
LPCSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
);
static const struct hook_symbol iidxhook5_Advapi32_syms[] = {
{
.name = "RegQueryValueExA",
.patch = my_RegQueryValueExA,
.link = (void **) &real_RegQueryValueExA
},
};
#define CUSTOM_DEVICE_HANDLE (void*)0x12341230
#define CUSTOM_REGISTRY_HANDLE (void*)0x4242ccc0
static BOOL my_SetupDiDestroyDeviceInfoList(
HDEVINFO DeviceInfoSet
){
if (DeviceInfoSet == CUSTOM_DEVICE_HANDLE){
log_info("Inside: %s", __FUNCTION__);
return true;
}
return real_SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
static BOOL my_SetupDiEnumDeviceInfo(
HDEVINFO DeviceInfoSet,
DWORD MemberIndex,
PSP_DEVINFO_DATA DeviceInfoData
){
if (DeviceInfoSet == CUSTOM_DEVICE_HANDLE){
log_info("Inside: %s", __FUNCTION__);
return true;
}
return real_SetupDiEnumDeviceInfo(DeviceInfoSet, MemberIndex, DeviceInfoData);
}
static HKEY my_SetupDiOpenDevRegKey(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Scope,
DWORD HwProfile,
DWORD KeyType,
REGSAM samDesired
){
if (DeviceInfoSet == CUSTOM_DEVICE_HANDLE){
log_info("Inside: %s", __FUNCTION__);
return CUSTOM_REGISTRY_HANDLE;
}
return real_SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, KeyType, samDesired);
}
static BOOL my_SetupDiGetDeviceRegistryPropertyA(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Property,
PDWORD PropertyRegDataType,
PBYTE PropertyBuffer,
DWORD PropertyBufferSize,
PDWORD RequiredSize
){
if (DeviceInfoSet == CUSTOM_DEVICE_HANDLE){
log_info("Inside: %s", __FUNCTION__);
log_info("%s: Found CUSTOM HANDLE", __FUNCTION__);
if (PropertyBuffer && (PropertyBufferSize >= 12)){
log_info("%s: Copying property name (%ld)", __FUNCTION__, PropertyBufferSize);
strncpy((char*)PropertyBuffer, "BIO2(VIDEO)", PropertyBufferSize);
log_info("%s: Done copying property name", __FUNCTION__);
// Sleep(500);
} else {
log_info("%s: Returning size", __FUNCTION__);
*RequiredSize = 12;
}
log_info("%s: STUB RETURN", __FUNCTION__);
return true;
}
return real_SetupDiGetDeviceRegistryPropertyA(DeviceInfoSet, DeviceInfoData, Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, RequiredSize);
}
static BOOL my_SetupDiGetDeviceInfoListDetailA(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_LIST_DETAIL_DATA_A DeviceInfoSetDetailData
){
if (DeviceInfoSet == CUSTOM_DEVICE_HANDLE){
log_info("Inside: %s", __FUNCTION__);
return true;
}
return real_SetupDiGetDeviceInfoListDetailA(DeviceInfoSet, DeviceInfoSetDetailData);
}
DEFINE_GUID(GUID_COM_BUS_ENUMERATOR,
0x4D36E978, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18);
static HDEVINFO my_SetupDiGetClassDevsA(
CONST GUID *ClassGuid,
PCSTR Enumerator,
HWND hwndParent,
DWORD Flags
){
if (ClassGuid) {
if (IsEqualGUID(ClassGuid, &GUID_COM_BUS_ENUMERATOR)){
log_info("Inside: %s", __FUNCTION__);
return CUSTOM_DEVICE_HANDLE;
}
}
return real_SetupDiGetClassDevsA(ClassGuid, Enumerator, hwndParent, Flags);
}
static LSTATUS my_RegQueryValueExA(
HKEY hKey,
LPCSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
){
if (hKey == CUSTOM_REGISTRY_HANDLE){
if (strcmp(lpValueName, "PortName") == 0) {
log_info("Inside: %s", __FUNCTION__);
if (lpData){
strncpy((char*)lpData, "COM4", *lpcbData);
return ERROR_SUCCESS;
}
return ERROR_MORE_DATA;
}
}
return real_RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
}
void setupapi_hook_init(void)
{
hook_table_apply(
NULL,
"setupapi.dll",
iidxhook5_setupapi_syms,
lengthof(iidxhook5_setupapi_syms));
hook_table_apply(
NULL,
"Advapi32.dll",
iidxhook5_Advapi32_syms,
lengthof(iidxhook5_Advapi32_syms));
log_info("Inserted setupapi hooks");
}
+6
View File
@@ -0,0 +1,6 @@
#ifndef IIDXHOOK_SETUPAPI_H
#define IIDXHOOK_SETUPAPI_H
void setupapi_hook_init(void);
#endif