From b6216c696e7f0f7a87f1ef644d33a34401e7f079 Mon Sep 17 00:00:00 2001 From: Will Xyen Date: Sat, 12 Oct 2019 05:28:18 -0400 Subject: [PATCH] bio2emu: Add missing CM hooks for device index retrieval Used by games that access the BIO2 through libacio --- src/main/bio2emu/setupapi.c | 79 ++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 9 deletions(-) diff --git a/src/main/bio2emu/setupapi.c b/src/main/bio2emu/setupapi.c index 3acf78d..3ce17cc 100644 --- a/src/main/bio2emu/setupapi.c +++ b/src/main/bio2emu/setupapi.c @@ -1,9 +1,11 @@ #define LOG_MODULE "setupapi-hook" #include -#include #include +#include +#include + #include "hook/table.h" #include "bio2emu/setupapi.h" @@ -14,8 +16,6 @@ #include "util/str.h" #include "util/time.h" -#define MAX_INSTANCES_HOOKED 8 - static struct array* bio2_assigned_ports = NULL; static BOOL my_SetupDiDestroyDeviceInfoList( @@ -100,6 +100,20 @@ static HDEVINFO(*real_SetupDiGetClassDevsA)( DWORD Flags ); +static CONFIGRET my_CM_Get_Device_IDA( + DEVINST dnDevInst, + PSTR Buffer, + ULONG BufferLen, + ULONG ulFlags +); + +static CONFIGRET(*real_CM_Get_Device_IDA)( + DEVINST dnDevInst, + PSTR Buffer, + ULONG BufferLen, + ULONG ulFlags +); + static const struct hook_symbol bio2emu_setupapi_syms[] = { { .name = "SetupDiDestroyDeviceInfoList", @@ -131,6 +145,11 @@ static const struct hook_symbol bio2emu_setupapi_syms[] = { .patch = my_SetupDiGetClassDevsA, .link = (void **) &real_SetupDiGetClassDevsA }, + { + .name = "CM_Get_Device_IDA", + .patch = my_CM_Get_Device_IDA, + .link = (void **) &real_CM_Get_Device_IDA + }, }; static LSTATUS my_RegQueryValueExA( @@ -158,6 +177,11 @@ static const struct hook_symbol bio2emu_Advapi32_syms[] = { }, }; +#define MAX_INSTANCES_HOOKED 16 +#define CUSTOM_DEVICE_INSTANCE 0x3113ca70 +#define CUSTOM_DEVICE_INSTANCE_MASK 0xfffffff0 +#define CUSTOM_DEVICE_INSTANCE_IDXMASK 0x0000000f + static void* CUSTOM_DEVICE_HANDLE; static struct HKEY__ CUSTOM_REGISTRY_HANDLE[MAX_INSTANCES_HOOKED]; @@ -174,6 +198,21 @@ static size_t get_match_index(HKEY ptr, HKEY base) { return -1; } +static BOOL check_instances_limit(DWORD devinst) { + if ((devinst & CUSTOM_DEVICE_INSTANCE_MASK) != CUSTOM_DEVICE_INSTANCE) { + return false; + } + + size_t num = devinst & CUSTOM_DEVICE_INSTANCE_IDXMASK; + if (num >= MAX_INSTANCES_HOOKED) { + return false; + } + if (num >= bio2_assigned_ports->nitems) { + return false; + } + return true; +} + static BOOL my_SetupDiDestroyDeviceInfoList( HDEVINFO DeviceInfoSet ){ @@ -191,8 +230,8 @@ static BOOL my_SetupDiEnumDeviceInfo( ){ if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE){ log_info("%s: Loaded idx %ld", __FUNCTION__, MemberIndex); - if (MemberIndex < MAX_INSTANCES_HOOKED) { - DeviceInfoData->DevInst = MemberIndex; + if (MemberIndex < bio2_assigned_ports->nitems) { + DeviceInfoData->DevInst = CUSTOM_DEVICE_INSTANCE | MemberIndex; return true; } return false; @@ -209,9 +248,9 @@ static HKEY my_SetupDiOpenDevRegKey( REGSAM samDesired ){ if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE){ - if (DeviceInfoData->DevInst < MAX_INSTANCES_HOOKED){ + if (check_instances_limit(DeviceInfoData->DevInst)){ log_info("%s: matched instance", __FUNCTION__); - return &CUSTOM_REGISTRY_HANDLE[DeviceInfoData->DevInst]; + return &CUSTOM_REGISTRY_HANDLE[DeviceInfoData->DevInst & CUSTOM_DEVICE_INSTANCE_IDXMASK]; } } return real_SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, KeyType, samDesired); @@ -230,8 +269,8 @@ static BOOL my_SetupDiGetDeviceRegistryPropertyA( PDWORD RequiredSize ){ if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE){ - if (DeviceInfoData->DevInst< MAX_INSTANCES_HOOKED){ - struct bio2emu_port* selected_port = *array_item(struct bio2emu_port*, bio2_assigned_ports, DeviceInfoData->DevInst); + if (check_instances_limit(DeviceInfoData->DevInst)){ + struct bio2emu_port* selected_port = *array_item(struct bio2emu_port*, bio2_assigned_ports, DeviceInfoData->DevInst & CUSTOM_DEVICE_INSTANCE_IDXMASK); size_t portname_len = strlen(selected_port->port); size_t required_size = (DEVICE_PROPERTY_LENGTH + portname_len + 1 + 1); // + 1 for ')', + 1 for NULL @@ -307,6 +346,28 @@ static LSTATUS my_RegQueryValueExA( return real_RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); } + +static const char devpath[] = "USB\\VID_5730&PID_804C&MI_00\\000"; +static const size_t devpathsize = 32; +static CONFIGRET my_CM_Get_Device_IDA( + DEVINST dnDevInst, + PSTR Buffer, + ULONG BufferLen, + ULONG ulFlags +){ + if (Buffer && BufferLen > devpathsize) { + if (check_instances_limit(dnDevInst)) { + log_info("%s: Injecting custom parent ID for BIO2", __FUNCTION__); + strcpy(Buffer, devpath); + + Buffer[devpathsize - 1] = '\0' + (dnDevInst & CUSTOM_DEVICE_INSTANCE_IDXMASK); + log_info("%s: %s", __FUNCTION__, Buffer); + return CR_SUCCESS; + } + } + return real_CM_Get_Device_IDA(dnDevInst, Buffer, BufferLen, ulFlags); +} + void bio2emu_setupapi_hook_init(struct array* bio2_ports) { bio2_assigned_ports = bio2_ports;