From f0511e0f67de8f61ad596eb8869278503ab55c32 Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Sat, 7 Jan 2023 00:52:08 -0500 Subject: [PATCH] progress on ES3 dongle --- amcus/config.c | 4 +- meson.build | 1 + platform/es3sec.c | 241 ++++++++++++++++++++++++++++++++++++++++++- platform/es3sec.h | 6 +- platform/meson.build | 2 + platform/platform.c | 10 +- 6 files changed, 258 insertions(+), 6 deletions(-) diff --git a/amcus/config.c b/amcus/config.c index 781ba43..6e04538 100644 --- a/amcus/config.c +++ b/amcus/config.c @@ -12,7 +12,7 @@ void amcus_config_load(struct amcus_config *cfg, const wchar_t *filename) GetPrivateProfileStringW(L"amcus", L"cacfg_game_ver", L"00.01", cfg->cacfg_game_ver, _countof(cfg->cacfg_game_ver), filename); GetPrivateProfileStringW(L"amcus", L"server_uri", L"localhost", cfg->server_uri, _countof(cfg->server_uri), filename); GetPrivateProfileStringW(L"amcus", L"server_host", L"localhost", cfg->server_host, _countof(cfg->server_host), filename); - GetPrivateProfileStringW(L"amcus", L"am_serial", L"ABLN6789012", cfg->am_serial, _countof(cfg->am_serial), filename); + GetPrivateProfileStringW(L"amcus", L"am_serial", L"ABGN6789012", cfg->am_serial, _countof(cfg->am_serial), filename); es3sec_config_load(&cfg->dongle, filename); -} \ No newline at end of file +} diff --git a/meson.build b/meson.build index 7d47b4d..a0465c6 100644 --- a/meson.build +++ b/meson.build @@ -38,6 +38,7 @@ shlwapi_lib = cc.find_library('shlwapi') dinput8_lib = cc.find_library('dinput8') dxguid_lib = cc.find_library('dxguid') xinput_lib = cc.find_library('xinput') +cfgmgr32_lib = cc.find_library('cfgmgr32') inc = include_directories('.') capnhook = subproject('capnhook') diff --git a/platform/es3sec.c b/platform/es3sec.c index e3dfb0a..b85c929 100644 --- a/platform/es3sec.c +++ b/platform/es3sec.c @@ -1,4 +1,243 @@ #include #include +#include -#include "es3sec.h" \ No newline at end of file +#include "hook/table.h" +#include "hook/iohook.h" +#include "hooklib/setupapi.h" + +#include "util/dprintf.h" +#include "util/str.h" +#include "es3sec.h" + +const wchar_t *DEVNAME_HUB = L"$hub"; +const wchar_t *DEVNAME_DONGLE = L"$dongle"; +const wchar_t HUB_DRIVER_KEY[] = L"{36fc9e60-c465-11cf-8056-444553540000}\\0001"; +const DEVINST HUB_DEVINST = 573; +static struct es3sec_config config; +static HANDLE dongle_fd; +static HANDLE hub_fd; +static IID hubs_iid; +DEVINST root_dev_inst; + +static HRESULT es3sec_handle_hub_irp(struct irp *irp); +static HRESULT es3sec_handle_hub_open(struct irp *irp); +static HRESULT es3sec_handle_hub_close(struct irp *irp); +static HRESULT es3sec_handle_hub_ioctl(struct irp *irp); +static HRESULT es3sec_handle_dongle_irp(struct irp *irp); +static HRESULT es3sec_handle_dongle_open(struct irp *irp); +static HRESULT es3sec_handle_dongle_close(struct irp *irp); +static HRESULT es3sec_handle_dongle_ioctl(struct irp *irp); + +static HRESULT es3sec_hub_handle_driverkey(struct irp *irp); + +static CONFIGRET my_CM_Get_Child(PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags); +static CONFIGRET (*next_CM_Get_Child)(PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags); + +static CONFIGRET my_CM_Get_DevNode_Registry_PropertyW( + DEVINST dnDevInst, + ULONG ulProperty, + PULONG pulRegDataType, + PVOID Buffer, + PULONG pulLength, + ULONG ulFlags +); +static CONFIGRET (*next_CM_Get_DevNode_Registry_PropertyW)( + DEVINST dnDevInst, + ULONG ulProperty, + PULONG pulRegDataType, + PVOID Buffer, + PULONG pulLength, + ULONG ulFlags +); + +static const struct hook_symbol cm_syms[] = { + { + .name = "CM_Get_DevNode_Registry_PropertyW", + .patch = my_CM_Get_DevNode_Registry_PropertyW, + .link = (void **) &next_CM_Get_DevNode_Registry_PropertyW + }, + { + .name = "CM_Get_Child", + .patch = my_CM_Get_Child, + .link = (void **) &next_CM_Get_Child + }, +}; + +HRESULT es3sec_hook_init(const struct es3sec_config *cfg, char *vid, char *pid) +{ + HRESULT hr; + assert(cfg != NULL); + + if (!cfg->enable) { + return S_FALSE; + } + + IIDFromString(L"{3ABF6F2D-71C4-462a-8A92-1E6861E6AF27}", &hubs_iid); + setupapi_add_phantom_dev(&hubs_iid, DEVNAME_HUB); + + hr = iohook_open_nul_fd(&dongle_fd); + hr = iohook_open_nul_fd(&hub_fd); + + if (FAILED(hr)) { + return hr; + } + + hr = iohook_push_handler(es3sec_handle_hub_irp); + hr = iohook_push_handler(es3sec_handle_dongle_irp); + + if (FAILED(hr)) { + return hr; + } + + hook_table_apply(NULL, "setupapi.dll", cm_syms, _countof(cm_syms)); + + CM_Locate_DevNodeW(&root_dev_inst, NULL, CM_LOCATE_DEVNODE_NORMAL); + + dprintf("ES3 Dongle: init with VID %s PID %s (root node DEVINST %lx)\n", vid, pid, root_dev_inst); + + memcpy(&config, cfg, sizeof(*cfg)); + return S_OK; +} + +static HRESULT es3sec_handle_hub_irp(struct irp *irp) +{ + assert(irp != NULL); + if (irp->op != IRP_OP_OPEN && irp->fd != hub_fd) { + return iohook_invoke_next(irp); + } + + switch (irp->op) { + case IRP_OP_OPEN: return es3sec_handle_hub_open(irp); + case IRP_OP_CLOSE: return es3sec_handle_hub_close(irp); + case IRP_OP_IOCTL: return es3sec_handle_hub_ioctl(irp); + default: return HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION); + } +} + +static HRESULT es3sec_handle_hub_open(struct irp *irp) +{ + if (!wstr_ieq(irp->open_filename, DEVNAME_HUB)) { + return iohook_invoke_next(irp); + } + + dprintf("ES3 Dongle: Open USB Hub\n"); + irp->fd = hub_fd; + return S_OK; +} + +static HRESULT es3sec_handle_hub_close(struct irp *irp) +{ + dprintf("ES3 Dongle: Close Hub\n"); + return S_OK; +} + +static HRESULT es3sec_handle_hub_ioctl(struct irp *irp) +{ + switch (irp->ioctl) { + case 0x220424: return es3sec_hub_handle_driverkey(irp); + default: dprintf("ES3 Dongle: Unknown hub IOCTL %X\n", irp->ioctl); return HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION); + } + + return iohook_invoke_next(irp); +} + +static HRESULT es3sec_hub_handle_driverkey(struct irp *irp) +{ + int actual_length = sizeof(HUB_DRIVER_KEY); + PUSB_HCD_DRIVERKEY_NAME usb_hcd_driver_key_name = (PUSB_HCD_DRIVERKEY_NAME) malloc(sizeof(USB_HCD_DRIVERKEY_NAME) + 2 * actual_length); + + usb_hcd_driver_key_name->ActualLength = actual_length; + errno_t err = wcscpy_s( + usb_hcd_driver_key_name->DriverKeyName, + _countof(HUB_DRIVER_KEY), + HUB_DRIVER_KEY + ); + + if (err) { + dprintf("ES3 Dongle: es3sec_hub_handle_driverkey wcscpy_s failed with %X", err); + return E_FAIL; + } + + iobuf_write(&irp->read, usb_hcd_driver_key_name, sizeof(usb_hcd_driver_key_name)); + + dprintf("ES3 Dongle: Get Hub Driver Key\n"); + return S_OK; +} + +static HRESULT es3sec_handle_dongle_irp(struct irp *irp) +{ + assert(irp != NULL); + if (irp->op != IRP_OP_OPEN && irp->fd != dongle_fd) { + return iohook_invoke_next(irp); + } + + switch (irp->op) { + case IRP_OP_OPEN: return es3sec_handle_dongle_open(irp); + case IRP_OP_CLOSE: return es3sec_handle_dongle_close(irp); + case IRP_OP_IOCTL: return es3sec_handle_dongle_ioctl(irp); + default: return HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION); + } +} + +static HRESULT es3sec_handle_dongle_open(struct irp *irp) +{ + if (!wstr_ieq(irp->open_filename, DEVNAME_DONGLE)) { + return iohook_invoke_next(irp); + } + + dprintf("ES3 Dongle: Open dongle\n"); + irp->fd = dongle_fd; + return S_OK; +} + +static HRESULT es3sec_handle_dongle_close(struct irp *irp) +{ + dprintf("ES3 Dongle: Close dongle\n"); + return S_OK; +} + +static HRESULT es3sec_handle_dongle_ioctl(struct irp *irp) +{ + dprintf("ES3 Dongle: IOCTL %X\n", irp->ioctl); + return iohook_invoke_next(irp); +} + +static CONFIGRET my_CM_Get_DevNode_Registry_PropertyW( + DEVINST dnDevInst, + ULONG ulProperty, + PULONG pulRegDataType, + PVOID Buffer, + PULONG pulLength, + ULONG ulFlags +) +{ + CONFIGRET cr = next_CM_Get_DevNode_Registry_PropertyW(dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength, ulFlags); + if (dnDevInst != HUB_DEVINST) { + return cr; + } + + switch (ulProperty) { + case CM_DRP_DEVICEDESC: wcscpy_s(Buffer, _countof(L"Disk drive"), L"Disk drive"); break; + + case CM_DRP_DRIVER: wcscpy_s(Buffer, _countof(HUB_DRIVER_KEY), HUB_DRIVER_KEY); break; + + default: + dprintf("ES3 Dongle: my_CM_Get_DevNode_Registry_PropertyW Unhandled property %lX\n", ulProperty); + return CR_FAILURE; + } + + dprintf("ES3 Dongle: my_CM_Get_DevNode_Registry_PropertyW %lX\n", ulProperty); + return CR_SUCCESS; +} + +static CONFIGRET my_CM_Get_Child(PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags) +{ + if (dnDevInst != root_dev_inst) { + return next_CM_Get_Child(pdnDevInst, dnDevInst, ulFlags); + } + + dprintf("ES3 Dongle: Adding fake hub to root node\n"); + *pdnDevInst = HUB_DEVINST; + return CR_SUCCESS; +} diff --git a/platform/es3sec.h b/platform/es3sec.h index 1b99579..f520043 100644 --- a/platform/es3sec.h +++ b/platform/es3sec.h @@ -5,4 +5,8 @@ struct es3sec_config { bool enable; wchar_t serial[13]; -}; \ No newline at end of file + wchar_t vid[5]; + wchar_t pid[5]; +}; + +HRESULT es3sec_hook_init(const struct es3sec_config *cfg, char *vid, char *pid); diff --git a/platform/meson.build b/platform/meson.build index 458e077..7bd7cd5 100644 --- a/platform/meson.build +++ b/platform/meson.build @@ -6,6 +6,7 @@ platform_lib = static_library( dependencies : [ capnhook.get_variable('hook_dep'), shlwapi_lib, + cfgmgr32_lib, ], link_with : [ board_lib @@ -29,6 +30,7 @@ platform_lib = static_library( 'misc.h', 'vfs.c', 'vfs.h', + 'es3sec.c', 'es3sec.h', ], ) diff --git a/platform/platform.c b/platform/platform.c index 91e68f4..ac2cdc6 100644 --- a/platform/platform.c +++ b/platform/platform.c @@ -36,7 +36,7 @@ HRESULT platform_hook_init( return hr; } - if (jvs != NULL) { + if (jvs != NULL) { hr = jvs_hook_init(&cfg->jvs, jvs); if (FAILED(hr)) { @@ -56,5 +56,11 @@ HRESULT platform_hook_init( return hr; } + hr = es3sec_hook_init(&cfg->dongle, "", ""); + + if (FAILED(hr)) { + return hr; + } + return S_OK; -} \ No newline at end of file +}